chore: add i18n for onboarding flow and cleanup (#5285)
This commit is contained in:
parent
0b7d31a20c
commit
74efe58c7b
8 changed files with 179 additions and 68 deletions
|
|
@ -9,6 +9,7 @@
|
|||
"save": "Save"
|
||||
},
|
||||
"app": {
|
||||
"back": "Back",
|
||||
"collapse_sidebar": "Collapse Sidebar",
|
||||
"continue_to_dashboard": "Continue to Dashboard",
|
||||
"expand_sidebar": "Expand Sidebar",
|
||||
|
|
@ -173,6 +174,53 @@
|
|||
"toggle_description": "Get updates about the latest at Hoppscotch",
|
||||
"unsubscribe": "Unsubscribe"
|
||||
},
|
||||
"onboarding": {
|
||||
"add_atleast_one_auth_provider": "Please add at least one authentication provider to continue.",
|
||||
"add_configurations": "Please add the configurations for the selected authentication methods.",
|
||||
"add_oauth_config": "Add Auth Configurations",
|
||||
"auth_setup": "Authentication Setup",
|
||||
"auth_successfully_configured": "authentication has been successfully configured.",
|
||||
"complete": "Complete",
|
||||
"complete_description": "You have completed the onboarding process. You can now start using Hoppscotch.",
|
||||
"complete_title": "Onboarding Complete",
|
||||
"configurations": "Configurations",
|
||||
"configurations_added_successfully": "Onboarding Configurations added successfully.",
|
||||
"configurations_adding_failed": "Failed to add onboarding configs, please try again.",
|
||||
"configurations_description": "Configure your Hoppscotch instance settings.",
|
||||
"configuration_error": "Failed to add configurations",
|
||||
"configurations_title": "Server Configurations",
|
||||
"configuration_summary": "Configuration Summary",
|
||||
"oauth": {
|
||||
"description": "Set up OAuth providers like Google, GitHub, Microsoft, etc.",
|
||||
"description_accordian": "Select the OAuth providers you want to enable and provide the necessary configurations.",
|
||||
"title": "OAuth"
|
||||
},
|
||||
"onboarding_incomplete": {
|
||||
"description": "You have not completed the onboarding process. Please set up at least one authentication provider to continue.",
|
||||
"title": "Onboarding Incomplete"
|
||||
},
|
||||
"onboarding_fail_help": "If you are facing issues with the onboarding process, please contact support or check",
|
||||
"please_fill_configurations": "Please fill the required field {fieldName}",
|
||||
"save_auth_config": "Save Auth Config",
|
||||
"setup_complete": {
|
||||
"title": "Setup Complete",
|
||||
"description": "You have successfully completed the onboarding process for your Hoppscotch instance.",
|
||||
"description_sub": "The page will automatically redirect to the dashboard in a few seconds or you can reload once the server is restarted."
|
||||
},
|
||||
"server_restarting": "Server is restarting in {time} seconds...",
|
||||
"smtp": {
|
||||
"description": "Set up SMTP for email authentication.",
|
||||
"description_accordian": "Configure the SMTP settings for sending emails.",
|
||||
"title": "SMTP"
|
||||
},
|
||||
"smtp_advanced_config_enable": "Enable to configure your own SMTP credentials",
|
||||
"select_auth_provider": "Please select the authentication methods you want to set up.",
|
||||
"select_atleast_one": "Please select at least one authentication provider to continue.",
|
||||
"start_onboarding": "Start Onboarding",
|
||||
"welcome": "Welcome",
|
||||
"welcome_screen_description": "Welcome to Hoppscotch! Let's get started with the setup.",
|
||||
"welcome_screen_sub_description": "Please set up either SMTP or OAuth for authentication."
|
||||
},
|
||||
"settings": {
|
||||
"settings": "Settings"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
>
|
||||
<div>
|
||||
<h1 class="text-[1rem] font-normal">
|
||||
Please select the authentication methods you want to set up.
|
||||
{{ t('onboarding.select_auth_provider') }}
|
||||
</h1>
|
||||
</div>
|
||||
<div>
|
||||
|
|
@ -20,9 +20,11 @@
|
|||
}"
|
||||
@click="toggleSelectedOption('OAuth')"
|
||||
>
|
||||
<span class="text-[0.9rem] text-secondaryDark"> OAuth </span>
|
||||
<span class="text-[0.9rem] text-secondaryDark">
|
||||
{{ t('onboarding.oauth.title') }}
|
||||
</span>
|
||||
<span class="text-secondaryLight h-10">
|
||||
Set up OAuth providers like Google, GitHub, Microsoft, etc.
|
||||
{{ t('onboarding.oauth.description') }}
|
||||
</span>
|
||||
<div class="my-4">
|
||||
<div class="flex items-center -space-x-2">
|
||||
|
|
@ -52,9 +54,11 @@
|
|||
}"
|
||||
@click="toggleSelectedOption('SMTP')"
|
||||
>
|
||||
<span class="text-[0.9rem] text-secondaryDark"> SMTP </span>
|
||||
<span class="text-[0.9rem] text-secondaryDark">
|
||||
{{ t('onboarding.smtp.title') }}
|
||||
</span>
|
||||
<span class="text-secondaryLight h-10">
|
||||
Set up SMTP for email authentication.
|
||||
{{ t('onboarding.smtp.description') }}
|
||||
</span>
|
||||
<div class="my-4">
|
||||
<div class="flex items-center -space-x-2">
|
||||
|
|
@ -68,7 +72,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<HoppButtonPrimary
|
||||
:label="'Add Auth Configs'"
|
||||
:label="t('onboarding.add_oauth_config')"
|
||||
@click="addAuthConfig"
|
||||
:icon="IconLucideArrowRight"
|
||||
:reverse="true"
|
||||
|
|
@ -87,10 +91,12 @@
|
|||
<span class="group-hover:opacity-80 transition-opacity">
|
||||
<IconLucideArrowLeft class="svg-icons" />
|
||||
</span>
|
||||
<span class="group-hover:opacity-80 transition-opacity">Back</span>
|
||||
<span class="group-hover:opacity-80 transition-opacity">
|
||||
{{ t('app.back') }}
|
||||
</span>
|
||||
</button>
|
||||
<h2>
|
||||
Please add the configurations for the selected authentication methods.
|
||||
{{ t('onboarding.add_configurations') }}
|
||||
</h2>
|
||||
|
||||
<div class="my-5 overflow-y-auto max-h-[60vh]">
|
||||
|
|
@ -107,7 +113,9 @@
|
|||
<template v-slot:header="{ isOpen, toggleAccordion }">
|
||||
<div class="w-full">
|
||||
<div class="flex items-center justify-between flex-1 mb-2">
|
||||
<span class="font-semibold text-[0.8rem]">OAuth </span>
|
||||
<span class="font-semibold text-[0.8rem]"
|
||||
>{{ t('onboarding.oauth.title') }}
|
||||
</span>
|
||||
|
||||
<span>
|
||||
<HoppSmartToggle
|
||||
|
|
@ -123,9 +131,7 @@
|
|||
</span>
|
||||
</div>
|
||||
<span class="text-tiny text-secondaryLight">
|
||||
Select the OAuth providers you want to enable and provide
|
||||
<br />
|
||||
the necessary configurations.
|
||||
{{ t('onboarding.oauth.description_accordian') }}
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -146,7 +152,9 @@
|
|||
<template v-slot:header="{ isOpen, toggleAccordion }">
|
||||
<div class="w-full">
|
||||
<div class="flex items-center justify-between flex-1 mb-2">
|
||||
<span class="font-semibold text-[0.8rem]">SMTP</span>
|
||||
<span class="font-semibold text-[0.8rem]">
|
||||
{{ t('onboarding.smtp.title') }}
|
||||
</span>
|
||||
<span>
|
||||
<HoppSmartToggle
|
||||
:on="isOpen"
|
||||
|
|
@ -162,7 +170,7 @@
|
|||
</span>
|
||||
</div>
|
||||
<p class="text-secondaryLight text-tiny">
|
||||
Configure the SMTP settings for sending emails.
|
||||
{{ t('onboarding.smtp.description_accordian') }}
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -176,10 +184,11 @@
|
|||
</div>
|
||||
</div>
|
||||
<HoppButtonPrimary
|
||||
:label="'Save Auth Configs'"
|
||||
:label="t('onboarding.save_auth_config')"
|
||||
@click="addOnboardingConfigs"
|
||||
:reverse="true"
|
||||
:icon="IconLucideSave"
|
||||
:loading="submittingConfigs"
|
||||
class="mt-4"
|
||||
/>
|
||||
</div>
|
||||
|
|
@ -200,7 +209,9 @@ import IconLucideArrowRight from '~icons/lucide/arrow-right';
|
|||
import IconLucideArrowLeft from '~icons/lucide/arrow-left';
|
||||
import IconLucideSave from '~icons/lucide/save';
|
||||
import { useToast } from '~/composables/toast';
|
||||
import { useI18n } from '~/composables/i18n';
|
||||
|
||||
const t = useI18n();
|
||||
const toast = useToast();
|
||||
|
||||
const props = withDefaults(
|
||||
|
|
@ -296,7 +307,7 @@ const toggleSelectedOption = (option: 'OAuth' | 'SMTP') => {
|
|||
|
||||
const addAuthConfig = () => {
|
||||
if (selectedOptions.value.length === 0) {
|
||||
toast.error('Please select at least one authentication method.');
|
||||
toast.error(t('onboarding.select_atleast_one'));
|
||||
return;
|
||||
}
|
||||
authConfigStep.value = 2;
|
||||
|
|
|
|||
|
|
@ -6,62 +6,82 @@
|
|||
onBoardingSummary.configsAdded.length > 0
|
||||
"
|
||||
>
|
||||
<h1 class="text-2xl font-bold text-white">Setup Complete 🎉</h1>
|
||||
<h1 class="text-2xl font-bold text-white flex items-center space-x-2">
|
||||
<span></span>
|
||||
{{ t('onboarding.setup_complete.title') }}
|
||||
<span class="">
|
||||
<icon-lucide-badge-check class="svg-icons text-green-500 !h-8 !w-8" />
|
||||
</span>
|
||||
</h1>
|
||||
<h2>
|
||||
You have successfully completed the onboarding process for your
|
||||
Hoppscotch instance.
|
||||
{{ t('onboarding.setup_complete.description') }}
|
||||
<br />
|
||||
The page will automatically redirect to the dashboard in a few seconds
|
||||
or you can reload once the server is restarted.
|
||||
<span class="text-secondaryLight text-tiny">
|
||||
{{ t('onboarding.setup_complete.description_sub') }}
|
||||
</span>
|
||||
</h2>
|
||||
<div
|
||||
class="my-4 p-4 bg-primaryLight rounded-lg border border-primaryDark shadow"
|
||||
>
|
||||
<h3 class="text-lg mb-6">Configuration Summary</h3>
|
||||
<h3 class="text-lg mb-6">
|
||||
{{ t('onboarding.configuration_summary') }}
|
||||
</h3>
|
||||
<div v-for="config in onBoardingSummary.configsAdded" class="my-2">
|
||||
<div class="flex items-center space-x-2">
|
||||
<icon-lucide-check class="svg-icons text-green-500" />
|
||||
<p class="text-secondary">
|
||||
<span class="capitalize"> {{ config.toLocaleLowerCase() }}</span>
|
||||
authentication has been successfully configured.
|
||||
{{ t('onboarding.auth_successfully_configured') }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<HoppButtonPrimary
|
||||
v-if="duration"
|
||||
:label="`Server is restarting in ${duration} seconds...`"
|
||||
:label="
|
||||
t('onboarding.server_restarting', {
|
||||
time: duration,
|
||||
})
|
||||
"
|
||||
:disabled="duration > 0"
|
||||
@click="emit('finish')"
|
||||
class="w-min"
|
||||
/>
|
||||
<HoppButtonPrimary
|
||||
v-else
|
||||
label="Go to Dashboard"
|
||||
:label="t('app.continue_to_dashboard')"
|
||||
@click="emit('finish')"
|
||||
class="w-min"
|
||||
/>
|
||||
</template>
|
||||
<template v-else>
|
||||
<h1 class="text-2xl font-bold text-white">Onboarding Incomplete</h1>
|
||||
<h2>
|
||||
There was an issue completing the onboarding process. Please check the
|
||||
configurations and try again.
|
||||
</h2>
|
||||
<HoppButtonPrimary
|
||||
label="Retry Onboarding"
|
||||
@click="emit('back')"
|
||||
class="w-min"
|
||||
/>
|
||||
<p class="text-secondaryLight text-tiny mt-2">
|
||||
If you need help, please refer to the
|
||||
<a
|
||||
href="https://docs.hoppscotch.io/documentation/self-host/community-edition"
|
||||
target="_blank"
|
||||
class="text-secondaryLight underline"
|
||||
>documentation</a
|
||||
>.
|
||||
</p>
|
||||
<div class="flex flex-col space-y-4 p-4 max-w-screen-md mx-auto w-full">
|
||||
<h1 class="text-2xl font-bold text-white flex items-center space-x-2">
|
||||
<span>
|
||||
{{ t('onboarding.onboarding_incomplete.title') }}
|
||||
</span>
|
||||
<icon-lucide-alert-triangle
|
||||
class="svg-icons text-yellow-500 !h-8 !w-8"
|
||||
/>
|
||||
</h1>
|
||||
<h2>
|
||||
{{ t('onboarding.onboarding_incomplete.description') }}
|
||||
</h2>
|
||||
<HoppButtonPrimary
|
||||
label="Retry Onboarding"
|
||||
@click="emit('back')"
|
||||
class="w-min"
|
||||
/>
|
||||
<p class="text-secondaryLight text-tiny mt-2">
|
||||
{{ t('onboarding.onboarding_fail_help') }}
|
||||
<a
|
||||
href="https://docs.hoppscotch.io/documentation/self-host/community-edition"
|
||||
target="_blank"
|
||||
class="text-secondaryLight underline"
|
||||
>documentation</a
|
||||
>.
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -70,8 +90,10 @@
|
|||
import { HoppButtonPrimary } from '@hoppscotch/ui';
|
||||
import { onMounted, onUnmounted, ref } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { useI18n } from '~/composables/i18n';
|
||||
import { OnBoardingSummary } from '~/composables/useOnboardingConfigHandler';
|
||||
|
||||
const t = useI18n();
|
||||
const router = useRouter();
|
||||
|
||||
const props = defineProps<{
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@
|
|||
{{ smtp.USE_CUSTOM_CONFIGS.text }}
|
||||
</HoppSmartCheckbox>
|
||||
<p class="text-secondaryLight text-tiny mt-2">
|
||||
Enable to configure your own SMTP credentials
|
||||
{{ t('onboarding.smtp_advanced_config_enable') }}
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -69,6 +69,9 @@ import {
|
|||
EnabledConfig,
|
||||
MailerConfigKeys,
|
||||
} from '~/composables/useOnboardingConfigHandler';
|
||||
import { useI18n } from '~/composables/i18n';
|
||||
|
||||
const t = useI18n();
|
||||
|
||||
const props = defineProps<{
|
||||
currentConfigs: Configs;
|
||||
|
|
|
|||
|
|
@ -3,16 +3,26 @@
|
|||
<div class="max-w-screen-md mx-auto p-8 flex flex-col space-y-4">
|
||||
<div class="flex flex-col space-y-2 mb-4">
|
||||
<img src="/logo.svg" alt="hoppscotch-logo" class="w-20 mb-4" />
|
||||
<h1 class="text-3xl font-bold text-secondaryDark">Welcome</h1>
|
||||
<h1 class="text-3xl font-bold text-secondaryDark">
|
||||
{{ t('onboarding.welcome') }}
|
||||
</h1>
|
||||
<h2 class="mt-3">
|
||||
This is the onboarding process for setting up your Hoppscotch
|
||||
instance.
|
||||
{{ t('onboarding.welcome_screen_description') }}
|
||||
</h2>
|
||||
<p class="text-secondaryLight">
|
||||
Please set up either SMTP or OAuth for authentication.
|
||||
{{ t('onboarding.welcome_screen_sub_description') }}
|
||||
</p>
|
||||
</div>
|
||||
<HoppButtonPrimary label="Start Onboarding" @click="$emit('next')" />
|
||||
<HoppButtonPrimary
|
||||
:label="t('onboarding.start_onboarding')"
|
||||
@click="$emit('next')"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useI18n } from '~/composables/i18n';
|
||||
|
||||
const t = useI18n();
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -111,8 +111,8 @@ export function useOnboardingConfigHandler() {
|
|||
|
||||
const onBoardingSummary = ref<OnBoardingSummary>({
|
||||
type: 'success',
|
||||
message: t('onboarding.addConfigsSuccess'),
|
||||
description: t('onboarding.addConfigsDescription'),
|
||||
message: t('onboarding.setup_complete.title'),
|
||||
description: t('onboarding.setup_complete.description'),
|
||||
configsAdded: [] as string[],
|
||||
});
|
||||
|
||||
|
|
@ -182,9 +182,10 @@ export function useOnboardingConfigHandler() {
|
|||
if (addedConfigs.length === 0) {
|
||||
return {
|
||||
type: 'error',
|
||||
message: t('onboarding.addConfigsError'),
|
||||
description: t('onboarding.addConfigsDescription', {
|
||||
error: error?.message || t('onboarding.addConfigsDefaultError'),
|
||||
message: t('onboarding.onboarding_incomplete.title'),
|
||||
description: t('onboarding.onboarding_incomplete.description', {
|
||||
error:
|
||||
error?.message || t('onboarding.onboarding_incomplete.description'),
|
||||
}),
|
||||
configsAdded: [],
|
||||
};
|
||||
|
|
@ -192,8 +193,8 @@ export function useOnboardingConfigHandler() {
|
|||
|
||||
return {
|
||||
type: 'success',
|
||||
message: t('onboarding.addConfigsSuccess'),
|
||||
description: t('onboarding.addConfigsDescription'),
|
||||
message: t('onboarding.setup_complete.title'),
|
||||
description: t('onboarding.setup_complete.description'),
|
||||
configsAdded: addedConfigs.filter((key) => key !== 'MAILER'),
|
||||
};
|
||||
};
|
||||
|
|
@ -235,7 +236,7 @@ export function useOnboardingConfigHandler() {
|
|||
*/
|
||||
const validateConfigs = (configs: Partial<Record<string, string>>) => {
|
||||
if (!configs || Object.keys(configs).length === 0) {
|
||||
toast.error(t('onboarding.addConfigsError'));
|
||||
toast.error(t('onboarding.configuration_error'));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -250,7 +251,9 @@ export function useOnboardingConfigHandler() {
|
|||
neededKeys.forEach((key) => {
|
||||
if (!configs[key])
|
||||
toast.error(
|
||||
`Please fill the required field: ${makeReadableKey(key)}`
|
||||
t('onboarding.please_fill_configurations', {
|
||||
fieldName: makeReadableKey(key),
|
||||
})
|
||||
);
|
||||
});
|
||||
return;
|
||||
|
|
@ -284,7 +287,8 @@ export function useOnboardingConfigHandler() {
|
|||
const validated = validateConfigs(payload);
|
||||
|
||||
if (!validated || Object.keys(validated).length === 0) {
|
||||
toast.error('Please add at least one config');
|
||||
toast.error(t('onboarding.add_atleast_one_auth_provider'));
|
||||
submittingConfigs.value = false;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -299,13 +303,13 @@ export function useOnboardingConfigHandler() {
|
|||
const res = await auth.addOnBoardingConfigs(configWithAuth);
|
||||
if (res?.token) {
|
||||
setLocalConfig('access_token', res.token);
|
||||
toast.success('Onboarding configs added successfully');
|
||||
toast.success(t('onboarding.configurations_added_successfully'));
|
||||
onBoardingSummary.value = makeOnboardingSummary();
|
||||
return res;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Failed to add onboarding configs', err);
|
||||
toast.error('Failed to add onboarding configs');
|
||||
toast.error(t('onboarding.configurations_adding_failed'));
|
||||
onBoardingSummary.value = makeOnboardingSummary(err as Error);
|
||||
} finally {
|
||||
submittingConfigs.value = false;
|
||||
|
|
|
|||
|
|
@ -45,7 +45,14 @@ export default <HoppModule>{
|
|||
return next();
|
||||
}
|
||||
|
||||
const isAdmin = res.data?.me.isAdmin;
|
||||
if (
|
||||
!onboardingStatus?.onboardingCompleted &&
|
||||
!onboardingStatus?.canReRunOnboarding &&
|
||||
to.name !== 'index' &&
|
||||
to.name === 'onboarding'
|
||||
) {
|
||||
return next();
|
||||
}
|
||||
|
||||
if (
|
||||
onboardingStatus?.onboardingCompleted &&
|
||||
|
|
@ -56,6 +63,8 @@ export default <HoppModule>{
|
|||
return next({ name: 'index' });
|
||||
}
|
||||
|
||||
const isAdmin = res.data?.me.isAdmin;
|
||||
|
||||
// Route Guards
|
||||
if (!isGuestRoute(to.name) && !isAdmin) {
|
||||
/**
|
||||
|
|
@ -65,7 +74,7 @@ export default <HoppModule>{
|
|||
return next({ name: 'index' });
|
||||
}
|
||||
|
||||
if (isAdmin) {
|
||||
if (isAdmin && onboardingStatus?.onboardingCompleted) {
|
||||
// These route guards applies to the case where the user is logged in successfully and validated as an admin
|
||||
const isInfraNotSetup = await getFirstTimeInfraSetupStatus();
|
||||
|
||||
|
|
|
|||
|
|
@ -3,10 +3,10 @@
|
|||
<div
|
||||
class="fixed top-0 left-0 p-5 flex items-center justify-between w-full"
|
||||
>
|
||||
<span class="text-md font-bold">HOPPSCOTCH</span>
|
||||
<span class="text-md font-bold">{{ t('app.name') }}</span>
|
||||
<HoppButtonPrimary
|
||||
v-if="!isFirstTimeSetup"
|
||||
label="Go to Dashboard"
|
||||
:label="t('app.continue_to_dashboard')"
|
||||
@click="goToDashboard"
|
||||
/>
|
||||
</div>
|
||||
|
|
@ -41,9 +41,11 @@ import { useRouter } from 'vue-router';
|
|||
import AuthSetup from '~/components/onboarding/AuthSetup.vue';
|
||||
import CompleteOnboarding from '~/components/onboarding/CompleteScreen.vue';
|
||||
import WelcomeScreen from '~/components/onboarding/WelcomeScreen.vue';
|
||||
import { useI18n } from '~/composables/i18n';
|
||||
import { OnBoardingSummary } from '~/composables/useOnboardingConfigHandler';
|
||||
import { auth } from '~/helpers/auth';
|
||||
|
||||
const t = useI18n();
|
||||
const router = useRouter();
|
||||
|
||||
// Steps
|
||||
|
|
@ -99,8 +101,10 @@ watch(
|
|||
);
|
||||
|
||||
// Push to URL when step changes
|
||||
watch(step, (newStep) => {
|
||||
router.replace({ name: 'onboarding', query: { step: newStep.toString() } });
|
||||
watch(step, async (newStep) => {
|
||||
if (newStep !== STEP.COMPLETE) {
|
||||
router.replace({ name: 'onboarding', query: { step: newStep.toString() } });
|
||||
}
|
||||
});
|
||||
|
||||
// Load onboarding status
|
||||
|
|
|
|||
Loading…
Reference in a new issue