mirror of
https://github.com/FJurmanovic/wallet-web.git
synced 2026-02-06 06:08:10 +00:00
added child routes and dynamic routes
This commit is contained in:
@@ -42,17 +42,28 @@ class AppMainElement extends BaseComponentElement {
|
|||||||
layout: "menu-layout",
|
layout: "menu-layout",
|
||||||
middleware: this.isAuth,
|
middleware: this.isAuth,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "/wallet",
|
||||||
|
component: "history-page",
|
||||||
|
layout: "menu-layout",
|
||||||
|
middleware: this.isAuth,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: "/:walletId",
|
||||||
|
component: "history-page",
|
||||||
|
layout: "menu-layout",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: "/register",
|
path: "/register",
|
||||||
component: "register-page",
|
component: "register-page",
|
||||||
layout: "menu-layout",
|
layout: "menu-layout",
|
||||||
middleware: this.isAuth,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/login",
|
path: "/login",
|
||||||
component: "login-page",
|
component: "login-page",
|
||||||
layout: "menu-layout",
|
layout: "menu-layout",
|
||||||
middleware: this.isAuth,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/unauthorized",
|
path: "/unauthorized",
|
||||||
@@ -64,6 +75,11 @@ class AppMainElement extends BaseComponentElement {
|
|||||||
component: "login-page",
|
component: "login-page",
|
||||||
layout: "menu-layout",
|
layout: "menu-layout",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "/not-found",
|
||||||
|
component: "not-found",
|
||||||
|
layout: "menu-layout",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: "/logout",
|
path: "/logout",
|
||||||
component: "logout-page",
|
component: "logout-page",
|
||||||
@@ -81,6 +97,7 @@ class AppMainElement extends BaseComponentElement {
|
|||||||
|
|
||||||
createModal = (element: string) => {
|
createModal = (element: string) => {
|
||||||
this.closeModal();
|
this.closeModal();
|
||||||
|
this.appMain.addEventListener("routechanged", this.closeModal);
|
||||||
|
|
||||||
const _appModal = this.createAppModal();
|
const _appModal = this.createAppModal();
|
||||||
const _modalContent = this.createModalContent(element);
|
const _modalContent = this.createModalContent(element);
|
||||||
@@ -131,6 +148,7 @@ class AppMainElement extends BaseComponentElement {
|
|||||||
|
|
||||||
closeModal = () => {
|
closeModal = () => {
|
||||||
if (this.appModal) this.removeChild(this.appModal);
|
if (this.appModal) this.removeChild(this.appModal);
|
||||||
|
this.appMain.removeEventListener("routechanged", this.closeModal);
|
||||||
};
|
};
|
||||||
|
|
||||||
isAuth = (): boolean => {
|
isAuth = (): boolean => {
|
||||||
|
|||||||
@@ -32,14 +32,27 @@ class RouterService {
|
|||||||
public setRoutes = (routes: Array<any>): void => {
|
public setRoutes = (routes: Array<any>): void => {
|
||||||
if (!Array.isArray(this._routes)) this._routes = [];
|
if (!Array.isArray(this._routes)) this._routes = [];
|
||||||
routes.forEach((route) => {
|
routes.forEach((route) => {
|
||||||
const { path, component, data, layout, middleware } = route;
|
const { path, component, data, layout, middleware, children } =
|
||||||
|
route;
|
||||||
|
const _pathArr = path?.split?.("/").filter((a) => a);
|
||||||
|
let newPath = ["", ..._pathArr].join("/");
|
||||||
|
if (newPath == "") newPath = "/";
|
||||||
const _routeState: RouteState = new RouteState(
|
const _routeState: RouteState = new RouteState(
|
||||||
path,
|
newPath,
|
||||||
component,
|
component,
|
||||||
data,
|
data,
|
||||||
layout,
|
layout,
|
||||||
middleware
|
middleware
|
||||||
);
|
);
|
||||||
|
if (Array.isArray(children) && children?.length > 0) {
|
||||||
|
children.forEach((child) => {
|
||||||
|
const _childState: RouteState = this.createChildState(
|
||||||
|
child,
|
||||||
|
route
|
||||||
|
);
|
||||||
|
this._routes?.push(_childState);
|
||||||
|
});
|
||||||
|
}
|
||||||
this._routes?.push(_routeState);
|
this._routes?.push(_routeState);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -47,9 +60,24 @@ class RouterService {
|
|||||||
public update = (): void => {
|
public update = (): void => {
|
||||||
if (!this._routes) return;
|
if (!this._routes) return;
|
||||||
const path = window.location.pathname;
|
const path = window.location.pathname;
|
||||||
|
const [hasDynamic, _dynamicIndex] = this.hasDynamicPath(path);
|
||||||
const _mainRoot = this.mainRoot;
|
const _mainRoot = this.mainRoot;
|
||||||
const route = this.routerState;
|
let route: RouteState = this.routerState;
|
||||||
if (path == route?.path || route?.path == "/not-found") {
|
if (route?.middleware) {
|
||||||
|
if (
|
||||||
|
!(
|
||||||
|
typeof route?.middleware == "function" && route.middleware()
|
||||||
|
) ||
|
||||||
|
route.middleware === false
|
||||||
|
) {
|
||||||
|
return this.goTo("/unauthorized");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
path == route?.path ||
|
||||||
|
route?.path == "/not-found" ||
|
||||||
|
(hasDynamic && this?._routes?.[_dynamicIndex]?.path == route?.path)
|
||||||
|
) {
|
||||||
let changed: boolean = false;
|
let changed: boolean = false;
|
||||||
if (_mainRoot?.childNodes.length > 0) {
|
if (_mainRoot?.childNodes.length > 0) {
|
||||||
_mainRoot?.childNodes?.forEach?.((child: BaseLayoutElement) => {
|
_mainRoot?.childNodes?.forEach?.((child: BaseLayoutElement) => {
|
||||||
@@ -114,26 +142,53 @@ class RouterService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const newRoute = this.findByPath();
|
const [isDynamic, _dynamicIndex, dynamicProps] =
|
||||||
|
this.hasDynamicPath(path);
|
||||||
|
let newRoute: RouteState;
|
||||||
|
if (isDynamic && _dynamicIndex !== -1) {
|
||||||
|
newRoute = this._routes[_dynamicIndex];
|
||||||
|
newRoute.data = dynamicProps;
|
||||||
|
} else {
|
||||||
|
newRoute = this.findByPath();
|
||||||
|
}
|
||||||
this.historyStack.push(newRoute);
|
this.historyStack.push(newRoute);
|
||||||
this.update();
|
this.update();
|
||||||
}
|
}
|
||||||
this.appMain.dispatchEvent(this.domEvents.routechanged);
|
this.appMain.dispatchEvent(this.domEvents.routechanged);
|
||||||
};
|
};
|
||||||
|
|
||||||
public goTo = (path: string): void => {
|
public goTo = (path: string, data?: any): void => {
|
||||||
if (!Array.isArray(this.historyStack)) this.historyStack = [];
|
if (!Array.isArray(this.historyStack)) this.historyStack = [];
|
||||||
const currentPath = window.location.pathname;
|
const currentPath = window.location.pathname;
|
||||||
if (path == currentPath) return;
|
if (path == currentPath) return;
|
||||||
const _index = this._routes.findIndex((route) => route.path === path);
|
const _index = this._routes.findIndex((route) => route.path === path);
|
||||||
if (_index >= 0) {
|
const _indexOfEmpty = this._routes.findIndex(
|
||||||
const newRoute = this._routes[_index];
|
(route) => route.path === "/not-found"
|
||||||
this.historyStack.push(newRoute);
|
);
|
||||||
const url = new URL(window.location.toString());
|
const [isDynamic, _dynamicIndex, dynamicProps] =
|
||||||
url.pathname = path;
|
this.hasDynamicPath(path);
|
||||||
window.history.pushState({}, "", url.toString());
|
if (isDynamic) {
|
||||||
this.update();
|
const [isCurrentDynamic, currIndex] =
|
||||||
|
this.hasDynamicPath(currentPath);
|
||||||
|
if (isCurrentDynamic && currIndex === _dynamicIndex) return;
|
||||||
}
|
}
|
||||||
|
let newRoute: RouteState;
|
||||||
|
if (isDynamic && _dynamicIndex !== -1) {
|
||||||
|
newRoute = this._routes[_dynamicIndex];
|
||||||
|
newRoute.data = dynamicProps;
|
||||||
|
} else if (_index === -1 && _indexOfEmpty !== -1) {
|
||||||
|
newRoute = this._routes[_indexOfEmpty];
|
||||||
|
} else if (_index === -1 && _indexOfEmpty === -1) {
|
||||||
|
newRoute = new RouteState("/not-found", "not-found");
|
||||||
|
} else {
|
||||||
|
newRoute = this._routes[_index];
|
||||||
|
}
|
||||||
|
|
||||||
|
this.historyStack.push(newRoute);
|
||||||
|
const url = new URL(window.location.toString());
|
||||||
|
url.pathname = path;
|
||||||
|
window.history.pushState({}, "", url.toString());
|
||||||
|
this.update();
|
||||||
};
|
};
|
||||||
|
|
||||||
public goBack = (): void => {
|
public goBack = (): void => {
|
||||||
@@ -177,6 +232,59 @@ class RouterService {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private createChildState = (child: any, parent: any): RouteState => {
|
||||||
|
const { path, middleware, layout, component, data, children } = child;
|
||||||
|
const _pathArr = path?.split?.("/").filter((a) => a);
|
||||||
|
const _parentArr = parent?.path?.split?.("/").filter((a) => a);
|
||||||
|
const newPath = ["", ..._parentArr, ..._pathArr].join("/");
|
||||||
|
const _child = new RouteState(
|
||||||
|
newPath,
|
||||||
|
component,
|
||||||
|
data,
|
||||||
|
layout,
|
||||||
|
middleware ? middleware : parent?.middleware
|
||||||
|
);
|
||||||
|
|
||||||
|
if (Array.isArray(children) && children?.length > 0) {
|
||||||
|
children.forEach((child2) => {
|
||||||
|
const _childState: RouteState = this.createChildState(
|
||||||
|
child2,
|
||||||
|
_child
|
||||||
|
);
|
||||||
|
this._routes?.push(_childState);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return _child;
|
||||||
|
};
|
||||||
|
|
||||||
|
private hasDynamicPath = (path: string): [boolean, number, any] => {
|
||||||
|
const _pathArr = path.split("/").filter((a) => a);
|
||||||
|
let matchedIndex: number = 0;
|
||||||
|
let matched: boolean = false;
|
||||||
|
let dynamicProps: any = {};
|
||||||
|
this._routes.forEach((route, _routeId) => {
|
||||||
|
const _routeArr = route.path.split("/").filter((a) => a);
|
||||||
|
if (_pathArr.length === _routeArr.length) {
|
||||||
|
let pathMatches: number = 0;
|
||||||
|
let hasDynamic: boolean = false;
|
||||||
|
_pathArr.forEach((pathr, i) => {
|
||||||
|
if (pathr == _routeArr[i]) {
|
||||||
|
pathMatches++;
|
||||||
|
} else if (_routeArr[i].startsWith?.(":")) {
|
||||||
|
pathMatches++;
|
||||||
|
hasDynamic = true;
|
||||||
|
dynamicProps[_routeArr[i].substr(1)] = pathr;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (pathMatches === _pathArr.length && hasDynamic) {
|
||||||
|
matchedIndex = _routeId;
|
||||||
|
matched = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return [matched, matchedIndex, dynamicProps];
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
class RouteState {
|
class RouteState {
|
||||||
@@ -189,4 +297,9 @@ class RouteState {
|
|||||||
) {}
|
) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type DynamicProp = {
|
||||||
|
index: string;
|
||||||
|
path: string;
|
||||||
|
};
|
||||||
|
|
||||||
export default RouterService;
|
export default RouterService;
|
||||||
|
|||||||
Reference in New Issue
Block a user