Skip to content

Commit e02e0c0

Browse files
luannmoreiragustavosbarreto
authored andcommitted
refactor(ui): centralize layout handling and simplify auth check
Refactored App.vue and layouts to use <script setup> syntax. Introduced layout meta field in routes for centralized layout control. Simplified router guard to handle auth and layout setup consistently.
1 parent 6fcc765 commit e02e0c0

File tree

7 files changed

+69
-79
lines changed

7 files changed

+69
-79
lines changed

ui/admin/src/App.vue

Lines changed: 11 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,23 @@
11
<template>
22
<v-app>
3-
<component :is="layout" :data-test="`${layout}-component`" />
3+
<component
4+
:is="layout"
5+
:data-test="`${layout}-component`" />
46
</v-app>
57
</template>
68

7-
<script lang="ts">
8-
import { defineComponent, onMounted, computed } from "vue";
9-
import { useRouter } from "vue-router";
9+
<script setup lang="ts">
10+
import { computed } from "vue";
1011
import SimpleLayout from "./layouts/SimpleLayout.vue";
1112
import AppLayout from "./layouts/AppLayout.vue";
1213
import { useStore } from "./store";
13-
import { INotificationsError } from "./interfaces/INotifications";
1414
15-
export default defineComponent({
16-
name: "App",
17-
components: {
18-
appLayout: AppLayout,
19-
simpleLayout: SimpleLayout,
20-
},
21-
setup() {
22-
const store = useStore();
23-
const router = useRouter();
15+
const components = {
16+
SimpleLayout,
17+
AppLayout,
18+
};
2419
25-
const layout = computed(() => store.getters["layout/getLayout"]);
20+
const store = useStore();
2621
27-
const isLoggedIn = computed(() => store.getters["auth/isLoggedIn"]);
28-
29-
const currentRoute = computed(() => router.currentRoute.value.path);
30-
31-
onMounted(async () => {
32-
if (!isLoggedIn.value) {
33-
try {
34-
await store.dispatch("auth/logout");
35-
store.dispatch("layout/setLayout", "simpleLayout");
36-
router.push("/login");
37-
} catch {
38-
store.dispatch("snackbar/showSnackbarErrorAction", INotificationsError.namespaceLoad);
39-
}
40-
}
41-
42-
if (isLoggedIn.value && currentRoute.value !== "/login") {
43-
const license = await store.dispatch("license/get");
44-
if (!license || license.expired) {
45-
store.dispatch("snackbar/showSnackbarErrorAction", INotificationsError.license);
46-
store.dispatch("layout/setLayout", "appLayout");
47-
router.push("/license");
48-
}
49-
store.dispatch("layout/setLayout", "appLayout");
50-
}
51-
});
52-
53-
return {
54-
layout,
55-
};
56-
},
57-
});
22+
const layout = computed(() => components[store.getters["layout/getLayout"]]);
5823
</script>

