feat(ui): enable i18n
This commit is contained in:
parent
3531e7a265
commit
eb6d9c2490
15 changed files with 408 additions and 252 deletions
|
@ -22,14 +22,8 @@ describe("Browser", () => {
|
|||
updater().setClients(usersCl, filesCl);
|
||||
|
||||
const browser = new Browser({
|
||||
dirPath: coreState.browser.dirPath,
|
||||
isSharing: coreState.browser.isSharing,
|
||||
items: coreState.browser.items,
|
||||
uploadings: coreState.browser.uploadings,
|
||||
sharings: coreState.browser.sharings,
|
||||
uploadFiles: coreState.browser.uploadFiles,
|
||||
uploadValue: coreState.browser.uploadValue,
|
||||
isVertical: coreState.browser.isVertical,
|
||||
browser: coreState.browser,
|
||||
msg: coreState.msg,
|
||||
update: (updater: (prevState: ICoreState) => ICoreState) => {},
|
||||
});
|
||||
|
||||
|
|
|
@ -16,9 +16,8 @@ describe("Login", () => {
|
|||
|
||||
const coreState = newWithWorker(mockWorker);
|
||||
const pane = new AuthPane({
|
||||
userRole: coreState.login.userRole,
|
||||
authed: coreState.login.authed,
|
||||
captchaID: coreState.login.captchaID,
|
||||
login: coreState.login,
|
||||
msg: coreState.msg,
|
||||
update: (updater: (prevState: ICoreState) => ICoreState) => {},
|
||||
});
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ import FileSize from "filesize";
|
|||
|
||||
import { alertMsg, comfirmMsg } from "../common/env";
|
||||
import { updater } from "./state_updater";
|
||||
import { ICoreState } from "./core_state";
|
||||
import { ICoreState, MsgProps } from "./core_state";
|
||||
import { MetadataResp, UploadInfo } from "../client";
|
||||
import { Up } from "../worker/upload_mgr";
|
||||
import { UploadEntry } from "../worker/interface";
|
||||
|
@ -18,7 +18,7 @@ export interface Item {
|
|||
selected: boolean;
|
||||
}
|
||||
|
||||
export interface Props {
|
||||
export interface BrowserProps {
|
||||
dirPath: List<string>;
|
||||
isSharing: boolean;
|
||||
items: List<MetadataResp>;
|
||||
|
@ -29,7 +29,11 @@ export interface Props {
|
|||
uploadValue: string;
|
||||
|
||||
isVertical: boolean;
|
||||
}
|
||||
|
||||
export interface Props {
|
||||
browser: BrowserProps;
|
||||
msg: MsgProps;
|
||||
update?: (updater: (prevState: ICoreState) => ICoreState) => void;
|
||||
}
|
||||
|
||||
|
@ -90,7 +94,7 @@ export class Browser extends React.Component<Props, State, {}> {
|
|||
.deleteUpload(filePath)
|
||||
.then((ok: boolean) => {
|
||||
if (!ok) {
|
||||
alertMsg(`Failed to delete uploading ${filePath}`);
|
||||
alertMsg(this.props.msg.pkg.get("browser.upload.del.fail"));
|
||||
}
|
||||
return updater().refreshUploadings();
|
||||
})
|
||||
|
@ -106,19 +110,19 @@ export class Browser extends React.Component<Props, State, {}> {
|
|||
|
||||
onMkDir = () => {
|
||||
if (this.state.inputValue === "") {
|
||||
alertMsg("folder name can not be empty");
|
||||
alertMsg(this.props.msg.pkg.get("browser.folder.add.fail"));
|
||||
return;
|
||||
}
|
||||
|
||||
const dirPath = getItemPath(
|
||||
this.props.dirPath.join("/"),
|
||||
this.props.browser.dirPath.join("/"),
|
||||
this.state.inputValue
|
||||
);
|
||||
updater()
|
||||
.mkDir(dirPath)
|
||||
.then(() => {
|
||||
this.setState({ inputValue: "" });
|
||||
return updater().setItems(this.props.dirPath);
|
||||
return updater().setItems(this.props.browser.dirPath);
|
||||
})
|
||||
.then(() => {
|
||||
this.update(updater().updateBrowser);
|
||||
|
@ -126,10 +130,10 @@ export class Browser extends React.Component<Props, State, {}> {
|
|||
};
|
||||
|
||||
delete = () => {
|
||||
if (this.props.dirPath.join("/") !== this.state.selectedSrc) {
|
||||
alertMsg("please select file or folder to delete at first");
|
||||
if (this.props.browser.dirPath.join("/") !== this.state.selectedSrc) {
|
||||
alertMsg(this.props.msg.pkg.get("browser.del.fail"));
|
||||
this.setState({
|
||||
selectedSrc: this.props.dirPath.join("/"),
|
||||
selectedSrc: this.props.browser.dirPath.join("/"),
|
||||
selectedItems: Map<string, boolean>(),
|
||||
});
|
||||
return;
|
||||
|
@ -141,7 +145,11 @@ export class Browser extends React.Component<Props, State, {}> {
|
|||
}
|
||||
|
||||
updater()
|
||||
.delete(this.props.dirPath, this.props.items, this.state.selectedItems)
|
||||
.delete(
|
||||
this.props.browser.dirPath,
|
||||
this.props.browser.items,
|
||||
this.state.selectedItems
|
||||
)
|
||||
.then(() => {
|
||||
this.update(updater().updateBrowser);
|
||||
this.setState({
|
||||
|
@ -153,16 +161,16 @@ export class Browser extends React.Component<Props, State, {}> {
|
|||
|
||||
moveHere = () => {
|
||||
const oldDir = this.state.selectedSrc;
|
||||
const newDir = this.props.dirPath.join("/");
|
||||
const newDir = this.props.browser.dirPath.join("/");
|
||||
if (oldDir === newDir) {
|
||||
alertMsg("source directory is same as destination directory");
|
||||
alertMsg(this.props.msg.pkg.get("browser.move.fail"));
|
||||
return;
|
||||
}
|
||||
|
||||
updater()
|
||||
.moveHere(
|
||||
this.state.selectedSrc,
|
||||
this.props.dirPath.join("/"),
|
||||
this.props.browser.dirPath.join("/"),
|
||||
this.state.selectedItems
|
||||
)
|
||||
.then(() => {
|
||||
|
@ -175,11 +183,11 @@ export class Browser extends React.Component<Props, State, {}> {
|
|||
};
|
||||
|
||||
gotoChild = (childDirName: string) => {
|
||||
this.chdir(this.props.dirPath.push(childDirName));
|
||||
this.chdir(this.props.browser.dirPath.push(childDirName));
|
||||
};
|
||||
|
||||
chdir = async (dirPath: List<string>) => {
|
||||
if (dirPath === this.props.dirPath) {
|
||||
if (dirPath === this.props.browser.dirPath) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -199,7 +207,7 @@ export class Browser extends React.Component<Props, State, {}> {
|
|||
updateProgress = (infos: Map<string, UploadEntry>) => {
|
||||
updater().setUploadings(infos);
|
||||
updater()
|
||||
.setItems(this.props.dirPath)
|
||||
.setItems(this.props.browser.dirPath)
|
||||
.then(() => {
|
||||
this.update(updater().updateBrowser);
|
||||
});
|
||||
|
@ -211,7 +219,7 @@ export class Browser extends React.Component<Props, State, {}> {
|
|||
: this.state.selectedItems.set(itemName, true);
|
||||
|
||||
this.setState({
|
||||
selectedSrc: this.props.dirPath.join("/"),
|
||||
selectedSrc: this.props.browser.dirPath.join("/"),
|
||||
selectedItems: selectedItems,
|
||||
});
|
||||
};
|
||||
|
@ -220,17 +228,17 @@ export class Browser extends React.Component<Props, State, {}> {
|
|||
let newSelected = Map<string, boolean>();
|
||||
const someSelected = this.state.selectedItems.size === 0 ? true : false;
|
||||
if (someSelected) {
|
||||
this.props.items.forEach((item) => {
|
||||
this.props.browser.items.forEach((item) => {
|
||||
newSelected = newSelected.set(item.name, true);
|
||||
});
|
||||
} else {
|
||||
this.props.items.forEach((item) => {
|
||||
this.props.browser.items.forEach((item) => {
|
||||
newSelected = newSelected.delete(item.name);
|
||||
});
|
||||
}
|
||||
|
||||
this.setState({
|
||||
selectedSrc: this.props.dirPath.join("/"),
|
||||
selectedSrc: this.props.browser.dirPath.join("/"),
|
||||
selectedItems: newSelected,
|
||||
});
|
||||
};
|
||||
|
@ -240,7 +248,7 @@ export class Browser extends React.Component<Props, State, {}> {
|
|||
.addSharing()
|
||||
.then((ok) => {
|
||||
if (!ok) {
|
||||
alertMsg("failed to enable sharing");
|
||||
alertMsg(this.props.msg.pkg.get("browser.share.add.fail"));
|
||||
} else {
|
||||
updater().setSharing(true);
|
||||
return this.listSharings();
|
||||
|
@ -256,7 +264,7 @@ export class Browser extends React.Component<Props, State, {}> {
|
|||
.deleteSharing(dirPath)
|
||||
.then((ok) => {
|
||||
if (!ok) {
|
||||
alertMsg("failed to disable sharing");
|
||||
alertMsg(this.props.msg.pkg.get("browser.share.del.fail"));
|
||||
} else {
|
||||
updater().setSharing(false);
|
||||
return this.listSharings();
|
||||
|
@ -278,13 +286,15 @@ export class Browser extends React.Component<Props, State, {}> {
|
|||
};
|
||||
|
||||
render() {
|
||||
const breadcrumb = this.props.dirPath.map(
|
||||
const breadcrumb = this.props.browser.dirPath.map(
|
||||
(pathPart: string, key: number) => {
|
||||
return (
|
||||
<span key={pathPart}>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => this.chdir(this.props.dirPath.slice(0, key + 1))}
|
||||
onClick={() =>
|
||||
this.chdir(this.props.browser.dirPath.slice(0, key + 1))
|
||||
}
|
||||
className="white-font margin-r-m"
|
||||
style={{ backgroundColor: "rgba(0, 0, 0, 0.7)" }}
|
||||
>
|
||||
|
@ -296,10 +306,14 @@ export class Browser extends React.Component<Props, State, {}> {
|
|||
);
|
||||
|
||||
const nameCellClass = `item-name item-name-${
|
||||
this.props.isVertical ? "vertical" : "horizontal"
|
||||
this.props.browser.isVertical ? "vertical" : "horizontal"
|
||||
} pointer`;
|
||||
const sizeCellClass = this.props.isVertical ? `hidden margin-s` : ``;
|
||||
const modTimeCellClass = this.props.isVertical ? `hidden margin-s` : ``;
|
||||
const sizeCellClass = this.props.browser.isVertical
|
||||
? `hidden margin-s`
|
||||
: ``;
|
||||
const modTimeCellClass = this.props.browser.isVertical
|
||||
? `hidden margin-s`
|
||||
: ``;
|
||||
|
||||
const ops = (
|
||||
<div>
|
||||
|
@ -310,13 +324,13 @@ export class Browser extends React.Component<Props, State, {}> {
|
|||
onChange={this.onInputChange}
|
||||
value={this.state.inputValue}
|
||||
className="black0-font margin-r-m"
|
||||
placeholder="folder name"
|
||||
placeholder={this.props.msg.pkg.get("browser.folder.name")}
|
||||
/>
|
||||
<button
|
||||
onClick={this.onMkDir}
|
||||
className="grey1-bg white-font margin-r-m"
|
||||
>
|
||||
Create Folder
|
||||
{this.props.msg.pkg.get("browser.folder.add")}
|
||||
</button>
|
||||
</span>
|
||||
<span className="inline-block margin-t-m margin-b-m">
|
||||
|
@ -324,13 +338,13 @@ export class Browser extends React.Component<Props, State, {}> {
|
|||
onClick={this.onClickUpload}
|
||||
className="green0-bg white-font"
|
||||
>
|
||||
Upload Files
|
||||
{this.props.msg.pkg.get("browser.upload")}
|
||||
</button>
|
||||
<input
|
||||
type="file"
|
||||
onChange={this.addUploads}
|
||||
multiple={true}
|
||||
value={this.props.uploadValue}
|
||||
value={this.props.browser.uploadValue}
|
||||
ref={this.assignInput}
|
||||
className="black0-font hidden"
|
||||
/>
|
||||
|
@ -345,24 +359,24 @@ export class Browser extends React.Component<Props, State, {}> {
|
|||
onClick={() => this.delete()}
|
||||
className="red0-bg white-font margin-t-m margin-b-m margin-r-m"
|
||||
>
|
||||
Delete Selected
|
||||
{this.props.msg.pkg.get("browser.delete")}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => this.moveHere()}
|
||||
className="grey1-bg white-font margin-t-m margin-b-m margin-r-m"
|
||||
>
|
||||
Paste
|
||||
{this.props.msg.pkg.get("browser.paste")}
|
||||
</button>
|
||||
{this.props.isSharing ? (
|
||||
{this.props.browser.isSharing ? (
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
this.deleteSharing(this.props.dirPath.join("/"));
|
||||
this.deleteSharing(this.props.browser.dirPath.join("/"));
|
||||
}}
|
||||
className="red0-bg white-font margin-t-m margin-b-m"
|
||||
>
|
||||
Stop Sharing
|
||||
{this.props.msg.pkg.get("browser.share.del")}
|
||||
</button>
|
||||
) : (
|
||||
<button
|
||||
|
@ -370,16 +384,16 @@ export class Browser extends React.Component<Props, State, {}> {
|
|||
onClick={this.addSharing}
|
||||
className="green0-bg white-font margin-t-m margin-b-m"
|
||||
>
|
||||
Share Folder
|
||||
{this.props.msg.pkg.get("browser.share.add")}
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
const itemList = this.props.items.map((item: MetadataResp) => {
|
||||
const itemList = this.props.browser.items.map((item: MetadataResp) => {
|
||||
const isSelected = this.state.selectedItems.has(item.name);
|
||||
const dirPath = this.props.dirPath.join("/");
|
||||
const dirPath = this.props.browser.dirPath.join("/");
|
||||
const itemPath = dirPath.endsWith("/")
|
||||
? `${dirPath}${item.name}`
|
||||
: `${dirPath}/${item.name}`;
|
||||
|
@ -404,7 +418,9 @@ export class Browser extends React.Component<Props, State, {}> {
|
|||
className={`white-font ${isSelected ? "blue0-bg" : "grey1-bg"}`}
|
||||
style={{ width: "8rem", display: "inline-block" }}
|
||||
>
|
||||
{isSelected ? "Deselect" : "Select"}
|
||||
{isSelected
|
||||
? this.props.msg.pkg.get("browser.deselect")
|
||||
: this.props.msg.pkg.get("browser.select")}
|
||||
</button>
|
||||
</span>
|
||||
</span>
|
||||
|
@ -435,7 +451,9 @@ export class Browser extends React.Component<Props, State, {}> {
|
|||
className={`white-font ${isSelected ? "blue0-bg" : "grey1-bg"}`}
|
||||
style={{ width: "8rem", display: "inline-block" }}
|
||||
>
|
||||
{isSelected ? "Deselect" : "Select"}
|
||||
{isSelected
|
||||
? this.props.msg.pkg.get("browser.deselect")
|
||||
: this.props.msg.pkg.get("browser.select")}
|
||||
</button>
|
||||
</span>
|
||||
</span>
|
||||
|
@ -443,43 +461,45 @@ export class Browser extends React.Component<Props, State, {}> {
|
|||
);
|
||||
});
|
||||
|
||||
const uploadingList = this.props.uploadings.map((uploading: UploadInfo) => {
|
||||
const pathParts = uploading.realFilePath.split("/");
|
||||
const fileName = pathParts[pathParts.length - 1];
|
||||
const uploadingList = this.props.browser.uploadings.map(
|
||||
(uploading: UploadInfo) => {
|
||||
const pathParts = uploading.realFilePath.split("/");
|
||||
const fileName = pathParts[pathParts.length - 1];
|
||||
|
||||
return (
|
||||
<div key={fileName} className="flex-list-container">
|
||||
<span className="flex-list-item-l">
|
||||
<span className="vbar blue2-bg"></span>
|
||||
<div className={nameCellClass}>
|
||||
<span className="bold">{fileName}</span>
|
||||
<div className="grey1-font">
|
||||
{FileSize(uploading.uploaded, { round: 0 })}
|
||||
/ {FileSize(uploading.size, { round: 0 })}
|
||||
return (
|
||||
<div key={fileName} className="flex-list-container">
|
||||
<span className="flex-list-item-l">
|
||||
<span className="vbar blue2-bg"></span>
|
||||
<div className={nameCellClass}>
|
||||
<span className="bold">{fileName}</span>
|
||||
<div className="grey1-font">
|
||||
{FileSize(uploading.uploaded, { round: 0 })}
|
||||
/ {FileSize(uploading.size, { round: 0 })}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</span>
|
||||
<span className="flex-list-item-r padding-r-m">
|
||||
<div className="item-op">
|
||||
<button
|
||||
onClick={() => this.stopUploading(uploading.realFilePath)}
|
||||
className="grey1-bg white-font margin-r-m"
|
||||
>
|
||||
Stop
|
||||
</button>
|
||||
<button
|
||||
onClick={() => this.deleteUpload(uploading.realFilePath)}
|
||||
className="grey1-bg white-font"
|
||||
>
|
||||
Delete
|
||||
</button>
|
||||
</div>
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
</span>
|
||||
<span className="flex-list-item-r padding-r-m">
|
||||
<div className="item-op">
|
||||
<button
|
||||
onClick={() => this.stopUploading(uploading.realFilePath)}
|
||||
className="grey1-bg white-font margin-r-m"
|
||||
>
|
||||
{this.props.msg.pkg.get("browser.stop")}
|
||||
</button>
|
||||
<button
|
||||
onClick={() => this.deleteUpload(uploading.realFilePath)}
|
||||
className="grey1-bg white-font"
|
||||
>
|
||||
{this.props.msg.pkg.get("browser.delete")}
|
||||
</button>
|
||||
</div>
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
const sharingList = this.props.sharings.map((dirPath: string) => {
|
||||
const sharingList = this.props.browser.sharings.map((dirPath: string) => {
|
||||
return (
|
||||
<div key={dirPath} className="flex-list-container">
|
||||
<span className="flex-list-item-l">
|
||||
|
@ -501,7 +521,7 @@ export class Browser extends React.Component<Props, State, {}> {
|
|||
}}
|
||||
className="grey1-bg white-font"
|
||||
>
|
||||
Disable
|
||||
{this.props.msg.pkg.get("browser.share.del")}
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
|
@ -525,17 +545,17 @@ export class Browser extends React.Component<Props, State, {}> {
|
|||
borderRadius: "0.5rem",
|
||||
}}
|
||||
>
|
||||
Location:
|
||||
{this.props.msg.pkg.get("browser.location")}
|
||||
</span>
|
||||
{breadcrumb}
|
||||
</div>
|
||||
|
||||
{this.props.uploadings.size === 0 ? null : (
|
||||
{this.props.browser.uploadings.size === 0 ? null : (
|
||||
<div className="container">
|
||||
<div className="flex-list-container bold">
|
||||
<span className="flex-list-item-l">
|
||||
<span className="dot black-bg"></span>
|
||||
<span>Uploading Files</span>
|
||||
<span>{this.props.msg.pkg.get("browser.upload.title")}</span>
|
||||
</span>
|
||||
<span className="flex-list-item-r padding-r-m"></span>
|
||||
</div>
|
||||
|
@ -543,12 +563,12 @@ export class Browser extends React.Component<Props, State, {}> {
|
|||
</div>
|
||||
)}
|
||||
|
||||
{this.props.sharings.size === 0 ? null : (
|
||||
{this.props.browser.sharings.size === 0 ? null : (
|
||||
<div className="container">
|
||||
<div className="flex-list-container bold">
|
||||
<span className="flex-list-item-l">
|
||||
<span className="dot black-bg"></span>
|
||||
<span>Sharing Folders</span>
|
||||
<span>{this.props.msg.pkg.get("browser.share.title")}</span>
|
||||
</span>
|
||||
<span className="flex-list-item-r padding-r-m"></span>
|
||||
</div>
|
||||
|
@ -560,9 +580,7 @@ export class Browser extends React.Component<Props, State, {}> {
|
|||
<div className="flex-list-container bold">
|
||||
<span className="flex-list-item-l">
|
||||
<span className="dot black-bg"></span>
|
||||
<span>Name</span>
|
||||
{/* <span>File Size</span>
|
||||
<span>Mod Time</span> */}
|
||||
<span>{this.props.msg.pkg.get("browser.item.title")}</span>
|
||||
</span>
|
||||
<span className="flex-list-item-r padding-r-m">
|
||||
<button
|
||||
|
@ -570,7 +588,7 @@ export class Browser extends React.Component<Props, State, {}> {
|
|||
className={`grey1-bg white-font`}
|
||||
style={{ width: "8rem", display: "inline-block" }}
|
||||
>
|
||||
Select All
|
||||
{this.props.msg.pkg.get("browser.selectAll")}
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
|
|
|
@ -4,16 +4,20 @@ import BgWorker from "../worker/upload.bg.worker";
|
|||
import { FgWorker } from "../worker/upload.fg.worker";
|
||||
|
||||
// import { Props as PanelProps } from "./root_frame";
|
||||
import { Props as BrowserProps } from "./browser";
|
||||
import { PanesProps as PanesProps } from "./panes";
|
||||
import { Props as LoginProps } from "./pane_login";
|
||||
import { Props as AdminProps } from "./pane_admin";
|
||||
import { Props as SettingsProps } from "./pane_settings";
|
||||
import { BrowserProps } from "./browser";
|
||||
import { PanesProps } from "./panes";
|
||||
import { LoginProps } from "./pane_login";
|
||||
import { AdminProps } from "./pane_admin";
|
||||
|
||||
import { MsgPackage } from "../i18n/msger";
|
||||
import { Item } from "./browser";
|
||||
import { UploadInfo, User } from "../client";
|
||||
import { initUploadMgr, IWorker } from "../worker/upload_mgr";
|
||||
|
||||
export interface MsgProps {
|
||||
lan: string;
|
||||
pkg: Map<string, string>;
|
||||
}
|
||||
export interface ICoreState {
|
||||
// panel: PanelProps;
|
||||
isVertical: boolean;
|
||||
|
@ -21,6 +25,7 @@ export interface ICoreState {
|
|||
panes: PanesProps;
|
||||
login: LoginProps;
|
||||
admin: AdminProps;
|
||||
msg: MsgProps;
|
||||
// settings: SettingsProps;
|
||||
}
|
||||
|
||||
|
@ -62,6 +67,10 @@ export function initState(): ICoreState {
|
|||
users: Map<string, User>(),
|
||||
roles: Set<string>(),
|
||||
},
|
||||
msg: {
|
||||
lan: "en_US",
|
||||
pkg: MsgPackage.get("en_US"),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -1,13 +1,19 @@
|
|||
import * as React from "react";
|
||||
import { Map, Set } from "immutable";
|
||||
|
||||
import { ICoreState } from "./core_state";
|
||||
import { alertMsg } from "../common/env";
|
||||
import { ICoreState, MsgProps } from "./core_state";
|
||||
import { User, Quota } from "../client";
|
||||
import { updater } from "./state_updater";
|
||||
|
||||
export interface Props {
|
||||
export interface AdminProps {
|
||||
users: Map<string, User>;
|
||||
roles: Set<string>;
|
||||
}
|
||||
|
||||
export interface Props {
|
||||
admin: AdminProps;
|
||||
msg: MsgProps;
|
||||
update?: (updater: (prevState: ICoreState) => ICoreState) => void;
|
||||
}
|
||||
|
||||
|
@ -18,6 +24,7 @@ export interface UserFormProps {
|
|||
role: string;
|
||||
quota: Quota;
|
||||
roles: Set<string>;
|
||||
msg: MsgProps;
|
||||
update?: (updater: (prevState: ICoreState) => ICoreState) => void;
|
||||
}
|
||||
|
||||
|
@ -90,7 +97,7 @@ export class UserForm extends React.Component<
|
|||
|
||||
setPwd = () => {
|
||||
if (this.state.newPwd1 !== this.state.newPwd2) {
|
||||
alert("2 passwords do not match, please check.");
|
||||
alertMsg(this.props.msg.pkg.get("settings.pwd.notSame"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -98,9 +105,9 @@ export class UserForm extends React.Component<
|
|||
.forceSetPwd(this.state.id, this.state.newPwd1)
|
||||
.then((ok: boolean) => {
|
||||
if (ok) {
|
||||
alert("password is updated");
|
||||
alertMsg(this.props.msg.pkg.get("update.ok"));
|
||||
} else {
|
||||
alert("failed to update password");
|
||||
alertMsg(this.props.msg.pkg.get("update.fail"));
|
||||
}
|
||||
this.setState({
|
||||
newPwd1: "",
|
||||
|
@ -114,9 +121,9 @@ export class UserForm extends React.Component<
|
|||
.setUser(this.props.id, this.state.role, this.state.quota)
|
||||
.then((ok: boolean) => {
|
||||
if (!ok) {
|
||||
alert("failed to set user");
|
||||
alertMsg(this.props.msg.pkg.get("update.fail"));
|
||||
} else {
|
||||
alert("user is updated");
|
||||
alertMsg(this.props.msg.pkg.get("update.ok"));
|
||||
}
|
||||
return updater().listUsers();
|
||||
})
|
||||
|
@ -130,7 +137,7 @@ export class UserForm extends React.Component<
|
|||
.delUser(this.state.id)
|
||||
.then((ok: boolean) => {
|
||||
if (!ok) {
|
||||
alert("failed to delete user");
|
||||
alertMsg(this.props.msg.pkg.get("delete.fail"));
|
||||
}
|
||||
return updater().listUsers();
|
||||
})
|
||||
|
@ -155,8 +162,12 @@ export class UserForm extends React.Component<
|
|||
}}
|
||||
className="bold item-name"
|
||||
>
|
||||
<div>ID: {this.props.id}</div>
|
||||
<div>Name: {this.props.name}</div>
|
||||
<div>
|
||||
{this.props.msg.pkg.get("user.id")} {this.props.id}
|
||||
</div>
|
||||
<div>
|
||||
{this.props.msg.pkg.get("user.name")} {this.props.name}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -172,7 +183,7 @@ export class UserForm extends React.Component<
|
|||
onClick={this.delUser}
|
||||
className="grey1-bg white-font margin-r-m"
|
||||
>
|
||||
Delete User
|
||||
{this.props.msg.pkg.get("delete")}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -196,7 +207,7 @@ export class UserForm extends React.Component<
|
|||
|
||||
<div className="margin-t-m">
|
||||
<div className="margin-r-m font-size-s grey1-font">
|
||||
Space Limit
|
||||
{this.props.msg.pkg.get("spaceLimit")}
|
||||
</div>
|
||||
<input
|
||||
name={`${this.props.id}-spaceLimit`}
|
||||
|
@ -210,7 +221,7 @@ export class UserForm extends React.Component<
|
|||
|
||||
<div className="margin-t-m">
|
||||
<div className="margin-r-m font-size-s grey1-font">
|
||||
Upload Speed Limit
|
||||
{this.props.msg.pkg.get("uploadLimit")}
|
||||
</div>
|
||||
<input
|
||||
name={`${this.props.id}-uploadSpeedLimit`}
|
||||
|
@ -224,7 +235,7 @@ export class UserForm extends React.Component<
|
|||
|
||||
<div className="margin-t-m">
|
||||
<div className="margin-r-m font-size-s grey1-font">
|
||||
Download Speed Limit
|
||||
{this.props.msg.pkg.get("downloadLimit")}
|
||||
</div>
|
||||
<input
|
||||
name={`${this.props.id}-downloadSpeedLimit`}
|
||||
|
@ -242,7 +253,7 @@ export class UserForm extends React.Component<
|
|||
onClick={this.setUser}
|
||||
className="grey1-bg white-font margin-r-m"
|
||||
>
|
||||
Update User
|
||||
{this.props.msg.pkg.get("update")}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -262,7 +273,7 @@ export class UserForm extends React.Component<
|
|||
onChange={this.changePwd1}
|
||||
value={this.state.newPwd1}
|
||||
className="black0-font margin-b-m"
|
||||
placeholder="new password"
|
||||
placeholder={this.props.msg.pkg.get("settings.pwd.new1")}
|
||||
/>
|
||||
<input
|
||||
name={`${this.props.id}-pwd2`}
|
||||
|
@ -270,7 +281,7 @@ export class UserForm extends React.Component<
|
|||
onChange={this.changePwd2}
|
||||
value={this.state.newPwd2}
|
||||
className="black0-font margin-b-m"
|
||||
placeholder="repeat password"
|
||||
placeholder={this.props.msg.pkg.get("settings.pwd.new2")}
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
@ -279,7 +290,7 @@ export class UserForm extends React.Component<
|
|||
onClick={this.setPwd}
|
||||
className="grey1-bg white-font margin-r-m"
|
||||
>
|
||||
Update
|
||||
{this.props.msg.pkg.get("update")}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -328,7 +339,9 @@ export class AdminPane extends React.Component<Props, State, {}> {
|
|||
.addRole(this.state.newRole)
|
||||
.then((ok: boolean) => {
|
||||
if (!ok) {
|
||||
alert("failed to add role");
|
||||
alertMsg(this.props.msg.pkg.get("add.fail"));
|
||||
} else {
|
||||
alertMsg(this.props.msg.pkg.get("add.ok"));
|
||||
}
|
||||
return updater().listRoles();
|
||||
})
|
||||
|
@ -340,7 +353,7 @@ export class AdminPane extends React.Component<Props, State, {}> {
|
|||
delRole = (role: string) => {
|
||||
if (
|
||||
!confirm(
|
||||
"After deleting this role, some of users may not be able to login."
|
||||
this.props.msg.pkg.get("role.delete.warning") // "After deleting this role, some of users may not be able to login."
|
||||
)
|
||||
) {
|
||||
return;
|
||||
|
@ -350,7 +363,9 @@ export class AdminPane extends React.Component<Props, State, {}> {
|
|||
.delRole(role)
|
||||
.then((ok: boolean) => {
|
||||
if (!ok) {
|
||||
alert("failed to delete role");
|
||||
this.props.msg.pkg.get("delete.fail");
|
||||
} else {
|
||||
this.props.msg.pkg.get("delete.ok");
|
||||
}
|
||||
return updater().listRoles();
|
||||
})
|
||||
|
@ -361,7 +376,7 @@ export class AdminPane extends React.Component<Props, State, {}> {
|
|||
|
||||
addUser = () => {
|
||||
if (this.state.newUserPwd1 !== this.state.newUserPwd2) {
|
||||
alert("2 passwords do not match, please check.");
|
||||
alertMsg(this.props.msg.pkg.get("settings.pwd.notSame"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -375,7 +390,9 @@ export class AdminPane extends React.Component<Props, State, {}> {
|
|||
})
|
||||
.then((ok: boolean) => {
|
||||
if (!ok) {
|
||||
alert("failed to add user");
|
||||
alertMsg(this.props.msg.pkg.get("add.fail"));
|
||||
} else {
|
||||
alertMsg(this.props.msg.pkg.get("add.ok"));
|
||||
}
|
||||
this.setState({
|
||||
newUserName: "",
|
||||
|
@ -391,7 +408,7 @@ export class AdminPane extends React.Component<Props, State, {}> {
|
|||
};
|
||||
|
||||
render() {
|
||||
const userList = this.props.users.valueSeq().map((user: User) => {
|
||||
const userList = this.props.admin.users.valueSeq().map((user: User) => {
|
||||
return (
|
||||
<div key={user.id} className="margin-t-m">
|
||||
<UserForm
|
||||
|
@ -400,14 +417,15 @@ export class AdminPane extends React.Component<Props, State, {}> {
|
|||
name={user.name}
|
||||
role={user.role}
|
||||
quota={user.quota}
|
||||
roles={this.props.roles}
|
||||
roles={this.props.admin.roles}
|
||||
msg={this.props.msg}
|
||||
update={this.props.update}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
const roleList = this.props.roles.valueSeq().map((role: string) => {
|
||||
const roleList = this.props.admin.roles.valueSeq().map((role: string) => {
|
||||
return (
|
||||
<div key={role} className="flex-list-container margin-b-m">
|
||||
<div className="flex-list-item-l">
|
||||
|
@ -421,7 +439,7 @@ export class AdminPane extends React.Component<Props, State, {}> {
|
|||
}}
|
||||
className="grey1-bg white-font margin-r-m"
|
||||
>
|
||||
Delete
|
||||
{this.props.msg.pkg.get("delete")}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -434,7 +452,7 @@ export class AdminPane extends React.Component<Props, State, {}> {
|
|||
<div className="flex-list-container bold">
|
||||
<span className="flex-list-item-l">
|
||||
<span className="dot black-bg"></span>
|
||||
<span>Add New User</span>
|
||||
<span>{this.props.msg.pkg.get("user.add")}</span>
|
||||
</span>
|
||||
<span className="flex-list-item-r padding-r-m"></span>
|
||||
</div>
|
||||
|
@ -452,28 +470,28 @@ export class AdminPane extends React.Component<Props, State, {}> {
|
|||
onChange={this.onChangeUserName}
|
||||
value={this.state.newUserName}
|
||||
className="black0-font margin-b-m"
|
||||
placeholder="new user name"
|
||||
placeholder={this.props.msg.pkg.get("user.name")}
|
||||
/>
|
||||
<input
|
||||
type="text"
|
||||
onChange={this.onChangeUserRole}
|
||||
value={this.state.newUserRole}
|
||||
className="black0-font margin-b-m"
|
||||
placeholder="new user role"
|
||||
placeholder={this.props.msg.pkg.get("user.role")}
|
||||
/>
|
||||
<input
|
||||
type="password"
|
||||
onChange={this.onChangeUserPwd1}
|
||||
value={this.state.newUserPwd1}
|
||||
className="black0-font margin-b-m"
|
||||
placeholder="password"
|
||||
placeholder={this.props.msg.pkg.get("user.password")}
|
||||
/>
|
||||
<input
|
||||
type="password"
|
||||
onChange={this.onChangeUserPwd2}
|
||||
value={this.state.newUserPwd2}
|
||||
className="black0-font margin-b-m"
|
||||
placeholder="repeat password"
|
||||
placeholder={this.props.msg.pkg.get("settings.pwd.new2")}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex-list-item-r">
|
||||
|
@ -481,7 +499,7 @@ export class AdminPane extends React.Component<Props, State, {}> {
|
|||
onClick={this.addUser}
|
||||
className="grey1-bg white-font margin-r-m"
|
||||
>
|
||||
Create User
|
||||
{this.props.msg.pkg.get("add")}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -492,7 +510,7 @@ export class AdminPane extends React.Component<Props, State, {}> {
|
|||
<div className="flex-list-container bold">
|
||||
<span className="flex-list-item-l">
|
||||
<span className="dot black-bg"></span>
|
||||
<span>Users</span>
|
||||
<span>{this.props.msg.pkg.get("admin.users")}</span>
|
||||
</span>
|
||||
<span className="flex-list-item-r padding-r-m"></span>
|
||||
</div>
|
||||
|
@ -504,7 +522,7 @@ export class AdminPane extends React.Component<Props, State, {}> {
|
|||
<div className="flex-list-container bold">
|
||||
<span className="flex-list-item-l">
|
||||
<span className="dot black-bg"></span>
|
||||
<span>Add New Role</span>
|
||||
<span>{this.props.msg.pkg.get("role.add")}</span>
|
||||
</span>
|
||||
<span className="flex-list-item-r padding-r-m"></span>
|
||||
</div>
|
||||
|
@ -517,7 +535,7 @@ export class AdminPane extends React.Component<Props, State, {}> {
|
|||
onChange={this.onChangeRole}
|
||||
value={this.state.newRole}
|
||||
className="black0-font margin-r-m"
|
||||
placeholder="new role name"
|
||||
placeholder={this.props.msg.pkg.get("role.name")}
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
|
@ -526,7 +544,7 @@ export class AdminPane extends React.Component<Props, State, {}> {
|
|||
onClick={this.addRole}
|
||||
className="grey1-bg white-font margin-r-m"
|
||||
>
|
||||
Create Role
|
||||
{this.props.msg.pkg.get("add")}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -537,7 +555,7 @@ export class AdminPane extends React.Component<Props, State, {}> {
|
|||
<div className="flex-list-container bold margin-b-m">
|
||||
<span className="flex-list-item-l">
|
||||
<span className="dot black-bg"></span>
|
||||
<span>Roles</span>
|
||||
<span>{this.props.msg.pkg.get("admin.roles")}</span>
|
||||
</span>
|
||||
<span className="flex-list-item-r padding-r-m"></span>
|
||||
</div>
|
||||
|
|
|
@ -1,14 +1,19 @@
|
|||
import * as React from "react";
|
||||
import { List } from "immutable";
|
||||
|
||||
import { ICoreState } from "./core_state";
|
||||
import { ICoreState, MsgProps } from "./core_state";
|
||||
import { updater } from "./state_updater";
|
||||
import { alertMsg } from "../common/env";
|
||||
|
||||
export interface Props {
|
||||
export interface LoginProps {
|
||||
userRole: string;
|
||||
authed: boolean;
|
||||
captchaID: string;
|
||||
}
|
||||
|
||||
export interface Props {
|
||||
login: LoginProps;
|
||||
msg: MsgProps;
|
||||
update?: (updater: (prevState: ICoreState) => ICoreState) => void;
|
||||
}
|
||||
|
||||
|
@ -47,7 +52,7 @@ export class AuthPane extends React.Component<Props, State, {}> {
|
|||
.login(
|
||||
this.state.user,
|
||||
this.state.pwd,
|
||||
this.props.captchaID,
|
||||
this.props.login.captchaID,
|
||||
this.state.captchaInput
|
||||
)
|
||||
.then((ok: boolean): Promise<any> => {
|
||||
|
@ -85,7 +90,7 @@ export class AuthPane extends React.Component<Props, State, {}> {
|
|||
if (ok) {
|
||||
this.update(updater().updateLogin);
|
||||
} else {
|
||||
alertMsg("Failed to logout.");
|
||||
alertMsg(this.props.msg.pkg.get("login.logout.fail"));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
@ -103,7 +108,7 @@ export class AuthPane extends React.Component<Props, State, {}> {
|
|||
<span>
|
||||
<div
|
||||
className="container"
|
||||
style={{ display: this.props.authed ? "none" : "block" }}
|
||||
style={{ display: this.props.login.authed ? "none" : "block" }}
|
||||
>
|
||||
<div className="padding-l">
|
||||
<div className="flex-list-container">
|
||||
|
@ -114,7 +119,7 @@ export class AuthPane extends React.Component<Props, State, {}> {
|
|||
onChange={this.changeUser}
|
||||
value={this.state.user}
|
||||
className="black0-font margin-t-m margin-b-m margin-r-m"
|
||||
placeholder="user name"
|
||||
placeholder={this.props.msg.pkg.get("login.username")}
|
||||
/>
|
||||
<input
|
||||
name="pwd"
|
||||
|
@ -122,7 +127,7 @@ export class AuthPane extends React.Component<Props, State, {}> {
|
|||
onChange={this.changePwd}
|
||||
value={this.state.pwd}
|
||||
className="black0-font margin-t-m margin-b-m"
|
||||
placeholder="password"
|
||||
placeholder={this.props.msg.pkg.get("login.pwd")}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex-list-item-r">
|
||||
|
@ -130,7 +135,7 @@ export class AuthPane extends React.Component<Props, State, {}> {
|
|||
onClick={this.login}
|
||||
className="green0-bg white-font margin-t-m margin-b-m"
|
||||
>
|
||||
Log in
|
||||
{this.props.msg.pkg.get("login.login")}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -143,10 +148,10 @@ export class AuthPane extends React.Component<Props, State, {}> {
|
|||
onChange={this.changeCaptcha}
|
||||
value={this.state.captchaInput}
|
||||
className="black0-font margin-t-m margin-b-m margin-r-m"
|
||||
placeholder="captcha"
|
||||
placeholder={this.props.msg.pkg.get("login.captcha")}
|
||||
/>
|
||||
<img
|
||||
src={`/v1/captchas/imgs?capid=${this.props.captchaID}`}
|
||||
src={`/v1/captchas/imgs?capid=${this.props.login.captchaID}`}
|
||||
className="captcha"
|
||||
onClick={this.refreshCaptcha}
|
||||
/>
|
||||
|
@ -156,9 +161,9 @@ export class AuthPane extends React.Component<Props, State, {}> {
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<span style={{ display: this.props.authed ? "inherit" : "none" }}>
|
||||
<span style={{ display: this.props.login.authed ? "inherit" : "none" }}>
|
||||
<button onClick={this.logout} className="grey1-bg white-font">
|
||||
Log out
|
||||
{this.props.msg.pkg.get("login.logout")}
|
||||
</button>
|
||||
</span>
|
||||
</span>
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import * as React from "react";
|
||||
|
||||
import { ICoreState } from "./core_state";
|
||||
import { AuthPane, Props as LoginProps } from "./pane_login";
|
||||
import { ICoreState, MsgProps } from "./core_state";
|
||||
import { AuthPane, LoginProps } from "./pane_login";
|
||||
import { updater } from "./state_updater";
|
||||
import { alertMsg } from "../common/env";
|
||||
|
||||
export interface Props {
|
||||
login: LoginProps;
|
||||
msg: MsgProps;
|
||||
update?: (updater: (prevState: ICoreState) => ICoreState) => void;
|
||||
}
|
||||
|
||||
|
@ -40,19 +40,19 @@ export class PaneSettings extends React.Component<Props, State, {}> {
|
|||
|
||||
setPwd = () => {
|
||||
if (this.state.newPwd1 !== this.state.newPwd2) {
|
||||
alertMsg("new passwords are not same");
|
||||
alertMsg(this.props.msg.pkg.get("settings.pwd.notSame"));
|
||||
} else if (this.state.newPwd1 == "") {
|
||||
alertMsg("new passwords can not be empty");
|
||||
alertMsg(this.props.msg.pkg.get("settings.pwd.empty"));
|
||||
} else if (this.state.oldPwd == this.state.newPwd1) {
|
||||
alertMsg("old and new passwords are same");
|
||||
alertMsg(this.props.msg.pkg.get("settings.pwd.notChanged"));
|
||||
} else {
|
||||
updater()
|
||||
.setPwd(this.state.oldPwd, this.state.newPwd1)
|
||||
.then((ok: boolean) => {
|
||||
if (ok) {
|
||||
alertMsg("Password is updated");
|
||||
alertMsg(this.props.msg.pkg.get("settings.pwd.updated"));
|
||||
} else {
|
||||
alertMsg("Failed to update password");
|
||||
alertMsg(this.props.msg.pkg.get("settings.pwd.fail"));
|
||||
}
|
||||
this.setState({
|
||||
oldPwd: "",
|
||||
|
@ -64,36 +64,6 @@ export class PaneSettings extends React.Component<Props, State, {}> {
|
|||
};
|
||||
|
||||
render() {
|
||||
const inputs: Array<JSX.Element> = [
|
||||
<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"
|
||||
/>,
|
||||
<input
|
||||
name="new_pwd1"
|
||||
type="password"
|
||||
onChange={this.changeNewPwd1}
|
||||
value={this.state.newPwd1}
|
||||
className="black0-font margin-t-m margin-b-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"
|
||||
/>,
|
||||
<button onClick={this.setPwd} className="grey1-bg white-font">
|
||||
Update
|
||||
</button>,
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="container">
|
||||
<div className="padding-l">
|
||||
|
@ -104,7 +74,7 @@ export class PaneSettings extends React.Component<Props, State, {}> {
|
|||
</div>
|
||||
<div className="flex-list-item-r">
|
||||
<button onClick={this.setPwd} className="grey1-bg white-font">
|
||||
Update
|
||||
{this.props.msg.pkg.get("update")}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -116,7 +86,7 @@ export class PaneSettings extends React.Component<Props, State, {}> {
|
|||
onChange={this.changeOldPwd}
|
||||
value={this.state.oldPwd}
|
||||
className="black0-font margin-t-m margin-b-m"
|
||||
placeholder="old password"
|
||||
placeholder={this.props.msg.pkg.get("settings.pwd.old")}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
|
@ -126,7 +96,7 @@ export class PaneSettings extends React.Component<Props, State, {}> {
|
|||
onChange={this.changeNewPwd1}
|
||||
value={this.state.newPwd1}
|
||||
className="black0-font margin-t-m margin-b-m margin-r-m"
|
||||
placeholder="new password"
|
||||
placeholder={this.props.msg.pkg.get("settings.pwd.new1")}
|
||||
/>
|
||||
<input
|
||||
name="new_pwd2"
|
||||
|
@ -134,7 +104,7 @@ export class PaneSettings extends React.Component<Props, State, {}> {
|
|||
onChange={this.changeNewPwd2}
|
||||
value={this.state.newPwd2}
|
||||
className="black0-font margin-t-m margin-b-m"
|
||||
placeholder="new password again"
|
||||
placeholder={this.props.msg.pkg.get("settings.pwd.new2")}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -148,9 +118,8 @@ export class PaneSettings extends React.Component<Props, State, {}> {
|
|||
</div>
|
||||
<div className="flex-list-item-r">
|
||||
<AuthPane
|
||||
userRole={this.props.login.userRole}
|
||||
authed={this.props.login.authed}
|
||||
captchaID={this.props.login.captchaID}
|
||||
login={this.props.login}
|
||||
msg={this.props.msg}
|
||||
update={this.update}
|
||||
/>
|
||||
</div>
|
||||
|
|
|
@ -2,10 +2,10 @@ import * as React from "react";
|
|||
import { Set, Map } from "immutable";
|
||||
|
||||
import { updater } from "./state_updater";
|
||||
import { ICoreState } from "./core_state";
|
||||
import { ICoreState, MsgProps } from "./core_state";
|
||||
import { PaneSettings } from "./pane_settings";
|
||||
import { AdminPane, Props as AdminPaneProps } from "./pane_admin";
|
||||
import { AuthPane, Props as AuthPaneProps } from "./pane_login";
|
||||
import { AdminPane, AdminProps } from "./pane_admin";
|
||||
import { AuthPane, LoginProps } from "./pane_login";
|
||||
|
||||
export interface PanesProps {
|
||||
displaying: string;
|
||||
|
@ -13,8 +13,9 @@ export interface PanesProps {
|
|||
}
|
||||
export interface Props {
|
||||
panes: PanesProps;
|
||||
login: AuthPaneProps;
|
||||
admin: AdminPaneProps;
|
||||
login: LoginProps;
|
||||
admin: AdminProps;
|
||||
msg: MsgProps;
|
||||
update?: (updater: (prevState: ICoreState) => ICoreState) => void;
|
||||
}
|
||||
|
||||
|
@ -41,14 +42,17 @@ export class Panes extends React.Component<Props, State, {}> {
|
|||
|
||||
let panesMap: Map<string, JSX.Element> = Map({
|
||||
settings: (
|
||||
<PaneSettings login={this.props.login} update={this.props.update} />
|
||||
<PaneSettings
|
||||
login={this.props.login}
|
||||
msg={this.props.msg}
|
||||
update={this.props.update}
|
||||
/>
|
||||
),
|
||||
login: (
|
||||
<AuthPane
|
||||
userRole={this.props.login.userRole}
|
||||
authed={this.props.login.authed}
|
||||
captchaID={this.props.login.captchaID}
|
||||
login={this.props.login}
|
||||
update={this.props.update}
|
||||
msg={this.props.msg}
|
||||
/>
|
||||
),
|
||||
});
|
||||
|
@ -57,8 +61,8 @@ export class Panes extends React.Component<Props, State, {}> {
|
|||
panesMap = panesMap.set(
|
||||
"admin",
|
||||
<AdminPane
|
||||
users={this.props.admin.users}
|
||||
roles={this.props.admin.roles}
|
||||
admin={this.props.admin}
|
||||
msg={this.props.msg}
|
||||
update={this.props.update}
|
||||
/>
|
||||
);
|
||||
|
@ -86,7 +90,7 @@ export class Panes extends React.Component<Props, State, {}> {
|
|||
onClick={this.closePane}
|
||||
className={`red0-bg white-font ${btnClass}`}
|
||||
>
|
||||
Close
|
||||
{this.props.msg.pkg.get("panes.close")}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,14 +1,18 @@
|
|||
import * as React from "react";
|
||||
|
||||
import { ICoreState } from "./core_state";
|
||||
import { Browser, Props as BrowserProps } from "./browser";
|
||||
import { Props as PaneLoginProps } from "./pane_login";
|
||||
import { Panes, Props as PanesProps } from "./panes";
|
||||
import { ICoreState, MsgProps } from "./core_state";
|
||||
import { Browser, BrowserProps } from "./browser";
|
||||
import { LoginProps } from "./pane_login";
|
||||
import { Panes, PanesProps } from "./panes";
|
||||
import { AdminProps } from "./pane_admin";
|
||||
import { TopBar } from "./topbar";
|
||||
|
||||
export interface Props {
|
||||
browser: BrowserProps;
|
||||
panes: PanesProps;
|
||||
admin: AdminProps;
|
||||
login: LoginProps;
|
||||
msg: MsgProps;
|
||||
update?: (updater: (prevState: ICoreState) => ICoreState) => void;
|
||||
}
|
||||
|
||||
|
@ -23,25 +27,24 @@ export class RootFrame extends React.Component<Props, State, {}> {
|
|||
<div className="theme-white desktop">
|
||||
<div id="bg" className="bg bg-img font-m">
|
||||
<Panes
|
||||
panes={this.props.panes.panes}
|
||||
login={this.props.panes.login}
|
||||
admin={this.props.panes.admin}
|
||||
panes={this.props.panes}
|
||||
login={this.props.login}
|
||||
admin={this.props.admin}
|
||||
msg={this.props.msg}
|
||||
update={this.props.update}
|
||||
/>
|
||||
|
||||
<TopBar login={this.props.panes.login} update={this.props.update}></TopBar>
|
||||
<TopBar
|
||||
login={this.props.login}
|
||||
msg={this.props.msg}
|
||||
update={this.props.update}
|
||||
/>
|
||||
|
||||
<div className="container-center">
|
||||
<Browser
|
||||
dirPath={this.props.browser.dirPath}
|
||||
items={this.props.browser.items}
|
||||
uploadings={this.props.browser.uploadings}
|
||||
sharings={this.props.browser.sharings}
|
||||
isSharing={this.props.browser.isSharing}
|
||||
browser={this.props.browser}
|
||||
msg={this.props.msg}
|
||||
update={this.props.update}
|
||||
uploadFiles={this.props.browser.uploadFiles}
|
||||
uploadValue={this.props.browser.uploadValue}
|
||||
isVertical={this.props.browser.isVertical}
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -56,7 +56,7 @@ export class StateMgr extends React.Component<Props, State, {}> {
|
|||
})
|
||||
.then((ok: boolean) => {
|
||||
if (!ok) {
|
||||
alertMsg("failed to get captcha id");
|
||||
alertMsg(this.state.msg.pkg.get("stateMgr.cap.fail"));
|
||||
} else {
|
||||
this.update(updater().updateLogin);
|
||||
}
|
||||
|
@ -114,11 +114,10 @@ export class StateMgr extends React.Component<Props, State, {}> {
|
|||
return (
|
||||
<RootFrame
|
||||
browser={this.state.browser}
|
||||
panes={{
|
||||
panes: this.state.panes,
|
||||
login: this.state.login,
|
||||
admin: this.state.admin,
|
||||
}}
|
||||
msg={this.state.msg}
|
||||
panes={this.state.panes}
|
||||
login={this.state.login}
|
||||
admin={this.state.admin}
|
||||
update={this.update}
|
||||
/>
|
||||
);
|
||||
|
|
|
@ -18,6 +18,8 @@ import { UploadEntry } from "../worker/interface";
|
|||
import { Up } from "../worker/upload_mgr";
|
||||
import { alertMsg } from "../common/env";
|
||||
|
||||
import { MsgPackage } from "../i18n/msger";
|
||||
|
||||
export class Updater {
|
||||
props: ICoreState;
|
||||
private usersClient: IUsersClient = new UsersClient("");
|
||||
|
@ -220,7 +222,11 @@ export class Updater {
|
|||
return resp.status === 200;
|
||||
};
|
||||
|
||||
setUser = async (userID: string, role: string, quota: Quota): Promise<boolean> => {
|
||||
setUser = async (
|
||||
userID: string,
|
||||
role: string,
|
||||
quota: Quota
|
||||
): Promise<boolean> => {
|
||||
const resp = await this.usersClient.setUser(userID, role, quota);
|
||||
return resp.status === 200;
|
||||
};
|
||||
|
@ -306,11 +312,9 @@ export class Updater {
|
|||
};
|
||||
|
||||
initIsAuthed = async (): Promise<void> => {
|
||||
return this
|
||||
.isAuthed()
|
||||
.then((isAuthed) => {
|
||||
updater().setAuthed(isAuthed);
|
||||
});
|
||||
return this.isAuthed().then((isAuthed) => {
|
||||
updater().setAuthed(isAuthed);
|
||||
});
|
||||
};
|
||||
|
||||
setAuthed = (isAuthed: boolean) => {
|
||||
|
@ -331,6 +335,21 @@ export class Updater {
|
|||
return resp.status === 200;
|
||||
};
|
||||
|
||||
setLan = (lan: string) => {
|
||||
switch (lan) {
|
||||
case "en_US":
|
||||
this.props.msg.lan = "en_US";
|
||||
this.props.msg.pkg = MsgPackage.get(lan);
|
||||
break;
|
||||
case "zh_CN":
|
||||
this.props.msg.lan = "zh_CN";
|
||||
this.props.msg.pkg = MsgPackage.get(lan);
|
||||
break;
|
||||
default:
|
||||
alertMsg("language package not found");
|
||||
}
|
||||
};
|
||||
|
||||
updateBrowser = (prevState: ICoreState): ICoreState => {
|
||||
return {
|
||||
...prevState,
|
||||
|
@ -358,6 +377,13 @@ export class Updater {
|
|||
admin: { ...prevState.admin, ...this.props.admin },
|
||||
};
|
||||
};
|
||||
|
||||
updateMsg = (prevState: ICoreState): ICoreState => {
|
||||
return {
|
||||
...prevState,
|
||||
msg: { ...prevState.msg, ...this.props.msg },
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export let coreUpdater = new Updater();
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
import * as React from "react";
|
||||
|
||||
import { ICoreState } from "./core_state";
|
||||
import { Props as LoginProps } from "./pane_login";
|
||||
import { ICoreState, MsgProps } from "./core_state";
|
||||
import { LoginProps } from "./pane_login";
|
||||
import { updater } from "./state_updater";
|
||||
|
||||
export interface State {}
|
||||
export interface Props {
|
||||
login: LoginProps;
|
||||
msg: MsgProps;
|
||||
update?: (updater: (prevState: ICoreState) => ICoreState) => void;
|
||||
}
|
||||
|
||||
|
@ -57,13 +58,13 @@ export class TopBar extends React.Component<Props, State, {}> {
|
|||
onClick={this.showSettings}
|
||||
className="grey1-bg white-font margin-r-m"
|
||||
>
|
||||
Settings
|
||||
{this.props.msg.pkg.get("settings")}
|
||||
</button>
|
||||
<button
|
||||
onClick={this.showAdmin}
|
||||
className="grey1-bg white-font margin-r-m"
|
||||
>
|
||||
Admin
|
||||
{this.props.msg.pkg.get("admin")}
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
|
|
|
@ -1,8 +1,64 @@
|
|||
import { Map } from "immutable";
|
||||
|
||||
const adContent = `
|
||||
If you have any question, you can submit an issue in the github repo. But owner may be out of the office in the weekend 😎.`;
|
||||
|
||||
export const msgs: Map<string, string> = Map({
|
||||
"loader.top.about": "关于",
|
||||
});
|
||||
"stateMgr.cap.fail": "failed to get captcha id",
|
||||
"browser.upload.del.fail": "Failed to delete uploadini item",
|
||||
"browser.folder.add.fail": "Folder name can not be empty",
|
||||
"browser.del.fail": "Please select file or folder to delete at first",
|
||||
"browser.move.fail": "Source directory is same as destination directory",
|
||||
"browser.share.add.fail": "Failed to enable sharing",
|
||||
"browser.share.del.fail": "Failed to disable sharing",
|
||||
"browser.share.del": "Stop sharing",
|
||||
"browser.share.add": "Share it",
|
||||
"browser.share.title": "Sharings",
|
||||
"browser.folder.name": "Folder name",
|
||||
"browser.folder.add": "Add Folder",
|
||||
"browser.upload": "Upload",
|
||||
"browser.delete": "Delete",
|
||||
"browser.paste": "Paste",
|
||||
"browser.select": "Select",
|
||||
"browser.deselect": "Deselect",
|
||||
"browser.selectAll": "Select All",
|
||||
"browser.stop": "Stop",
|
||||
"browser.disable": "Disable",
|
||||
"browser.location": "Location",
|
||||
"browser.item.title": "Items",
|
||||
"panes.close": "Close",
|
||||
"login.logout.fail": "Failed to log out",
|
||||
"login.username": "User Name",
|
||||
"login.captcha": "Captcha",
|
||||
"login.pwd": "Password",
|
||||
"login.login": "Login",
|
||||
"login.logout": "Logout",
|
||||
"settings.pwd.notSame": "Input passwords are not identical",
|
||||
"settings.pwd.empty": "Password can not be empty",
|
||||
"settings.pwd.notChanged": "New Password can be identical to old password",
|
||||
update: "Update",
|
||||
"settings.pwd.old": "current password",
|
||||
"settings.pwd.new1": "new password",
|
||||
"settings.pwd.new2": "input again password",
|
||||
settings: "Settings",
|
||||
admin: "Admin",
|
||||
"update.ok": "Succeeded to update",
|
||||
"update.fail": "Failed to update",
|
||||
"delete.fail": "Failed to delete",
|
||||
"delete.ok": "Succeeded to delete",
|
||||
delete: "Delete",
|
||||
spaceLimit: "Space Limit",
|
||||
uploadLimit: "Upload Speed Limit",
|
||||
downloadLimit: "Download Speed Limit",
|
||||
"add.fail": "Failed to create",
|
||||
"add.ok": "Succeeded to create",
|
||||
"role.delete.warning":
|
||||
"After deleting this role, some of users may not be able to login.",
|
||||
"user.id": "User ID",
|
||||
"user.add": "Add User",
|
||||
"user.name": "User Name",
|
||||
"user.role": "User Role",
|
||||
"user.password": "User Password",
|
||||
add: "Add",
|
||||
"admin.users": "Users",
|
||||
"role.add": "Add Role",
|
||||
"role.name": "Role Name",
|
||||
"admin.roles": "Roles",
|
||||
});
|
||||
|
|
|
@ -8,13 +8,13 @@ export class Msger {
|
|||
constructor(msgs: Map<string, string>) {
|
||||
this.msgs = msgs;
|
||||
}
|
||||
getMsg(key: string): string {
|
||||
m(key: string): string {
|
||||
return this.msgs.get(key, "");
|
||||
}
|
||||
}
|
||||
|
||||
export class MsgPackage {
|
||||
static getPkg(key: string): Map<string, string> {
|
||||
static get(key: string): Map<string, string> {
|
||||
switch (key) {
|
||||
case "en-US":
|
||||
return Map(enMsgs);
|
||||
|
|
|
@ -1,8 +1,63 @@
|
|||
import { Map } from "immutable";
|
||||
|
||||
const adContent = `
|
||||
发现bug等, 可至下方github库提交issue, 不过周末可能不上班😎.`;
|
||||
|
||||
export const msgs: Map<string, string> = Map({
|
||||
"loader.top.about": "关于",
|
||||
});
|
||||
"stateMgr.cap.fail": "获取captcha id失败",
|
||||
"browser.upload.del.fail": "删除上传失败",
|
||||
"browser.upload.title": "正在上传",
|
||||
"browser.folder.add.fail": "文件夹名不可为空",
|
||||
"browser.del.fail": "至少选择一个文件或文件夹",
|
||||
"browser.move.fail": "源与目标相同",
|
||||
"browser.share.add.fail": "共享失败",
|
||||
"browser.share.del.fail": "删除共享失败",
|
||||
"browser.share.del": "停止共享",
|
||||
"browser.share.add": "开始共享",
|
||||
"browser.share.title": "共享列表",
|
||||
"browser.folder.name": "文件夹名",
|
||||
"browser.folder.add": "添加文件夹",
|
||||
"browser.upload": "上传",
|
||||
"browser.delete": "删除",
|
||||
"browser.paste": "粘贴",
|
||||
"browser.select": "选择",
|
||||
"browser.deselect": "不选",
|
||||
"browser.selectAll": "选择所有",
|
||||
"browser.stop": "停止",
|
||||
"browser.location": "位置",
|
||||
"browser.item.title": "列表",
|
||||
"panes.close": "关闭",
|
||||
"login.logout.fail": "登出失败",
|
||||
"login.username": "用户名",
|
||||
"login.captcha": "验证码",
|
||||
"login.pwd": "密码",
|
||||
"login.login": "登入",
|
||||
"login.logout": "登出",
|
||||
"settings.pwd.notSame": "两次密码不同",
|
||||
"settings.pwd.empty": "密码不能为空",
|
||||
"settings.pwd.notChanged": "新老密码不能相同",
|
||||
update: "更新",
|
||||
"settings.pwd.old": "当前密码",
|
||||
"settings.pwd.new1": "新密码",
|
||||
"settings.pwd.new2": "再次输入新密码",
|
||||
settings: "设置",
|
||||
admin: "管理",
|
||||
"update.ok": "更新成功",
|
||||
"update.fail": "更新失败",
|
||||
"delete.fail": "删除失败",
|
||||
"delete.ok": "删除成功",
|
||||
delete: "删除",
|
||||
spaceLimit: "空间上限",
|
||||
uploadLimit: "上传速度限制",
|
||||
downloadLimit: "下载速度限制",
|
||||
"add.fail": "新增失败",
|
||||
"add.ok": "新增成功",
|
||||
"role.delete.warning": "注意删除角色后,该角色的用户可能不能登入",
|
||||
"user.id": "用户ID",
|
||||
"user.add": "新增用户",
|
||||
"user.name": "用户名",
|
||||
"user.role": "橘色",
|
||||
"user.password": "密码",
|
||||
add: "新增",
|
||||
"admin.users": "用户列表",
|
||||
"role.add": "新增角色",
|
||||
"role.name": "角色名字",
|
||||
"admin.roles": "角色列表",
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue