Add tsx syntax to Login.
This commit is contained in:
parent
5b52fd34d6
commit
9648d6027f
|
@ -1,100 +0,0 @@
|
||||||
import { addClipboardNotifications } from "../pageUtils";
|
|
||||||
import { makeElement } from "z-makeelement";
|
|
||||||
import ClipboardJS from "clipboard";
|
|
||||||
import FileSaver from "file-saver";
|
|
||||||
import UIkit from "uikit";
|
|
||||||
import i18next from "i18next";
|
|
||||||
|
|
||||||
type FileSaverType = {
|
|
||||||
saveAs: (blob: Blob, name: string) => void;
|
|
||||||
};
|
|
||||||
|
|
||||||
type ModalType = HTMLElement & {
|
|
||||||
show: () => void;
|
|
||||||
};
|
|
||||||
|
|
||||||
export function CopyableModal(name: string, contentString: string): ModalType {
|
|
||||||
const modal = makeElement({
|
|
||||||
tag: "div",
|
|
||||||
class: "modal-sections",
|
|
||||||
attributes: {
|
|
||||||
"uk-modal": "",
|
|
||||||
},
|
|
||||||
children: makeElement({
|
|
||||||
tag: "div",
|
|
||||||
class: "uk-modal-dialog",
|
|
||||||
children: [
|
|
||||||
makeElement({
|
|
||||||
tag: "button",
|
|
||||||
class: "uk-modal-close-default",
|
|
||||||
attributes: {
|
|
||||||
"uk-close": "",
|
|
||||||
type: "button",
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
makeElement({
|
|
||||||
tag: "div",
|
|
||||||
class: "uk-modal-header",
|
|
||||||
children: makeElement({
|
|
||||||
tag: "h2",
|
|
||||||
class: "uk-modal-title",
|
|
||||||
text: name,
|
|
||||||
}),
|
|
||||||
}),
|
|
||||||
makeElement({
|
|
||||||
tag: "div",
|
|
||||||
class: ["uk-modal-body"],
|
|
||||||
children: makeElement({
|
|
||||||
tag: "pre",
|
|
||||||
class: "wrap-pre",
|
|
||||||
text: contentString,
|
|
||||||
}),
|
|
||||||
}),
|
|
||||||
makeElement({
|
|
||||||
tag: "div",
|
|
||||||
class: ["uk-modal-footer", "uk-text-right"],
|
|
||||||
children: [
|
|
||||||
makeElement({
|
|
||||||
tag: "button",
|
|
||||||
class: ["uk-button", "uk-button-primary"],
|
|
||||||
attributes: {
|
|
||||||
type: "button",
|
|
||||||
"data-clipboard-text": contentString,
|
|
||||||
},
|
|
||||||
text: i18next.t("copy_modal_download_btn"),
|
|
||||||
onclick: () => {
|
|
||||||
const blob = new Blob([contentString], {
|
|
||||||
type: "text/plain;charset=utf-8",
|
|
||||||
});
|
|
||||||
(FileSaver as FileSaverType).saveAs(blob, "result.txt");
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
makeElement({
|
|
||||||
tag: "button",
|
|
||||||
class: ["uk-button", "uk-button-primary"],
|
|
||||||
attributes: {
|
|
||||||
type: "button",
|
|
||||||
"data-clipboard-text": contentString,
|
|
||||||
},
|
|
||||||
text: i18next.t("copy_modal_copy_btn"),
|
|
||||||
thenRun: (e) => {
|
|
||||||
const clipboard = new ClipboardJS(e);
|
|
||||||
addClipboardNotifications(clipboard);
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
makeElement({
|
|
||||||
tag: "button",
|
|
||||||
class: ["uk-button", "uk-button-secondary", "uk-modal-close"],
|
|
||||||
attributes: { type: "button" },
|
|
||||||
text: i18next.t("copy_modal_close_btn"),
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
}),
|
|
||||||
}) as ModalType;
|
|
||||||
modal.show = () => {
|
|
||||||
UIkit.modal(modal).show();
|
|
||||||
};
|
|
||||||
return modal;
|
|
||||||
}
|
|
|
@ -1,38 +0,0 @@
|
||||||
import { makeElement } from "z-makeelement";
|
|
||||||
import i18next from "i18next";
|
|
||||||
|
|
||||||
export function FileUploadInput(name: string): Element {
|
|
||||||
const fileInput = makeElement({
|
|
||||||
tag: "input",
|
|
||||||
attributes: {
|
|
||||||
name: name,
|
|
||||||
type: "file",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const selectInput = makeElement({
|
|
||||||
tag: "input",
|
|
||||||
class: ["uk-input", "uk-form-width-medium"],
|
|
||||||
attributes: {
|
|
||||||
type: "text",
|
|
||||||
placeholder: i18next.t("file_upload_input_btn"),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const fileIcon = makeElement({
|
|
||||||
tag: "a",
|
|
||||||
class: "uk-form-icon",
|
|
||||||
attributes: {
|
|
||||||
"uk-icon": "icon: upload",
|
|
||||||
role: "img",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
return makeElement({
|
|
||||||
tag: "div",
|
|
||||||
attributes: {
|
|
||||||
"uk-form-custom": "target: true",
|
|
||||||
},
|
|
||||||
children: [fileIcon, fileInput, selectInput],
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -1,172 +0,0 @@
|
||||||
import { Form } from "../elements/Form";
|
|
||||||
import { Margin } from "../elements/Margin";
|
|
||||||
import { MarginInline } from "../elements/MarginInline";
|
|
||||||
import { Page } from "../types/Page";
|
|
||||||
import { lookupSelf } from "../api/sys/lookupSelf";
|
|
||||||
import { makeElement } from "z-makeelement";
|
|
||||||
import { setErrorText } from "../pageUtils";
|
|
||||||
import { usernameLogin } from "../api/auth/usernameLogin";
|
|
||||||
import i18next from "i18next";
|
|
||||||
|
|
||||||
export class LoginPage extends Page {
|
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
async render(): Promise<void> {
|
|
||||||
const tokenLoginForm = Form(
|
|
||||||
[
|
|
||||||
Margin(
|
|
||||||
makeElement({
|
|
||||||
tag: "input",
|
|
||||||
class: ["uk-input", "uk-form-width-medium"],
|
|
||||||
attributes: {
|
|
||||||
required: "true",
|
|
||||||
type: "password",
|
|
||||||
placeholder: i18next.t("token_input"),
|
|
||||||
name: "token",
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
MarginInline(
|
|
||||||
makeElement({
|
|
||||||
tag: "button",
|
|
||||||
class: ["uk-button", "uk-button-primary"],
|
|
||||||
text: i18next.t("log_in_btn"),
|
|
||||||
attributes: {
|
|
||||||
type: "submit",
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
async (form: HTMLFormElement) => {
|
|
||||||
const formData = new FormData(form);
|
|
||||||
const token = formData.get("token");
|
|
||||||
this.state.token = token as string;
|
|
||||||
|
|
||||||
try {
|
|
||||||
await lookupSelf();
|
|
||||||
await this.router.changePage("HOME");
|
|
||||||
} catch (e: unknown) {
|
|
||||||
const error = e as Error;
|
|
||||||
document.getElementById("tokenInput").classList.add("uk-form-danger");
|
|
||||||
if (error.message == "permission denied") {
|
|
||||||
setErrorText(i18next.t("token_login_error"));
|
|
||||||
} else {
|
|
||||||
setErrorText(error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
const usernameLoginForm = Form(
|
|
||||||
[
|
|
||||||
Margin(
|
|
||||||
makeElement({
|
|
||||||
tag: "input",
|
|
||||||
id: "usernameInput",
|
|
||||||
class: ["uk-input", "uk-form-width-medium"],
|
|
||||||
attributes: {
|
|
||||||
required: "true",
|
|
||||||
type: "text",
|
|
||||||
placeholder: i18next.t("username_input"),
|
|
||||||
name: "username",
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
Margin(
|
|
||||||
makeElement({
|
|
||||||
tag: "input",
|
|
||||||
id: "passwordInput",
|
|
||||||
class: ["uk-input", "uk-form-width-medium"],
|
|
||||||
attributes: {
|
|
||||||
required: "true",
|
|
||||||
type: "password",
|
|
||||||
placeholder: i18next.t("password_input"),
|
|
||||||
name: "password",
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
MarginInline(
|
|
||||||
makeElement({
|
|
||||||
tag: "button",
|
|
||||||
class: ["uk-button", "uk-button-primary"],
|
|
||||||
text: i18next.t("log_in_btn"),
|
|
||||||
attributes: {
|
|
||||||
type: "submit",
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
async (form: HTMLFormElement) => {
|
|
||||||
const formData = new FormData(form);
|
|
||||||
|
|
||||||
try {
|
|
||||||
const res = await usernameLogin(
|
|
||||||
formData.get("username") as string,
|
|
||||||
formData.get("password") as string,
|
|
||||||
);
|
|
||||||
this.state.token = res;
|
|
||||||
await this.router.changePage("HOME");
|
|
||||||
} catch (e: unknown) {
|
|
||||||
const error = e as Error;
|
|
||||||
document.getElementById("usernameInput").classList.add("uk-form-danger");
|
|
||||||
document.getElementById("passwordInput").classList.add("uk-form-danger");
|
|
||||||
setErrorText(error.message);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
await this.router.setPageContent(
|
|
||||||
makeElement({
|
|
||||||
tag: "div",
|
|
||||||
children: [
|
|
||||||
makeElement({
|
|
||||||
tag: "ul",
|
|
||||||
class: ["uk-subnav", "uk-subnav-pill"],
|
|
||||||
attributes: { "uk-switcher": "" },
|
|
||||||
children: [
|
|
||||||
makeElement({
|
|
||||||
tag: "li",
|
|
||||||
id: "tokenInput",
|
|
||||||
children: makeElement({
|
|
||||||
tag: "a",
|
|
||||||
text: i18next.t("log_in_with_token"),
|
|
||||||
}),
|
|
||||||
}),
|
|
||||||
makeElement({
|
|
||||||
tag: "li",
|
|
||||||
children: makeElement({
|
|
||||||
tag: "a",
|
|
||||||
text: i18next.t("log_in_with_username"),
|
|
||||||
}),
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
}),
|
|
||||||
makeElement({
|
|
||||||
tag: "p",
|
|
||||||
id: "errorText",
|
|
||||||
class: "uk-text-danger",
|
|
||||||
}),
|
|
||||||
makeElement({
|
|
||||||
tag: "ul",
|
|
||||||
class: ["uk-switcher", "uk-margin"],
|
|
||||||
children: [
|
|
||||||
makeElement({
|
|
||||||
tag: "li",
|
|
||||||
children: tokenLoginForm,
|
|
||||||
}),
|
|
||||||
makeElement({
|
|
||||||
tag: "li",
|
|
||||||
children: usernameLoginForm,
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
get name(): string {
|
|
||||||
return i18next.t("log_in_title");
|
|
||||||
}
|
|
||||||
}
|
|
146
src/pages/Login.tsx
Normal file
146
src/pages/Login.tsx
Normal file
|
@ -0,0 +1,146 @@
|
||||||
|
import { Component, JSX, render } from "preact";
|
||||||
|
import { Form } from "../elements/ReactForm";
|
||||||
|
import { Margin } from "../elements/ReactMargin";
|
||||||
|
import { MarginInline } from "../elements/ReactMarginInline";
|
||||||
|
import { Page } from "../types/Page";
|
||||||
|
import { lookupSelf } from "../api/sys/lookupSelf";
|
||||||
|
import { setErrorText } from "../pageUtils";
|
||||||
|
import { usernameLogin } from "../api/auth/usernameLogin";
|
||||||
|
import i18next from "i18next";
|
||||||
|
|
||||||
|
export class TokenLoginForm extends Component<{ page: Page }, unknown> {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
render(): JSX.Element {
|
||||||
|
return (
|
||||||
|
<Form onSubmit={(data) => this.onSubmit(data)}>
|
||||||
|
<Margin>
|
||||||
|
<input
|
||||||
|
class="uk-input uk-form-width-medium"
|
||||||
|
id="tokenInput"
|
||||||
|
name="token"
|
||||||
|
type="password"
|
||||||
|
placeholder={i18next.t("token_input")}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</Margin>
|
||||||
|
<MarginInline>
|
||||||
|
<button class="uk-button uk-button-primary" type="submit">
|
||||||
|
{i18next.t("log_in_btn")}
|
||||||
|
</button>
|
||||||
|
</MarginInline>
|
||||||
|
</Form>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async onSubmit(data: FormData): Promise<void> {
|
||||||
|
const page = this.props.page;
|
||||||
|
const token = data.get("token");
|
||||||
|
page.state.token = token as string;
|
||||||
|
|
||||||
|
try {
|
||||||
|
await lookupSelf();
|
||||||
|
await page.router.changePage("HOME");
|
||||||
|
} catch (e: unknown) {
|
||||||
|
const error = e as Error;
|
||||||
|
document.getElementById("tokenInput").classList.add("uk-form-danger");
|
||||||
|
if (error.message == "permission denied") {
|
||||||
|
setErrorText(i18next.t("token_login_error"));
|
||||||
|
} else {
|
||||||
|
setErrorText(error.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class UsernameLoginForm extends Component<{ page: Page }, unknown> {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
render(): JSX.Element {
|
||||||
|
return (
|
||||||
|
<Form onSubmit={(data) => this.onSubmit(data)}>
|
||||||
|
<Margin>
|
||||||
|
<input
|
||||||
|
class="uk-input uk-form-width-medium"
|
||||||
|
id="usernameInput"
|
||||||
|
name="username"
|
||||||
|
type="text"
|
||||||
|
placeholder={i18next.t("username_input")}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</Margin>
|
||||||
|
<Margin>
|
||||||
|
<input
|
||||||
|
class="uk-input uk-form-width-medium"
|
||||||
|
id="passwordInput"
|
||||||
|
name="password"
|
||||||
|
type="password"
|
||||||
|
placeholder={i18next.t("password_input")}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</Margin>
|
||||||
|
<MarginInline>
|
||||||
|
<button class="uk-button uk-button-primary" type="submit">
|
||||||
|
{i18next.t("log_in_btn")}
|
||||||
|
</button>
|
||||||
|
</MarginInline>
|
||||||
|
</Form>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async onSubmit(data: FormData): Promise<void> {
|
||||||
|
const page = this.props.page;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const res = await usernameLogin(
|
||||||
|
data.get("username") as string,
|
||||||
|
data.get("password") as string,
|
||||||
|
);
|
||||||
|
page.state.token = res;
|
||||||
|
await page.router.changePage("HOME");
|
||||||
|
} catch (e: unknown) {
|
||||||
|
const error = e as Error;
|
||||||
|
document.getElementById("usernameInput").classList.add("uk-form-danger");
|
||||||
|
document.getElementById("passwordInput").classList.add("uk-form-danger");
|
||||||
|
setErrorText(error.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class LoginPage extends Page {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
async render(): Promise<void> {
|
||||||
|
render(
|
||||||
|
<div>
|
||||||
|
<ul class="uk-subnav uk-subnav-pill" uk-switcher=".switcher-container">
|
||||||
|
<li>
|
||||||
|
<a>{i18next.t("log_in_with_token")}</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a>{i18next.t("log_in_with_username")}</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<p id="errorText" class="uk-text-danger" />
|
||||||
|
<ul class="uk-switcher uk-margin switcher-container">
|
||||||
|
<li>
|
||||||
|
<TokenLoginForm page={this} />
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<UsernameLoginForm page={this} />
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>,
|
||||||
|
this.router.pageContentElement,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
get name(): string {
|
||||||
|
return i18next.t("log_in_title");
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue