refactor(sh-admin): dashboard settings page redesign (#5014)

This commit is contained in:
Joel Jacob Stephen 2025-04-24 09:54:32 -05:00 committed by GitHub
parent a208125c7d
commit 485ac8c3c6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 160 additions and 43 deletions

View file

@ -17,16 +17,31 @@
"open_navigation": "Open Navigation",
"read_documentation": "Read Documentation"
},
"auth": {
"email_auth": "Email Authentication",
"email_auth_description": "Enable or disable email-based authentication for your users.",
"email_auth_enabled": "Email authentication is enabled and ready to use.",
"email_auth_smtp_note": "To use email-based authentication, you need to enable and configure SMTP in the SMTP tab first.",
"enable_email_auth": "Enable Email Authentication",
"smtp_required": "SMTP must be enabled and configured to use email based authentication."
},
"configs": {
"auth_providers": {
"auth_provider_config": "Authentication Configurations",
"auth_provider_description": "Set up authentication methods for your Hoppscotch instance using OAuth or Email.",
"callback_url": "CALLBACK URL",
"client_id": "CLIENT ID",
"client_secret": "CLIENT SECRET",
"description": "Configure authentication providers for your server",
"email": "Email",
"github_enterprise": "Enable Github Enterprise",
"oauth": "OAuth",
"oauth_providers": "OAuth Providers",
"provider_not_specified": "Please enable at least one authentication provider",
"scope": "SCOPE",
"sso": "SSO",
"tenant": "TENANT",
"title": "Authentication Providers",
"title": "OAuth Providers",
"update_failure": "Failed to update authentication provider configurations!!"
},
"confirm_changes": "Hoppscotch server must restart to reflect the new changes. Confirm changes made to the server configurations?",
@ -83,6 +98,14 @@
"title": "Server is restarting"
},
"save_changes": "Save Changes",
"tabs": {
"auth": "Authentication",
"activity": "Activity",
"infra_tokens": "Infra Tokens",
"smtp": "SMTP",
"miscellaneous": "Miscellaneous",
"reset": "Reset Configurations"
},
"title": "Configurations",
"update_failure": "Failed to update server configurations"
},

View file

@ -42,10 +42,13 @@ declare module 'vue' {
IconLucideInfo: typeof import('~icons/lucide/info')['default']
IconLucideSearch: typeof import('~icons/lucide/search')['default']
IconLucideUser: typeof import('~icons/lucide/user')['default']
SettingsAuthConfiguration: typeof import('./components/settings/AuthConfiguration.vue')['default']
SettingsAuthConfigurations: typeof import('./components/settings/AuthConfigurations.vue')['default']
SettingsAuthProvider: typeof import('./components/settings/AuthProvider.vue')['default']
SettingsConfigurations: typeof import('./components/settings/Configurations.vue')['default']
SettingsDataSharing: typeof import('./components/settings/DataSharing.vue')['default']
SettingsHistoryConfiguration: typeof import('./components/settings/HistoryConfiguration.vue')['default']
SettingsOAuthProviderConfigurations: typeof import('./components/settings/OAuthProviderConfigurations.vue')['default']
SettingsReset: typeof import('./components/settings/Reset.vue')['default']
SettingsServerRestart: typeof import('./components/settings/ServerRestart.vue')['default']
SettingsSmtpConfiguration: typeof import('./components/settings/SmtpConfiguration.vue')['default']

View file

@ -0,0 +1,114 @@
<template>
<div class="flex flex-col pt-8">
<div class="px-4 mb-4">
<h3 class="heading">
{{ t('configs.auth_providers.auth_provider_config') }}
</h3>
<p class="my-1 text-secondaryLight">
{{ t('configs.auth_providers.auth_provider_description') }}
</p>
</div>
<HoppSmartTabs v-model="selectedAuthSubTab" render-inactive-tabs>
<HoppSmartTab
id="auth-providers"
:label="t('configs.auth_providers.oauth')"
>
<div class="pb-8 px-4">
<SettingsOAuthProviderConfigurations
v-model:config="workingConfigs"
/>
</div>
</HoppSmartTab>
<HoppSmartTab id="email-auth" :label="t('configs.auth_providers.email')">
<div class="pb-8 px-4 grid md:grid-cols-3 gap-4 md:gap-4 pt-8">
<div class="md:col-span-1">
<h3 class="heading">{{ t('auth.email_auth') }}</h3>
<p class="my-1 text-secondaryLight">
{{ t('auth.email_auth_description') }}
</p>
<p class="my-1 text-secondaryLight mt-4">
{{ t('auth.email_auth_smtp_note') }}
</p>
</div>
<div class="sm:px-8 md:col-span-2">
<section>
<h4 class="font-semibold text-secondaryDark">
{{ t('auth.email_auth') }}
</h4>
<div class="space-y-4 py-4">
<div class="flex justify-between">
<HoppSmartToggle
:on="isEmailAuthEnabled && isSMTPEnabled && isSMTPActivated"
:disabled="!isSMTPEnabled || !isSMTPActivated"
@change="toggleEmailAuth"
>
{{ t('auth.enable_email_auth') }}
</HoppSmartToggle>
</div>
<div
v-if="!isSMTPActivated"
class="flex items-center mt-5 p-3 bg-yellow-700/30 border border-yellow-900 text-secondaryDark max-w-md rounded-md"
>
<icon-lucide-info class="svg-icons mr-2" />
<span>{{ t('auth.smtp_required') }}</span>
</div>
</div>
</section>
</div>
</div>
</HoppSmartTab>
</HoppSmartTabs>
</div>
</template>
<script setup lang="ts">
import { useVModel } from '@vueuse/core';
import { computed, onMounted, ref } from 'vue';
import { useI18n } from '~/composables/i18n';
import { ServerConfigs } from '~/helpers/configs';
const t = useI18n();
const props = defineProps<{
config: ServerConfigs;
}>();
const emit = defineEmits<{
(e: 'update:config', v: ServerConfigs): void;
}>();
// Auth Sub Tabs
type AuthSubTabs = 'auth-providers' | 'email-auth';
const selectedAuthSubTab = ref<AuthSubTabs>('auth-providers');
const workingConfigs = useVModel(props, 'config', emit);
// Check if SMTP is activated but not saved yet. Used to track if SMTP was enabled after the last save.
const isSMTPActivated = computed(
() => workingConfigs.value?.mailConfigs.enabled ?? false
);
// Check if Email authentication is enabled
const isEmailAuthEnabled = computed(() => {
return workingConfigs.value?.mailConfigs.fields.email_auth ?? false;
});
// Toggle Email authentication
const toggleEmailAuth = () => {
if (isSMTPEnabled.value && isSMTPActivated.value) {
workingConfigs.value.mailConfigs.fields.email_auth =
!workingConfigs.value.mailConfigs.fields.email_auth;
}
};
// Check if SMTP is enabled on mount
const isSMTPEnabled = ref(false);
onMounted(() => {
isSMTPEnabled.value = workingConfigs.value?.mailConfigs.enabled ?? false;
});
</script>

View file

@ -1,24 +0,0 @@
<template>
<div class="flex flex-col space-y-8 divide-y divide-divider">
<SettingsAuthProvider v-model:config="workingConfigs" />
<SettingsSmtpConfiguration v-model:config="workingConfigs" />
<SettingsHistoryConfiguration v-model:config="workingConfigs" />
<SettingsDataSharing v-model:config="workingConfigs" />
<SettingsReset />
</div>
</template>
<script setup lang="ts">
import { useVModel } from '@vueuse/core';
import { ServerConfigs } from '~/helpers/configs';
const props = defineProps<{
config: ServerConfigs;
}>();
const emit = defineEmits<{
(e: 'update:config', v: ServerConfigs): void;
}>();
const workingConfigs = useVModel(props, 'config', emit);
</script>

View file

@ -1,5 +1,5 @@
<template>
<div v-if="workingConfigs" class="grid md:grid-cols-3 gap-8 md:gap-4">
<div v-if="workingConfigs" class="grid md:grid-cols-3 gap-8 md:gap-4 pt-8">
<div class="md:col-span-1">
<h3 class="heading">{{ t('configs.auth_providers.title') }}</h3>
<p class="my-1 text-secondaryLight">

View file

@ -35,15 +35,6 @@
<div v-if="smtpConfigs.enabled" class="ml-12">
<div class="flex flex-col items-start gap-5">
<HoppSmartCheckbox
:on="smtpConfigs.fields.email_auth"
@change="
smtpConfigs.fields.email_auth = !smtpConfigs.fields.email_auth
"
>
{{ t('configs.mail_configs.enable_email_auth') }}
</HoppSmartCheckbox>
<HoppSmartCheckbox
:on="smtpConfigs.fields.mailer_use_custom_configs"
:title="t('configs.mail_configs.custom_smtp_configs')"

View file

@ -18,15 +18,25 @@
<div v-else-if="workingConfigs" class="flex flex-col py-8">
<HoppSmartTabs v-model="selectedOptionTab" render-inactive-tabs>
<HoppSmartTab :id="'config'" :label="t('configs.title')">
<SettingsConfigurations
v-model:config="workingConfigs"
class="py-8 px-4"
/>
<HoppSmartTab id="auth" :label="t('configs.tabs.auth')">
<SettingsAuthConfigurations v-model:config="workingConfigs" />
</HoppSmartTab>
<HoppSmartTab :id="'token'" :label="t('infra_tokens.tab_title')">
<HoppSmartTab id="smtp" :label="t('configs.tabs.smtp')">
<div class="pb-8 px-4 flex flex-col space-y-8 divide-y divide-divider">
<SettingsSmtpConfiguration v-model:config="workingConfigs" />
</div>
</HoppSmartTab>
<HoppSmartTab :id="'token'" :label="t('configs.tabs.infra_tokens')">
<Tokens />
</HoppSmartTab>
<HoppSmartTab id="miscellaneous" :label="t('configs.tabs.miscellaneous')">
<div class="pb-8 px-4 flex flex-col space-y-8 divide-y divide-divider">
<SettingsDataSharing v-model:config="workingConfigs" />
<SettingsReset />
</div>
</HoppSmartTab>
</HoppSmartTabs>
</div>
@ -66,8 +76,8 @@ const showSaveChangesModal = ref(false);
const initiateServerRestart = ref(false);
// Tabs
type OptionTabs = 'config' | 'token';
const selectedOptionTab = ref<OptionTabs>('config');
type OptionTabs = 'auth' | 'smtp' | 'token' | 'miscellaneous';
const selectedOptionTab = ref<OptionTabs>('auth');
// Obtain the current and working configs from the useConfigHandler composable
const {