feat(fe/loading): introduce loading layer

This commit is contained in:
hexxa 2022-01-22 11:46:16 +08:00 committed by Hexxa
parent f06c5f5a7d
commit 2904d03bdb
7 changed files with 82 additions and 44 deletions

View file

@ -70,6 +70,7 @@
.theme-default #layers {
height: 0;
z-index: 3;
}
.theme-default #panes .container {
@ -499,12 +500,28 @@
bottom: 0;
background-color: rgba(0, 0, 0, 0.5);
overflow: scroll;
z-index: 100;
}
.theme-default #login-layer {
z-index: 200;
}
.theme-default #loading-layer {
z-index: 201;
}
.theme-default #loading-container {
background-color: rgba(255, 255, 255, 1);
border-radius: 0.6rem;
padding: 0.5rem;
position: fixed;
right: 2rem;
bottom: 2rem;
height: 3rem;
z-index: 201;
}
.theme-default #settings-layer {
z-index: 100;
}

View file

@ -4,4 +4,5 @@ export const sharingCtrl = "sharingCtrl";
export const filesViewCtrl = "filesView";
export const ctrlHidden = "hidden";
export const ctrlOn = "on";
export const ctrlOff = "off";
export const ctrlOff = "off";
export const loadingCtrl = "loading";

View file

