fix(ui): fix layout of list & pane (#66)

* fix(ui): refine pane layout

* fix(test): add pane_admin component
This commit is contained in:
Hexxa 2021-07-25 03:19:57 -05:00 committed by GitHub
parent df46915147
commit 916ec7c2dc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 294 additions and 46 deletions

View file

@ -73,17 +73,6 @@ img {
max-width: 100%; max-width: 100%;
} }
p,
h1,
h2,
h3,
h4,
h5,
h6 {
text-align: left;
padding: 1rem 0;
}
table { table {
border-collapse: collapse; border-collapse: collapse;
border-spacing: 0; border-spacing: 0;

View file

@ -53,7 +53,7 @@
.container-center { .container-center {
margin: 2rem auto auto auto; margin: 2rem auto auto auto;
width: 96%; width: 96%;
max-width: 800px; max-width: 80rem;
z-index: 9; z-index: 9;
} }
@ -75,7 +75,7 @@
} }
#panes .container { #panes .container {
max-width: 960px; max-width: 80rem;
width: 96%; width: 96%;
background-color: white; background-color: white;
z-index: 101; z-index: 101;
@ -630,3 +630,7 @@ div.hr {
.breadcrumb { .breadcrumb {
font-size: 1.4rem; font-size: 1.4rem;
} }
.txt-cap {
text-transform: capitalize;
}

View file

@ -2,6 +2,13 @@ import axios, { AxiosRequestConfig } from "axios";
export const defaultTimeout = 10000; export const defaultTimeout = 10000;
export interface User {
ID: string;
Name: string;
Pwd: string;
Role: string;
}
export interface MetadataResp { export interface MetadataResp {
name: string; name: string;
size: number; size: number;

View file

@ -1,11 +1,11 @@
import { List, Set } from "immutable"; import { List, Set, Map } from "immutable";
import BgWorker from "../worker/upload.bg.worker"; import BgWorker from "../worker/upload.bg.worker";
import { FgWorker } from "../worker/upload.fgworker"; import { FgWorker } from "../worker/upload.fgworker";
import { Props as PanelProps } from "./root_frame"; import { Props as PanelProps } from "./root_frame";
import { Item } from "./browser"; import { Item } from "./browser";
import { UploadInfo } from "../client"; import { UploadInfo, User } from "../client";
import { Up, initUploadMgr, IWorker } from "../worker/upload_mgr"; import { Up, initUploadMgr, IWorker } from "../worker/upload_mgr";
export class BaseUpdater { export class BaseUpdater {
@ -66,6 +66,10 @@ export function initState(): ICoreState {
authed: false, authed: false,
}, },
}, },
admin: {
users: Map<string, User>(),
roles: Set<string>()
}
}, },
}; };
} }
@ -94,6 +98,10 @@ export function mockState(): ICoreState {
authed: false, authed: false,
}, },
}, },
admin: {
users: Map<string, User>(),
roles: Set<string>()
}
}, },
}; };
} }

View file