ui/admin/src/layouts/AppLayout.vue

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -188,8 +188,9 @@ const logout = async () => {
188188
await store.dispatch("auth/logout");
189189
await router.push("/login");
190190
createNewClient();
191-
store.dispatch("layout/setLayout", "simpleLayout");
191+
store.dispatch("layout/setLayout", "SimpleLayout");
192192
};
193+
193194
const triggerClick = (item: MenuItem): void => {
194195
switch (item.type) {
195196
case "path":
@@ -293,10 +294,14 @@ const getFilteredChildren = (children: DrawerItem[]) => expiredLicense.value
293294
294295
const visibleItems = computed(() => {
295296
if (expiredLicense.value) {
296-
return items.filter(
297-
(item) => item.title === "Settings" && item.children?.some((child) => child.title === "License"),
298-
);
297+
return items
298+
.filter((item) => item.title === "Settings")
299+
.map((item) => ({
300+
...item,
301+
children: item.children?.filter((child) => child.title === "License"),
302+
}));
299303
}
304+
300305
return items.filter((item) => !item.hidden);
301306
});
302307

ui/admin/src/layouts/SimpleLayout.vue

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,11 @@
22
<router-view :key="currentRoute.value.path" />
33
</template>
44

5-
<script lang="ts">
5+
<script setup lang="ts">
66
import { computed } from "vue";
77
import { useRouter } from "vue-router";
88
9-
export default {
10-
name: "SimpleLayout",
11-
setup() {
12-
const router = useRouter();
9+
const router = useRouter();
1310
14-
const currentRoute = computed(() => router.currentRoute);
15-
16-
return {
17-
currentRoute,
18-
};
19-
},
20-
};
11+
const currentRoute = computed(() => router.currentRoute);
2112
</script>

ui/admin/src/router/index.ts

Lines changed: 40 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { createRouter, createWebHistory } from "vue-router";
1+
import { createRouter, createWebHistory, NavigationGuardNext, RouteLocationNormalized } from "vue-router";
22
import Login from "@admin/views/Login.vue";
33
import Dashboard from "@admin/views/Dashboard.vue";
44
import Users from "@admin/views/Users.vue";
@@ -7,13 +7,19 @@ import SettingsAuthentication from "@admin/components/Settings/SettingsAuthentic
77
import Namespaces from "@admin/views/Namespaces.vue";
88
import Settings from "@admin/views/Settings.vue";
99

10+
import { INotificationsError } from "@admin/interfaces/INotifications";
11+
import { computed } from "vue";
1012
import { store } from "../store";
1113

1214
const routes = [
1315
{
1416
path: "/login",
1517
name: "login",
1618
component: Login,
19+
meta: {
20+
layout: "SimpleLayout",
21+
requiresAuth: false,
22+
},
1723
},
1824
{
1925
path: "/",
@@ -120,21 +126,41 @@ const router = createRouter({
120126
routes,
121127
});
122128

123-
router.beforeEach((to, from, next) => {
124-
if (to.path !== "/login") {
125-
if (store.getters["auth/isLoggedIn"]) {
126-
return next();
129+
router.beforeEach(
130+
async (to: RouteLocationNormalized, from: RouteLocationNormalized, next: NavigationGuardNext) => {
131+
const isLoggedIn: boolean = store.getters["auth/isLoggedIn"];
132+
const requiresAuth = to.meta.requiresAuth ?? true;
133+
134+
const layout = to.meta.layout || "AppLayout";
135+
await store.dispatch("layout/setLayout", layout);
136+
137+
if (!isLoggedIn && requiresAuth) {
138+
return next({
139+
name: "login",
140+
query: { redirect: to.fullPath },
141+
});
127142
}
128-
return next(`/login?redirect=${to.path}`);
129-
}
130-
if (store.getters["auth/isLoggedIn"]) {
131-
if (to.path === "/login" && to.query.token) {
132-
return next();
143+
144+
if (isLoggedIn && !to.meta.requiresAuth) {
145+
const license = computed(() => store.getters["license/license"]);
146+
147+
try {
148+
await store.dispatch("license/get");
149+
150+
if (license.value.expired && to.name !== "SettingLicense") {
151+
store.dispatch("snackbar/showSnackbarErrorAction", INotificationsError.license);
152+
return next({ name: "SettingLicense" });
153+
}
154+
} catch {
155+
if (to.name !== "SettingLicense") {
156+
store.dispatch("snackbar/showSnackbarErrorAction", INotificationsError.license);
157+
return next({ name: "SettingLicense" });
158+
}
159+
}
133160
}
134-
return next("/");
135-
}
136161

137-
return next();
138-
});
162+
return next();
163+
},
164+
);
139165

140166
export default router;

ui/admin/src/store/modules/auth.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ export const auth: Module<AuthState, State> = {
2020
tenant: localStorage.getItem("tenant") || "",
2121
},
2222
getters: {
23-
isLoggedIn: (state) => state.token,
23+
isLoggedIn: (state) => !!state.token,
2424
currentUser: (state) => state.user,
2525
authStatus: (state) => state.status,
2626
tenant: (state) => state.tenant,

ui/admin/src/store/modules/license.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ export interface LicenseState {
99

1010
export const license: Module<LicenseState, State> = {
1111
namespaced: true,
12+
state: {
13+
license: {} as ILicense,
14+
},
1215

1316
getters: {
1417
isExpired: (state) => (state.license && state.license.expired)

ui/admin/tests/unit/store/modules/Auth.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,13 @@ describe("Auth", () => {
3838

3939
store.commit("auth/authSuccess", { token, user, tenant });
4040
expect(store.getters["auth/authStatus"]).toEqual(statusSuccess);
41-
expect(store.getters["auth/isLoggedIn"]).toEqual(token);
41+
expect(store.getters["auth/isLoggedIn"]).toEqual(true);
4242
expect(store.getters["auth/currentUser"]).toEqual(user);
4343
expect(store.getters["auth/tenant"]).toEqual(tenant);
4444

4545
store.commit("auth/logout");
4646
expect(store.getters["auth/authStatus"]).toEqual("");
47-
expect(store.getters["auth/isLoggedIn"]).toEqual("");
47+
expect(store.getters["auth/isLoggedIn"]).toEqual(false);
4848
expect(store.getters["auth/currentUser"]).toEqual("");
4949
expect(store.getters["auth/tenant"]).toEqual("");
5050
});

0 commit comments

Comments
 (0)