2024-09-18 13:10:56 +05:30
/* eslint-disable sonarjs/cognitive-complexity */
import '../OnboardingQuestionaire.styles.scss' ;
2024-09-20 01:51:46 +05:30
import { Color } from '@signozhq/design-tokens' ;
import { Button , Input , Typography } from 'antd' ;
import logEvent from 'api/common/logEvent' ;
2025-05-12 18:14:58 +05:30
import editOrg from 'api/organization/editOrg' ;
2024-10-29 19:57:00 +05:30
import { useNotifications } from 'hooks/useNotifications' ;
2024-10-23 19:07:37 +05:30
import { ArrowRight , CheckCircle , Loader2 } from 'lucide-react' ;
2024-12-20 14:00:02 +05:30
import { useAppContext } from 'providers/App/App' ;
import { useEffect , useState } from 'react' ;
2024-10-29 19:57:00 +05:30
import { useTranslation } from 'react-i18next' ;
2024-09-18 13:10:56 +05:30
2024-10-23 19:07:37 +05:30
export interface OrgData {
id : string ;
2025-04-25 19:38:15 +05:30
displayName : string ;
2024-10-23 19:07:37 +05:30
}
export interface OrgDetails {
organisationName : string ;
usesObservability : boolean | null ;
observabilityTool : string | null ;
otherTool : string | null ;
2025-06-23 18:57:05 +05:30
usesOtel : boolean | null ;
2024-10-23 19:07:37 +05:30
}
2024-09-18 13:10:56 +05:30
interface OrgQuestionsProps {
2024-10-29 19:57:00 +05:30
currentOrgData : OrgData | null ;
2024-10-23 19:07:37 +05:30
orgDetails : OrgDetails ;
2024-10-29 19:57:00 +05:30
onNext : ( details : OrgDetails ) = > void ;
2024-09-18 13:10:56 +05:30
}
2024-10-23 19:07:37 +05:30
const observabilityTools = {
AWSCloudwatch : 'AWS Cloudwatch' ,
DataDog : 'DataDog' ,
NewRelic : 'New Relic' ,
GrafanaPrometheus : 'Grafana / Prometheus' ,
AzureAppMonitor : 'Azure App Monitor' ,
GCPNativeO11yTools : 'GCP-native o11y tools' ,
Honeycomb : 'Honeycomb' ,
} ;
2024-09-20 01:51:46 +05:30
function OrgQuestions ( {
2024-10-29 19:57:00 +05:30
currentOrgData ,
2024-09-20 01:51:46 +05:30
orgDetails ,
onNext ,
} : OrgQuestionsProps ) : JSX . Element {
2024-12-20 14:00:02 +05:30
const { user , updateOrg } = useAppContext ( ) ;
2024-10-29 19:57:00 +05:30
const { notifications } = useNotifications ( ) ;
const { t } = useTranslation ( [ 'organizationsettings' , 'common' ] ) ;
2024-10-23 19:07:37 +05:30
2024-09-20 01:51:46 +05:30
const [ organisationName , setOrganisationName ] = useState < string > (
orgDetails ? . organisationName || '' ,
) ;
2024-09-18 13:10:56 +05:30
const [ usesObservability , setUsesObservability ] = useState < boolean | null > (
2024-09-20 01:51:46 +05:30
orgDetails ? . usesObservability || null ,
2024-09-18 13:10:56 +05:30
) ;
const [ observabilityTool , setObservabilityTool ] = useState < string | null > (
2024-09-20 01:51:46 +05:30
orgDetails ? . observabilityTool || null ,
) ;
const [ otherTool , setOtherTool ] = useState < string > (
orgDetails ? . otherTool || '' ,
) ;
2024-09-18 13:10:56 +05:30
const [ isNextDisabled , setIsNextDisabled ] = useState < boolean > ( true ) ;
2024-10-23 19:07:37 +05:30
useEffect ( ( ) = > {
setOrganisationName ( orgDetails . organisationName ) ;
} , [ orgDetails . organisationName ] ) ;
2024-10-29 19:57:00 +05:30
const [ isLoading , setIsLoading ] = useState < boolean > ( false ) ;
2025-06-23 18:57:05 +05:30
const [ usesOtel , setUsesOtel ] = useState < boolean | null > (
orgDetails ? . usesOtel || null ,
) ;
2024-10-29 19:57:00 +05:30
const handleOrgNameUpdate = async ( ) : Promise < void > = > {
/* Early bailout if orgData is not set or if the organisation name is not set or if the organisation name is empty or if the organisation name is the same as the one in the orgData */
if (
! currentOrgData ||
! organisationName ||
organisationName === '' ||
orgDetails . organisationName === organisationName
) {
2024-11-08 12:22:39 +05:30
logEvent ( 'Org Onboarding: Answered' , {
usesObservability ,
observabilityTool ,
otherTool ,
2025-06-23 18:57:05 +05:30
usesOtel ,
2024-11-08 12:22:39 +05:30
} ) ;
2024-10-29 19:57:00 +05:30
onNext ( {
organisationName ,
usesObservability ,
observabilityTool ,
otherTool ,
2025-06-23 18:57:05 +05:30
usesOtel ,
2024-10-29 19:57:00 +05:30
} ) ;
return ;
}
try {
setIsLoading ( true ) ;
const { statusCode , error } = await editOrg ( {
2025-04-25 19:38:15 +05:30
displayName : organisationName ,
2024-10-29 19:57:00 +05:30
orgId : currentOrgData.id ,
} ) ;
2025-04-25 19:38:15 +05:30
if ( statusCode === 204 ) {
updateOrg ( currentOrgData ? . id , organisationName ) ;
2024-10-29 19:57:00 +05:30
2024-11-08 12:22:39 +05:30
logEvent ( 'Org Onboarding: Org Name Updated' , {
2025-04-25 19:38:15 +05:30
organisationName ,
2024-10-29 19:57:00 +05:30
} ) ;
2024-11-08 12:22:39 +05:30
logEvent ( 'Org Onboarding: Answered' , {
usesObservability ,
observabilityTool ,
otherTool ,
2025-06-23 18:57:05 +05:30
usesOtel ,
2024-11-08 12:22:39 +05:30
} ) ;
2024-10-29 19:57:00 +05:30
onNext ( {
organisationName ,
usesObservability ,
observabilityTool ,
otherTool ,
2025-06-23 18:57:05 +05:30
usesOtel ,
2024-10-29 19:57:00 +05:30
} ) ;
} else {
2024-11-08 12:22:39 +05:30
logEvent ( 'Org Onboarding: Org Name Update Failed' , {
2024-10-29 19:57:00 +05:30
organisationName : orgDetails.organisationName ,
} ) ;
notifications . error ( {
message :
error ||
t ( 'something_went_wrong' , {
ns : 'common' ,
} ) ,
} ) ;
}
setIsLoading ( false ) ;
} catch ( error ) {
setIsLoading ( false ) ;
notifications . error ( {
message : t ( 'something_went_wrong' , {
ns : 'common' ,
} ) ,
} ) ;
}
} ;
2024-10-23 19:07:37 +05:30
const isValidUsesObservability = ( ) : boolean = > {
if ( usesObservability === null ) {
return false ;
}
if ( usesObservability && ( ! observabilityTool || observabilityTool === '' ) ) {
return false ;
}
// eslint-disable-next-line sonarjs/prefer-single-boolean-return
if ( usesObservability && observabilityTool === 'Others' && otherTool === '' ) {
return false ;
}
return true ;
} ;
2024-09-18 13:10:56 +05:30
useEffect ( ( ) = > {
2024-10-23 19:07:37 +05:30
const isValidObservability = isValidUsesObservability ( ) ;
2025-06-23 18:57:05 +05:30
if ( organisationName !== '' && usesOtel !== null && isValidObservability ) {
2024-09-18 13:10:56 +05:30
setIsNextDisabled ( false ) ;
} else {
setIsNextDisabled ( true ) ;
}
2024-10-23 19:07:37 +05:30
// eslint-disable-next-line react-hooks/exhaustive-deps
2024-09-18 13:10:56 +05:30
} , [
organisationName ,
usesObservability ,
2025-06-23 18:57:05 +05:30
usesOtel ,
2024-09-18 13:10:56 +05:30
observabilityTool ,
otherTool ,
] ) ;
2024-09-20 01:51:46 +05:30
const handleOnNext = ( ) : void = > {
2024-10-29 19:57:00 +05:30
handleOrgNameUpdate ( ) ;
2024-09-20 01:51:46 +05:30
} ;
2024-09-18 13:10:56 +05:30
return (
< div className = "questions-container" >
< Typography.Title level = { 3 } className = "title" >
2025-09-15 18:54:37 +05:30
{ user ? . displayName ? ` Welcome, ${ user . displayName } ! ` : 'Welcome!' }
2024-09-18 13:10:56 +05:30
< / Typography.Title >
< Typography.Paragraph className = "sub-title" >
We & apos ; ll help you get the most out of SigNoz , whether you & apos ; re new to
observability or a seasoned pro .
< / Typography.Paragraph >
< div className = "questions-form-container" >
< div className = "questions-form" >
< div className = "form-group" >
< label className = "question" htmlFor = "organisationName" >
Your Organisation Name
< / label >
< input
type = "text"
name = "organisationName"
2024-10-23 19:07:37 +05:30
id = "organisationName"
2024-09-18 13:10:56 +05:30
placeholder = "For eg. Simpsonville..."
autoComplete = "off"
value = { organisationName }
onChange = { ( e ) : void = > setOrganisationName ( e . target . value ) }
/ >
< / div >
< div className = "form-group" >
< label className = "question" htmlFor = "usesObservability" >
Do you currently use any observability / monitoring tool ?
< / label >
2024-09-20 01:51:46 +05:30
< div className = "two-column-grid" >
< Button
type = "primary"
2024-09-18 13:10:56 +05:30
name = "usesObservability"
2024-09-20 01:51:46 +05:30
className = { ` onboarding-questionaire-button ${
usesObservability === true ? 'active' : ''
} ` }
2024-09-18 13:10:56 +05:30
onClick = { ( ) : void = > {
setUsesObservability ( true ) ;
} }
>
2024-09-20 01:51:46 +05:30
Yes { ' ' }
{ usesObservability === true && (
< CheckCircle size = { 12 } color = { Color . BG_FOREST_500 } / >
) }
< / Button >
< Button
type = "primary"
className = { ` onboarding-questionaire-button ${
2024-09-18 13:10:56 +05:30
usesObservability === false ? 'active' : ''
} ` }
onClick = { ( ) : void = > {
setUsesObservability ( false ) ;
setObservabilityTool ( null ) ;
setOtherTool ( '' ) ;
} }
>
2024-09-20 01:51:46 +05:30
No { ' ' }
{ usesObservability === false && (
< CheckCircle size = { 12 } color = { Color . BG_FOREST_500 } / >
) }
< / Button >
2024-09-18 13:10:56 +05:30
< / div >
< / div >
{ usesObservability && (
< div className = "form-group" >
< label className = "question" htmlFor = "observabilityTool" >
Which observability tool do you currently use ?
< / label >
2024-09-20 01:51:46 +05:30
< div className = "two-column-grid" >
2024-10-23 19:07:37 +05:30
{ Object . keys ( observabilityTools ) . map ( ( tool ) = > (
2024-09-20 01:51:46 +05:30
< Button
key = { tool }
type = "primary"
className = { ` onboarding-questionaire-button ${
observabilityTool === tool ? 'active' : ''
} ` }
onClick = { ( ) : void = > setObservabilityTool ( tool ) }
>
2024-10-23 19:07:37 +05:30
{ observabilityTools [ tool as keyof typeof observabilityTools ] }
2024-09-20 01:51:46 +05:30
{ observabilityTool === tool && (
< CheckCircle size = { 12 } color = { Color . BG_FOREST_500 } / >
) }
< / Button >
) ) }
2024-09-18 13:10:56 +05:30
{ observabilityTool === 'Others' ? (
2024-09-20 01:51:46 +05:30
< Input
2024-09-18 13:10:56 +05:30
type = "text"
2024-09-20 01:51:46 +05:30
className = "onboarding-questionaire-other-input"
2024-09-18 13:10:56 +05:30
placeholder = "Please specify the tool"
2024-10-23 19:07:37 +05:30
value = { otherTool || '' }
2024-09-20 01:51:46 +05:30
autoFocus
addonAfter = {
2024-10-23 19:07:37 +05:30
otherTool && otherTool !== '' ? (
2024-09-20 01:51:46 +05:30
< CheckCircle size = { 12 } color = { Color . BG_FOREST_500 } / >
) : (
''
)
}
2024-09-18 13:10:56 +05:30
onChange = { ( e ) : void = > setOtherTool ( e . target . value ) }
/ >
) : (
2025-09-15 18:54:37 +05:30
< Button
type = "primary"
2024-09-20 01:51:46 +05:30
className = { ` onboarding-questionaire-button ${
2024-09-18 13:10:56 +05:30
observabilityTool === 'Others' ? 'active' : ''
} ` }
onClick = { ( ) : void = > setObservabilityTool ( 'Others' ) }
>
Others
2025-09-15 18:54:37 +05:30
< / Button >
2024-09-18 13:10:56 +05:30
) }
< / div >
< / div >
) }
< div className = "form-group" >
2025-06-23 18:57:05 +05:30
< div className = "question" > Do you already use OpenTelemetry ? < / div >
2024-09-20 01:51:46 +05:30
< div className = "two-column-grid" >
2025-06-23 18:57:05 +05:30
< Button
type = "primary"
name = "usesObservability"
className = { ` onboarding-questionaire-button ${
usesOtel === true ? 'active' : ''
} ` }
onClick = { ( ) : void = > {
setUsesOtel ( true ) ;
} }
>
Yes { ' ' }
{ usesOtel === true && (
< CheckCircle size = { 12 } color = { Color . BG_FOREST_500 } / >
) }
< / Button >
< Button
type = "primary"
className = { ` onboarding-questionaire-button ${
usesOtel === false ? 'active' : ''
} ` }
onClick = { ( ) : void = > {
setUsesOtel ( false ) ;
} }
>
No { ' ' }
{ usesOtel === false && (
< CheckCircle size = { 12 } color = { Color . BG_FOREST_500 } / >
) }
< / Button >
2024-09-18 13:10:56 +05:30
< / div >
< / div >
< / div >
< div className = "next-prev-container" >
< Button
type = "primary"
className = { ` next-button ${ isNextDisabled ? 'disabled' : '' } ` }
2024-09-20 01:51:46 +05:30
onClick = { handleOnNext }
2024-09-18 13:10:56 +05:30
disabled = { isNextDisabled }
>
Next
2024-10-23 19:07:37 +05:30
{ isLoading ? (
< Loader2 className = "animate-spin" / >
) : (
< ArrowRight size = { 14 } / >
) }
2024-09-18 13:10:56 +05:30
< / Button >
< / div >
< / div >
< / div >
) ;
}
export default OrgQuestions ;