@ -0,0 +1,178 @@
import * as React from "react";
import { Map, Set } from "immutable";
import { ICoreState } from "./core_state";
import { IUsersClient, User} from "../client";
import { UsersClient } from "../client/users";
import { Updater as PanesUpdater } from "./panes";
import { updater as BrowserUpdater } from "./browser.updater";
import { Layouter } from "./layouter";
export interface Props {
users: Map<string, User>;
roles: Set<string>;
update?: (updater: (prevState: ICoreState) => ICoreState) => void;
}
export class Updater {
private static props: Props;
private static client: IUsersClient;
static init = (props: Props) => (Updater.props = { ...props });
static setClient = (client: IUsersClient): void => {
Updater.client = client;
};
// static adduser = async (user: User): Promise<boolean> => {
// const resp = await Updater.client.add
// }
// static login = async (user: string, pwd: string): Promise<boolean> => {
// const resp = await Updater.client.login(user, pwd);
// Updater.setAuthed(resp.status === 200);
// return resp.status === 200;
// };
// static logout = async (): Promise<boolean> => {
// const resp = await Updater.client.logout();
// Updater.setAuthed(false);
// return resp.status === 200;
// };
// static isAuthed = async (): Promise<boolean> => {
// const resp = await Updater.client.isAuthed();
// return resp.status === 200;
// };
// static initIsAuthed = async (): Promise<void> => {
// return Updater.isAuthed().then((isAuthed) => {
// Updater.setAuthed(isAuthed);
// });
// };
static setState = (preState: ICoreState): ICoreState => {
preState.panel.authPane = {
...preState.panel.authPane,
...Updater.props,
};
return preState;
};
}
// export interface State {
// user: string;
// pwd: string;
// }
// export class AuthPane extends React.Component<Props, State, {}> {
// private update: (updater: (prevState: ICoreState) => ICoreState) => void;
// constructor(p: Props) {
// super(p);
// Updater.init(p);
// Updater.setClient(new UsersClient(""));
// this.update = p.update;
// this.state = {
// user: "",
// pwd: "",
// };
// this.initIsAuthed();
// }
// changeUser = (ev: React.ChangeEvent<HTMLInputElement>) => {
// this.setState({ user: ev.target.value });
// };
// changePwd = (ev: React.ChangeEvent<HTMLInputElement>) => {
// this.setState({ pwd: ev.target.value });
// };
// initIsAuthed = () => {
// Updater.initIsAuthed().then(() => {
// this.update(Updater.setAuthPane);
// });
// };
// login = () => {
// Updater.login(this.state.user, this.state.pwd)
// .then((ok: boolean) => {
// if (ok) {
// this.update(Updater.setAuthPane);
// this.setState({ user: "", pwd: "" });
// // close all the panes
// PanesUpdater.displayPane("");
// this.update(PanesUpdater.updateState);
// // refresh
// return BrowserUpdater().setHomeItems();
// } else {
// this.setState({ user: "", pwd: "" });
// alert("Failed to login.");
// }
// })
// .then(() => {
// return BrowserUpdater().refreshUploadings();
// })
// .then((_: boolean) => {
// this.update(BrowserUpdater().setBrowser);
// });
// };
// logout = () => {
// Updater.logout().then((ok: boolean) => {
// if (ok) {
// this.update(Updater.setAuthPane);
// } else {
// alert("Failed to logout.");
// }
// });
// };
// render() {
// const elements: Array<JSX.Element> = [
// <input
// name="user"
// type="text"
// onChange={this.changeUser}
// value={this.state.user}
// className="black0-font margin-t-m margin-b-m"
// // style={{ width: "80%" }}
// placeholder="user name"
// />,
// <input
// name="pwd"
// type="password"
// onChange={this.changePwd}
// value={this.state.pwd}
// className="black0-font margin-t-m margin-b-m"
// // style={{ width: "80%" }}
// placeholder="password"
// />,
// <button
// onClick={this.login}
// className="green0-bg white-font margin-t-m margin-b-m"
// >
// Log in
// </button>,
// ];
// return (
// <span>
// <div
// className="margin-l-l"
// style={{ display: this.props.authed ? "none" : "block" }}
// >
// {/* <h5 className="black-font">Login</h5> */}
// <Layouter isHorizontal={false} elements={elements} />
// </div>
// <span style={{ display: this.props.authed ? "inherit" : "none" }}>
// <button onClick={this.logout} className="grey1-bg white-font">
// Log out
// </button>
// </span>
// </span>
// );
// }
// }

View file

