diff --git a/frontend/src/AppRoutes/Private.tsx b/frontend/src/AppRoutes/Private.tsx index 436b184ca4..754b6cbf40 100644 --- a/frontend/src/AppRoutes/Private.tsx +++ b/frontend/src/AppRoutes/Private.tsx @@ -47,6 +47,8 @@ function PrivateRoute({ children }: PrivateRouteProps): JSX.Element { const dispatch = useDispatch>(); + const [notifications, NotificationElement] = notification.useNotification(); + const currentRoute = mapRoutes.get('current'); const navigateToLoginIfNotLoggedIn = (isLoggedIn = isLoggedInState): void => { @@ -106,7 +108,7 @@ function PrivateRoute({ children }: PrivateRouteProps): JSX.Element { } else { Logout(); - notification.error({ + notifications.error({ message: response.error || t('something_went_wrong'), }); } @@ -155,7 +157,12 @@ function PrivateRoute({ children }: PrivateRouteProps): JSX.Element { // NOTE: disabling this rule as there is no need to have div // eslint-disable-next-line react/jsx-no-useless-fragment - return <>{children}; + return ( + <> + {NotificationElement} + {children} + + ); } interface PrivateRouteProps { diff --git a/frontend/src/components/Logs/CopyClipboardHOC.tsx b/frontend/src/components/Logs/CopyClipboardHOC.tsx index bac9dca86a..f7aa461d88 100644 --- a/frontend/src/components/Logs/CopyClipboardHOC.tsx +++ b/frontend/src/components/Logs/CopyClipboardHOC.tsx @@ -7,14 +7,14 @@ function CopyClipboardHOC({ children, }: CopyClipboardHOCProps): JSX.Element { const [value, setCopy] = useCopyToClipboard(); - + const [notifications, NotificationElement] = notification.useNotification(); useEffect(() => { if (value.value) { - notification.success({ + notifications.success({ message: 'Copied to clipboard', }); } - }, [value]); + }, [value, notifications]); const onClick = useCallback((): void => { setCopy(textToCopy); @@ -22,6 +22,7 @@ function CopyClipboardHOC({ return ( + {NotificationElement} Copy to clipboard} diff --git a/frontend/src/components/Logs/LogItem/index.tsx b/frontend/src/components/Logs/LogItem/index.tsx index b21b50b43c..bc061651e7 100644 --- a/frontend/src/components/Logs/LogItem/index.tsx +++ b/frontend/src/components/Logs/LogItem/index.tsx @@ -79,6 +79,7 @@ function LogItem({ logData }: LogItemProps): JSX.Element { const dispatch = useDispatch(); const flattenLogData = useMemo(() => FlatLogData(logData), [logData]); const [, setCopy] = useCopyToClipboard(); + const [notifications, NotificationElement] = notification.useNotification(); const handleDetailedView = useCallback(() => { dispatch({ @@ -89,13 +90,14 @@ function LogItem({ logData }: LogItemProps): JSX.Element { const handleCopyJSON = (): void => { setCopy(JSON.stringify(logData, null, 2)); - notification.success({ + notifications.success({ message: 'Copied to clipboard', }); }; return ( + {NotificationElement}
{'{'} diff --git a/frontend/src/container/AllError/index.tsx b/frontend/src/container/AllError/index.tsx index 78db55123e..894bc84bc5 100644 --- a/frontend/src/container/AllError/index.tsx +++ b/frontend/src/container/AllError/index.tsx @@ -127,14 +127,15 @@ function AllErrors(): JSX.Element { enabled: !loading, }, ]); + const [notifications, NotificationElement] = notification.useNotification(); useEffect(() => { if (data?.error) { - notification.error({ + notifications.error({ message: data.error || t('something_went_wrong'), }); } - }, [data?.error, data?.payload, t]); + }, [data?.error, data?.payload, t, notifications]); const getDateValue = (value: string): JSX.Element => ( {dayjs(value).format('DD/MM/YYYY HH:mm:ss A')} @@ -379,21 +380,24 @@ function AllErrors(): JSX.Element { ); return ( - + <> + {NotificationElement} +
+ ); } diff --git a/frontend/src/container/AppLayout/index.tsx b/frontend/src/container/AppLayout/index.tsx index 3ff1cfe6c4..189aac2e33 100644 --- a/frontend/src/container/AppLayout/index.tsx +++ b/frontend/src/container/AppLayout/index.tsx @@ -91,6 +91,8 @@ function AppLayout(props: AppLayoutProps): JSX.Element { const latestVersionCounter = useRef(0); const latestConfigCounter = useRef(0); + const [notifications, NotificationElement] = notification.useNotification(); + useEffect(() => { if ( getUserLatestVersionResponse.isFetched && @@ -105,7 +107,7 @@ function AppLayout(props: AppLayoutProps): JSX.Element { isError: true, }, }); - notification.error({ + notifications.error({ message: t('oops_something_went_wrong_version'), }); } @@ -123,7 +125,7 @@ function AppLayout(props: AppLayoutProps): JSX.Element { isError: true, }, }); - notification.error({ + notifications.error({ message: t('oops_something_went_wrong_version'), }); } @@ -219,12 +221,14 @@ function AppLayout(props: AppLayoutProps): JSX.Element { getDynamicConfigsResponse.data, getDynamicConfigsResponse.isFetched, getDynamicConfigsResponse.isSuccess, + notifications, ]); const isToDisplayLayout = isLoggedIn; return ( + {NotificationElement} {isToDisplayLayout &&
} {isToDisplayLayout && } diff --git a/frontend/src/container/ErrorDetails/index.tsx b/frontend/src/container/ErrorDetails/index.tsx index d42d2e4a3e..26a73700e3 100644 --- a/frontend/src/container/ErrorDetails/index.tsx +++ b/frontend/src/container/ErrorDetails/index.tsx @@ -77,13 +77,15 @@ function ErrorDetails(props: ErrorDetailsProps): JSX.Element { [], ); + const [notifications, NotificationElement] = notification.useNotification(); + const onClickErrorIdHandler = async ( id: string, timestamp: string, ): Promise => { try { if (id.length === 0) { - notification.error({ + notifications.error({ message: 'Error Id cannot be empty', }); return; @@ -95,7 +97,7 @@ function ErrorDetails(props: ErrorDetailsProps): JSX.Element { }×tamp=${getNanoSeconds(timestamp)}&errorId=${id}`, ); } catch (error) { - notification.error({ + notifications.error({ message: t('something_went_wrong'), }); } @@ -116,6 +118,7 @@ function ErrorDetails(props: ErrorDetailsProps): JSX.Element { return ( <> + {NotificationElement} {errorDetail.exceptionType} {errorDetail.exceptionMessage} diff --git a/frontend/src/container/FormAlertRules/ChannelSelect/index.tsx b/frontend/src/container/FormAlertRules/ChannelSelect/index.tsx index 99c3038a42..84ce85b786 100644 --- a/frontend/src/container/FormAlertRules/ChannelSelect/index.tsx +++ b/frontend/src/container/FormAlertRules/ChannelSelect/index.tsx @@ -20,12 +20,14 @@ function ChannelSelect({ const { loading, payload, error, errorMessage } = useFetch(getChannels); + const [notifications, NotificationElement] = notification.useNotification(); + const handleChange = (value: string[]): void => { onSelectChannels(value); }; if (error && errorMessage !== '') { - notification.error({ + notifications.error({ message: 'Error', description: errorMessage, }); @@ -48,19 +50,22 @@ function ChannelSelect({ return children; }; return ( - { - handleChange(value as string[]); - }} - optionLabelProp="label" - > - {renderOptions()} - + <> + {NotificationElement} + { + handleChange(value as string[]); + }} + optionLabelProp="label" + > + {renderOptions()} + + ); } diff --git a/frontend/src/container/FormAlertRules/QuerySection.tsx b/frontend/src/container/FormAlertRules/QuerySection.tsx index a0fe8ac2b7..cbb1db83e8 100644 --- a/frontend/src/container/FormAlertRules/QuerySection.tsx +++ b/frontend/src/container/FormAlertRules/QuerySection.tsx @@ -163,10 +163,11 @@ function QuerySection({ ...allQueries, }); }; + const [notifications, NotificationElement] = notification.useNotification(); const addMetricQuery = useCallback(() => { if (Object.keys(metricQueries).length > 5) { - notification.error({ + notifications.error({ message: t('metric_query_max_limit'), }); return; @@ -191,7 +192,7 @@ function QuerySection({ expression: queryLabel, }; setMetricQueries({ ...queries }); - }, [t, getNextQueryLabel, metricQueries, setMetricQueries]); + }, [t, getNextQueryLabel, metricQueries, setMetricQueries, notifications]); const addFormula = useCallback(() => { // defaulting to F1 as only one formula is supported @@ -350,6 +351,7 @@ function QuerySection({ }; return ( <> + {NotificationElement} {t('alert_form_step1')}
{renderTabs(alertType)}
diff --git a/frontend/src/container/FormAlertRules/index.tsx b/frontend/src/container/FormAlertRules/index.tsx index c96b02719d..efd2179f94 100644 --- a/frontend/src/container/FormAlertRules/index.tsx +++ b/frontend/src/container/FormAlertRules/index.tsx @@ -190,12 +190,14 @@ function FormAlertRules({ }); } }; + const [notifications, NotificationElement] = notification.useNotification(); + const validatePromParams = useCallback((): boolean => { let retval = true; if (queryCategory !== EQueryType.PROM) return retval; if (!promQueries || Object.keys(promQueries).length === 0) { - notification.error({ + notifications.error({ message: 'Error', description: t('promql_required'), }); @@ -204,7 +206,7 @@ function FormAlertRules({ Object.keys(promQueries).forEach((key) => { if (promQueries[key].query === '') { - notification.error({ + notifications.error({ message: 'Error', description: t('promql_required'), }); @@ -213,14 +215,14 @@ function FormAlertRules({ }); return retval; - }, [t, promQueries, queryCategory]); + }, [t, promQueries, queryCategory, notifications]); const validateChQueryParams = useCallback((): boolean => { let retval = true; if (queryCategory !== EQueryType.CLICKHOUSE) return retval; if (!chQueries || Object.keys(chQueries).length === 0) { - notification.error({ + notifications.error({ message: 'Error', description: t('chquery_required'), }); @@ -229,7 +231,7 @@ function FormAlertRules({ Object.keys(chQueries).forEach((key) => { if (chQueries[key].rawQuery === '') { - notification.error({ + notifications.error({ message: 'Error', description: t('chquery_required'), }); @@ -238,14 +240,14 @@ function FormAlertRules({ }); return retval; - }, [t, chQueries, queryCategory]); + }, [t, chQueries, queryCategory, notifications]); const validateQBParams = useCallback((): boolean => { let retval = true; if (queryCategory !== EQueryType.QUERY_BUILDER) return true; if (!metricQueries || Object.keys(metricQueries).length === 0) { - notification.error({ + notifications.error({ message: 'Error', description: t('condition_required'), }); @@ -253,7 +255,7 @@ function FormAlertRules({ } if (!alertDef.condition?.target) { - notification.error({ + notifications.error({ message: 'Error', description: t('target_missing'), }); @@ -262,7 +264,7 @@ function FormAlertRules({ Object.keys(metricQueries).forEach((key) => { if (metricQueries[key].metricName === '') { - notification.error({ + notifications.error({ message: 'Error', description: t('metricname_missing', { where: metricQueries[key].name }), }); @@ -272,7 +274,7 @@ function FormAlertRules({ Object.keys(formulaQueries).forEach((key) => { if (formulaQueries[key].expression === '') { - notification.error({ + notifications.error({ message: 'Error', description: t('expression_missing', formulaQueries[key].name), }); @@ -280,11 +282,11 @@ function FormAlertRules({ } }); return retval; - }, [t, alertDef, queryCategory, metricQueries, formulaQueries]); + }, [t, alertDef, queryCategory, metricQueries, formulaQueries, notifications]); const isFormValid = useCallback((): boolean => { if (!alertDef.alert || alertDef.alert === '') { - notification.error({ + notifications.error({ message: 'Error', description: t('alertname_required'), }); @@ -300,7 +302,14 @@ function FormAlertRules({ } return validateQBParams(); - }, [t, validateQBParams, validateChQueryParams, alertDef, validatePromParams]); + }, [ + t, + validateQBParams, + validateChQueryParams, + alertDef, + validatePromParams, + notifications, + ]); const preparePostData = (): AlertDef => { const postableAlert: AlertDef = { @@ -348,7 +357,7 @@ function FormAlertRules({ const response = await saveAlertApi(apiReq); if (response.statusCode === 200) { - notification.success({ + notifications.success({ message: 'Success', description: !ruleId || ruleId === 0 ? t('rule_created') : t('rule_edited'), @@ -361,19 +370,26 @@ function FormAlertRules({ history.replace(ROUTES.LIST_ALL_ALERT); }, 2000); } else { - notification.error({ + notifications.error({ message: 'Error', description: response.error || t('unexpected_error'), }); } } catch (e) { - notification.error({ + notifications.error({ message: 'Error', description: t('unexpected_error'), }); } setLoading(false); - }, [t, isFormValid, ruleId, ruleCache, memoizedPreparePostData]); + }, [ + t, + isFormValid, + ruleId, + ruleCache, + memoizedPreparePostData, + notifications, + ]); const onSaveHandler = useCallback(async () => { const content = ( @@ -407,30 +423,30 @@ function FormAlertRules({ if (response.statusCode === 200) { const { payload } = response; if (payload?.alertCount === 0) { - notification.error({ + notifications.error({ message: 'Error', description: t('no_alerts_found'), }); } else { - notification.success({ + notifications.success({ message: 'Success', description: t('rule_test_fired'), }); } } else { - notification.error({ + notifications.error({ message: 'Error', description: response.error || t('unexpected_error'), }); } } catch (e) { - notification.error({ + notifications.error({ message: 'Error', description: t('unexpected_error'), }); } setLoading(false); - }, [t, isFormValid, memoizedPreparePostData]); + }, [t, isFormValid, memoizedPreparePostData, notifications]); const renderBasicInfo = (): JSX.Element => ( @@ -467,6 +483,7 @@ function FormAlertRules({ ); return ( <> + {NotificationElement} {Element} diff --git a/frontend/src/container/GeneralSettings/GeneralSettings.tsx b/frontend/src/container/GeneralSettings/GeneralSettings.tsx index 5a7f0504bb..85a4d30ae9 100644 --- a/frontend/src/container/GeneralSettings/GeneralSettings.tsx +++ b/frontend/src/container/GeneralSettings/GeneralSettings.tsx @@ -172,6 +172,8 @@ function GeneralSettings({ logsTtlValuesPayload.status === 'pending' ? 1000 : null, ); + const [notifications, NotificationElement] = notification.useNotification(); + const onModalToggleHandler = (type: TTTLType): void => { if (type === 'metrics') setModalMetrics((modal) => !modal); if (type === 'traces') setModalTraces((modal) => !modal); @@ -186,14 +188,14 @@ function GeneralSettings({ const onClickSaveHandler = useCallback( (type: TTTLType) => { if (!setRetentionPermission) { - notification.error({ + notifications.error({ message: `Sorry you don't have permission to make these changes`, }); return; } onModalToggleHandler(type); }, - [setRetentionPermission], + [setRetentionPermission, notifications], ); const s3Enabled = useMemo( @@ -352,7 +354,7 @@ function GeneralSettings({ let hasSetTTLFailed = false; if (setTTLResponse.statusCode === 409) { hasSetTTLFailed = true; - notification.error({ + notifications.error({ message: 'Error', description: t('retention_request_race_condition'), placement: 'topRight', @@ -390,7 +392,7 @@ function GeneralSettings({ }); } } catch (error) { - notification.error({ + notifications.error({ message: 'Error', description: t('retention_failed_message'), placement: 'topRight', @@ -591,6 +593,7 @@ function GeneralSettings({ return ( <> + {NotificationElement} {Element}
diff --git a/frontend/src/container/GridGraphLayout/index.tsx b/frontend/src/container/GridGraphLayout/index.tsx index 553632e0d6..158fb927de 100644 --- a/frontend/src/container/GridGraphLayout/index.tsx +++ b/frontend/src/container/GridGraphLayout/index.tsx @@ -204,6 +204,8 @@ function GridGraph(props: Props): JSX.Element { [widgets, onDragSelect], ); + const [notifications, NotificationElement] = notification.useNotification(); + const onEmptyWidgetHandler = useCallback(async () => { try { const id = 'empty'; @@ -219,22 +221,25 @@ function GridGraph(props: Props): JSX.Element { ...(data.layout || []), ]; - await UpdateDashboard({ - data, - generateWidgetId: id, - graphType: 'EMPTY_WIDGET', - selectedDashboard, - layout, - isRedirected: false, - }); + await UpdateDashboard( + { + data, + generateWidgetId: id, + graphType: 'EMPTY_WIDGET', + selectedDashboard, + layout, + isRedirected: false, + }, + notifications, + ); setLayoutFunction(layout); } catch (error) { - notification.error({ + notifications.error({ message: error instanceof Error ? error.toString() : 'Something went wrong', }); } - }, [data, selectedDashboard, setLayoutFunction]); + }, [data, selectedDashboard, setLayoutFunction, notifications]); const onLayoutChangeHandler = async (layout: Layout[]): Promise => { setLayoutFunction(layout); @@ -255,7 +260,7 @@ function GridGraph(props: Props): JSX.Element { toggleAddWidget(true); }) .catch(() => { - notification.error(t('something_went_wrong')); + notifications.error(t('something_went_wrong')); }); } else { toggleAddWidget(true); @@ -263,26 +268,29 @@ function GridGraph(props: Props): JSX.Element { } } catch (error) { if (typeof error === 'string') { - notification.error({ + notifications.error({ message: error || t('something_went_wrong'), }); } } - }, [layouts, onEmptyWidgetHandler, t, toggleAddWidget]); + }, [layouts, onEmptyWidgetHandler, t, toggleAddWidget, notifications]); return ( - + <> + {NotificationElement} + + ); } diff --git a/frontend/src/container/GridGraphLayout/utils.ts b/frontend/src/container/GridGraphLayout/utils.ts index d06c69c757..95d3574b7e 100644 --- a/frontend/src/container/GridGraphLayout/utils.ts +++ b/frontend/src/container/GridGraphLayout/utils.ts @@ -1,4 +1,4 @@ -import { notification } from 'antd'; +import { NotificationInstance } from 'antd/es/notification/interface'; import updateDashboardApi from 'api/dashboard/update'; import { ClickHouseQueryTemplate, @@ -12,14 +12,17 @@ import store from 'store'; import { Dashboard } from 'types/api/dashboard/getAll'; import { EQueryType } from 'types/common/dashboard'; -export const UpdateDashboard = async ({ - data, - graphType, - generateWidgetId, - layout, - selectedDashboard, - isRedirected, -}: UpdateDashboardProps): Promise => { +export const UpdateDashboard = async ( + { + data, + graphType, + generateWidgetId, + layout, + selectedDashboard, + isRedirected, + }: UpdateDashboardProps, + notify: NotificationInstance, +): Promise => { const updatedSelectedDashboard: Dashboard = { ...selectedDashboard, data: { @@ -89,7 +92,7 @@ export const UpdateDashboard = async ({ if (response.statusCode === 200) { return response.payload; } - notification.error({ + notify.error({ message: response.error || 'Something went wrong', }); return undefined; diff --git a/frontend/src/container/Licenses/ApplyLicenseForm.tsx b/frontend/src/container/Licenses/ApplyLicenseForm.tsx index 858bf38d54..95035f2a51 100644 --- a/frontend/src/container/Licenses/ApplyLicenseForm.tsx +++ b/frontend/src/container/Licenses/ApplyLicenseForm.tsx @@ -26,10 +26,12 @@ function ApplyLicenseForm({ enabled: false, }); + const [notifications, NotificationElement] = notification.useNotification(); + const onFinish = async (values: unknown | { key: string }): Promise => { const params = values as { key: string }; if (params.key === '' || !params.key) { - notification.error({ + notifications.error({ message: 'Error', description: t('enter_license_key'), }); @@ -53,18 +55,18 @@ function ApplyLicenseForm({ payload: featureFlagsResponse.data.payload, }); } - notification.success({ + notifications.success({ message: 'Success', description: t('license_applied'), }); } else { - notification.error({ + notifications.error({ message: 'Error', description: response.error || t('unexpected_error'), }); } } catch (e) { - notification.error({ + notifications.error({ message: 'Error', description: t('unexpected_error'), }); @@ -74,6 +76,7 @@ function ApplyLicenseForm({ return ( + {NotificationElement} { (async (): Promise => { const { data: refetchData, status } = await refetch(); @@ -37,7 +39,7 @@ function ListAlert({ allAlertRules, refetch }: ListAlertProps): JSX.Element { setData(refetchData?.payload || []); } if (status === 'error') { - notification.error({ + notificationsApi.error({ message: t('something_went_wrong'), }); } @@ -145,6 +147,7 @@ function ListAlert({ allAlertRules, refetch }: ListAlertProps): JSX.Element { return ( <> + {NotificationElement} {Element} diff --git a/frontend/src/container/ListAlertRules/ToggleAlertState.tsx b/frontend/src/container/ListAlertRules/ToggleAlertState.tsx index 69c888e7ab..58e4f7d71e 100644 --- a/frontend/src/container/ListAlertRules/ToggleAlertState.tsx +++ b/frontend/src/container/ListAlertRules/ToggleAlertState.tsx @@ -20,6 +20,8 @@ function ToggleAlertState({ payload: undefined, }); + const [notifications, NotificationElement] = notification.useNotification(); + const defaultErrorMessage = 'Something went wrong'; const onToggleHandler = async ( @@ -58,7 +60,7 @@ function ToggleAlertState({ loading: false, payload: response.payload, })); - notification.success({ + notifications.success({ message: 'Success', }); } else { @@ -69,7 +71,7 @@ function ToggleAlertState({ errorMessage: response.error || defaultErrorMessage, })); - notification.error({ + notifications.error({ message: response.error || defaultErrorMessage, }); } @@ -81,21 +83,24 @@ function ToggleAlertState({ errorMessage: defaultErrorMessage, })); - notification.error({ + notifications.error({ message: defaultErrorMessage, }); } }; return ( - => onToggleHandler(id, !disabled)} - type="link" - > - {disabled ? 'Enable' : 'Disable'} - + <> + {NotificationElement} + => onToggleHandler(id, !disabled)} + type="link" + > + {disabled ? 'Enable' : 'Disable'} + + ); } diff --git a/frontend/src/container/ListAlertRules/index.tsx b/frontend/src/container/ListAlertRules/index.tsx index 7af7bad976..e985a270d2 100644 --- a/frontend/src/container/ListAlertRules/index.tsx +++ b/frontend/src/container/ListAlertRules/index.tsx @@ -17,28 +17,38 @@ function ListAlertRules(): JSX.Element { cacheTime: 0, }); + const [notifications, NotificationElement] = notification.useNotification(); + useEffect(() => { if (status === 'error' || (status === 'success' && data.statusCode >= 400)) { - notification.error({ + notifications.error({ message: data?.error || t('something_went_wrong'), }); } - }, [data?.error, data?.statusCode, status, t]); + }, [data?.error, data?.statusCode, status, t, notifications]); // api failed to load the data if (isError) { - return
{data?.error || t('something_went_wrong')}
; + return ( +
+ {NotificationElement} + {data?.error || t('something_went_wrong')} +
+ ); } // api is successful but error is present if (status === 'success' && data.statusCode >= 400) { return ( - + <> + {NotificationElement} + + ); } @@ -49,6 +59,7 @@ function ListAlertRules(): JSX.Element { return ( + {NotificationElement} (''); + const [notifications, NotificationElement] = notification.useNotification(); + const onChangeHandler: UploadProps['onChange'] = (info) => { const { fileList } = info; const reader = new FileReader(); @@ -106,7 +108,7 @@ function ImportJSON({ }, 10); } else { setIsCreateDashboardError(true); - notification.error({ + notifications.error({ message: response.error || t('something_went_wrong', { @@ -130,58 +132,61 @@ function ImportJSON({ ); return ( - - {t('import_json')} - {t('import_dashboard_by_pasting')} - - } - footer={ - - - {isCreateDashboardError && getErrorNode(t('error_loading_json'))} - - } - > -
- - false} - action="none" - data={jsonData} - > - - - {isUploadJSONError && <>{getErrorNode(t('error_upload_json'))}} - + <> + {NotificationElement} + + {t('import_json')} + {t('import_dashboard_by_pasting')} + + } + footer={ + + + {isCreateDashboardError && getErrorNode(t('error_loading_json'))} + + } + > +
+ + false} + action="none" + data={jsonData} + > + + + {isUploadJSONError && <>{getErrorNode(t('error_upload_json'))}} + - - {t('paste_json_below')} - setEditorValue(newValue)} - value={editorValue} - language="json" - /> - -
-
+ + {t('paste_json_below')} + setEditorValue(newValue)} + value={editorValue} + language="json" + /> + +
+
+ ); } diff --git a/frontend/src/container/Login/index.tsx b/frontend/src/container/Login/index.tsx index 2b46ffcf45..bb7f7302df 100644 --- a/frontend/src/container/Login/index.tsx +++ b/frontend/src/container/Login/index.tsx @@ -42,6 +42,8 @@ function Login({ const [precheckInProcess, setPrecheckInProcess] = useState(false); const [precheckComplete, setPrecheckComplete] = useState(false); + const [notifications, NotificationElement] = notification.useNotification(); + useEffect(() => { if (withPassword === 'Y') { setPrecheckComplete(true); @@ -62,15 +64,15 @@ function Login({ useEffect(() => { if (ssoerror !== '') { - notification.error({ + notifications.error({ message: t('failed_to_login'), }); } - }, [ssoerror, t]); + }, [ssoerror, t, notifications]); const onNextHandler = async (): Promise => { if (!email) { - notification.error({ + notifications.error({ message: t('invalid_email'), }); return; @@ -88,18 +90,18 @@ function Login({ if (isUser) { setPrecheckComplete(true); } else { - notification.error({ + notifications.error({ message: t('invalid_account'), }); } } else { - notification.error({ + notifications.error({ message: t('invalid_config'), }); } } catch (e) { console.log('failed to call precheck Api', e); - notification.error({ message: t('unexpected_error') }); + notifications.error({ message: t('unexpected_error') }); } setPrecheckInProcess(false); }; @@ -144,14 +146,14 @@ function Login({ ); history.push(ROUTES.APPLICATION); } else { - notification.error({ + notifications.error({ message: response.error || t('unexpected_error'), }); } setIsLoading(false); } catch (error) { setIsLoading(false); - notification.error({ + notifications.error({ message: t('unexpected_error'), }); } @@ -183,6 +185,7 @@ function Login({ return ( + {NotificationElement} {t('login_page_title')} diff --git a/frontend/src/container/LogsSearchFilter/SearchFields/index.tsx b/frontend/src/container/LogsSearchFilter/SearchFields/index.tsx index 5fcd180515..551c47bc41 100644 --- a/frontend/src/container/LogsSearchFilter/SearchFields/index.tsx +++ b/frontend/src/container/LogsSearchFilter/SearchFields/index.tsx @@ -36,6 +36,8 @@ function SearchFields({ const keyPrefixRef = useRef(hashCode(JSON.stringify(fieldsQuery))); + const [notifications, NotificationElement] = notification.useNotification(); + useEffect(() => { const updatedFieldsQuery = createParsedQueryStructure([ ...parsedQuery, @@ -81,7 +83,7 @@ function SearchFields({ const flatParsedQuery = flatten(fieldsQuery); if (!fieldsQueryIsvalid(flatParsedQuery)) { - notification.error({ + notifications.error({ message: 'Please enter a valid criteria for each of the selected fields', }); return; @@ -90,7 +92,7 @@ function SearchFields({ keyPrefixRef.current = hashCode(JSON.stringify(flatParsedQuery)); updateParsedQuery(flatParsedQuery); onDropDownToggleHandler(false)(); - }, [onDropDownToggleHandler, fieldsQuery, updateParsedQuery]); + }, [onDropDownToggleHandler, fieldsQuery, updateParsedQuery, notifications]); const clearFilters = useCallback((): void => { keyPrefixRef.current = hashCode(JSON.stringify([])); @@ -100,6 +102,7 @@ function SearchFields({ return ( <> + {NotificationElement} { if (currentPassword && !isPasswordValid(currentPassword)) { setIsPasswordPolicyError(true); @@ -52,13 +54,13 @@ function PasswordContainer(): JSX.Element { }); if (statusCode === 200) { - notification.success({ + notifications.success({ message: t('success', { ns: 'common', }), }); } else { - notification.error({ + notifications.error({ message: error || t('something_went_wrong', { @@ -70,7 +72,7 @@ function PasswordContainer(): JSX.Element { } catch (error) { setIsLoading(false); - notification.error({ + notifications.error({ message: t('something_went_wrong', { ns: 'common', }), @@ -80,6 +82,7 @@ function PasswordContainer(): JSX.Element { return ( + {NotificationElement} {t('change_password', { ns: 'settings', diff --git a/frontend/src/container/MySettings/UpdateName/index.tsx b/frontend/src/container/MySettings/UpdateName/index.tsx index fccb5a7285..2a9dbcc576 100644 --- a/frontend/src/container/MySettings/UpdateName/index.tsx +++ b/frontend/src/container/MySettings/UpdateName/index.tsx @@ -21,6 +21,8 @@ function UpdateName(): JSX.Element { const [changedName, setChangedName] = useState(user?.name || ''); const [loading, setLoading] = useState(false); + const [notifications, NotificationElement] = notification.useNotification(); + if (!user || !org) { return
; } @@ -34,7 +36,7 @@ function UpdateName(): JSX.Element { }); if (statusCode === 200) { - notification.success({ + notifications.success({ message: t('success', { ns: 'common', }), @@ -51,7 +53,7 @@ function UpdateName(): JSX.Element { }, }); } else { - notification.error({ + notifications.error({ message: t('something_went_wrong', { ns: 'common', }), @@ -59,7 +61,7 @@ function UpdateName(): JSX.Element { } setLoading(false); } catch (error) { - notification.error({ + notifications.error({ message: t('something_went_wrong', { ns: 'common', }), @@ -70,6 +72,7 @@ function UpdateName(): JSX.Element { return (
+ {NotificationElement} Name state.dashboards, ); + const [notifications, NotificationElement] = notification.useNotification(); + const [selectedDashboard] = dashboards; const { data } = selectedDashboard; @@ -31,7 +33,7 @@ function DashboardGraphSlider({ toggleAddWidget }: Props): JSX.Element { const emptyLayout = data.layout?.find((e) => e.i === 'empty'); if (emptyLayout === undefined) { - notification.error({ + notifications.error({ message: 'Please click on Add Panel Button', }); return; @@ -43,18 +45,19 @@ function DashboardGraphSlider({ toggleAddWidget }: Props): JSX.Element { `${history.location.pathname}/new?graphType=${name}&widgetId=${emptyLayout.i}`, ); } catch (error) { - notification.error({ + notifications.error({ message: 'Something went wrong', }); } }, - [data, toggleAddWidget], + [data, toggleAddWidget, notifications], ); const isDarkMode = useIsDarkMode(); const fillColor: React.CSSProperties['color'] = isDarkMode ? 'white' : 'black'; return ( + {NotificationElement} {menuItems.map(({ name, Icon, display }) => ( { diff --git a/frontend/src/container/NewDashboard/DashboardSettings/Variables/index.tsx b/frontend/src/container/NewDashboard/DashboardSettings/Variables/index.tsx index 8dfc3a73e0..3e1904a28a 100644 --- a/frontend/src/container/NewDashboard/DashboardSettings/Variables/index.tsx +++ b/frontend/src/container/NewDashboard/DashboardSettings/Variables/index.tsx @@ -1,6 +1,7 @@ import { blue, red } from '@ant-design/colors'; import { PlusOutlined } from '@ant-design/icons'; -import { Button, Modal, Row, Space, Table, Tag } from 'antd'; +import { Button, Modal, notification, Row, Space, Table, Tag } from 'antd'; +import { NotificationInstance } from 'antd/es/notification/interface'; import React, { useRef, useState } from 'react'; import { connect, useSelector } from 'react-redux'; import { bindActionCreators, Dispatch } from 'redux'; @@ -24,6 +25,8 @@ function VariablesSetting({ (state) => state.dashboards, ); + const [notifications, NotificationElement] = notification.useNotification(); + const [selectedDashboard] = dashboards; const { @@ -74,8 +77,7 @@ function VariablesSetting({ if (oldName) { delete newVariables[oldName]; } - - updateDashboardVariables(newVariables); + updateDashboardVariables(newVariables, notifications); onDoneVariableViewMode(); }; @@ -87,7 +89,7 @@ function VariablesSetting({ const handleDeleteConfirm = (): void => { const newVariables = { ...variables }; if (variableToDelete?.current) delete newVariables[variableToDelete?.current]; - updateDashboardVariables(newVariables); + updateDashboardVariables(newVariables, notifications); variableToDelete.current = null; setDeleteVariableModal(false); }; @@ -137,6 +139,7 @@ function VariablesSetting({ return ( <> + {NotificationElement} {variableViewMode ? ( , + notify: NotificationInstance, ) => (dispatch: Dispatch) => void; } diff --git a/frontend/src/container/NewDashboard/DashboardVariablesSelection/index.tsx b/frontend/src/container/NewDashboard/DashboardVariablesSelection/index.tsx index 18f909d3ac..77d50cd521 100644 --- a/frontend/src/container/NewDashboard/DashboardVariablesSelection/index.tsx +++ b/frontend/src/container/NewDashboard/DashboardVariablesSelection/index.tsx @@ -1,4 +1,5 @@ -import { Row } from 'antd'; +import { notification, Row } from 'antd'; +import { NotificationInstance } from 'antd/es/notification/interface'; import { map, sortBy } from 'lodash-es'; import React, { useState } from 'react'; import { connect, useSelector } from 'react-redux'; @@ -25,6 +26,7 @@ function DashboardVariableSelection({ const [update, setUpdate] = useState(false); const [lastUpdatedVar, setLastUpdatedVar] = useState(''); + const [notifications, NotificationElement] = notification.useNotification(); const onVarChanged = (name: string): void => { setLastUpdatedVar(name); @@ -45,7 +47,7 @@ function DashboardVariableSelection({ ): void => { const updatedVariablesData = { ...variables }; updatedVariablesData[name].selectedValue = value; - updateDashboardVariables(updatedVariablesData); + updateDashboardVariables(updatedVariablesData, notifications); onVarChanged(name); }; const onAllSelectedUpdate = ( @@ -54,12 +56,13 @@ function DashboardVariableSelection({ ): void => { const updatedVariablesData = { ...variables }; updatedVariablesData[name].allSelected = value; - updateDashboardVariables(updatedVariablesData); + updateDashboardVariables(updatedVariablesData, notifications); onVarChanged(name); }; return ( + {NotificationElement} {map(sortBy(Object.keys(variables)), (variableName) => ( [0], + notify: NotificationInstance, ) => (dispatch: Dispatch) => void; } diff --git a/frontend/src/container/NewDashboard/DescriptionOfDashboard/ShareModal.tsx b/frontend/src/container/NewDashboard/DescriptionOfDashboard/ShareModal.tsx index b177f056d2..b9cd5b6167 100644 --- a/frontend/src/container/NewDashboard/DescriptionOfDashboard/ShareModal.tsx +++ b/frontend/src/container/NewDashboard/DescriptionOfDashboard/ShareModal.tsx @@ -32,10 +32,11 @@ function ShareModal({ const [isViewJSON, setIsViewJSON] = useState(false); const { t } = useTranslation(['dashboard', 'common']); const [state, setCopy] = useCopyToClipboard(); + const [notifications, NotificationElement] = notification.useNotification(); useEffect(() => { if (state.error) { - notification.error({ + notifications.error({ message: t('something_went_wrong', { ns: 'common', }), @@ -43,13 +44,13 @@ function ShareModal({ } if (state.value) { - notification.success({ + notifications.success({ message: t('success', { ns: 'common', }), }); } - }, [state.error, state.value, t]); + }, [state.error, state.value, t, notifications]); const selectedDataCleaned = cleardQueryData(selectedData); const GetFooterComponent = useMemo(() => { @@ -83,28 +84,34 @@ function ShareModal({ }, [isViewJSON, jsonValue, selectedData, selectedDataCleaned, setCopy, t]); return ( - { - onToggleHandler(); - setIsViewJSON(false); - }} - width="70vw" - centered - title={t('share', { - ns: 'common', - })} - okText={t('download_json')} - cancelText={t('cancel')} - destroyOnClose - footer={GetFooterComponent} - > - {!isViewJSON ? ( - {t('export_dashboard')} - ) : ( - setJSONValue(value)} value={jsonValue} /> - )} - + <> + {NotificationElement} + { + onToggleHandler(); + setIsViewJSON(false); + }} + width="70vw" + centered + title={t('share', { + ns: 'common', + })} + okText={t('download_json')} + cancelText={t('cancel')} + destroyOnClose + footer={GetFooterComponent} + > + {!isViewJSON ? ( + {t('export_dashboard')} + ) : ( + setJSONValue(value)} + value={jsonValue} + /> + )} + + ); } diff --git a/frontend/src/container/NewWidget/LeftContainer/QuerySection/QueryBuilder/queryBuilder/index.tsx b/frontend/src/container/NewWidget/LeftContainer/QuerySection/QueryBuilder/queryBuilder/index.tsx index f485b4e95c..589ff88147 100644 --- a/frontend/src/container/NewWidget/LeftContainer/QuerySection/QueryBuilder/queryBuilder/index.tsx +++ b/frontend/src/container/NewWidget/LeftContainer/QuerySection/QueryBuilder/queryBuilder/index.tsx @@ -37,6 +37,7 @@ function QueryBuilderQueryContainer({ metricsBuilderQueries, selectedGraph, }: IQueryBuilderQueryContainerProps): JSX.Element | null { + const [notifications, NotificationElement] = notification.useNotification(); const handleQueryBuilderQueryChange = ({ queryIndex, aggregateFunction, @@ -113,7 +114,7 @@ function QueryBuilderQueryContainer({ }; const addQueryHandler = (): void => { if (!canCreateQueryAndFormula(queryData)) { - notification.error({ + notifications.error({ message: 'Unable to create query. You can create at max 10 queries and formulae.', }); @@ -130,7 +131,7 @@ function QueryBuilderQueryContainer({ const addFormulaHandler = (): void => { if (!canCreateQueryAndFormula(queryData)) { - notification.error({ + notifications.error({ message: 'Unable to create formula. You can create at max 10 queries and formulae.', }); @@ -155,6 +156,7 @@ function QueryBuilderQueryContainer({ } return ( <> + {NotificationElement} {metricsBuilderQueries.queryBuilder.map((q, idx) => ( ((state) => state.app); + const [notifications, NotificationElement] = notification.useNotification(); + const onCreateHandler = async (): Promise => { try { const response = await createDomainApi({ @@ -29,19 +31,19 @@ function AddDomain({ refetch }: Props): JSX.Element { }); if (response.statusCode === 200) { - notification.success({ + notifications.success({ message: 'Your domain has been added successfully.', duration: 15, }); setIsDomain(false); refetch(); } else { - notification.error({ + notifications.error({ message: t('common:something_went_wrong'), }); } } catch (error) { - notification.error({ + notifications.error({ message: t('common:something_went_wrong'), }); } @@ -49,6 +51,7 @@ function AddDomain({ refetch }: Props): JSX.Element { return ( <> + {NotificationElement} {t('authenticated_domains', { diff --git a/frontend/src/container/OrganizationSettings/AuthDomains/Edit/index.tsx b/frontend/src/container/OrganizationSettings/AuthDomains/Edit/index.tsx index 8bbe3f2f78..7adefc6b2e 100644 --- a/frontend/src/container/OrganizationSettings/AuthDomains/Edit/index.tsx +++ b/frontend/src/container/OrganizationSettings/AuthDomains/Edit/index.tsx @@ -31,6 +31,8 @@ function EditSSO({ const { t } = useTranslation(['common']); + const [notifications, NotificationElement] = notification.useNotification(); + const onFinishHandler = useCallback(() => { form .validateFields() @@ -44,11 +46,11 @@ function EditSSO({ }); }) .catch(() => { - notification.error({ + notifications.error({ message: t('something_went_wrong', { ns: 'common' }), }); }); - }, [form, onRecordUpdateHandler, record, t]); + }, [form, onRecordUpdateHandler, record, t, notifications]); const onResetHandler = useCallback(() => { form.resetFields(); @@ -61,7 +63,7 @@ function EditSSO({ initialValues={record} onFinishFailed={(error): void => { error.errorFields.forEach(({ errors }) => { - notification.error({ + notifications.error({ message: errors[0].toString() || t('something_went_wrong', { ns: 'common' }), }); @@ -73,6 +75,7 @@ function EditSSO({ autoComplete="off" form={form} > + {NotificationElement} {renderFormInputs(record)} { setCurrentDomain({ ...currentDomain, ssoType: typ } as AuthDomain); @@ -76,7 +78,7 @@ function AuthDomains(): JSX.Element { const response = await updateDomain(record); if (response.statusCode === 200) { - notification.success({ + notifications.success({ message: t('saml_settings', { ns: 'organizationsettings', }), @@ -87,7 +89,7 @@ function AuthDomains(): JSX.Element { return true; } - notification.error({ + notifications.error({ message: t('something_went_wrong', { ns: 'common', }), @@ -95,7 +97,7 @@ function AuthDomains(): JSX.Element { return false; } catch (error) { - notification.error({ + notifications.error({ message: t('something_went_wrong', { ns: 'common', }), @@ -103,7 +105,7 @@ function AuthDomains(): JSX.Element { return false; } }, - [refetch, t, onCloseHandler], + [refetch, t, onCloseHandler, notifications], ); const onOpenHandler = useCallback( @@ -142,19 +144,19 @@ function AuthDomains(): JSX.Element { }); if (response.statusCode === 200) { - notification.success({ + notifications.success({ message: t('common:success'), }); refetch(); } else { - notification.error({ + notifications.error({ message: t('common:something_went_wrong'), }); } }, }); }, - [refetch, t], + [refetch, t, notifications], ); const onClickLicenseHandler = useCallback(() => { @@ -247,6 +249,7 @@ function AuthDomains(): JSX.Element { if (!isLoading && data?.payload?.length === 0) { return ( + {NotificationElement} + {NotificationElement} (false); const dispatch = useDispatch>(); + const [notifications, NotificationElement] = notification.useNotification(); const onSubmit = async ({ name: orgName }: OnSubmitProps): Promise => { try { @@ -31,7 +32,7 @@ function DisplayName({ orgId, }); if (statusCode === 200) { - notification.success({ + notifications.success({ message: t('success', { ns: 'common', }), @@ -44,7 +45,7 @@ function DisplayName({ }, }); } else { - notification.error({ + notifications.error({ message: error || t('something_went_wrong', { @@ -55,7 +56,7 @@ function DisplayName({ setIsLoading(false); } catch (error) { setIsLoading(false); - notification.error({ + notifications.error({ message: t('something_went_wrong', { ns: 'common', }), @@ -75,6 +76,7 @@ function DisplayName({ onFinish={onSubmit} autoComplete="off" > + {NotificationElement} diff --git a/frontend/src/container/OrganizationSettings/EditMembersDetails/index.tsx b/frontend/src/container/OrganizationSettings/EditMembersDetails/index.tsx index 378ec91c47..10f589e7cc 100644 --- a/frontend/src/container/OrganizationSettings/EditMembersDetails/index.tsx +++ b/frontend/src/container/OrganizationSettings/EditMembersDetails/index.tsx @@ -36,19 +36,21 @@ function EditMembersDetails({ [], ); + const [notifications, NotificationElement] = notification.useNotification(); + useEffect(() => { if (state.error) { - notification.error({ + notifications.error({ message: t('something_went_wrong'), }); } if (state.value) { - notification.success({ + notifications.success({ message: t('success'), }); } - }, [state.error, state.value, t]); + }, [state.error, state.value, t, notifications]); const onPasswordChangeHandler: React.ChangeEventHandler = useCallback( (event) => { @@ -67,7 +69,7 @@ function EditMembersDetails({ if (response.statusCode === 200) { setPasswordLink(getPasswordLink(response.payload.token)); } else { - notification.error({ + notifications.error({ message: response.error || t('something_went_wrong', { @@ -79,7 +81,7 @@ function EditMembersDetails({ } catch (error) { setIsLoading(false); - notification.error({ + notifications.error({ message: t('something_went_wrong', { ns: 'common', }), @@ -89,6 +91,7 @@ function EditMembersDetails({ return ( + {NotificationElement} Email address (false); const [isUpdateLoading, setIsUpdateLoading] = useState(false); + const [notifications, NotificationElement] = notification.useNotification(); const onUpdateDetailsHandler = (): void => { setDataSource((data) => { @@ -88,14 +89,14 @@ function UserFunction({ if (response.statusCode === 200) { onDelete(); - notification.success({ + notifications.success({ message: t('success', { ns: 'common', }), }); setIsDeleteModalVisible(false); } else { - notification.error({ + notifications.error({ message: response.error || t('something_went_wrong', { @@ -107,7 +108,7 @@ function UserFunction({ } catch (error) { setIsDeleteLoading(false); - notification.error({ + notifications.error({ message: t('something_went_wrong', { ns: 'common', }), @@ -134,13 +135,13 @@ function UserFunction({ updateRoleResponse.statusCode === 200 ) { onUpdateDetailsHandler(); - notification.success({ + notifications.success({ message: t('success', { ns: 'common', }), }); } else { - notification.error({ + notifications.error({ message: editUserResponse.error || updateRoleResponse.error || @@ -151,7 +152,7 @@ function UserFunction({ } setIsUpdateLoading(false); } catch (error) { - notification.error({ + notifications.error({ message: t('something_went_wrong', { ns: 'common', }), @@ -162,6 +163,7 @@ function UserFunction({ return ( <> + {NotificationElement} onModalToggleHandler(setIsModalVisible, true)} diff --git a/frontend/src/container/OrganizationSettings/PendingInvitesContainer/index.tsx b/frontend/src/container/OrganizationSettings/PendingInvitesContainer/index.tsx index 2316bab5e0..2afa7c9c29 100644 --- a/frontend/src/container/OrganizationSettings/PendingInvitesContainer/index.tsx +++ b/frontend/src/container/OrganizationSettings/PendingInvitesContainer/index.tsx @@ -25,22 +25,23 @@ function PendingInvitesContainer(): JSX.Element { const [isInvitingMembers, setIsInvitingMembers] = useState(false); const { t } = useTranslation(['organizationsettings', 'common']); const [state, setText] = useCopyToClipboard(); + const [notifications, NotificationElement] = notification.useNotification(); useEffect(() => { if (state.error) { - notification.error({ + notifications.error({ message: state.error.message, }); } if (state.value) { - notification.success({ + notifications.success({ message: t('success', { ns: 'common', }), }); } - }, [state.error, state.value, t]); + }, [state.error, state.value, t, notifications]); const getPendingInvitesResponse = useQuery({ queryFn: () => getPendingInvites(), @@ -112,13 +113,13 @@ function PendingInvitesContainer(): JSX.Element { ...dataSource.slice(index + 1, dataSource.length), ]); } - notification.success({ + notifications.success({ message: t('success', { ns: 'common', }), }); } else { - notification.error({ + notifications.error({ message: response.error || t('something_went_wrong', { @@ -127,7 +128,7 @@ function PendingInvitesContainer(): JSX.Element { }); } } catch (error) { - notification.error({ + notifications.error({ message: t('something_went_wrong', { ns: 'common', }), @@ -192,7 +193,7 @@ function PendingInvitesContainer(): JSX.Element { }); if (statusCode !== 200) { - notification.error({ + notifications.error({ message: error || t('something_went_wrong', { @@ -212,7 +213,7 @@ function PendingInvitesContainer(): JSX.Element { toggleModal(false); }, 2000); } catch (error) { - notification.error({ + notifications.error({ message: t('something_went_wrong', { ns: 'common', }), @@ -222,6 +223,7 @@ function PendingInvitesContainer(): JSX.Element { return (
+ {NotificationElement} { if (!token) { @@ -53,14 +54,14 @@ function ResetPassword({ version }: ResetPasswordProps): JSX.Element { }); if (response.statusCode === 200) { - notification.success({ + notifications.success({ message: t('success', { ns: 'common', }), }); history.push(ROUTES.LOGIN); } else { - notification.error({ + notifications.error({ message: response.error || t('something_went_wrong', { @@ -72,7 +73,7 @@ function ResetPassword({ version }: ResetPasswordProps): JSX.Element { setLoading(false); } catch (error) { setLoading(false); - notification.error({ + notifications.error({ message: t('something_went_wrong', { ns: 'common', }), @@ -82,70 +83,73 @@ function ResetPassword({ version }: ResetPasswordProps): JSX.Element { return ( - -
- Reset Your Password + <> + {NotificationElement} + + + Reset Your Password -
- - { - setState(e.target.value, setPassword); - }} - required - id="currentPassword" - /> -
-
- - { - const updateValue = e.target.value; - setState(updateValue, setConfirmPassword); - if (password !== updateValue) { - setConfirmPasswordError(true); - } else { - setConfirmPasswordError(false); - } - }} - required - id="UpdatePassword" - /> - - {confirmPasswordError && ( - + + { + setState(e.target.value, setPassword); }} - > - Passwords don’t match. Please try again - - )} -
+ required + id="currentPassword" + /> +
+
+ + { + const updateValue = e.target.value; + setState(updateValue, setConfirmPassword); + if (password !== updateValue) { + setConfirmPasswordError(true); + } else { + setConfirmPasswordError(false); + } + }} + required + id="UpdatePassword" + /> - - - - - + {confirmPasswordError && ( + + Passwords don’t match. Please try again + + )} +
+ + + + + + + ); } diff --git a/frontend/src/container/Trace/Filters/Panel/PanelBody/Common/Checkbox.tsx b/frontend/src/container/Trace/Filters/Panel/PanelBody/Common/Checkbox.tsx index a30118fe36..3baf556d39 100644 --- a/frontend/src/container/Trace/Filters/Panel/PanelBody/Common/Checkbox.tsx +++ b/frontend/src/container/Trace/Filters/Panel/PanelBody/Common/Checkbox.tsx @@ -38,6 +38,8 @@ function CheckBoxComponent(props: CheckBoxProps): JSX.Element { (userSelectedFilter.get(name) || []).find((e) => e === keyValue) !== undefined; + const [notifications, NotificationElement] = notification.useNotification(); + // eslint-disable-next-line sonarjs/cognitive-complexity const onCheckHandler = async (): Promise => { try { @@ -141,12 +143,12 @@ function CheckBoxComponent(props: CheckBoxProps): JSX.Element { } else { setIsLoading(false); - notification.error({ + notifications.error({ message: response.error || 'Something went wrong', }); } } catch (error) { - notification.error({ + notifications.error({ message: (error as AxiosError).toString() || 'Something went wrong', }); setIsLoading(false); @@ -161,6 +163,7 @@ function CheckBoxComponent(props: CheckBoxProps): JSX.Element { return ( + {NotificationElement} (''); + const [notifications, NotificationElement] = notification.useNotification(); useEffect(() => { setUserEnteredValue(selectedFilter.get('traceID')?.[0] || ''); }, [selectedFilter]); @@ -91,7 +92,7 @@ function TraceID(): JSX.Element { ); } } catch (error) { - notification.error({ + notifications.error({ message: (error as AxiosError).toString() || 'Something went wrong', }); } finally { @@ -108,6 +109,7 @@ function TraceID(): JSX.Element { }; return (
+ {NotificationElement} = async (e) => { try { @@ -119,14 +121,14 @@ function PanelHeading(props: PanelHeadingProps): JSX.Element { spansAggregate.orderParam, ); } else { - notification.error({ + notifications.error({ message: response.error || defaultErrorMessage, }); } setIsLoading(false); } catch (error) { - notification.error({ + notifications.error({ message: (error as AxiosError).toString() || defaultErrorMessage, }); } @@ -225,13 +227,13 @@ function PanelHeading(props: PanelHeadingProps): JSX.Element { spansAggregate.orderParam, ); } else { - notification.error({ + notifications.error({ message: response.error || 'Something went wrong', }); } setIsLoading(false); } catch (error) { - notification.error({ + notifications.error({ message: (error as AxiosError).toString(), }); setIsLoading(false); @@ -295,6 +297,7 @@ function PanelHeading(props: PanelHeadingProps): JSX.Element { return ( <> + {NotificationElement} {PanelName !== 'duration' && } diff --git a/frontend/src/container/TriggeredAlerts/index.tsx b/frontend/src/container/TriggeredAlerts/index.tsx index 787bdfb85b..b877728e19 100644 --- a/frontend/src/container/TriggeredAlerts/index.tsx +++ b/frontend/src/container/TriggeredAlerts/index.tsx @@ -17,6 +17,7 @@ function TriggeredAlerts(): JSX.Element { payload: [], }); const { t } = useTranslation(['common']); + const [notifications, NotificationElement] = notification.useNotification(); const fetchData = useCallback(async () => { try { @@ -61,18 +62,28 @@ function TriggeredAlerts(): JSX.Element { useEffect(() => { if (groupState.error) { - notification.error({ + notifications.error({ message: groupState.errorMessage || t('something_went_wrong'), }); } - }, [groupState.error, groupState.errorMessage, t]); + }, [groupState.error, groupState.errorMessage, t, notifications]); if (groupState.error) { - return ; + return ( + <> + {NotificationElement} + + + ); } if (groupState.loading || groupState.payload === undefined) { - return ; + return ( + <> + {NotificationElement} + + + ); } // commented the reduce() call as we no longer use /alerts/groups @@ -84,7 +95,12 @@ function TriggeredAlerts(): JSX.Element { // return [...acc, ...curr.alerts]; // }, initialAlerts); - return ; + return ( + <> + {NotificationElement} + + + ); } export default TriggeredAlerts; diff --git a/frontend/src/pages/EditRules/index.tsx b/frontend/src/pages/EditRules/index.tsx index 0217e40efc..2c1b512977 100644 --- a/frontend/src/pages/EditRules/index.tsx +++ b/frontend/src/pages/EditRules/index.tsx @@ -26,21 +26,28 @@ function EditRules(): JSX.Element { enabled: isValidRuleId, }); + const [notifications, NotificationElement] = notification.useNotification(); + useEffect(() => { if (!isValidRuleId) { - notification.error({ + notifications.error({ message: 'Rule Id is required', }); history.replace(ROUTES.LIST_ALL_ALERT); } - }, [isValidRuleId, ruleId]); + }, [isValidRuleId, ruleId, notifications]); if ( (isError && !isValidRuleId) || ruleId == null || (data?.payload?.data === undefined && !isLoading) ) { - return
{data?.error || t('something_went_wrong')}
; + return ( +
+ {NotificationElement} + {data?.error || t('something_went_wrong')} +
+ ); } if (isLoading || !data?.payload) { @@ -48,10 +55,13 @@ function EditRules(): JSX.Element { } return ( - + <> + {NotificationElement} + + ); } diff --git a/frontend/src/pages/Metrics/index.tsx b/frontend/src/pages/Metrics/index.tsx index a83aaef5ae..a00cb2b84a 100644 --- a/frontend/src/pages/Metrics/index.tsx +++ b/frontend/src/pages/Metrics/index.tsx @@ -30,14 +30,15 @@ function Metrics({ getService }: MetricsProps): JSX.Element { error, errorMessage, } = useSelector((state) => state.metrics); + const [notifications, NotificationElement] = notification.useNotification(); useEffect(() => { if (error) { - notification.error({ + notifications.error({ message: errorMessage, }); } - }, [error, errorMessage]); + }, [error, errorMessage, notifications]); const selectedTags = useMemo( () => @@ -90,6 +91,7 @@ function Metrics({ getService }: MetricsProps): JSX.Element { return ( + {NotificationElement} diff --git a/frontend/src/pages/SignUp/SignUp.tsx b/frontend/src/pages/SignUp/SignUp.tsx index 2589c32ed6..4d632ea0d4 100644 --- a/frontend/src/pages/SignUp/SignUp.tsx +++ b/frontend/src/pages/SignUp/SignUp.tsx @@ -56,6 +56,8 @@ function SignUp({ version }: SignUpProps): JSX.Element { enabled: token !== null, }); + const [notifications, NotificationElement] = notification.useNotification(); + useEffect(() => { if ( getInviteDetailsResponse.status === 'success' && @@ -73,7 +75,7 @@ function SignUp({ version }: SignUpProps): JSX.Element { getInviteDetailsResponse.data?.error ) { const { error } = getInviteDetailsResponse.data; - notification.error({ + notifications.error({ message: error, }); } @@ -82,6 +84,7 @@ function SignUp({ version }: SignUpProps): JSX.Element { getInviteDetailsResponse.data?.error, getInviteDetailsResponse.status, getInviteDetailsResponse, + notifications, ]); const setState = ( @@ -122,17 +125,17 @@ function SignUp({ version }: SignUpProps): JSX.Element { callback(userResponse); } } else { - notification.error({ + notifications.error({ message: loginResponse.error || t('unexpected_error'), }); } } else { - notification.error({ + notifications.error({ message: response.error || t('unexpected_error'), }); } } catch (error) { - notification.error({ + notifications.error({ message: t('unexpected_error'), }); } @@ -150,7 +153,7 @@ function SignUp({ version }: SignUpProps): JSX.Element { if (editResponse.statusCode === 200) { history.push(ROUTES.APPLICATION); } else { - notification.error({ + notifications.error({ message: editResponse.error || t('unexpected_error'), }); } @@ -159,7 +162,7 @@ function SignUp({ version }: SignUpProps): JSX.Element { e: React.FormEvent, ): Promise => { if (!params.get('token')) { - notification.error({ + notifications.error({ message: t('token_required'), }); return; @@ -182,7 +185,7 @@ function SignUp({ version }: SignUpProps): JSX.Element { if (response.payload?.ssoUrl) { window.location.href = response.payload?.ssoUrl; } else { - notification.error({ + notifications.error({ message: t('failed_to_initiate_login'), }); // take user to login page as there is nothing to do here @@ -190,12 +193,12 @@ function SignUp({ version }: SignUpProps): JSX.Element { } } } else { - notification.error({ + notifications.error({ message: response.error || t('unexpected_error'), }); } } catch (error) { - notification.error({ + notifications.error({ message: t('unexpected_error'), }); } @@ -227,7 +230,7 @@ function SignUp({ version }: SignUpProps): JSX.Element { setLoading(false); } catch (error) { - notification.error({ + notifications.error({ message: t('unexpected_error'), }); setLoading(false); @@ -263,164 +266,169 @@ function SignUp({ version }: SignUpProps): JSX.Element { return ( - -
- Create your account -
- - { - setState(e.target.value, setEmail); - }} - required - id="signupEmail" - disabled={isDetailsDisable} - /> -
- - {isNameVisible && ( + <> + {NotificationElement} + + + Create your account
- + { - setState(e.target.value, setFirstName); + setState(e.target.value, setEmail); }} required - id="signupFirstName" + id="signupEmail" disabled={isDetailsDisable} />
- )} -
- - { - setState(e.target.value, setOrganizationName); - }} - required - id="organizationName" - disabled={isDetailsDisable} - /> -
- {!precheck.sso && ( + {isNameVisible && ( +
+ + { + setState(e.target.value, setFirstName); + }} + required + id="signupFirstName" + disabled={isDetailsDisable} + /> +
+ )} +
- - {t('label_orgname')} + { - setState(e.target.value, setPassword); + setState(e.target.value, setOrganizationName); }} required - id="currentPassword" + id="organizationName" + disabled={isDetailsDisable} />
- )} - {!precheck.sso && ( -
- - { - const updateValue = e.target.value; - setState(updateValue, setConfirmPassword); + {!precheck.sso && ( +
+ + { + setState(e.target.value, setPassword); + }} + required + id="currentPassword" + /> +
+ )} + {!precheck.sso && ( +
+ + { + const updateValue = e.target.value; + setState(updateValue, setConfirmPassword); + }} + required + id="confirmPassword" + /> + + {confirmPasswordError && ( + + {t('failed_confirm_password')} + + )} + {isPasswordPolicyError && ( + + {isPasswordNotValidMessage} + + )} +
+ )} + + {isPreferenceVisible && ( + <> + + + + onSwitchHandler(value, setHasOptedUpdates) + } + checked={hasOptedUpdates} + /> + {t('prompt_keepme_posted')} + + + + + + onSwitchHandler(value, setIsAnonymous)} + checked={isAnonymous} + /> + {t('prompt_anonymise')} + + + + )} + + {isPreferenceVisible && ( + + > + This will create an admin account. If you are not an admin, please ask + your admin for an invite link + + )} - {confirmPasswordError && ( - - {t('failed_confirm_password')} - - )} - {isPasswordPolicyError && ( - - {isPasswordNotValidMessage} - - )} -
- )} - - {isPreferenceVisible && ( - <> - - - onSwitchHandler(value, setHasOptedUpdates)} - checked={hasOptedUpdates} - /> - {t('prompt_keepme_posted')} - - - - - - onSwitchHandler(value, setIsAnonymous)} - checked={isAnonymous} - /> - {t('prompt_anonymise')} - - - - )} - - {isPreferenceVisible && ( - - This will create an admin account. If you are not an admin, please ask - your admin for an invite link - - )} - - - - - -
+ + + + +
+
); } diff --git a/frontend/src/pages/Trace/index.tsx b/frontend/src/pages/Trace/index.tsx index 9a8727baec..437d65da5c 100644 --- a/frontend/src/pages/Trace/index.tsx +++ b/frontend/src/pages/Trace/index.tsx @@ -1,4 +1,5 @@ -import { Card } from 'antd'; +import { Card, notification } from 'antd'; +import { NotificationInstance } from 'antd/es/notification/interface'; import ROUTES from 'constants/routes'; import Filters from 'container/Trace/Filters'; import TraceGraph from 'container/Trace/Graph'; @@ -52,21 +53,26 @@ function Trace({ isFilterExclude, } = useSelector((state) => state.traces); - useEffect(() => { - getInitialFilter(minTime, maxTime); - }, [maxTime, minTime, getInitialFilter, isChanged]); + const [notifications, NotificationElement] = notification.useNotification(); useEffect(() => { - getSpansAggregate({ - maxTime, - minTime, - selectedFilter, - current: spansAggregate.currentPage, - pageSize: spansAggregate.pageSize, - selectedTags, - order: spansAggregate.order, - orderParam: spansAggregate.orderParam, - }); + getInitialFilter(minTime, maxTime, notifications); + }, [maxTime, minTime, getInitialFilter, isChanged, notifications]); + + useEffect(() => { + getSpansAggregate( + { + maxTime, + minTime, + selectedFilter, + current: spansAggregate.currentPage, + pageSize: spansAggregate.pageSize, + selectedTags, + order: spansAggregate.order, + orderParam: spansAggregate.orderParam, + }, + notifications, + ); }, [ selectedTags, selectedFilter, @@ -77,19 +83,23 @@ function Trace({ spansAggregate.pageSize, spansAggregate.order, spansAggregate.orderParam, + notifications, ]); useEffect(() => { - getSpans({ - end: maxTime, - function: selectedFunction, - groupBy: selectedGroupBy, - selectedFilter, - selectedTags, - start: minTime, - step: getStep({ start: minTime, end: maxTime, inputFormat: 'ns' }), - isFilterExclude, - }); + getSpans( + { + end: maxTime, + function: selectedFunction, + groupBy: selectedGroupBy, + selectedFilter, + selectedTags, + start: minTime, + step: getStep({ start: minTime, end: maxTime, inputFormat: 'ns' }), + isFilterExclude, + }, + notifications, + ); }, [ selectedFunction, selectedGroupBy, @@ -99,6 +109,7 @@ function Trace({ minTime, getSpans, isFilterExclude, + notifications, ]); useEffect( @@ -128,6 +139,7 @@ function Trace({ return ( <> + {NotificationElement}
@@ -155,11 +167,15 @@ function Trace({ } interface DispatchProps { - getSpansAggregate: (props: GetSpansAggregateProps) => void; - getSpans: (props: GetSpansProps) => void; + getSpansAggregate: ( + props: GetSpansAggregateProps, + notify: NotificationInstance, + ) => void; + getSpans: (props: GetSpansProps, notify: NotificationInstance) => void; getInitialFilter: ( minTime: GlobalReducer['minTime'], maxTime: GlobalReducer['maxTime'], + notify: NotificationInstance, ) => void; } diff --git a/frontend/src/store/actions/dashboard/updatedDashboardVariables.ts b/frontend/src/store/actions/dashboard/updatedDashboardVariables.ts index 82fecc9ac4..4b1d2091f5 100644 --- a/frontend/src/store/actions/dashboard/updatedDashboardVariables.ts +++ b/frontend/src/store/actions/dashboard/updatedDashboardVariables.ts @@ -1,4 +1,4 @@ -import { notification } from 'antd'; +import { NotificationInstance } from 'antd/es/notification/interface'; import update from 'api/dashboard/update'; import { Dispatch } from 'redux'; import store from 'store/index'; @@ -8,6 +8,7 @@ import { IDashboardVariable } from 'types/api/dashboard/getAll'; export const UpdateDashboardVariables = ( variables: Record, + notify: NotificationInstance, ): ((dispatch: Dispatch) => void) => async ( dispatch: Dispatch, ): Promise => { @@ -28,7 +29,7 @@ export const UpdateDashboardVariables = ( }); if (response.statusCode !== 200) { - notification.error({ + notify.error({ message: response.error, }); } diff --git a/frontend/src/store/actions/trace/getInitialFilter.ts b/frontend/src/store/actions/trace/getInitialFilter.ts index 8cbc554e0a..7737b3887e 100644 --- a/frontend/src/store/actions/trace/getInitialFilter.ts +++ b/frontend/src/store/actions/trace/getInitialFilter.ts @@ -1,4 +1,4 @@ -import { notification } from 'antd'; +import { NotificationInstance } from 'antd/es/notification/interface'; import getFiltersApi from 'api/trace/getFilters'; import xor from 'lodash-es/xor'; import { Dispatch, Store } from 'redux'; @@ -29,6 +29,7 @@ import { export const GetInitialTraceFilter = ( minTime: GlobalReducer['minTime'], maxTime: GlobalReducer['maxTime'], + notify: NotificationInstance, ): (( dispatch: Dispatch, getState: Store['getState'], @@ -166,7 +167,7 @@ export const GetInitialTraceFilter = ( }, }); } else { - notification.error({ + notify.error({ message: response.error || 'Something went wrong', }); } diff --git a/frontend/src/store/actions/trace/getInitialSpansAggregate.ts b/frontend/src/store/actions/trace/getInitialSpansAggregate.ts index 2581065abb..c8a07b99de 100644 --- a/frontend/src/store/actions/trace/getInitialSpansAggregate.ts +++ b/frontend/src/store/actions/trace/getInitialSpansAggregate.ts @@ -1,4 +1,4 @@ -import { notification } from 'antd'; +import { NotificationInstance } from 'antd/es/notification/interface'; import getSpansAggregate from 'api/trace/getSpansAggregate'; import { Dispatch, Store } from 'redux'; import { AppState } from 'store/reducers'; @@ -12,6 +12,7 @@ import { updateURL } from './util'; export const GetSpansAggregate = ( props: GetSpansAggregateProps, + notify: NotificationInstance, ): (( dispatch: Dispatch, getState: Store['getState'], @@ -91,7 +92,7 @@ export const GetSpansAggregate = ( spansAggregate.orderParam, ); } else { - notification.error({ + notify.error({ message: response.error || 'Something went wrong', }); diff --git a/frontend/src/store/actions/trace/getSpans.ts b/frontend/src/store/actions/trace/getSpans.ts index d907cde7c7..a2336bd91d 100644 --- a/frontend/src/store/actions/trace/getSpans.ts +++ b/frontend/src/store/actions/trace/getSpans.ts @@ -1,4 +1,4 @@ -import { notification } from 'antd'; +import { NotificationInstance } from 'antd/es/notification/interface'; import getSpans from 'api/trace/getSpans'; import { Dispatch, Store } from 'redux'; import { AppState } from 'store/reducers'; @@ -12,6 +12,7 @@ import { Props } from 'types/api/trace/getSpans'; export const GetSpans = ( props: GetSpansProps, + notify: NotificationInstance, ): (( dispatch: Dispatch, getState: Store['getState'], @@ -72,7 +73,7 @@ export const GetSpans = ( }, }); } else { - notification.error({ + notify.error({ message: response.error || defaultMessage, }); dispatch({