feat(layers): replaces panes with layers and dialogs

This commit is contained in:
hexxa 2021-11-28 12:06:42 +08:00 committed by Hexxa
parent 7df3cd0981
commit dc6babcc17
7 changed files with 227 additions and 48 deletions

View file

@ -30,7 +30,7 @@
box-shadow: 0 5px 30px 0 rgba(31, 38, 135, 0.1); box-shadow: 0 5px 30px 0 rgba(31, 38, 135, 0.1);
backdrop-filter: blur(9.5px); backdrop-filter: blur(9.5px);
color: #16a085; color: #16a085;
padding: 1rem 2rem 1rem 2rem; padding: 0.5rem 1rem;
-webkit-backdrop-filter: blur(9.5px); -webkit-backdrop-filter: blur(9.5px);
} }
@ -52,10 +52,12 @@
.theme-default #root-container { .theme-default #root-container {
max-width: 80rem; max-width: 80rem;
width: 96%; width: 96%;
z-index: 101;
text-align: left; text-align: left;
margin: 3rem auto 8rem auto; margin: 3rem auto 8rem auto;
border-radius: 0.6rem; }
.theme-default #layers {
height: 0;
} }
.theme-default #panes .container { .theme-default #panes .container {
@ -222,7 +224,7 @@
} }
.theme-default #pane-settings { .theme-default #pane-settings {
padding: 2rem; /* padding: 2rem; */
} }
.theme-default #pane-settings #profile { .theme-default #pane-settings #profile {
@ -254,6 +256,24 @@
margin-top: 0.5rem; margin-top: 0.5rem;
} }
.theme-default .layer {
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.5);
overflow: scroll;
}
.theme-default #login-layer {
z-index: 100;
}
.theme-default #settings-layer {
z-index: 1;
}
.theme-default .value { .theme-default .value {
color: #697384; color: #697384;
} }

View file

@ -2,10 +2,12 @@ import { List, Set, Map } from "immutable";
import { UploadEntry } from "../worker/interface"; import { UploadEntry } from "../worker/interface";
import { loginDialogCtrl, settingsDialogCtrl } from "./layers";
import { FilesProps } from "./panel_files"; import { FilesProps } from "./panel_files";
import { UploadingsProps } from "./panel_uploadings"; import { UploadingsProps } from "./panel_uploadings";
import { SharingsProps } from "./panel_sharings"; import { SharingsProps } from "./panel_sharings";
import { controlName as panelTabs } from "./root_frame"; import { controlName as panelTabs } from "./root_frame";
import { settingsTabsCtrl } from "./dialog_settings";
import { PanesProps } from "./panes"; import { PanesProps } from "./panes";
import { LoginProps } from "./pane_login"; import { LoginProps } from "./pane_login";
import { AdminProps } from "./pane_admin"; import { AdminProps } from "./pane_admin";
@ -112,6 +114,9 @@ export function initState(): ICoreState {
control: { control: {
controls: Map<string, string>({ controls: Map<string, string>({
[panelTabs]: "filesPanel", [panelTabs]: "filesPanel",
[loginDialogCtrl]: "on",
[settingsDialogCtrl]: "off",
[settingsTabsCtrl]: "settingsPane",
}), }),
options: Map<string, Set<string>>({ options: Map<string, Set<string>>({
[panelTabs]: Set<string>([ [panelTabs]: Set<string>([
@ -119,6 +124,9 @@ export function initState(): ICoreState {
"uploadingsPanel", "uploadingsPanel",
"sharingsPanel", "sharingsPanel",
]), ]),
[loginDialogCtrl]: Set<string>(["on", "off"]),
[settingsDialogCtrl]: Set<string>(["on", "off"]),
[settingsTabsCtrl]: Set<string>(["settingsPane", "managementPane"]),
}), }),
}, },
}, },

View file

