feat: complete admin panel and backend admin api migration
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,182 @@
|
||||
// Ported from legacy henza_admin/src/router/branch.js
|
||||
//
|
||||
// Converted MECHANICALLY (see scratchpad/convert_routes.js) so every path, name,
|
||||
// meta.role, breadcrumb and pageTitle survives byte-exact. Only the component
|
||||
// imports are rewritten to point at the ported views. As of Batch 15 every
|
||||
// referenced view exists, so no placeholder is emitted.
|
||||
//
|
||||
// NOTE: legacy also shipped 8 router files with zero importers (apps.js,
|
||||
// category.js, customer.js, dashboard.js, full.js, manage.js, order.js,
|
||||
// product.js, temp.js). They are dead code and are not ported.
|
||||
import type { RouteRecordRaw } from 'vue-router';
|
||||
|
||||
export const branchRoute: RouteRecordRaw[] = [
|
||||
{
|
||||
path: '/',
|
||||
name: 'main',
|
||||
redirect: '/dashboard'
|
||||
},
|
||||
{
|
||||
path: '/dashboard',
|
||||
name: 'dashboard',
|
||||
component: () => import('../views/branch/dashboard.vue'),
|
||||
meta: {
|
||||
rule: 'admin',
|
||||
role: 'dashboard.omde'
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/products',
|
||||
name: 'product-list',
|
||||
component: () => import('../views/apps/product/ProductList.vue'),
|
||||
meta: {
|
||||
rule: 'editor',
|
||||
role: 'product.list',
|
||||
parent: 'product',
|
||||
no_scroll: true
|
||||
}
|
||||
},
|
||||
/*{
|
||||
path: '/order',
|
||||
redirect: '/order/list',
|
||||
name: 'order'
|
||||
},*/
|
||||
{
|
||||
path: '/order/list',
|
||||
component: () => import('../views/order/List.vue'),
|
||||
meta: {
|
||||
rule: 'editor',
|
||||
role: 'order.list',
|
||||
parent: 'order',
|
||||
no_scroll: true
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/buy/order/list',
|
||||
component: () => import('../views/branch/buyList.vue'),
|
||||
meta: {
|
||||
rule: 'editor',
|
||||
role: 'order.list',
|
||||
parent: 'order',
|
||||
no_scroll: true
|
||||
}
|
||||
},
|
||||
/*{
|
||||
path: '/buy/order/list',
|
||||
component: () => import('../views/order/List.vue'),
|
||||
meta: {
|
||||
rule: 'editor',
|
||||
role: 'buy.order.list',
|
||||
no_scroll: true
|
||||
}
|
||||
},*/
|
||||
{
|
||||
path: '/order/create',
|
||||
component: () => import('../views/branch/order/create.vue'),
|
||||
meta: {
|
||||
rule: 'editor',
|
||||
role: 'order.create',
|
||||
parent: 'order',
|
||||
no_scroll: true
|
||||
}
|
||||
},
|
||||
/*{
|
||||
path: '/singleCustomer/edit/:id',
|
||||
name: 'singleCustomer-edit',
|
||||
component: () => import('../views/apps/customer/EditSingleCustomer.vue'),
|
||||
meta: {
|
||||
rule: 'editor',
|
||||
role: 'persons.list.client.single.edit',
|
||||
parent: 'product',
|
||||
no_scroll: true
|
||||
}
|
||||
},*/
|
||||
{
|
||||
path: '/singleCustomer/view/:id',
|
||||
name: 'singleCustomer-view',
|
||||
component: () => import('../views/customer/single-customer/ViewSingleCustomer.vue'),
|
||||
meta: {
|
||||
rule: 'editor',
|
||||
role: 'persons.list.client.single.view',
|
||||
parent: 'product',
|
||||
no_scroll: true
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/singleCustomer/edit/:id',
|
||||
name: 'singleCustomer-edit',
|
||||
component: () => import('../views/apps/customer/EditSingleCustomer.vue'),
|
||||
meta: {
|
||||
rule: 'editor',
|
||||
role: 'persons.list.client.single.edit',
|
||||
parent: 'product',
|
||||
no_scroll: true
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/customer/add',
|
||||
name: 'add-customer',
|
||||
component: () => import('../views/branch/addCustomer.vue'),
|
||||
meta: {
|
||||
role: 'persons.create',
|
||||
rule: 'editor'
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/customer/list',
|
||||
name: 'list-customer',
|
||||
component: () => import('../views/customer/single-customer/SingleCustomer.vue'),
|
||||
meta: {
|
||||
role: 'persons.list.client.single',
|
||||
rule: 'editor'
|
||||
}
|
||||
},
|
||||
/*{
|
||||
path: '/report/order_item',
|
||||
name: 'report_order_item',
|
||||
component: () => import('../views/report/order_item.vue'),
|
||||
meta: {
|
||||
/!* breadcrumb: [
|
||||
{title: 'خانه', url: '/'},
|
||||
{title: 'مشتریان'}
|
||||
],*!/
|
||||
//pageTitle: 'لیست مشتریان',
|
||||
role: 'report.order.item',
|
||||
rule: 'editor'
|
||||
}
|
||||
},*/
|
||||
/*{
|
||||
path: '/report/product',
|
||||
name: 'report_product',
|
||||
component: () => import('../views/report/product.vue'),
|
||||
meta: {
|
||||
role: 'report.product',
|
||||
rule: 'editor'
|
||||
}
|
||||
},*/
|
||||
/*{
|
||||
path: '/finical/list',
|
||||
name: 'finical_list',
|
||||
component: () => import('../views/finical/list.vue'),
|
||||
meta: {
|
||||
/!* breadcrumb: [
|
||||
{title: 'خانه', url: '/'},
|
||||
{title: 'مشتریان'}
|
||||
],*!/
|
||||
//pageTitle: 'لیست مشتریان',
|
||||
role: 'document.list',
|
||||
rule: 'editor'
|
||||
}
|
||||
},*/
|
||||
]
|
||||
|
||||
export const fullPageBranchRoute: RouteRecordRaw[] = [ {
|
||||
path: '/auth/login',
|
||||
name: 'page-login',
|
||||
//component: () => import('../views/auth/Login.vue'),
|
||||
component: () => import('../views/branch/login.vue'),
|
||||
meta: {
|
||||
rule: 'editor'
|
||||
}
|
||||
},
|
||||
]
|
||||
-1
@@ -1 +0,0 @@
|
||||
export declare const router: import("vue-router").Router;
|
||||
@@ -1,12 +0,0 @@
|
||||
import { createRouter, createWebHistory } from 'vue-router';
|
||||
import DashboardView from '../views/DashboardView.vue';
|
||||
import OrderNewView from '../views/OrderNewView.vue';
|
||||
import OrderDetailView from '../views/OrderDetailView.vue';
|
||||
export const router = createRouter({
|
||||
history: createWebHistory(),
|
||||
routes: [
|
||||
{ path: '/', name: 'dashboard', component: DashboardView },
|
||||
{ path: '/orders/new', name: 'order-new', component: OrderNewView },
|
||||
{ path: '/orders/:id', name: 'order-detail', component: OrderDetailView },
|
||||
],
|
||||
});
|
||||
@@ -1,13 +1,128 @@
|
||||
// Ported from legacy henza_admin/src/router.js
|
||||
import { createRouter, createWebHistory } from 'vue-router';
|
||||
import DashboardView from '../views/DashboardView.vue';
|
||||
import OrderNewView from '../views/OrderNewView.vue';
|
||||
import OrderDetailView from '../views/OrderDetailView.vue';
|
||||
import { adminRoute, fullPageAdminRoute } from './admin';
|
||||
import { branchRoute, fullPageBranchRoute } from './branch';
|
||||
import { isBranch, tokenName, userName } from '../utils';
|
||||
import { useUsersStore } from '../stores/users';
|
||||
import api from '../api/client';
|
||||
|
||||
export const router = createRouter({
|
||||
history: createWebHistory(),
|
||||
const router = createRouter({
|
||||
history: createWebHistory(import.meta.env.BASE_URL),
|
||||
// legacy router.js:17-19
|
||||
scrollBehavior() {
|
||||
return { left: 0, top: 0 };
|
||||
},
|
||||
routes: [
|
||||
{ path: '/', name: 'dashboard', component: DashboardView },
|
||||
{ path: '/orders/new', name: 'order-new', component: OrderNewView },
|
||||
{ path: '/orders/:id', name: 'order-detail', component: OrderDetailView },
|
||||
// ── MAIN LAYOUT ROUTES ──────────────────────────────────────────
|
||||
{
|
||||
path: '',
|
||||
component: () => import('../layouts/main/Main.vue'),
|
||||
children: isBranch() ? branchRoute : adminRoute,
|
||||
},
|
||||
// ── FULL PAGE LAYOUTS ───────────────────────────────────────────
|
||||
{
|
||||
path: '',
|
||||
component: () => import('../layouts/full-page/FullPage.vue'),
|
||||
children: [
|
||||
...(isBranch() ? fullPageBranchRoute : fullPageAdminRoute),
|
||||
{
|
||||
path: '/pages/error-404',
|
||||
name: 'page-error-404',
|
||||
component: () => import('../views/pages/Error404.vue'),
|
||||
meta: { rule: 'editor' },
|
||||
},
|
||||
{
|
||||
path: '/pages/error-500',
|
||||
name: 'page-error-500',
|
||||
component: () => import('../views/pages/Error500.vue'),
|
||||
meta: { rule: 'editor' },
|
||||
},
|
||||
{
|
||||
path: '/pages/not-authorized',
|
||||
name: 'page-not-authorized',
|
||||
component: () => import('../views/pages/NotAuthorized.vue'),
|
||||
meta: { rule: 'editor' },
|
||||
},
|
||||
{
|
||||
path: '/pages/maintenance',
|
||||
name: 'page-maintenance',
|
||||
component: () => import('../views/pages/Maintenance.vue'),
|
||||
meta: { rule: 'editor' },
|
||||
},
|
||||
],
|
||||
},
|
||||
// Redirect to 404 page, if no match found
|
||||
{
|
||||
path: '/:pathMatch(.*)*',
|
||||
redirect: '/pages/error-404',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
// legacy router.js:147-153
|
||||
router.afterEach(() => {
|
||||
const appLoading = document.getElementById('loading-bg');
|
||||
if (appLoading) {
|
||||
appLoading.style.display = 'none';
|
||||
}
|
||||
});
|
||||
|
||||
// legacy router.js:156-161
|
||||
const noneAuthUrl = ['/auth/login', '/auth/forgot-password', '/auth/register', '/reg'];
|
||||
|
||||
/**
|
||||
* Port of legacy getPermission() (router.js:163-182).
|
||||
*
|
||||
* Legacy cached the result in a MODULE-SCOPED `let roles`, which was never reset
|
||||
* on logout — so the next user to sign in on the same tab inherited the previous
|
||||
* user's permissions (bug #2 in docs/ADMIN-PORT-PLAN.md). Here the cache is the
|
||||
* Pinia users store, which auth.logout() clears; `roles === undefined` still
|
||||
* means "not fetched", exactly as legacy's check did.
|
||||
*/
|
||||
async function getPermission(): Promise<string[] | undefined> {
|
||||
const users = useUsersStore();
|
||||
if (users.roles) return users.roles;
|
||||
|
||||
try {
|
||||
const { data } = await api.get('users/show');
|
||||
users.getRoles(data.permission);
|
||||
// Legacy stripped these before caching the user blob.
|
||||
delete data.permission;
|
||||
delete data.ut;
|
||||
if (data.api_token) {
|
||||
localStorage.setItem(tokenName, data.api_token);
|
||||
}
|
||||
localStorage.setItem(userName, JSON.stringify(data));
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
return users.roles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Port of legacy router.beforeEach (router.js:184-199).
|
||||
*
|
||||
* One deliberate change: legacy's final line was a bare
|
||||
* router.push({path: '/auth/login'})
|
||||
* with no next() call, which in Vue Router 4 leaves the navigation permanently
|
||||
* pending and hangs the app (bug #1). Returning the redirect is the Vue Router 4
|
||||
* equivalent and produces the same user-visible result.
|
||||
*/
|
||||
router.beforeEach(async (to) => {
|
||||
if (noneAuthUrl.indexOf(to.path) > -1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const token = localStorage.getItem(tokenName);
|
||||
if (token) {
|
||||
const roles = await getPermission();
|
||||
if (roles && to.meta && to.meta.role && !roles.includes(to.meta.role as string)) {
|
||||
return { name: 'page-not-authorized' };
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return { path: '/auth/login' };
|
||||
});
|
||||
|
||||
export default router;
|
||||
|
||||
Reference in New Issue
Block a user