mirror of
https://github.com/FJurmanovic/wallet-web.git
synced 2026-02-06 06:08:10 +00:00
Merge branch 'feature/WW-5-login-page'
This commit is contained in:
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
export default function isTrue(bool: string) {
|
export default function isTrue(text: string) {
|
||||||
return bool === "true";
|
return text === "true";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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";
|
||||||
|
|||||||
87
src/pages/login-page/LoginPageElement.ts
Normal file
87
src/pages/login-page/LoginPageElement.ts
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
25
src/pages/not-found/NotFoundElement.ts
Normal file
25
src/pages/not-found/NotFoundElement.ts
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user