fixed architecture to dispatch events when routes and token changes

This commit is contained in:
Fran Jurmanović
2021-05-31 12:00:07 +02:00
parent 48df6fc7cf
commit e1ab0e51d6
10 changed files with 131 additions and 29 deletions

View File

@@ -3,6 +3,7 @@ import { target } from "@github/catalyst";
class BaseLayoutElement extends HTMLElement { class BaseLayoutElement extends HTMLElement {
@target slotted: HTMLElement; @target slotted: HTMLElement;
public isLayout: boolean = true; public isLayout: boolean = true;
public _slotted: string;
constructor() { constructor() {
super(); super();
} }
@@ -19,7 +20,9 @@ class BaseLayoutElement extends HTMLElement {
}; };
setElement = (newTag: string) => { setElement = (newTag: string) => {
this.slotted.innerHTML = `<${newTag}></${newTag}>`; const _slotted = `<${newTag}></${newTag}>`;
this._slotted = _slotted;
this.slotted.innerHTML = _slotted;
}; };
} }

View File

@@ -21,13 +21,15 @@ class AppLinkElement extends HTMLElement {
this.routerService = this.appMain?.routerService; this.routerService = this.appMain?.routerService;
this.update(); this.update();
if (isTrue(this.goBack)) { if (isTrue(this.goBack)) {
window.addEventListener("routechanged", () => { window.addEventListener("routechanged", this.update);
this.update();
});
} }
} }
public disconnectedCallback(): void {} public disconnectedCallback(): void {
if (isTrue(this.goBack)) {
window.removeEventListener("routechanged", this.update);
}
}
goTo = () => { goTo = () => {
if (!isTrue(this.goBack) && this.to) { if (!isTrue(this.goBack) && this.to) {
@@ -55,7 +57,7 @@ class AppLinkElement extends HTMLElement {
>`}`; >`}`;
} }
update() { update = () => {
render(this.render(), this); render(this.render(), this);
} };
} }

View File

@@ -27,11 +27,12 @@ class AppMainElement extends HTMLElement {
path: "/", path: "/",
component: "home-page", component: "home-page",
layout: "menu-layout", layout: "menu-layout",
middleware: this.middleAuth,
}, },
{ {
path: "/home", path: "/home",
component: "home-page", component: "home-page",
layout: "menu-layout",
middleware: this.middleAuth,
}, },
{ {
path: "/register", path: "/register",
@@ -46,10 +47,16 @@ class AppMainElement extends HTMLElement {
{ {
path: "/unauthorized", path: "/unauthorized",
component: "login-page", component: "login-page",
layout: "menu-layout",
}, },
{ {
path: "token-expired", path: "/token-expired",
component: "login-page", component: "login-page",
layout: "menu-layout",
},
{
path: "/logout",
component: "logout-page",
}, },
]); ]);
this.routerService.init(); this.routerService.init();

View File

