fix(ui): fix layout of list & pane (#66)
* fix(ui): refine pane layout * fix(test): add pane_admin component
This commit is contained in:
parent
df46915147
commit
916ec7c2dc
10 changed files with 294 additions and 46 deletions
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
@ -629,4 +629,8 @@ div.hr {
|
||||||
|
|
||||||
.breadcrumb {
|
.breadcrumb {
|
||||||
font-size: 1.4rem;
|
font-size: 1.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.txt-cap {
|
||||||
|
text-transform: capitalize;
|
||||||
}
|
}
|
|
@ -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;
|
||||||
|
|
|
@ -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>()
|
||||||
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
178
src/client/web/src/components/pane_admin.tsx
Normal file
178
src/client/web/src/components/pane_admin.tsx
Normal 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>
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
// }
|
|
@ -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>
|
||||||
|
|
|
@ -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>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>
|
||||||
);
|
);
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue