feat(ui/browser): support used space
This commit is contained in:
parent
93d946e535
commit
c76e61a686
11 changed files with 162 additions and 61 deletions
|
@ -1,7 +1,6 @@
|
||||||
// TODO: replace this with jest mocks
|
// TODO: replace this with jest mocks
|
||||||
import { Response, Quota } from "./";
|
import { Response, Quota } from "./";
|
||||||
|
|
||||||
|
|
||||||
export interface UsersClientResps {
|
export interface UsersClientResps {
|
||||||
loginMockResp: Response;
|
loginMockResp: Response;
|
||||||
logoutMockResp: Response;
|
logoutMockResp: Response;
|
||||||
|
@ -77,6 +76,11 @@ export const resps = {
|
||||||
name: "mockUser",
|
name: "mockUser",
|
||||||
role: "admin",
|
role: "admin",
|
||||||
usedSpace: "256",
|
usedSpace: "256",
|
||||||
|
quota: {
|
||||||
|
spaceLimit: "7",
|
||||||
|
uploadSpeedLimit: 3,
|
||||||
|
downloadSpeedLimit: 3,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
getCaptchaIDMockResp: {
|
getCaptchaIDMockResp: {
|
||||||
|
@ -125,7 +129,6 @@ export class MockUsersClient {
|
||||||
setUser = (id: string, role: string, quota: Quota): Promise<Response> => {
|
setUser = (id: string, role: string, quota: Quota): Promise<Response> => {
|
||||||
return this.wrapPromise(this.resps.setUserMockResp);
|
return this.wrapPromise(this.resps.setUserMockResp);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
forceSetPwd = (userID: string, newPwd: string): Promise<Response> => {
|
forceSetPwd = (userID: string, newPwd: string): Promise<Response> => {
|
||||||
return this.wrapPromise(this.resps.forceSetPwdMockResp);
|
return this.wrapPromise(this.resps.forceSetPwdMockResp);
|
||||||
|
|
|
@ -36,6 +36,12 @@ describe("Login", () => {
|
||||||
userName: "mockUser",
|
userName: "mockUser",
|
||||||
userRole: "admin",
|
userRole: "admin",
|
||||||
authed: true,
|
authed: true,
|
||||||
|
usedSpace: "256",
|
||||||
|
quota: {
|
||||||
|
spaceLimit: "7",
|
||||||
|
uploadSpeedLimit: 3,
|
||||||
|
downloadSpeedLimit: 3,
|
||||||
|
},
|
||||||
captchaID: "",
|
captchaID: "",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -22,8 +22,8 @@ describe("State Manager", () => {
|
||||||
|
|
||||||
// TODO: depress warning
|
// TODO: depress warning
|
||||||
mgr.update = (apply: (prevState: ICoreState) => ICoreState): void => {
|
mgr.update = (apply: (prevState: ICoreState) => ICoreState): void => {
|
||||||
// no op
|
// no op
|
||||||
};
|
};
|
||||||
|
|
||||||
const coreState = newWithWorker(mockWorker);
|
const coreState = newWithWorker(mockWorker);
|
||||||
await mgr.initUpdater(coreState);
|
await mgr.initUpdater(coreState);
|
||||||
|
@ -52,6 +52,12 @@ describe("State Manager", () => {
|
||||||
userID: "0",
|
userID: "0",
|
||||||
userName: "mockUser",
|
userName: "mockUser",
|
||||||
userRole: "admin",
|
userRole: "admin",
|
||||||
|
usedSpace: "256",
|
||||||
|
quota: {
|
||||||
|
spaceLimit: "7",
|
||||||
|
uploadSpeedLimit: 3,
|
||||||
|
downloadSpeedLimit: 3,
|
||||||
|
},
|
||||||
authed: true,
|
authed: true,
|
||||||
captchaID: "mockCaptchaID",
|
captchaID: "mockCaptchaID",
|
||||||
});
|
});
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { RiFolder2Fill } from "@react-icons/all-files/ri/RiFolder2Fill";
|
||||||
import { RiFileList2Fill } from "@react-icons/all-files/ri/RiFileList2Fill";
|
import { RiFileList2Fill } from "@react-icons/all-files/ri/RiFileList2Fill";
|
||||||
import { RiFile2Fill } from "@react-icons/all-files/ri/RiFile2Fill";
|
import { RiFile2Fill } from "@react-icons/all-files/ri/RiFile2Fill";
|
||||||
import { RiShareBoxLine } from "@react-icons/all-files/ri/RiShareBoxLine";
|
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 { RiUploadCloudFill } from "@react-icons/all-files/ri/RiUploadCloudFill";
|
||||||
import { RiUploadCloudLine } from "@react-icons/all-files/ri/RiUploadCloudLine";
|
import { RiUploadCloudLine } from "@react-icons/all-files/ri/RiUploadCloudLine";
|
||||||
import { RiEmotionSadLine } from "@react-icons/all-files/ri/RiEmotionSadLine";
|
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 { alertMsg, comfirmMsg } from "../common/env";
|
||||||
import { updater } from "./state_updater";
|
import { updater } from "./state_updater";
|
||||||
import { ICoreState, MsgProps } from "./core_state";
|
import { ICoreState, MsgProps } from "./core_state";
|
||||||
|
import { LoginProps } from "./pane_login";
|
||||||
import { MetadataResp, UploadInfo } from "../client";
|
import { MetadataResp, UploadInfo } from "../client";
|
||||||
import { Up } from "../worker/upload_mgr";
|
import { Up } from "../worker/upload_mgr";
|
||||||
import { UploadEntry } from "../worker/interface";
|
import { UploadEntry } from "../worker/interface";
|
||||||
|
@ -44,6 +45,7 @@ export interface BrowserProps {
|
||||||
export interface Props {
|
export interface Props {
|
||||||
browser: BrowserProps;
|
browser: BrowserProps;
|
||||||
msg: MsgProps;
|
msg: MsgProps;
|
||||||
|
login: LoginProps;
|
||||||
update?: (updater: (prevState: ICoreState) => ICoreState) => void;
|
update?: (updater: (prevState: ICoreState) => ICoreState) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -477,6 +479,15 @@ export class Browser extends React.Component<Props, State, {}> {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
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 =
|
const itemListPane =
|
||||||
this.props.browser.tab === "" || this.props.browser.tab === "item" ? (
|
this.props.browser.tab === "" || this.props.browser.tab === "item" ? (
|
||||||
<div>
|
<div>
|
||||||
|
@ -485,49 +496,61 @@ export class Browser extends React.Component<Props, State, {}> {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="container">
|
<div className="container">
|
||||||
<div className="padding-m">
|
<Flexbox
|
||||||
{this.props.browser.isSharing ? (
|
children={List([
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
onClick={() => {
|
|
||||||
this.deleteSharing(this.props.browser.dirPath.join("/"));
|
|
||||||
}}
|
|
||||||
className="red0-bg white-font margin-r-m"
|
|
||||||
>
|
|
||||||
{this.props.msg.pkg.get("browser.share.del")}
|
|
||||||
</button>
|
|
||||||
) : (
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
onClick={this.addSharing}
|
|
||||||
className="green0-bg white-font margin-r-m"
|
|
||||||
>
|
|
||||||
{this.props.msg.pkg.get("browser.share.add")}
|
|
||||||
</button>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{this.state.selectedItems.size > 0 ? (
|
|
||||||
<span>
|
<span>
|
||||||
<button
|
{this.props.browser.isSharing ? (
|
||||||
type="button"
|
<button
|
||||||
onClick={() => this.delete()}
|
type="button"
|
||||||
className="red0-bg white-font margin-r-m"
|
onClick={() => {
|
||||||
>
|
this.deleteSharing(
|
||||||
{this.props.msg.pkg.get("browser.delete")}
|
this.props.browser.dirPath.join("/")
|
||||||
</button>
|
);
|
||||||
|
}}
|
||||||
|
className="red0-bg white-font margin-r-m"
|
||||||
|
>
|
||||||
|
{this.props.msg.pkg.get("browser.share.del")}
|
||||||
|
</button>
|
||||||
|
) : (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={this.addSharing}
|
||||||
|
className="green0-bg white-font margin-r-m"
|
||||||
|
>
|
||||||
|
{this.props.msg.pkg.get("browser.share.add")}
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
|
||||||
<button
|
{this.state.selectedItems.size > 0 ? (
|
||||||
type="button"
|
<span>
|
||||||
onClick={() => this.moveHere()}
|
<button
|
||||||
className="margin-r-m"
|
type="button"
|
||||||
>
|
onClick={() => this.delete()}
|
||||||
{this.props.msg.pkg.get("browser.paste")}
|
className="red0-bg white-font margin-r-m"
|
||||||
</button>
|
>
|
||||||
</span>
|
{this.props.msg.pkg.get("browser.delete")}
|
||||||
) : null}
|
</button>
|
||||||
|
|
||||||
<div className="hr white0-bg margin-t-m"></div>
|
<button
|
||||||
</div>
|
type="button"
|
||||||
|
onClick={() => this.moveHere()}
|
||||||
|
className="margin-r-m"
|
||||||
|
>
|
||||||
|
{this.props.msg.pkg.get("browser.paste")}
|
||||||
|
</button>
|
||||||
|
</span>
|
||||||
|
) : null}
|
||||||
|
</span>,
|
||||||
|
|
||||||
|
<span>
|
||||||
|
<span className="desc-m grey0-font">{`${this.props.msg.pkg.get(
|
||||||
|
"browser.used"
|
||||||
|
)} ${usedSpace} / ${spaceLimit}`}</span>
|
||||||
|
</span>,
|
||||||
|
])}
|
||||||
|
className="padding-m"
|
||||||
|
childrenStyles={List([{}, { justifyContent: "flex-end" }])}
|
||||||
|
/>
|
||||||
|
|
||||||
<Flexbox
|
<Flexbox
|
||||||
children={List([
|
children={List([
|
||||||
|
@ -539,18 +562,8 @@ export class Browser extends React.Component<Props, State, {}> {
|
||||||
className="margin-r-m black-font"
|
className="margin-r-m black-font"
|
||||||
/>,
|
/>,
|
||||||
|
|
||||||
// <span>
|
|
||||||
// <span className="title-l">
|
|
||||||
// {this.props.msg.pkg.get("browser.item.title")}
|
|
||||||
// </span>
|
|
||||||
// <span className="desc-l grey0-font">
|
|
||||||
// Files and folders in current path
|
|
||||||
// </span>
|
|
||||||
// </span>,
|
|
||||||
|
|
||||||
<Flexbox children={breadcrumb} />,
|
<Flexbox children={breadcrumb} />,
|
||||||
])}
|
])}
|
||||||
// style={{ flex: "column nowrap" }}
|
|
||||||
/>
|
/>
|
||||||
</span>,
|
</span>,
|
||||||
|
|
||||||
|
@ -687,7 +700,7 @@ export class Browser extends React.Component<Props, State, {}> {
|
||||||
children={List([
|
children={List([
|
||||||
<Flexbox
|
<Flexbox
|
||||||
children={List([
|
children={List([
|
||||||
<RiShareForwardBoxFill
|
<RiFolderSharedFill
|
||||||
size="3rem"
|
size="3rem"
|
||||||
className="purple0-font margin-r-m"
|
className="purple0-font margin-r-m"
|
||||||
/>,
|
/>,
|
||||||
|
|
|
@ -69,6 +69,12 @@ export function initState(): ICoreState {
|
||||||
userID: "",
|
userID: "",
|
||||||
userName: "",
|
userName: "",
|
||||||
userRole: "",
|
userRole: "",
|
||||||
|
usedSpace: "0",
|
||||||
|
quota: {
|
||||||
|
spaceLimit: "0",
|
||||||
|
uploadSpeedLimit: 0,
|
||||||
|
downloadSpeedLimit: 0,
|
||||||
|
},
|
||||||
authed: false,
|
authed: false,
|
||||||
captchaID: "",
|
captchaID: "",
|
||||||
},
|
},
|
||||||
|
|
|
@ -3,11 +3,14 @@ import * as React from "react";
|
||||||
import { ICoreState, MsgProps } from "./core_state";
|
import { ICoreState, MsgProps } from "./core_state";
|
||||||
import { updater } from "./state_updater";
|
import { updater } from "./state_updater";
|
||||||
import { alertMsg } from "../common/env";
|
import { alertMsg } from "../common/env";
|
||||||
|
import { Quota } from "../client";
|
||||||
|
|
||||||
export interface LoginProps {
|
export interface LoginProps {
|
||||||
userID: string;
|
userID: string;
|
||||||
userName: string;
|
userName: string;
|
||||||
userRole: string;
|
userRole: string;
|
||||||
|
usedSpace: string;
|
||||||
|
quota: Quota;
|
||||||
authed: boolean;
|
authed: boolean;
|
||||||
captchaID: string;
|
captchaID: string;
|
||||||
}
|
}
|
||||||
|
@ -85,11 +88,17 @@ export class AuthPane extends React.Component<Props, State, {}> {
|
||||||
|
|
||||||
updater().initLan();
|
updater().initLan();
|
||||||
this.update(updater().updateMsg);
|
this.update(updater().updateMsg);
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
return updater().isSharing(updater().props.browser.dirPath.join("/"));
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
this.update(updater().updateBrowser);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
logout = () => {
|
logout = async () => {
|
||||||
updater()
|
return updater()
|
||||||
.logout()
|
.logout()
|
||||||
.then((ok: boolean) => {
|
.then((ok: boolean) => {
|
||||||
if (ok) {
|
if (ok) {
|
||||||
|
@ -97,6 +106,9 @@ export class AuthPane extends React.Component<Props, State, {}> {
|
||||||
} else {
|
} else {
|
||||||
alertMsg(this.props.msg.pkg.get("login.logout.fail"));
|
alertMsg(this.props.msg.pkg.get("login.logout.fail"));
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
return this.refreshCaptcha();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -52,13 +52,14 @@ export class RootFrame extends React.Component<Props, State, {}> {
|
||||||
<Browser
|
<Browser
|
||||||
browser={this.props.browser}
|
browser={this.props.browser}
|
||||||
msg={this.props.msg}
|
msg={this.props.msg}
|
||||||
|
login={this.props.login}
|
||||||
update={this.props.update}
|
update={this.props.update}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="tail" className="container-center black0-font">
|
<div id="tail" className="container-center black0-font">
|
||||||
<a href="https://github.com/ihexxa/quickshare">Quickshare</a> -
|
<a href="https://github.com/ihexxa/quickshare">Quickshare</a> -
|
||||||
sharing in simple way.
|
quick and simple file sharing.
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -258,6 +258,8 @@ export class Updater {
|
||||||
this.props.login.userID = resp.data.id;
|
this.props.login.userID = resp.data.id;
|
||||||
this.props.login.userName = resp.data.name;
|
this.props.login.userName = resp.data.name;
|
||||||
this.props.login.userRole = resp.data.role;
|
this.props.login.userRole = resp.data.role;
|
||||||
|
this.props.login.usedSpace = resp.data.usedSpace;
|
||||||
|
this.props.login.quota = resp.data.quota;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
import * as React from "react";
|
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 { ICoreState, MsgProps } from "./core_state";
|
||||||
import { LoginProps } from "./pane_login";
|
import { LoginProps } from "./pane_login";
|
||||||
import { updater } from "./state_updater";
|
import { updater } from "./state_updater";
|
||||||
|
import { Flexbox } from "./layout/flexbox";
|
||||||
|
|
||||||
export interface State {}
|
export interface State {}
|
||||||
export interface Props {
|
export interface Props {
|
||||||
|
@ -43,6 +46,7 @@ export class TopBar extends React.Component<Props, State, {}> {
|
||||||
<button
|
<button
|
||||||
onClick={this.showAdmin}
|
onClick={this.showAdmin}
|
||||||
className="grey3-bg grey4-font margin-r-m"
|
className="grey3-bg grey4-font margin-r-m"
|
||||||
|
style={{ minWidth: "7rem" }}
|
||||||
>
|
>
|
||||||
{this.props.msg.pkg.get("admin")}
|
{this.props.msg.pkg.get("admin")}
|
||||||
</button>
|
</button>
|
||||||
|
@ -53,7 +57,48 @@ export class TopBar extends React.Component<Props, State, {}> {
|
||||||
id="top-bar"
|
id="top-bar"
|
||||||
className="top-bar cyan1-font padding-t-m padding-b-m padding-l-l padding-r-l"
|
className="top-bar cyan1-font padding-t-m padding-b-m padding-l-l padding-r-l"
|
||||||
>
|
>
|
||||||
<div className="flex-2col-parent">
|
<Flexbox
|
||||||
|
children={List([
|
||||||
|
<a
|
||||||
|
href="https://github.com/ihexxa/quickshare"
|
||||||
|
target="_blank"
|
||||||
|
className="h5"
|
||||||
|
>
|
||||||
|
Quickshare
|
||||||
|
{/* <RiGithubFill size="2rem" className="grey4-font margin-r-m" /> */}
|
||||||
|
</a>,
|
||||||
|
|
||||||
|
<Flexbox
|
||||||
|
children={List([
|
||||||
|
<span>
|
||||||
|
<span className="grey3-font font-s">
|
||||||
|
{this.props.login.userName}
|
||||||
|
</span>
|
||||||
|
-
|
||||||
|
<span className="grey0-font font-s margin-r-m">
|
||||||
|
{this.props.login.userRole}
|
||||||
|
</span>
|
||||||
|
</span>,
|
||||||
|
|
||||||
|
<button
|
||||||
|
onClick={this.showSettings}
|
||||||
|
className="grey3-bg grey4-font margin-r-m"
|
||||||
|
style={{ minWidth: "7rem" }}
|
||||||
|
>
|
||||||
|
{this.props.msg.pkg.get("settings")}
|
||||||
|
</button>,
|
||||||
|
|
||||||
|
adminBtn,
|
||||||
|
])}
|
||||||
|
childrenStyles={List([{}, {}, {}, {}])}
|
||||||
|
/>,
|
||||||
|
])}
|
||||||
|
childrenStyles={List([
|
||||||
|
{},
|
||||||
|
{ justifyContent: "flex-end", alignItems: "center" },
|
||||||
|
])}
|
||||||
|
/>
|
||||||
|
{/* <div className="flex-2col-parent">
|
||||||
<a
|
<a
|
||||||
href="https://github.com/ihexxa/quickshare"
|
href="https://github.com/ihexxa/quickshare"
|
||||||
className="flex-13col h5"
|
className="flex-13col h5"
|
||||||
|
@ -75,8 +120,13 @@ export class TopBar extends React.Component<Props, State, {}> {
|
||||||
{this.props.msg.pkg.get("settings")}
|
{this.props.msg.pkg.get("settings")}
|
||||||
</button>
|
</button>
|
||||||
{adminBtn}
|
{adminBtn}
|
||||||
|
|
||||||
|
<RiGithubFill
|
||||||
|
size="2rem"
|
||||||
|
className="grey4-font margin-r-m"
|
||||||
|
/>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div> */}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@ export const msgs: Map<string, string> = Map({
|
||||||
"browser.disable": "Disable",
|
"browser.disable": "Disable",
|
||||||
"browser.location": "Location",
|
"browser.location": "Location",
|
||||||
"browser.item.title": "Items",
|
"browser.item.title": "Items",
|
||||||
|
"browser.used": "Used Space",
|
||||||
"panes.close": "Close",
|
"panes.close": "Close",
|
||||||
"login.logout.fail": "Failed to log out",
|
"login.logout.fail": "Failed to log out",
|
||||||
"login.username": "User Name",
|
"login.username": "User Name",
|
||||||
|
|
|
@ -25,6 +25,7 @@ export const msgs: Map<string, string> = Map({
|
||||||
"browser.stop": "停止",
|
"browser.stop": "停止",
|
||||||
"browser.location": "位置",
|
"browser.location": "位置",
|
||||||
"browser.item.title": "列表",
|
"browser.item.title": "列表",
|
||||||
|
"browser.used": "已用空间",
|
||||||
"panes.close": "关闭",
|
"panes.close": "关闭",
|
||||||
"login.logout.fail": "登出失败",
|
"login.logout.fail": "登出失败",
|
||||||
"login.username": "用户名",
|
"login.username": "用户名",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue