created login page

This commit is contained in:
Fran Jurmanović
2021-05-30 13:29:30 +02:00
parent ffad98acd6
commit eb0cca567d
11 changed files with 230 additions and 66 deletions

View File

@@ -9,6 +9,7 @@ import { RouterService } from "core/services";
class AppLinkElement extends HTMLElement { class AppLinkElement extends HTMLElement {
@closest appMain: AppMainElement; @closest appMain: AppMainElement;
@attr to: string; @attr to: string;
@attr goBack: string;
@attr title: string; @attr title: string;
@target main: Element; @target main: Element;
routerService: RouterService; routerService: RouterService;
@@ -17,27 +18,44 @@ class AppLinkElement extends HTMLElement {
} }
public connectedCallback(): void { public connectedCallback(): void {
this.update();
this.routerService = this.appMain?.routerService; this.routerService = this.appMain?.routerService;
this.main.addEventListener("click", this.goTo); this.update();
if (isTrue(this.goBack)) {
window.addEventListener("routechanged", () => {
this.update();
});
}
} }
public disconnectedCallback(): void { public disconnectedCallback(): void {}
this.main.removeEventListener("click", this.goTo);
}
goTo = () => { goTo = () => {
if (!isTrue(this.goBack) && this.to) {
this.routerService.goTo(this.to); this.routerService.goTo(this.to);
} else {
this.routerService.goBack();
}
this.update();
}; };
update() { get disabled() {
render( return isTrue(this.goBack) && this.routerService.emptyState;
html`<span }
render() {
return html`${this.disabled
? html`<span data-target="app-link.main" style="color:grey"
>${this.title}</span
>`
: html`<span
data-target="app-link.main" data-target="app-link.main"
data-action="click:app-link#goTo"
style="text-decoration: underline; cursor: pointer;" style="text-decoration: underline; cursor: pointer;"
>${this.title}</span >${this.title}</span
>`, >`}`;
this }
);
update() {
render(this.render(), this);
} }
} }

View File

@@ -11,11 +11,13 @@ class AppMainElement extends HTMLElement {
public authStore: AuthStore; public authStore: AuthStore;
private httpClient: HttpClient; private httpClient: HttpClient;
public appService: AppService; public appService: AppService;
@closest appMain;
constructor() { constructor() {
super(); super();
} }
connectedCallback() { connectedCallback() {
if (this.appMain !== this) return;
this.httpClient = new HttpClient(); this.httpClient = new HttpClient();
this.appService = new AppService(this, this.httpClient); this.appService = new AppService(this, this.httpClient);
this.routerService = new RouterService(this); this.routerService = new RouterService(this);
@@ -32,16 +34,22 @@ class AppMainElement extends HTMLElement {
component: "home-page", component: "home-page",
}, },
{ {
path: "/rb", path: "/register",
component: "register-page", component: "register-page",
layout: "menu-layout",
},
{
path: "/login",
component: "login-page",
layout: "menu-layout",
}, },
{ {
path: "/unauthorized", path: "/unauthorized",
component: "register-page", component: "login-page",
}, },
{ {
path: "token-expired", path: "token-expired",
component: "register-page", component: "login-page",
}, },
]); ]);
this.routerService.init(); this.routerService.init();

View File

@@ -33,6 +33,10 @@ class InputFieldElement extends HTMLElement {
return !!this.error; return !!this.error;
} }
get required(): boolean {
return this.rules.includes("required");
}
@update @update
validate(): boolean { validate(): boolean {
let _return = true; let _return = true;
@@ -67,12 +71,14 @@ class InputFieldElement extends HTMLElement {
update() { update() {
render( render(
html`<span data-target="input-field.main"> html`<div data-target="input-field.main">
${this.label && ${this.label &&
html`<label for="${this.randId}">${this.label}</label>`} html`<label for="${this.randId}"
>${this.label}${this.required ? " (*)" : ""}</label
>`}
<input type="${this.type}" data-target="input-field.inp" /> <input type="${this.type}" data-target="input-field.inp" />
${this.error && html`<span>${this.error}</span>`} ${this.error && html`<span>${this.error}</span>`}
</span>`, </div>`,
this this
); );
} }

View File

@@ -46,7 +46,8 @@ class AuthStore {
userRegister = async (formObject) => { userRegister = async (formObject) => {
try { try {
await this.authService.register(formObject); const response = await this.authService.register(formObject);
return response;
} catch (err) { } catch (err) {
throw err; throw err;
} }

View File

@@ -1,3 +1,3 @@
export default function isTrue(bool: string) { export default function isTrue(text: string) {
return bool === "true"; return text === "true";
} }

View File

@@ -6,6 +6,8 @@ import { BaseLayoutElement } from "common/layouts";
@controller @controller
class MenuLayoutElement extends BaseLayoutElement { class MenuLayoutElement extends BaseLayoutElement {
@closest appMain;
constructor() { constructor() {
super(); super();
} }
@@ -13,13 +15,16 @@ class MenuLayoutElement extends BaseLayoutElement {
@update @update
connectedCallback() {} connectedCallback() {}
update() { render() {
render( return html`
html` <div>
<div>Menu</div> <app-link data-go-back="true" data-title="Go back"></app-link>
</div>
<div data-target="menu-layout.slotted"></div> <div data-target="menu-layout.slotted"></div>
`, `;
this }
);
update() {
render(this.render(), this);
} }
} }

View File

@@ -29,12 +29,15 @@ class HomePageElement extends HTMLElement {
return html`<div>${until(this.getPong())}</div>`; return html`<div>${until(this.getPong())}</div>`;
}; };
update() { render() {
render( return html`
html`<app-link data-to="/home" data-title="Home"></app-link> | <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="/rb" data-title="$1"></app-link>`, <app-link data-to="/login" data-title="Login"></app-link>
this `;
); }
update() {
render(this.render(), this);
} }
} }

View File

@@ -1,2 +1,4 @@
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 "./not-found/NotFoundElement";

View File

@@ -0,0 +1,87 @@
import { attr, targets, controller, target } from "@github/catalyst";
import { closest, index, update, isTrue } from "core/utils";
import { html, render, until } from "@github/jtml";
import { AuthService, PingService } from "services/";
import { AppMainElement, InputFieldElement } from "components/";
@controller
class LoginPageElement extends HTMLElement {
@targets inputs: Array<InputFieldElement>;
@closest appMain: AppMainElement;
authService: AuthService;
constructor() {
super();
}
@update
connectedCallback() {
this.authService = new AuthService(this.appMain.appService);
}
get values(): Object {
const formObject = {};
this.inputs.forEach((input: InputFieldElement) => {
const inputType = input.inp;
formObject[input.name] = (inputType as HTMLInputElement).value;
});
return formObject;
}
onSubmit = async () => {
try {
if (!this.validate()) {
return;
}
const response = await this.appMain.authStore.userLogin(
this.values
);
if (response?.token) {
this.appMain.routerService.goTo("/");
}
} catch (err) {}
};
validate(): boolean {
let _return = true;
this.inputs.forEach((input: InputFieldElement) => {
const valid: boolean = input.validate();
if (!valid) _return = false;
});
return _return;
}
render() {
return html`
<form>
<input-field
data-type="email"
data-name="email"
data-label="E-mail"
data-targets="login-page.inputs"
data-rules="required|isEmail"
></input-field>
<input-field
data-type="password"
data-name="password"
data-label="Password"
data-targets="login-page.inputs"
data-rules="required"
>
</input-field>
<button type="button" data-action="click:login-page#onSubmit">
Login
</button>
</form>
<div>
<app-link
data-to="/register"
data-title="Create new account"
></app-link>
</div>
`;
}
update() {
render(this.render(), this);
}
}

View File

@@ -0,0 +1,25 @@
import { controller } from "@github/catalyst";
import { closest, update } from "core/utils";
import { html, render } from "@github/jtml";
import { AppMainElement } from "components/";
@controller
class NotFoundElement extends HTMLElement {
@closest appMain: AppMainElement;
constructor() {
super();
}
@update
connectedCallback() {}
render() {
return html`
<div>404 - Page not found</div>
<div><app-link data-to="/" data-title="Homepage"></app-link></div>
`;
}
update() {
render(this.render(), this);
}
}

View File

@@ -31,12 +31,12 @@ class RegisterPageElement extends HTMLElement {
if (!this.validate()) { if (!this.validate()) {
return; return;
} }
const response = await this.appMain.authStore.userLogin( const response = await this.appMain.authStore.userRegister(
this.values this.values
); );
if (response?.token) { if (response?.id) {
this.appMain.routerService.goTo("/"); this.appMain.routerService.goTo("/login");
} }
} catch (err) {} } catch (err) {}
}; };
@@ -50,10 +50,16 @@ class RegisterPageElement extends HTMLElement {
return _return; return _return;
} }
update() { render() {
render( return html`
html`
<form> <form>
<input-field
data-type="text"
data-name="username"
data-label="Username"
data-targets="register-page.inputs"
data-rules="required"
></input-field>
<input-field <input-field
data-type="email" data-type="email"
data-name="email" data-name="email"
@@ -66,6 +72,7 @@ class RegisterPageElement extends HTMLElement {
data-name="password" data-name="password"
data-label="Password" data-label="Password"
data-targets="register-page.inputs" data-targets="register-page.inputs"
data-rules="required"
> >
</input-field> </input-field>
<button <button
@@ -75,8 +82,10 @@ class RegisterPageElement extends HTMLElement {
Register Register
</button> </button>
</form> </form>
`, `;
this }
);
update() {
render(this.render(), this);
} }
} }