@@ -43,7 +43,6 @@ class RouterService {
update() { update() {
if (!this._routes) return; if (!this._routes) return;
window.dispatchEvent(this.domEvents.routechanged);
const path = window.location.pathname; const path = window.location.pathname;
const _mainRoot = this.mainRoot; const _mainRoot = this.mainRoot;
const route = this.routerState; const route = this.routerState;
@@ -98,12 +97,12 @@ class RouterService {
_mainRoot.appendChild(_newElement); _mainRoot.appendChild(_newElement);
} }
} }
return;
} else { } else {
const newRoute = this.findByPath(); const newRoute = this.findByPath();
this.historyStack.push(newRoute); this.historyStack.push(newRoute);
this.update(); this.update();
} }
window.dispatchEvent(this.domEvents.routechanged);
} }
goTo(path: string) { goTo(path: string) {

View File

@@ -5,6 +5,9 @@ class AuthStore {
private _token; private _token;
private _userDetails; private _userDetails;
private authService: AuthService; private authService: AuthService;
private domEvents: any = {
tokenchange: new Event("tokenchange"),
};
constructor(private appService: AppService) { constructor(private appService: AppService) {
this.token = localStorage.getItem("token"); this.token = localStorage.getItem("token");
this.authService = new AuthService(this.appService); this.authService = new AuthService(this.appService);
@@ -19,6 +22,7 @@ class AuthStore {
set token(token) { set token(token) {
this._token = token; this._token = token;
localStorage.setItem("token", token); localStorage.setItem("token", token);
window.dispatchEvent(this.domEvents.tokenchange);
} }
get user() { get user() {
@@ -52,6 +56,11 @@ class AuthStore {
throw err; throw err;
} }
}; };
userLogout = () => {
this.token = null;
localStorage.removeItem("token");
};
} }
export default AuthStore; export default AuthStore;

View File

@@ -1,30 +1,51 @@
import { attr, targets, controller, target } from "@github/catalyst"; import { controller } from "@github/catalyst";
import { closest, index, update, isTrue } from "core/utils"; import { closest } from "core/utils";
import { html, render, until } from "@github/jtml"; import { html, render } from "@github/jtml";
import { PingService } from "services/";
import { BaseLayoutElement } from "common/layouts"; import { BaseLayoutElement } from "common/layouts";
import { AppMainElement } from "components/";
@controller @controller
class MenuLayoutElement extends BaseLayoutElement { class MenuLayoutElement extends BaseLayoutElement {
@closest appMain; @closest appMain: AppMainElement;
constructor() { constructor() {
super(); super();
} }
@update connectedCallback() {
connectedCallback() {} this.update();
window.addEventListener("tokenchange", this.updateAuth);
}
disconnectedCallback(): void {
window.removeEventListener("tokenchange", this.updateAuth);
}
get isAuth() {
const _hasToken = this.appMain?.isAuth;
const _hasData = this.appMain?.authStore?.user;
return _hasData && _hasToken;
}
updateAuth = () => {
this.update();
};
render() { render() {
return html` return html`
<div> ${this.isAuth &&
html`<div>
<app-link data-go-back="true" data-title="Go back"></app-link> <app-link data-go-back="true" data-title="Go back"></app-link>
</div> </div>`}
<div data-target="menu-layout.slotted"></div> <div data-target="menu-layout.slotted"></div>
`; `;
} }
update() { update = () => {
render(this.render(), this); render(this.render(), this);
const _slotted = this._slotted;
if (_slotted && this.slotted) {
this.slotted.innerHTML = _slotted;
} }
};
} }

View File

@@ -11,10 +11,16 @@ class HomePageElement extends HTMLElement {
constructor() { constructor() {
super(); super();
} }
@update
connectedCallback() { connectedCallback() {
this.pingService = new PingService(this.appMain?.appService); this.pingService = new PingService(this.appMain?.appService);
if (this.appMain.isAuth) this.getPong(); if (this.appMain.isAuth) this.getPong();
this.update();
window.addEventListener("tokenchange", this.update);
}
disconnectedCallback(): void {
window.removeEventListener("tokenchange", this.update);
} }
getPong = async () => { getPong = async () => {
@@ -31,13 +37,21 @@ class HomePageElement extends HTMLElement {
render() { render() {
return html` return html`
<app-link data-to="/home" data-title="Home"></app-link> |
<app-link data-to="/" data-title="Main"></app-link> | <app-link data-to="/" data-title="Main"></app-link> |
<app-link data-to="/login" data-title="Login"></app-link> ${this.appMain.isAuth
? html`<app-link data-to="/home" data-title="Home"></app-link>
|<app-link
data-to="/logout"
data-title="Logout"
></app-link>`
: html`<app-link
data-to="/login"
data-title="Login"
></app-link>`}
`; `;
} }
update() { update = () => {
render(this.render(), this); render(this.render(), this);
} };
} }

View File

@@ -1,3 +1,4 @@
export * from "./logout-page/LogoutPageElement";
export * from "./home-page/HomePageElement"; export * from "./home-page/HomePageElement";
export * from "./register-page/RegisterPageElement"; export * from "./register-page/RegisterPageElement";
export * from "./login-page/LoginPageElement"; export * from "./login-page/LoginPageElement";

View File

@@ -3,18 +3,37 @@ import { closest, index, update, isTrue } from "core/utils";
import { html, render, until } from "@github/jtml"; import { html, render, until } from "@github/jtml";
import { AuthService, PingService } from "services/"; import { AuthService, PingService } from "services/";
import { AppMainElement, InputFieldElement } from "components/"; import { AppMainElement, InputFieldElement } from "components/";
import { RouterService } from "core/services";
@controller @controller
class LoginPageElement extends HTMLElement { class LoginPageElement extends HTMLElement {
@targets inputs: Array<InputFieldElement>; @targets inputs: Array<InputFieldElement>;
@closest appMain: AppMainElement; @closest appMain: AppMainElement;
authService: AuthService; authService: AuthService;
routerService: RouterService;
constructor() { constructor() {
super(); super();
} }
@update @update
connectedCallback() { connectedCallback() {
this.authService = new AuthService(this.appMain.appService); this.authService = new AuthService(this.appMain.appService);
this.routerService = this.appMain.routerService;
}
get emailInput() {
for (const i in this.inputs) {
if (this.inputs[i]?.name == "email") {
return this.inputs[i];
}
}
}
get passwordInput() {
for (const i in this.inputs) {
if (this.inputs[i]?.name == "password") {
return this.inputs[i];
}
}
} }
get values(): Object { get values(): Object {
@@ -36,9 +55,18 @@ class LoginPageElement extends HTMLElement {
); );
if (response?.token) { if (response?.token) {
this.appMain.routerService.goTo("/"); console.log(this.appMain);
this.routerService.goTo("/");
}
} catch (err) {
if (err?.errorCode == 400103) {
this.emailInput.error = err?.message;
this.emailInput.update();
} else if (err?.errorCode == 400104) {
this.passwordInput.error = err?.message;
this.passwordInput.update();
}
} }
} catch (err) {}
}; };
validate(): boolean { validate(): boolean {

View File

@@ -0,0 +1,18 @@
import { controller } from "@github/catalyst";
import { closest, update } from "core/utils";
import { AuthService } from "services/";
import { AppMainElement } from "components/";
@controller
class LogoutPageElement extends HTMLElement {
@closest appMain: AppMainElement;
authService: AuthService;
constructor() {
super();
}
connectedCallback() {
this.authService = new AuthService(this.appMain.appService);
this.appMain?.authStore?.userLogout();
this.appMain?.routerService.goTo("/login");
}
}