@ -0,0 +1,86 @@
import * as React from "react";
import { Map } from "immutable";
import { ICoreState, MsgProps, UIProps } from "./core_state";
import { FilesPanel, FilesProps } from "./panel_files";
import { UploadingsPanel, UploadingsProps } from "./panel_uploadings";
import { SharingsPanel, SharingsProps } from "./panel_sharings";
import { IconProps } from "./visual/icons";
import { PaneSettings } from "./pane_settings";
import { AdminPane, AdminProps } from "./pane_admin";
import { Tabs } from "./control/tabs";
import { LoginProps } from "./pane_login";
import { RiShareBoxLine } from "@react-icons/all-files/ri/RiShareBoxLine";
import { roleAdmin } from "../client";
export const settingsTabsCtrl = "settingsTabs";
export interface Props {
admin: AdminProps;
login: LoginProps;
msg: MsgProps;
ui: UIProps;
update?: (updater: (prevState: ICoreState) => ICoreState) => void;
}
export interface State {}
export class SettingsDialog extends React.Component<Props, State, {}> {
constructor(p: Props) {
super(p);
}
render() {
const displaying = this.props.ui.control.controls.get(settingsTabsCtrl);
const showSettings = displaying === "settingsPane" ? "" : "hidden";
const showManagement =
this.props.login.userRole === roleAdmin && displaying === "managementPane"
? ""
: "hidden";
return (
<div id="settings-dialog">
<div className="container">
<Tabs
targetControl={settingsTabsCtrl}
tabIcons={Map<string, IconProps>({
settingsPane: {
name: "RiSettings3Fill",
size: "1.6rem",
color: "cyan0",
},
managementPane: {
name: "RiWindowFill",
size: "1.6rem",
color: "cyan0",
},
})}
login={this.props.login}
admin={this.props.admin}
ui={this.props.ui}
msg={this.props.msg}
update={this.props.update}
/>
</div>
<div className={`${showSettings}`}>
<PaneSettings
login={this.props.login}
msg={this.props.msg}
update={this.props.update}
/>
</div>
<div className={`${showManagement}`}>
<AdminPane
admin={this.props.admin}
ui={this.props.ui}
msg={this.props.msg}
update={this.props.update}
/>
</div>
</div>
);
}
}

View file

@ -0,0 +1,88 @@
import * as React from "react";
import { Set, List } from "immutable";
import { updater } from "./state_updater";
import { ICoreState, MsgProps, UIProps } from "./core_state";
// import { PaneSettings } from "./pane_settings";
import { AdminProps } from "./pane_admin";
import { SettingsDialog } from "./dialog_settings";
import { AuthPane, LoginProps } from "./pane_login";
import { Flexbox } from "./layout/flexbox";
export const loginDialogCtrl = "loginDialog";
export const settingsDialogCtrl = "settingsDialog";
export interface Props {
login: LoginProps;
admin: AdminProps;
ui: UIProps;
msg: MsgProps;
update?: (updater: (prevState: ICoreState) => ICoreState) => void;
}
export interface State {}
export class Layers extends React.Component<Props, State, {}> {
constructor(p: Props) {
super(p);
}
setControlOption = (targetControl: string, option: string) => {
updater().setControlOption(targetControl, option);
this.props.update(updater().updateUI);
};
render() {
const showLogin = this.props.login.authed ? "hidden" : "";
const showSettings =
this.props.ui.control.controls.get("settingsDialog") == "on"
? ""
: "hidden";
return (
<div id="layers">
<div id="login-layer" className={`layer ${showLogin}`}>
<div id="root-container">
<AuthPane
login={this.props.login}
update={this.props.update}
msg={this.props.msg}
/>
</div>
</div>
<div id="settings-layer" className={`layer ${showSettings}`}>
<div id="root-container">
<div className="container">
<div className="padding-m">
<Flexbox
children={List([
<h4 id="title">
{this.props.msg.pkg.get("pane.settings")}
</h4>,
<button
onClick={() => {
this.setControlOption("settingsDialog", "off");
}}
>
{this.props.msg.pkg.get("panes.close")}
</button>,
])}
childrenStyles={List([{}, { justifyContent: "flex-end" }])}
/>
</div>
</div>
<SettingsDialog
admin={this.props.admin}
login={this.props.login}
msg={this.props.msg}
ui={this.props.ui}
update={this.props.update}
/>
</div>
</div>
</div>
);
}
}

View file

@ -10,6 +10,7 @@ import { IconProps } from "./visual/icons";
import { Tabs } from "./control/tabs"; import { Tabs } from "./control/tabs";
import { LoginProps } from "./pane_login"; import { LoginProps } from "./pane_login";
import { Panes, PanesProps } from "./panes"; import { Panes, PanesProps } from "./panes";
import { Layers } from "./layers";
import { AdminProps } from "./pane_admin"; import { AdminProps } from "./pane_admin";
import { TopBar } from "./topbar"; import { TopBar } from "./topbar";
import { roleVisitor } from "../client"; import { roleVisitor } from "../client";
@ -67,8 +68,7 @@ export class RootFrame extends React.Component<Props, State, {}> {
return ( return (
<div id="root-frame" className={`${theme} ${fontSizeClass}`}> <div id="root-frame" className={`${theme} ${fontSizeClass}`}>
<div id="bg" style={bgStyle}> <div id="bg" style={bgStyle}>
<Panes <Layers
panes={this.props.panes}
login={this.props.login} login={this.props.login}
admin={this.props.admin} admin={this.props.admin}
ui={this.props.ui} ui={this.props.ui}

View file

@ -7,6 +7,7 @@ import { LoginProps } from "./pane_login";
import { PanesProps } from "./panes"; import { PanesProps } from "./panes";
import { updater } from "./state_updater"; import { updater } from "./state_updater";
import { Flexbox } from "./layout/flexbox"; import { Flexbox } from "./layout/flexbox";
import { getIcon } from "./visual/icons";
export interface State {} export interface State {}
export interface Props { export interface Props {
@ -22,24 +23,8 @@ export class TopBar extends React.Component<Props, State, {}> {
} }
showSettings = () => { showSettings = () => {
updater().displayPane("settings"); updater().setControlOption("settingsDialog", "on");
this.props.update(updater().updatePanes); this.props.update(updater().updateUI);
};
showAdmin = async () => {
return updater()
.self()
.then(() => {
// TODO: remove hardcode role
if (this.props.login.authed && this.props.login.userRole === "admin") {
return Promise.all([updater().listRoles(), updater().listUsers()]);
}
})
.then(() => {
updater().displayPane("admin");
this.props.update(updater().updateAdmin);
this.props.update(updater().updatePanes);
});
}; };
logout = async (): Promise<void> => { logout = async (): Promise<void> => {
@ -83,12 +68,7 @@ export class TopBar extends React.Component<Props, State, {}> {
}; };
render() { render() {
const showUserInfo = this.props.login.authed ? "" : "hidden";
const showLogin = this.props.login.authed ? "" : "hidden"; const showLogin = this.props.login.authed ? "" : "hidden";
const showSettings = this.props.panes.paneNames.get("settings")
? ""
: "hidden";
const showAdmin = this.props.panes.paneNames.get("admin") ? "" : "hidden";
return ( return (
<div id="top-bar"> <div id="top-bar">
@ -105,30 +85,23 @@ export class TopBar extends React.Component<Props, State, {}> {
<Flexbox <Flexbox
children={List([ children={List([
<span className={`${showUserInfo}`}> // <span className={`${showUserInfo}`}>
<span id="topbar-user-info"> // <span id="topbar-user-info">{this.props.login.userName}</span>
{this.props.login.userName} // </span>,
</span>
</span>,
<button <button onClick={this.showSettings} className={`margin-r-m`}>
onClick={this.showSettings}
className={`margin-r-m ${showSettings}`}
>
{this.props.msg.pkg.get("settings")} {this.props.msg.pkg.get("settings")}
{/* {getIcon("RiSettings4Line", "1.8rem", "cyan0")} */}
</button>, </button>,
<button // <button
onClick={this.showAdmin} // onClick={this.showAdmin}
className={`margin-r-m ${showAdmin}`} // className={`margin-r-m ${showAdmin}`}
> // >
{this.props.msg.pkg.get("admin")} // {this.props.msg.pkg.get("admin")}
</button>, // </button>,
<button <button onClick={this.logout} className={`${showLogin}`}>
onClick={this.logout}
className={`${showLogin}`}
>
{this.props.msg.pkg.get("login.logout")} {this.props.msg.pkg.get("login.logout")}
</button>, </button>,
])} ])}

View file

@ -5,6 +5,8 @@ import { IconType, IconBaseProps } from "@react-icons/all-files";
import { RiFolder2Fill } from "@react-icons/all-files/ri/RiFolder2Fill"; import { RiFolder2Fill } from "@react-icons/all-files/ri/RiFolder2Fill";
import { RiShareBoxLine } from "@react-icons/all-files/ri/RiShareBoxLine"; import { RiShareBoxLine } from "@react-icons/all-files/ri/RiShareBoxLine";
import { RiUploadCloudFill } from "@react-icons/all-files/ri/RiUploadCloudFill"; import { RiUploadCloudFill } from "@react-icons/all-files/ri/RiUploadCloudFill";
import { RiSettings3Fill } from "@react-icons/all-files/ri/RiSettings3Fill";
import { RiWindowFill } from "@react-icons/all-files/ri/RiWindowFill";
import { colorClass } from "./colors"; import { colorClass } from "./colors";
@ -18,6 +20,8 @@ const icons = Map<string, IconType>({
RiFolder2Fill: RiFolder2Fill, RiFolder2Fill: RiFolder2Fill,
RiShareBoxLine: RiShareBoxLine, RiShareBoxLine: RiShareBoxLine,
RiUploadCloudFill: RiUploadCloudFill, RiUploadCloudFill: RiUploadCloudFill,
RiSettings3Fill: RiSettings3Fill,
RiWindowFill: RiWindowFill,
}); });
export function getIconWithProps( export function getIconWithProps(