diff --git a/frontend/public/locales/en/titles.json b/frontend/public/locales/en/titles.json index 126b8a7ac1..aa59005c3f 100644 --- a/frontend/public/locales/en/titles.json +++ b/frontend/public/locales/en/titles.json @@ -4,6 +4,7 @@ "SERVICE_METRICS": "SigNoz | Service Metrics", "SERVICE_MAP": "SigNoz | Service Map", "GET_STARTED": "SigNoz | Get Started", + "GET_STARTED_V2": "SigNoz | Get Started", "GET_STARTED_APPLICATION_MONITORING": "SigNoz | Get Started | APM", "GET_STARTED_LOGS_MANAGEMENT": "SigNoz | Get Started | Logs", "GET_STARTED_INFRASTRUCTURE_MONITORING": "SigNoz | Get Started | Infrastructure", diff --git a/frontend/src/api/onboarding/updateProfile.ts b/frontend/src/api/onboarding/updateProfile.ts index f7f5ffe22c..a9e2d44653 100644 --- a/frontend/src/api/onboarding/updateProfile.ts +++ b/frontend/src/api/onboarding/updateProfile.ts @@ -1,26 +1,20 @@ import { GatewayApiV2Instance } from 'api'; -import { ErrorResponseHandler } from 'api/ErrorResponseHandler'; -import { AxiosError } from 'axios'; import { ErrorResponse, SuccessResponse } from 'types/api'; import { UpdateProfileProps } from 'types/api/onboarding/types'; const updateProfile = async ( props: UpdateProfileProps, ): Promise | ErrorResponse> => { - try { - const response = await GatewayApiV2Instance.put('/profiles/me', { - ...props, - }); + const response = await GatewayApiV2Instance.put('/profiles/me', { + ...props, + }); - return { - statusCode: 200, - error: null, - message: response.data.status, - payload: response.data.data, - }; - } catch (error) { - return ErrorResponseHandler(error as AxiosError); - } + return { + statusCode: 200, + error: null, + message: response.data.status, + payload: response.data.data, + }; }; export default updateProfile; diff --git a/frontend/src/api/user/inviteUsers.ts b/frontend/src/api/user/inviteUsers.ts index 6722b26593..28189159ff 100644 --- a/frontend/src/api/user/inviteUsers.ts +++ b/frontend/src/api/user/inviteUsers.ts @@ -1,25 +1,18 @@ -import { ErrorResponseHandler } from 'api/ErrorResponseHandler'; -import axios, { AxiosError } from 'axios'; +import axios from 'api'; import { ErrorResponse, SuccessResponse } from 'types/api'; import { PayloadProps, UsersProps } from 'types/api/user/inviteUsers'; const inviteUsers = async ( users: UsersProps, ): Promise | ErrorResponse> => { - try { - const response = await axios.post(`/invite/bulk`, { - ...users, - }); + const response = await axios.post(`/invite/bulk`, users); - return { - statusCode: 200, - error: null, - message: response.data.status, - payload: response.data, - }; - } catch (error) { - return ErrorResponseHandler(error as AxiosError); - } + return { + statusCode: 200, + error: null, + message: response.data.status, + payload: response.data, + }; }; export default inviteUsers; diff --git a/frontend/src/container/OnboardingQuestionaire/InviteTeamMembers/InviteTeamMembers.styles.scss b/frontend/src/container/OnboardingQuestionaire/InviteTeamMembers/InviteTeamMembers.styles.scss index aae10276f6..263e1d4e80 100644 --- a/frontend/src/container/OnboardingQuestionaire/InviteTeamMembers/InviteTeamMembers.styles.scss +++ b/frontend/src/container/OnboardingQuestionaire/InviteTeamMembers/InviteTeamMembers.styles.scss @@ -41,6 +41,7 @@ display: flex; align-items: center; gap: 8px; + text-transform: capitalize; } } } diff --git a/frontend/src/container/OnboardingQuestionaire/InviteTeamMembers/InviteTeamMembers.tsx b/frontend/src/container/OnboardingQuestionaire/InviteTeamMembers/InviteTeamMembers.tsx index cd5f0d53c4..e4d2a64bc7 100644 --- a/frontend/src/container/OnboardingQuestionaire/InviteTeamMembers/InviteTeamMembers.tsx +++ b/frontend/src/container/OnboardingQuestionaire/InviteTeamMembers/InviteTeamMembers.tsx @@ -2,6 +2,8 @@ import './InviteTeamMembers.styles.scss'; import { Color } from '@signozhq/design-tokens'; import { Button, Input, Select, Typography } from 'antd'; +import inviteUsers from 'api/user/inviteUsers'; +import { AxiosError } from 'axios'; import { cloneDeep, debounce, isEmpty } from 'lodash-es'; import { ArrowLeft, @@ -11,6 +13,8 @@ import { TriangleAlert, } from 'lucide-react'; import { useCallback, useEffect, useState } from 'react'; +import { useMutation } from 'react-query'; +import { ErrorResponse } from 'types/api'; import { v4 as uuid } from 'uuid'; interface TeamMember { @@ -37,18 +41,17 @@ function InviteTeamMembers({ const [teamMembersToInvite, setTeamMembersToInvite] = useState< TeamMember[] | null >(teamMembers); - const [emailValidity, setEmailValidity] = useState>( {}, ); - const [hasInvalidEmails, setHasInvalidEmails] = useState(false); + const [error, setError] = useState(null); const defaultTeamMember: TeamMember = { email: '', role: 'EDITOR', name: '', - frontendBaseUrl: '', + frontendBaseUrl: window.location.origin, id: '', }; @@ -65,7 +68,10 @@ function InviteTeamMembers({ }, [teamMembers]); const handleAddTeamMember = (): void => { - const newTeamMember = { ...defaultTeamMember, id: uuid() }; + const newTeamMember = { + ...defaultTeamMember, + id: uuid(), + }; setTeamMembersToInvite((prev) => [...(prev || []), newTeamMember]); }; @@ -89,10 +95,34 @@ function InviteTeamMembers({ return isValid; }; + const handleError = (error: AxiosError): void => { + const errorMessage = error.response?.data as ErrorResponse; + + setError(errorMessage.error); + }; + + const { mutate: sendInvites, isLoading: isSendingInvites } = useMutation( + inviteUsers, + { + onSuccess: (): void => { + onNext(); + }, + onError: (error): void => { + handleError(error as AxiosError); + }, + }, + ); + const handleNext = (): void => { if (validateAllUsers()) { setTeamMembers(teamMembersToInvite || []); - onNext(); + + setError(null); + setHasInvalidEmails(false); + + sendInvites({ + users: teamMembersToInvite || [], + }); } }; @@ -129,6 +159,10 @@ function InviteTeamMembers({ } }; + const handleDoLater = (): void => { + onNext(); + }; + return (
@@ -209,20 +243,33 @@ function InviteTeamMembers({
)} + {error && ( +
+ + {error} + +
+ )} +
-
-
diff --git a/frontend/src/container/OnboardingQuestionaire/OptimiseSignozNeeds/OptimiseSignozNeeds.tsx b/frontend/src/container/OnboardingQuestionaire/OptimiseSignozNeeds/OptimiseSignozNeeds.tsx index f5d4d410c1..d564158059 100644 --- a/frontend/src/container/OnboardingQuestionaire/OptimiseSignozNeeds/OptimiseSignozNeeds.tsx +++ b/frontend/src/container/OnboardingQuestionaire/OptimiseSignozNeeds/OptimiseSignozNeeds.tsx @@ -14,6 +14,7 @@ interface OptimiseSignozNeedsProps { setOptimiseSignozDetails: (details: OptimiseSignozDetails) => void; onNext: () => void; onBack: () => void; + onWillDoLater: () => void; isUpdatingProfile: boolean; } @@ -48,6 +49,7 @@ function OptimiseSignozNeeds({ setOptimiseSignozDetails, onNext, onBack, + onWillDoLater, }: OptimiseSignozNeedsProps): JSX.Element { const [logsPerDay, setLogsPerDay] = useState( optimiseSignozDetails?.logsPerDay || 25, @@ -95,6 +97,8 @@ function OptimiseSignozNeeds({ services: 0, }); + onWillDoLater(); + logEvent('Onboarding: Optimise SigNoz Needs: Will do later', { logsPerDay: 0, hostsPerDay: 0, diff --git a/frontend/src/container/OnboardingQuestionaire/index.tsx b/frontend/src/container/OnboardingQuestionaire/index.tsx index 39e34e1f82..974070b944 100644 --- a/frontend/src/container/OnboardingQuestionaire/index.tsx +++ b/frontend/src/container/OnboardingQuestionaire/index.tsx @@ -5,6 +5,7 @@ import updateProfileAPI from 'api/onboarding/updateProfile'; import editOrg from 'api/user/editOrg'; import { AxiosError } from 'axios'; import { SOMETHING_WENT_WRONG } from 'constants/api'; +import ROUTES from 'constants/routes'; import { InviteTeamMembersProps } from 'container/OrganizationSettings/PendingInvitesContainer'; import { useNotifications } from 'hooks/useNotifications'; import history from 'lib/history'; @@ -187,7 +188,7 @@ function OnboardingQuestionaire(): JSX.Element { }; const handleOnboardingComplete = (): void => { - history.push('/'); + history.push(ROUTES.APPLICATION); }; return ( @@ -222,6 +223,7 @@ function OnboardingQuestionaire(): JSX.Element { setOptimiseSignozDetails={setOptimiseSignozDetails} onBack={(): void => setCurrentStep(2)} onNext={handleUpdateProfile} + onWillDoLater={(): void => setCurrentStep(4)} // This is temporary, only to skip gateway api call as it's not setup on staging yet /> )} diff --git a/frontend/src/types/api/user/inviteUsers.ts b/frontend/src/types/api/user/inviteUsers.ts index cf12269e73..8491e31cc4 100644 --- a/frontend/src/types/api/user/inviteUsers.ts +++ b/frontend/src/types/api/user/inviteUsers.ts @@ -1,10 +1,9 @@ import { User } from 'types/reducer/app'; -import { ROLES } from 'types/roles'; export interface UserProps { name: User['name']; email: User['email']; - role: ROLES; + role: string; frontendBaseUrl: string; } diff --git a/frontend/src/utils/error.ts b/frontend/src/utils/error.ts new file mode 100644 index 0000000000..7a0318a3ab --- /dev/null +++ b/frontend/src/utils/error.ts @@ -0,0 +1,12 @@ +import { NotificationInstance } from 'antd/es/notification/interface'; +import axios from 'axios'; +import { SOMETHING_WENT_WRONG } from 'constants/api'; + +export const showErrorNotification = ( + notifications: NotificationInstance, + err: Error, +): void => { + notifications.error({ + message: axios.isAxiosError(err) ? err.message : SOMETHING_WENT_WRONG, + }); +};