@ -158,15 +158,16 @@ export class AuthPane extends React.Component<Props, State, {}> {
return ( return (
<span> <span>
<span style={{ display: this.props.authed ? "none" : "inherit" }}> <div
<h5 className="grey0-font">Login</h5> className="margin-l-l"
style={{ display: this.props.authed ? "none" : "block" }}
>
{/* <h5 className="black-font">Login</h5> */}
<Layouter isHorizontal={false} elements={elements} /> <Layouter isHorizontal={false} elements={elements} />
</span> </div>
<span style={{ display: this.props.authed ? "inherit" : "none" }}> <span style={{ display: this.props.authed ? "inherit" : "none" }}>
<button <button onClick={this.logout} className="grey1-bg white-font">
onClick={this.logout}
className="grey1-bg white-font margin-r-m"
>
Log out Log out
</button> </button>
</span> </span>

View file

@ -76,7 +76,7 @@ export class PaneSettings extends React.Component<Props, State, {}> {
if (ok) { if (ok) {
alert("Password is updated"); alert("Password is updated");
} else { } else {
alert("fail to update password"); alert("Failed to update password");
} }
this.setState({ this.setState({
oldPwd: "", oldPwd: "",
@ -120,12 +120,61 @@ export class PaneSettings extends React.Component<Props, State, {}> {
]; ];
return ( return (
<div> <div className="padding-l">
<h5 className="grey0-font">Update Password</h5> <div>
<Layouter isHorizontal={false} elements={inputs}></Layouter> <div className="flex-list-container">
<div className="hr"></div> <div className="flex-list-item-l">
<h5 className="black-font">Update Password</h5>
</div>
<div className="flex-list-item-r">
<button onClick={this.setPwd} className="grey1-bg white-font">
Update
</button>
</div>
</div>
<AuthPane authed={this.props.login.authed} update={this.update} /> <div>
<input
name="old_pwd"
type="password"
onChange={this.changeOldPwd}
value={this.state.oldPwd}
className="black0-font margin-t-m margin-b-m"
placeholder="old password"
/>
</div>
<div>
<input
name="new_pwd1"
type="password"
onChange={this.changeNewPwd1}
value={this.state.newPwd1}
className="black0-font margin-t-m margin-b-m margin-r-m"
placeholder="new password"
/>
<input
name="new_pwd2"
type="password"
onChange={this.changeNewPwd2}
value={this.state.newPwd2}
className="black0-font margin-t-m margin-b-m"
placeholder="new password again"
/>
</div>
</div>
<div className="hr white0-bg margin-t-m margin-b-m"></div>
<div>
<div className="flex-list-container">
<div className="flex-list-item-l">
<h5 className="black-font">Logout</h5>
</div>
<div className="flex-list-item-r">
<AuthPane authed={this.props.login.authed} update={this.update} />
</div>
</div>
</div>
</div> </div>
); );
} }

View file

@ -64,34 +64,43 @@ export class Panes extends React.Component<Props, State, {}> {
} }
const panesMap: Map<string, JSX.Element> = Map({ const panesMap: Map<string, JSX.Element> = Map({
settings: <PaneSettings login={this.props.login} update={this.props.update} />, settings: (
login: <AuthPane authed={this.props.login.authed} update={this.props.update} />, <PaneSettings login={this.props.login} update={this.props.update} />
),
login: (
<AuthPane authed={this.props.login.authed} update={this.props.update} />
),
}); });
const panes = panesMap.keySeq().map( const panes = panesMap.keySeq().map((paneName: string): JSX.Element => {
(paneName: string): JSX.Element => { const isDisplay = displaying === paneName ? "" : "hidden";
const isDisplay = displaying === paneName ? "" : "hidden"; return (
return ( <div key={paneName} className={`${isDisplay}`}>
<div key={paneName} className={`${isDisplay}`}> {panesMap.get(paneName)}
{panesMap.get(paneName)} </div>
</div> );
); });
}
);
const btnClass = displaying === "login" ? "hidden" : ""; const btnClass = displaying === "login" ? "hidden" : "";
return ( return (
<div id="panes" className={displaying === "" ? "hidden" : ""}> <div id="panes" className={displaying === "" ? "hidden" : ""}>
<div className="container"> <div className="container">
<div className="padding-l"> <div className="flex-list-container padding-l">
<div className={btnClass}> <h3 className="flex-list-item-l txt-cap">{displaying}</h3>
<button onClick={this.closePane} className="black0-bg white-font"> <div className="flex-list-item-r">
Return <button
onClick={this.closePane}
className={`black0-bg white-font ${btnClass}`}
>
Close
</button> </button>
<div className="hr"></div>
</div> </div>
{panes}
</div> </div>
<div className="hr white0-bg margin-b-m margin-l-m margin-r-m"></div>
{panes}
<div className="padding-l"></div>
</div> </div>
</div> </div>
); );

View file

@ -3,6 +3,7 @@ import * as React from "react";
import { ICoreState, BaseUpdater } from "./core_state"; import { ICoreState, BaseUpdater } from "./core_state";
import { Browser, Props as BrowserProps } from "./browser"; import { Browser, Props as BrowserProps } from "./browser";
import { Props as PaneLoginProps } from "./pane_login"; import { Props as PaneLoginProps } from "./pane_login";
import { Props as PaneAdminProps } from "./pane_admin";
import { Panes, Props as PanesProps, Updater as PanesUpdater } from "./panes"; import { Panes, Props as PanesProps, Updater as PanesUpdater } from "./panes";
export interface Props { export interface Props {
@ -10,6 +11,7 @@ export interface Props {
browser: BrowserProps; browser: BrowserProps;
authPane: PaneLoginProps; authPane: PaneLoginProps;
panes: PanesProps; panes: PanesProps;
admin: PaneAdminProps;
update?: (updater: (prevState: ICoreState) => ICoreState) => void; update?: (updater: (prevState: ICoreState) => ICoreState) => void;
} }

View file

@ -41,6 +41,7 @@ export class StateMgr extends React.Component<Props, State, {}> {
update={this.update} update={this.update}
browser={this.state.panel.browser} browser={this.state.panel.browser}
panes={this.state.panel.panes} panes={this.state.panel.panes}
admin={this.state.panel.admin}
/> />
); );
} }