From d2e78c4b5645171059e9f6c63b806c15b60d5a75 Mon Sep 17 00:00:00 2001 From: joan Date: Tue, 17 May 2022 14:58:01 +0200 Subject: [PATCH] feat(leftmenu): collapsable submodule routes #4044 --- src/components/LeftMenu.vue | 79 ++++++++++++++---- src/components/Navbar.vue | 8 ++ src/components/__tests__/Leftmenu.spec.js | 98 +++++++++++++++++++++++ src/i18n/en/index.js | 5 +- src/i18n/es/index.js | 5 +- src/router/modules/customer.js | 9 ++- src/router/modules/ticket.js | 17 +++- 7 files changed, 195 insertions(+), 26 deletions(-) create mode 100644 src/components/__tests__/Leftmenu.spec.js diff --git a/src/components/LeftMenu.vue b/src/components/LeftMenu.vue index 6b522ec9b..fccaef1cb 100644 --- a/src/components/LeftMenu.vue +++ b/src/components/LeftMenu.vue @@ -7,21 +7,37 @@ import routes from 'src/router/routes'; const { t } = useI18n(); const { hasAny } = useRole(); -const mainRoute = routes.find(route => route.path === '/'); -const moduleRoutes = mainRoute && mainRoute.children || [] +const mainRoute = routes.find((route) => route.path === '/'); +const moduleRoutes = (mainRoute && mainRoute.children) || []; const modules = ref([]); for (const route of moduleRoutes) { const module = { - path: route.path, + stateName: route.name, name: route.name.toLowerCase(), - roles: [] + roles: [], }; if (route.meta) { Object.assign(module, route.meta); } + if (route.children && route.children.length) { + const [moduleMain] = route.children; + const routes = moduleMain.children; + + module.children = routes.map((route) => { + const submodule = { + stateName: route.name, + name: route.name, + }; + + Object.assign(submodule, route.meta); + + return submodule; + }); + } + modules.value.push(module); } @@ -29,18 +45,47 @@ for (const route of moduleRoutes) { \ No newline at end of file + diff --git a/src/components/Navbar.vue b/src/components/Navbar.vue index 53bf6ca14..e26f120d9 100644 --- a/src/components/Navbar.vue +++ b/src/components/Navbar.vue @@ -50,9 +50,17 @@ function onToggleDrawer() { + 2 {{ t('globals.notifications') }} + + Notifications + +
+ +
+
diff --git a/src/components/__tests__/Leftmenu.spec.js b/src/components/__tests__/Leftmenu.spec.js new file mode 100644 index 000000000..26656c1d8 --- /dev/null +++ b/src/components/__tests__/Leftmenu.spec.js @@ -0,0 +1,98 @@ +import { jest, describe, expect, it, beforeAll } from '@jest/globals'; +import { createWrapper } from 'app/tests/jest/jestHelpers'; +import Leftmenu from '../LeftMenu.vue'; + +const mockPush = jest.fn(); + +jest.mock('vue-router', () => ({ + useRouter: () => ({ + push: mockPush, + currentRoute: { value: 'myCurrentRoute' } + }), +})); + +jest.mock('src/router/routes', () => ([ + { + path: '/', + name: 'Main', + children: [ + { + path: '/dashboard', + name: 'Dashboard', + meta: { title: 'dashboard', icon: 'dashboard' } + }, + { + path: '/customer', + name: 'Customer', + meta: { + title: 'customers', + icon: 'vn:client' + }, + children: [ + { + path: '', + name: 'CustomerMain', + children: [ + { + path: 'list', + name: 'CustomerList', + meta: { + title: 'list', + icon: 'view_list', + } + }, + { + path: 'create', + name: 'CustomerCreate', + meta: { + title: 'createCustomer', + icon: 'vn:addperson', + } + }, + ] + } + ] + } + ], + }, +])); + +describe('Leftmenu', () => { + let vm; + beforeAll(() => { + vm = createWrapper(Leftmenu).vm; + }); + + it('should return a proper formated object without the children property', async () => { + const expectedMenuItem = { + stateName: 'Dashboard', + name: 'dashboard', + roles: [], + icon: 'dashboard', + title: 'dashboard' + } + + const firstMenuItem = vm.modules[0]; + expect(firstMenuItem.children).toBeUndefined(); + expect(firstMenuItem).toEqual(expect.objectContaining(expectedMenuItem)); + }); + + it('should return a proper formated object with two child items', async () => { + const expectedMenuItem = [{ + name: 'CustomerList', + title: 'list', + icon: 'view_list', + stateName: 'CustomerList' + }, + { + name: 'CustomerCreate', + title: 'createCustomer', + icon: 'vn:addperson', + stateName: 'CustomerCreate' + }]; + + const secondMenuItem = vm.modules[1]; + expect(secondMenuItem.children).toEqual(expect.arrayContaining(expectedMenuItem)); + expect(secondMenuItem.children.length).toEqual(2) + }); +}); diff --git a/src/i18n/en/index.js b/src/i18n/en/index.js index 7fd3e5515..55a6a8b33 100644 --- a/src/i18n/en/index.js +++ b/src/i18n/en/index.js @@ -39,7 +39,10 @@ export default { }, ticket: { pageTitles: { - tickets: 'Tickets' + tickets: 'Tickets', + list: 'List', + createTicket: 'Create ticket', + basicData: 'Basic Data' } }, components: { diff --git a/src/i18n/es/index.js b/src/i18n/es/index.js index 89f10a7e6..f1eb82bb5 100644 --- a/src/i18n/es/index.js +++ b/src/i18n/es/index.js @@ -39,7 +39,10 @@ export default { }, ticket: { pageTitles: { - tickets: 'Tickets' + tickets: 'Tickets', + list: 'Listado', + createTicket: 'Crear ticket', + basicData: 'Datos básicos' } }, components: { diff --git a/src/router/modules/customer.js b/src/router/modules/customer.js index 764a41440..9fc377f62 100644 --- a/src/router/modules/customer.js +++ b/src/router/modules/customer.js @@ -5,8 +5,7 @@ export default { name: 'Customer', meta: { title: 'customers', - icon: 'vn:client', - roles: ['salesPerson'], + icon: 'vn:client' }, component: RouterView, redirect: { name: 'CustomerMain' }, @@ -21,7 +20,8 @@ export default { path: 'list', name: 'CustomerList', meta: { - title: 'list' + title: 'list', + icon: 'view_list', }, component: () => import('src/pages/Customer/CustomerList.vue'), }, @@ -29,7 +29,8 @@ export default { path: 'create', name: 'CustomerCreate', meta: { - title: 'createCustomer' + title: 'createCustomer', + icon: 'vn:addperson', }, component: () => import('src/pages/Customer/CustomerCreate.vue'), }, diff --git a/src/router/modules/ticket.js b/src/router/modules/ticket.js index a8dd42165..8920b1104 100644 --- a/src/router/modules/ticket.js +++ b/src/router/modules/ticket.js @@ -5,8 +5,7 @@ export default { name: 'Ticket', meta: { title: 'tickets', - icon: 'vn:ticket', - roles: ['salesPerson'], + icon: 'vn:ticket' }, component: RouterView, redirect: { name: 'TicketMain' }, @@ -21,10 +20,22 @@ export default { path: 'list', name: 'TicketList', meta: { - title: 'list' + title: 'list', + icon: 'view_list', }, component: () => import('src/pages/Ticket/TicketList.vue'), }, + { + path: 'create', + name: 'TicketCreate', + meta: { + title: 'createTicket', + icon: 'vn:ticketAdd', + roles: ['salesPerson'], + }, + component: () => import('src/pages/Ticket/TicketList.vue'), + }, + ] }, {