diff --git a/src/client/web/src/client/users_mock.ts b/src/client/web/src/client/users_mock.ts index 117bf7c..5d6cba1 100644 --- a/src/client/web/src/client/users_mock.ts +++ b/src/client/web/src/client/users_mock.ts @@ -1,7 +1,6 @@ // TODO: replace this with jest mocks import { Response, Quota } from "./"; - export interface UsersClientResps { loginMockResp: Response; logoutMockResp: Response; @@ -77,6 +76,11 @@ export const resps = { name: "mockUser", role: "admin", usedSpace: "256", + quota: { + spaceLimit: "7", + uploadSpeedLimit: 3, + downloadSpeedLimit: 3, + }, }, }, getCaptchaIDMockResp: { @@ -125,7 +129,6 @@ export class MockUsersClient { setUser = (id: string, role: string, quota: Quota): Promise => { return this.wrapPromise(this.resps.setUserMockResp); }; - forceSetPwd = (userID: string, newPwd: string): Promise => { return this.wrapPromise(this.resps.forceSetPwdMockResp); diff --git a/src/client/web/src/components/__test__/pane_login.test.tsx b/src/client/web/src/components/__test__/pane_login.test.tsx index 16ac0a3..db2a0a4 100644 --- a/src/client/web/src/components/__test__/pane_login.test.tsx +++ b/src/client/web/src/components/__test__/pane_login.test.tsx @@ -36,6 +36,12 @@ describe("Login", () => { userName: "mockUser", userRole: "admin", authed: true, + usedSpace: "256", + quota: { + spaceLimit: "7", + uploadSpeedLimit: 3, + downloadSpeedLimit: 3, + }, captchaID: "", }); diff --git a/src/client/web/src/components/__test__/state_mgr.test.tsx b/src/client/web/src/components/__test__/state_mgr.test.tsx index a902f02..dffc30f 100644 --- a/src/client/web/src/components/__test__/state_mgr.test.tsx +++ b/src/client/web/src/components/__test__/state_mgr.test.tsx @@ -22,8 +22,8 @@ describe("State Manager", () => { // TODO: depress warning mgr.update = (apply: (prevState: ICoreState) => ICoreState): void => { - // no op - }; + // no op + }; const coreState = newWithWorker(mockWorker); await mgr.initUpdater(coreState); @@ -52,6 +52,12 @@ describe("State Manager", () => { userID: "0", userName: "mockUser", userRole: "admin", + usedSpace: "256", + quota: { + spaceLimit: "7", + uploadSpeedLimit: 3, + downloadSpeedLimit: 3, + }, authed: true, captchaID: "mockCaptchaID", }); diff --git a/src/client/web/src/components/browser.tsx b/src/client/web/src/components/browser.tsx index 63537cf..14fb5f3 100644 --- a/src/client/web/src/components/browser.tsx +++ b/src/client/web/src/components/browser.tsx @@ -6,7 +6,7 @@ import { RiFolder2Fill } from "@react-icons/all-files/ri/RiFolder2Fill"; import { RiFileList2Fill } from "@react-icons/all-files/ri/RiFileList2Fill"; import { RiFile2Fill } from "@react-icons/all-files/ri/RiFile2Fill"; import { RiShareBoxLine } from "@react-icons/all-files/ri/RiShareBoxLine"; -import { RiShareForwardBoxFill } from "@react-icons/all-files/ri/RiShareForwardBoxFill"; +import { RiFolderSharedFill } from "@react-icons/all-files/ri/RiFolderSharedFill"; import { RiUploadCloudFill } from "@react-icons/all-files/ri/RiUploadCloudFill"; import { RiUploadCloudLine } from "@react-icons/all-files/ri/RiUploadCloudLine"; import { RiEmotionSadLine } from "@react-icons/all-files/ri/RiEmotionSadLine"; @@ -14,6 +14,7 @@ import { RiEmotionSadLine } from "@react-icons/all-files/ri/RiEmotionSadLine"; import { alertMsg, comfirmMsg } from "../common/env"; import { updater } from "./state_updater"; import { ICoreState, MsgProps } from "./core_state"; +import { LoginProps } from "./pane_login"; import { MetadataResp, UploadInfo } from "../client"; import { Up } from "../worker/upload_mgr"; import { UploadEntry } from "../worker/interface"; @@ -44,6 +45,7 @@ export interface BrowserProps { export interface Props { browser: BrowserProps; msg: MsgProps; + login: LoginProps; update?: (updater: (prevState: ICoreState) => ICoreState) => void; } @@ -477,6 +479,15 @@ export class Browser extends React.Component { ); }); + const usedSpace = FileSize(parseInt(this.props.login.usedSpace, 10), { + round: 0, + }); + const spaceLimit = FileSize( + parseInt(this.props.login.quota.spaceLimit, 10), + { + round: 0, + } + ); const itemListPane = this.props.browser.tab === "" || this.props.browser.tab === "item" ? (
@@ -485,49 +496,61 @@ export class Browser extends React.Component {
-
- {this.props.browser.isSharing ? ( - - ) : ( - - )} - - {this.state.selectedItems.size > 0 ? ( + - + {this.props.browser.isSharing ? ( + + ) : ( + + )} - - - ) : null} + {this.state.selectedItems.size > 0 ? ( + + -
-
+ + + ) : null} + , + + + {`${this.props.msg.pkg.get( + "browser.used" + )} ${usedSpace} / ${spaceLimit}`} + , + ])} + className="padding-m" + childrenStyles={List([{}, { justifyContent: "flex-end" }])} + /> { className="margin-r-m black-font" />, - // - // - // {this.props.msg.pkg.get("browser.item.title")} - // - // - // Files and folders in current path - // - // , - , ])} - // style={{ flex: "column nowrap" }} /> , @@ -687,7 +700,7 @@ export class Browser extends React.Component { children={List([ , diff --git a/src/client/web/src/components/core_state.ts b/src/client/web/src/components/core_state.ts index e93cc80..4cb3958 100644 --- a/src/client/web/src/components/core_state.ts +++ b/src/client/web/src/components/core_state.ts @@ -69,6 +69,12 @@ export function initState(): ICoreState { userID: "", userName: "", userRole: "", + usedSpace: "0", + quota: { + spaceLimit: "0", + uploadSpeedLimit: 0, + downloadSpeedLimit: 0, + }, authed: false, captchaID: "", }, diff --git a/src/client/web/src/components/pane_login.tsx b/src/client/web/src/components/pane_login.tsx index ff73996..3864b38 100644 --- a/src/client/web/src/components/pane_login.tsx +++ b/src/client/web/src/components/pane_login.tsx @@ -3,11 +3,14 @@ import * as React from "react"; import { ICoreState, MsgProps } from "./core_state"; import { updater } from "./state_updater"; import { alertMsg } from "../common/env"; +import { Quota } from "../client"; export interface LoginProps { userID: string; userName: string; userRole: string; + usedSpace: string; + quota: Quota; authed: boolean; captchaID: string; } @@ -85,11 +88,17 @@ export class AuthPane extends React.Component { updater().initLan(); this.update(updater().updateMsg); + }) + .then(() => { + return updater().isSharing(updater().props.browser.dirPath.join("/")); + }) + .then(() => { + this.update(updater().updateBrowser); }); }; - logout = () => { - updater() + logout = async () => { + return updater() .logout() .then((ok: boolean) => { if (ok) { @@ -97,6 +106,9 @@ export class AuthPane extends React.Component { } else { alertMsg(this.props.msg.pkg.get("login.logout.fail")); } + }) + .then(() => { + return this.refreshCaptcha(); }); }; diff --git a/src/client/web/src/components/root_frame.tsx b/src/client/web/src/components/root_frame.tsx index d07fbc0..50ca699 100644 --- a/src/client/web/src/components/root_frame.tsx +++ b/src/client/web/src/components/root_frame.tsx @@ -52,13 +52,14 @@ export class RootFrame extends React.Component {
Quickshare - - sharing in simple way. + quick and simple file sharing.
diff --git a/src/client/web/src/components/state_updater.ts b/src/client/web/src/components/state_updater.ts index 11a687c..5ebf58b 100644 --- a/src/client/web/src/components/state_updater.ts +++ b/src/client/web/src/components/state_updater.ts @@ -258,6 +258,8 @@ export class Updater { this.props.login.userID = resp.data.id; this.props.login.userName = resp.data.name; this.props.login.userRole = resp.data.role; + this.props.login.usedSpace = resp.data.usedSpace; + this.props.login.quota = resp.data.quota; return true; } return false; diff --git a/src/client/web/src/components/topbar.tsx b/src/client/web/src/components/topbar.tsx index 5d2473e..f1cb2b3 100644 --- a/src/client/web/src/components/topbar.tsx +++ b/src/client/web/src/components/topbar.tsx @@ -1,8 +1,11 @@ import * as React from "react"; +import { List } from "immutable"; +import { RiGithubFill } from "@react-icons/all-files/ri/RiGithubFill"; import { ICoreState, MsgProps } from "./core_state"; import { LoginProps } from "./pane_login"; import { updater } from "./state_updater"; +import { Flexbox } from "./layout/flexbox"; export interface State {} export interface Props { @@ -43,6 +46,7 @@ export class TopBar extends React.Component { @@ -53,7 +57,48 @@ export class TopBar extends React.Component { id="top-bar" className="top-bar cyan1-font padding-t-m padding-b-m padding-l-l padding-r-l" > -
+ + Quickshare + {/* */} + , + + + + {this.props.login.userName} + +  -  + + {this.props.login.userRole} + + , + + , + + adminBtn, + ])} + childrenStyles={List([{}, {}, {}, {}])} + />, + ])} + childrenStyles={List([ + {}, + { justifyContent: "flex-end", alignItems: "center" }, + ])} + /> + {/* +
*/} ); } diff --git a/src/client/web/src/i18n/en_US.ts b/src/client/web/src/i18n/en_US.ts index 3752be0..3693e67 100644 --- a/src/client/web/src/i18n/en_US.ts +++ b/src/client/web/src/i18n/en_US.ts @@ -26,6 +26,7 @@ export const msgs: Map = Map({ "browser.disable": "Disable", "browser.location": "Location", "browser.item.title": "Items", + "browser.used": "Used Space", "panes.close": "Close", "login.logout.fail": "Failed to log out", "login.username": "User Name", diff --git a/src/client/web/src/i18n/zh_CN.ts b/src/client/web/src/i18n/zh_CN.ts index 2c9e42f..f7672f7 100644 --- a/src/client/web/src/i18n/zh_CN.ts +++ b/src/client/web/src/i18n/zh_CN.ts @@ -25,6 +25,7 @@ export const msgs: Map = Map({ "browser.stop": "停止", "browser.location": "位置", "browser.item.title": "列表", + "browser.used": "已用空间", "panes.close": "关闭", "login.logout.fail": "登出失败", "login.username": "用户名",