diff --git a/public/static/css/white.css b/public/static/css/white.css index 68bb405..f223625 100644 --- a/public/static/css/white.css +++ b/public/static/css/white.css @@ -30,7 +30,7 @@ box-shadow: 0 5px 30px 0 rgba(31, 38, 135, 0.1); backdrop-filter: blur(9.5px); color: #16a085; - padding: 1rem 2rem 1rem 2rem; + padding: 0.5rem 1rem; -webkit-backdrop-filter: blur(9.5px); } @@ -52,10 +52,12 @@ .theme-default #root-container { max-width: 80rem; width: 96%; - z-index: 101; text-align: left; margin: 3rem auto 8rem auto; - border-radius: 0.6rem; +} + +.theme-default #layers { + height: 0; } .theme-default #panes .container { @@ -222,7 +224,7 @@ } .theme-default #pane-settings { - padding: 2rem; + /* padding: 2rem; */ } .theme-default #pane-settings #profile { @@ -254,6 +256,24 @@ 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 { color: #697384; } diff --git a/src/client/web/src/components/core_state.ts b/src/client/web/src/components/core_state.ts index 613ef60..6f93f8e 100644 --- a/src/client/web/src/components/core_state.ts +++ b/src/client/web/src/components/core_state.ts @@ -2,10 +2,12 @@ import { List, Set, Map } from "immutable"; import { UploadEntry } from "../worker/interface"; +import { loginDialogCtrl, settingsDialogCtrl } from "./layers"; import { FilesProps } from "./panel_files"; import { UploadingsProps } from "./panel_uploadings"; import { SharingsProps } from "./panel_sharings"; import { controlName as panelTabs } from "./root_frame"; +import { settingsTabsCtrl } from "./dialog_settings"; import { PanesProps } from "./panes"; import { LoginProps } from "./pane_login"; import { AdminProps } from "./pane_admin"; @@ -112,6 +114,9 @@ export function initState(): ICoreState { control: { controls: Map({ [panelTabs]: "filesPanel", + [loginDialogCtrl]: "on", + [settingsDialogCtrl]: "off", + [settingsTabsCtrl]: "settingsPane", }), options: Map>({ [panelTabs]: Set([ @@ -119,6 +124,9 @@ export function initState(): ICoreState { "uploadingsPanel", "sharingsPanel", ]), + [loginDialogCtrl]: Set(["on", "off"]), + [settingsDialogCtrl]: Set(["on", "off"]), + [settingsTabsCtrl]: Set(["settingsPane", "managementPane"]), }), }, }, diff --git a/src/client/web/src/components/dialog_settings.tsx b/src/client/web/src/components/dialog_settings.tsx new file mode 100644 index 0000000..a059582 --- /dev/null +++ b/src/client/web/src/components/dialog_settings.tsx @@ -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 { + 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 ( +
+
+ ({ + 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} + /> +
+ +
+ +
+ +
+ +
+
+ ); + } +} diff --git a/src/client/web/src/components/layers.tsx b/src/client/web/src/components/layers.tsx new file mode 100644 index 0000000..85531f2 --- /dev/null +++ b/src/client/web/src/components/layers.tsx @@ -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 { + 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 ( +
+
+
+ +
+
+ +
+
+
+
+ + {this.props.msg.pkg.get("pane.settings")} + , + , + ])} + childrenStyles={List([{}, { justifyContent: "flex-end" }])} + /> +
+
+ + +
+
+
+ ); + } +} diff --git a/src/client/web/src/components/root_frame.tsx b/src/client/web/src/components/root_frame.tsx index 92e8537..27a5f0b 100644 --- a/src/client/web/src/components/root_frame.tsx +++ b/src/client/web/src/components/root_frame.tsx @@ -10,6 +10,7 @@ import { IconProps } from "./visual/icons"; import { Tabs } from "./control/tabs"; import { LoginProps } from "./pane_login"; import { Panes, PanesProps } from "./panes"; +import { Layers } from "./layers"; import { AdminProps } from "./pane_admin"; import { TopBar } from "./topbar"; import { roleVisitor } from "../client"; @@ -67,8 +68,7 @@ export class RootFrame extends React.Component { return (
- { } showSettings = () => { - updater().displayPane("settings"); - this.props.update(updater().updatePanes); - }; - - 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); - }); + updater().setControlOption("settingsDialog", "on"); + this.props.update(updater().updateUI); }; logout = async (): Promise => { @@ -83,12 +68,7 @@ export class TopBar extends React.Component { }; render() { - const showUserInfo = 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 (
@@ -105,30 +85,23 @@ export class TopBar extends React.Component { - - {this.props.login.userName} - - , + // + // {this.props.login.userName} + // , - , - , + // , - , ])} diff --git a/src/client/web/src/components/visual/icons.tsx b/src/client/web/src/components/visual/icons.tsx index 8db3e7b..3b1e0a4 100644 --- a/src/client/web/src/components/visual/icons.tsx +++ b/src/client/web/src/components/visual/icons.tsx @@ -5,6 +5,8 @@ import { IconType, IconBaseProps } from "@react-icons/all-files"; import { RiFolder2Fill } from "@react-icons/all-files/ri/RiFolder2Fill"; import { RiShareBoxLine } from "@react-icons/all-files/ri/RiShareBoxLine"; 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"; @@ -18,6 +20,8 @@ const icons = Map({ RiFolder2Fill: RiFolder2Fill, RiShareBoxLine: RiShareBoxLine, RiUploadCloudFill: RiUploadCloudFill, + RiSettings3Fill: RiSettings3Fill, + RiWindowFill: RiWindowFill, }); export function getIconWithProps(