@ -17,6 +17,7 @@ import {
import { NewMockSettingsClient } from "../../client/settings_mock";
import { controlName as panelTabs } from "../root_frame";
import {
loadingCtrl,
sharingCtrl,
ctrlOn,
ctrlOff,
@ -131,6 +132,7 @@ describe("Login", () => {
[settingsTabsCtrl]: "preferencePane",
[sharingCtrl]: ctrlOff,
[filesViewCtrl]: "rows",
[loadingCtrl]: ctrlOff,
}),
options: Map<string, Set<string>>({
[panelTabs]: Set<string>([
@ -142,6 +144,7 @@ describe("Login", () => {
[settingsTabsCtrl]: Set<string>(["preferencePane", "managementPane"]),
[sharingCtrl]: Set<string>([ctrlOn, ctrlOff]),
[filesViewCtrl]: Set<string>(["rows", "table"]),
[loadingCtrl]: Set<string>([ctrlOn, ctrlOff]),
}),
},
});

View file

@ -14,6 +14,7 @@ import {
sharingCtrl,
ctrlOn,
ctrlOff,
loadingCtrl,
} from "../common/controls";
import { LoginProps } from "./pane_login";
import { AdminProps } from "./pane_admin";
@ -117,6 +118,7 @@ export function initState(): ICoreState {
[settingsTabsCtrl]: "preferencePane",
[sharingCtrl]: ctrlOff,
[filesViewCtrl]: "rows",
[loadingCtrl]: ctrlOff,
}),
options: Map<string, Set<string>>({
[panelTabs]: Set<string>([
@ -128,6 +130,7 @@ export function initState(): ICoreState {
[settingsTabsCtrl]: Set<string>(["preferencePane", "managementPane"]),
[sharingCtrl]: Set<string>([ctrlOn, ctrlOff]),
[filesViewCtrl]: Set<string>(["rows", "table"]),
[loadingCtrl]: Set<string>([ctrlOn, ctrlOff]),
}),
},
},

View file

@ -1,6 +1,8 @@
import * as React from "react";
import { List } from "immutable";
import { RiTimer2Line } from "@react-icons/all-files/ri/RiTimer2Line";
import { updater } from "./state_updater";
import { ICoreState, MsgProps, UIProps } from "./core_state";
import { AdminProps } from "./pane_admin";
@ -10,7 +12,7 @@ import { AuthPane, LoginProps } from "./pane_login";
import { FilesProps } from "./panel_files";
import { Flexbox } from "./layout/flexbox";
import { Container } from "./layout/container";
import { sharingCtrl, ctrlOn } from "../common/controls";
import { sharingCtrl, loadingCtrl, ctrlOn } from "../common/controls";
export interface Props {
filesInfo: FilesProps;
@ -40,9 +42,11 @@ export class Layers extends React.Component<Props, State, {}> {
? "hidden"
: "";
const showSettings =
this.props.ui.control.controls.get("settingsDialog") === "on"
this.props.ui.control.controls.get("settingsDialog") === ctrlOn
? ""
: "hidden";
const showLoading =
this.props.ui.control.controls.get(loadingCtrl) == ctrlOn ? "" : "hidden";
return (
<div id="layers">
@ -56,6 +60,12 @@ export class Layers extends React.Component<Props, State, {}> {
</div>
</div>
<div id="loading-layer" className={showLoading}>
<div id="loading-container">
<RiTimer2Line size="3rem" className="cyan1-font anm-rotate" />
</div>
</div>
<div id="settings-layer" className={`layer ${showSettings}`}>
<div id="root-container">
<Container>

View file

@ -7,6 +7,7 @@ import { updater } from "./state_updater";
import { alertMsg } from "../common/env";
import { Quota, Preferences } from "../client";
import { getErrMsg } from "../common/utils";
import { ctrlOn, ctrlOff, loadingCtrl } from "../common/controls";
export interface ExtInfo {
usedSpace: string;
@ -59,46 +60,47 @@ export class AuthPane extends React.Component<Props, State, {}> {
};
login = async () => {
return updater()
.login(
updater().setControlOption(loadingCtrl, ctrlOn);
this.props.update(updater().updateUI);
try {
const loginStatus = await updater().login(
this.state.user,
this.state.pwd,
this.props.login.captchaID,
this.state.captchaInput
)
.then((status: string): Promise<any> => {
this.setState({ captchaInput: "" });
if (status === "") {
const params = new URLSearchParams(
document.location.search.substring(1)
);
return updater().initAll(params);
} else {
throw status;
}
})
.then((status: string) => {
if (status !== "") {
throw status;
}
this.update(updater().updateAll);
})
.catch((status: Error) => {
alertMsg(getErrMsg(this.props.msg.pkg, "op.fail", status.toString()));
return updater().getCaptchaID();
});
);
if (loginStatus !== "") {
alertMsg(
getErrMsg(this.props.msg.pkg, "op.fail", loginStatus.toString())
);
return;
}
const params = new URLSearchParams(document.location.search.substring(1));
const initStatus = await updater().initAll(params);
if (initStatus !== "") {
alertMsg(
getErrMsg(this.props.msg.pkg, "op.fail", initStatus.toString())
);
}
this.setState({ user: "", pwd: "" });
} finally {
this.setState({ pwd: "", captchaInput: "" });
updater().setControlOption(loadingCtrl, ctrlOff);
await this.refreshCaptcha();
this.props.update(updater().updateAll);
}
};
refreshCaptcha = async () => {
return updater()
.getCaptchaID()
.then((status: string) => {
if (status !== "") {
alertMsg(getErrMsg(this.props.msg.pkg, "op.fail", status));
} else {
this.props.update(updater().updateLogin);
}
});
const status = await updater().getCaptchaID();
if (status !== "") {
alertMsg(getErrMsg(this.props.msg.pkg, "op.fail", status));
} else {
this.props.update(updater().updateLogin);
}
};
render() {

View file

@ -13,6 +13,7 @@ import { FilesClient } from "../client/files";
import { UsersClient } from "../client/users";
import { SettingsClient } from "../client/settings";
import { IUsersClient, IFilesClient, ISettingsClient } from "../client";
import { loadingCtrl, ctrlOn, ctrlOff } from "../common/controls";
export interface Props {}
export interface State extends ICoreState {}
@ -49,6 +50,9 @@ export class StateMgr extends React.Component<Props, State, {}> {
query: URLSearchParams
): Promise<void> => {
updater().init(state);
updater().setControlOption(loadingCtrl, ctrlOn);
this.update(updater().updateUI);
if (
this.usersClient == null ||
this.filesClient == null ||
@ -63,14 +67,12 @@ export class StateMgr extends React.Component<Props, State, {}> {
this.settingsClient
);
return updater()
.initAll(query)
.then((status: string) => {
if (status !== "") {
alertMsg(getErrMsg(state.msg.pkg, "op.fail", status));
}
this.update(updater().updateAll);
});
const status = await updater().initAll(query);
if (status !== "") {
alertMsg(getErrMsg(state.msg.pkg, "op.fail", status));
}
updater().setControlOption(loadingCtrl, ctrlOff);
this.update(updater().updateAll);
};
update = (update: (prevState: ICoreState) => ICoreState): void => {