fix: Handle login when there are no accounts (#12816)

This commit is contained in:
Pranav
2025-11-06 20:44:59 -08:00
committed by GitHub
parent 5bf39d20e5
commit 01363042ce
5 changed files with 62 additions and 15 deletions

View File

@@ -1,6 +1,5 @@
<script> <script>
import { mapGetters } from 'vuex'; import { mapGetters } from 'vuex';
import AddAccountModal from './components/app/AddAccountModal.vue';
import LoadingState from './components/widgets/LoadingState.vue'; import LoadingState from './components/widgets/LoadingState.vue';
import NetworkNotification from './components/NetworkNotification.vue'; import NetworkNotification from './components/NetworkNotification.vue';
import UpdateBanner from './components/app/UpdateBanner.vue'; import UpdateBanner from './components/app/UpdateBanner.vue';
@@ -25,7 +24,6 @@ export default {
name: 'App', name: 'App',
components: { components: {
AddAccountModal,
LoadingState, LoadingState,
NetworkNotification, NetworkNotification,
UpdateBanner, UpdateBanner,
@@ -51,7 +49,6 @@ export default {
}, },
data() { data() {
return { return {
showAddAccountModal: false,
latestChatwootVersion: null, latestChatwootVersion: null,
reconnectService: null, reconnectService: null,
}; };
@@ -64,21 +61,12 @@ export default {
authUIFlags: 'getAuthUIFlags', authUIFlags: 'getAuthUIFlags',
accountUIFlags: 'accounts/getUIFlags', accountUIFlags: 'accounts/getUIFlags',
}), }),
hasAccounts() {
const { accounts = [] } = this.currentUser || {};
return accounts.length > 0;
},
hideOnOnboardingView() { hideOnOnboardingView() {
return !isOnOnboardingView(this.$route); return !isOnOnboardingView(this.$route);
}, },
}, },
watch: { watch: {
currentUser() {
if (!this.hasAccounts) {
this.showAddAccountModal = true;
}
},
currentAccountId: { currentAccountId: {
immediate: true, immediate: true,
handler() { handler() {
@@ -156,7 +144,6 @@ export default {
<component :is="Component" /> <component :is="Component" />
</transition> </transition>
</router-view> </router-view>
<AddAccountModal :show="showAddAccountModal" :has-accounts="hasAccounts" />
<WootSnackbarBox /> <WootSnackbarBox />
<NetworkNotification /> <NetworkNotification />
</div> </div>

View File

@@ -251,6 +251,12 @@
"ACCOUNT_SUSPENDED": { "ACCOUNT_SUSPENDED": {
"TITLE": "Account Suspended", "TITLE": "Account Suspended",
"MESSAGE": "Your account is suspended. Please reach out to the support team for more information." "MESSAGE": "Your account is suspended. Please reach out to the support team for more information."
},
"NO_ACCOUNTS": {
"TITLE": "No account found",
"MESSAGE_CLOUD": "You are not part of any accounts right now. If you think this is a mistake, please reach out to our support team.",
"MESSAGE_SELF_HOSTED": "You are not part of any accounts right now. Please reach out to your administrator.",
"LOGOUT": "Log out"
} }
}, },
"COMPONENTS": { "COMPONENTS": {

View File

@@ -10,6 +10,7 @@ import campaignsRoutes from './campaigns/campaigns.routes';
import { routes as captainRoutes } from './captain/captain.routes'; import { routes as captainRoutes } from './captain/captain.routes';
import AppContainer from './Dashboard.vue'; import AppContainer from './Dashboard.vue';
import Suspended from './suspended/Index.vue'; import Suspended from './suspended/Index.vue';
import NoAccounts from './noAccounts/Index.vue';
export default { export default {
routes: [ routes: [
@@ -36,5 +37,10 @@ export default {
}, },
component: Suspended, component: Suspended,
}, },
{
path: frontendURL('no-accounts'),
name: 'no_accounts',
component: NoAccounts,
},
], ],
}; };

View File

@@ -0,0 +1,39 @@
<script setup>
import { computed } from 'vue';
import { useI18n } from 'vue-i18n';
import { useMapGetter } from 'dashboard/composables/store';
import EmptyState from 'dashboard/components/widgets/EmptyState.vue';
import NextButton from 'dashboard/components-next/button/Button.vue';
import Auth from 'dashboard/api/auth';
const { t } = useI18n();
const isOnChatwootCloud = useMapGetter('globalConfig/isOnChatwootCloud');
const message = computed(() => {
if (isOnChatwootCloud.value) {
return t('APP_GLOBAL.NO_ACCOUNTS.MESSAGE_CLOUD');
}
return t('APP_GLOBAL.NO_ACCOUNTS.MESSAGE_SELF_HOSTED');
});
const handleLogout = () => {
Auth.logout();
};
</script>
<template>
<div
class="flex flex-col flex-1 items-center justify-center w-full h-full gap-6 bg-n-slate-2"
>
<EmptyState
:title="$t('APP_GLOBAL.NO_ACCOUNTS.TITLE')"
:message="message"
/>
<NextButton
variant="smooth"
color-scheme="secondary"
:label="$t('APP_GLOBAL.NO_ACCOUNTS.LOGOUT')"
@click="handleLogout"
/>
</div>
</template>

View File

@@ -18,8 +18,17 @@ export const validateAuthenticateRoutePermission = (to, next) => {
return ''; return '';
} }
if (!to.name) { const { accounts = [], account_id: accountId } = user;
return next(frontendURL(`accounts/${user.account_id}/dashboard`));
if (!accounts.length) {
if (to.name === 'no_accounts') {
return next();
}
return next(frontendURL('no-accounts'));
}
if (to.name === 'no_accounts' || !to.name) {
return next(frontendURL(`accounts/${accountId}/dashboard`));
} }
const nextRoute = validateLoggedInRoutes(to, store.getters.getCurrentUser); const nextRoute = validateLoggedInRoutes(to, store.getters.getCurrentUser);