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);
|
updater().setClients(usersCl, filesCl);
|
||||||
|
|
||||||
const browser = new Browser({
|
const browser = new Browser({
|
||||||
dirPath: coreState.browser.dirPath,
|
browser: coreState.browser,
|
||||||
isSharing: coreState.browser.isSharing,
|
msg: coreState.msg,
|
||||||
items: coreState.browser.items,
|
|
||||||
uploadings: coreState.browser.uploadings,
|
|
||||||
sharings: coreState.browser.sharings,
|
|
||||||
uploadFiles: coreState.browser.uploadFiles,
|
|
||||||
uploadValue: coreState.browser.uploadValue,
|
|
||||||
isVertical: coreState.browser.isVertical,
|
|
||||||
update: (updater: (prevState: ICoreState) => ICoreState) => {},
|
update: (updater: (prevState: ICoreState) => ICoreState) => {},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -16,9 +16,8 @@ describe("Login", () => {
|
||||||
|
|
||||||
const coreState = newWithWorker(mockWorker);
|
const coreState = newWithWorker(mockWorker);
|
||||||
const pane = new AuthPane({
|
const pane = new AuthPane({
|
||||||
userRole: coreState.login.userRole,
|
login: coreState.login,
|
||||||
authed: coreState.login.authed,
|
msg: coreState.msg,
|
||||||
captchaID: coreState.login.captchaID,
|
|
||||||
update: (updater: (prevState: ICoreState) => ICoreState) => {},
|
update: (updater: (prevState: ICoreState) => ICoreState) => {},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ import FileSize from "filesize";
|
||||||
|
|
||||||
import { alertMsg, comfirmMsg } from "../common/env";
|
import { alertMsg, comfirmMsg } from "../common/env";
|
||||||
import { updater } from "./state_updater";
|
import { updater } from "./state_updater";
|
||||||
import { ICoreState } from "./core_state";
|
import { ICoreState, MsgProps } from "./core_state";
|
||||||
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";
|
||||||
|
@ -18,7 +18,7 @@ export interface Item {
|
||||||
selected: boolean;
|
selected: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Props {
|
export interface BrowserProps {
|
||||||
dirPath: List<string>;
|
dirPath: List<string>;
|
||||||
isSharing: boolean;
|
isSharing: boolean;
|
||||||
items: List<MetadataResp>;
|
items: List<MetadataResp>;
|
||||||
|
@ -29,7 +29,11 @@ export interface Props {
|
||||||
uploadValue: string;
|
uploadValue: string;
|
||||||
|
|
||||||
isVertical: boolean;
|
isVertical: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Props {
|
||||||
|
browser: BrowserProps;
|
||||||
|
msg: MsgProps;
|
||||||
update?: (updater: (prevState: ICoreState) => ICoreState) => void;
|
update?: (updater: (prevState: ICoreState) => ICoreState) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,7 +94,7 @@ export class Browser extends React.Component<Props, State, {}> {
|
||||||
.deleteUpload(filePath)
|
.deleteUpload(filePath)
|
||||||
.then((ok: boolean) => {
|
.then((ok: boolean) => {
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
alertMsg(`Failed to delete uploading ${filePath}`);
|
alertMsg(this.props.msg.pkg.get("browser.upload.del.fail"));
|
||||||
}
|
}
|
||||||
return updater().refreshUploadings();
|
return updater().refreshUploadings();
|
||||||
})
|
})
|
||||||
|
@ -106,19 +110,19 @@ export class Browser extends React.Component<Props, State, {}> {
|
||||||
|
|
||||||
onMkDir = () => {
|
onMkDir = () => {
|
||||||
if (this.state.inputValue === "") {
|
if (this.state.inputValue === "") {
|
||||||
alertMsg("folder name can not be empty");
|
alertMsg(this.props.msg.pkg.get("browser.folder.add.fail"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const dirPath = getItemPath(
|
const dirPath = getItemPath(
|
||||||
this.props.dirPath.join("/"),
|
this.props.browser.dirPath.join("/"),
|
||||||
this.state.inputValue
|
this.state.inputValue
|
||||||
);
|
);
|
||||||
updater()
|
updater()
|
||||||
.mkDir(dirPath)
|
.mkDir(dirPath)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
this.setState({ inputValue: "" });
|
this.setState({ inputValue: "" });
|
||||||
return updater().setItems(this.props.dirPath);
|
return updater().setItems(this.props.browser.dirPath);
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
this.update(updater().updateBrowser);
|
this.update(updater().updateBrowser);
|
||||||
|
@ -126,10 +130,10 @@ export class Browser extends React.Component<Props, State, {}> {
|
||||||
};
|
};
|
||||||
|
|
||||||
delete = () => {
|
delete = () => {
|
||||||
if (this.props.dirPath.join("/") !== this.state.selectedSrc) {
|
if (this.props.browser.dirPath.join("/") !== this.state.selectedSrc) {
|
||||||
alertMsg("please select file or folder to delete at first");
|
alertMsg(this.props.msg.pkg.get("browser.del.fail"));
|
||||||
this.setState({
|
this.setState({
|
||||||
selectedSrc: this.props.dirPath.join("/"),
|
selectedSrc: this.props.browser.dirPath.join("/"),
|
||||||
selectedItems: Map<string, boolean>(),
|
selectedItems: Map<string, boolean>(),
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
|
@ -141,7 +145,11 @@ export class Browser extends React.Component<Props, State, {}> {
|
||||||
}
|
}
|
||||||
|
|
||||||
updater()
|
updater()
|
||||||
.delete(this.props.dirPath, this.props.items, this.state.selectedItems)
|
.delete(
|
||||||
|
this.props.browser.dirPath,
|
||||||
|
this.props.browser.items,
|
||||||
|
this.state.selectedItems
|
||||||
|
)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
this.update(updater().updateBrowser);
|
this.update(updater().updateBrowser);
|
||||||
this.setState({
|
this.setState({
|
||||||
|
@ -153,16 +161,16 @@ export class Browser extends React.Component<Props, State, {}> {
|
||||||
|
|
||||||
moveHere = () => {
|
moveHere = () => {
|
||||||
const oldDir = this.state.selectedSrc;
|
const oldDir = this.state.selectedSrc;
|
||||||
const newDir = this.props.dirPath.join("/");
|
const newDir = this.props.browser.dirPath.join("/");
|
||||||
if (oldDir === newDir) {
|
if (oldDir === newDir) {
|
||||||
alertMsg("source directory is same as destination directory");
|
alertMsg(this.props.msg.pkg.get("browser.move.fail"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
updater()
|
updater()
|
||||||
.moveHere(
|
.moveHere(
|
||||||
this.state.selectedSrc,
|
this.state.selectedSrc,
|
||||||
this.props.dirPath.join("/"),
|
this.props.browser.dirPath.join("/"),
|
||||||
this.state.selectedItems
|
this.state.selectedItems
|
||||||
)
|
)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
@ -175,11 +183,11 @@ export class Browser extends React.Component<Props, State, {}> {
|
||||||
};
|
};
|
||||||
|
|
||||||
gotoChild = (childDirName: string) => {
|
gotoChild = (childDirName: string) => {
|
||||||
this.chdir(this.props.dirPath.push(childDirName));
|
this.chdir(this.props.browser.dirPath.push(childDirName));
|
||||||
};
|
};
|
||||||
|
|
||||||
chdir = async (dirPath: List<string>) => {
|
chdir = async (dirPath: List<string>) => {
|
||||||
if (dirPath === this.props.dirPath) {
|
if (dirPath === this.props.browser.dirPath) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -199,7 +207,7 @@ export class Browser extends React.Component<Props, State, {}> {
|
||||||
updateProgress = (infos: Map<string, UploadEntry>) => {
|
updateProgress = (infos: Map<string, UploadEntry>) => {
|
||||||
updater().setUploadings(infos);
|
updater().setUploadings(infos);
|
||||||
updater()
|
updater()
|
||||||
.setItems(this.props.dirPath)
|
.setItems(this.props.browser.dirPath)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
this.update(updater().updateBrowser);
|
this.update(updater().updateBrowser);
|
||||||
});
|
});
|
||||||
|
@ -211,7 +219,7 @@ export class Browser extends React.Component<Props, State, {}> {
|
||||||
: this.state.selectedItems.set(itemName, true);
|
: this.state.selectedItems.set(itemName, true);
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
selectedSrc: this.props.dirPath.join("/"),
|
selectedSrc: this.props.browser.dirPath.join("/"),
|
||||||
selectedItems: selectedItems,
|
selectedItems: selectedItems,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -220,17 +228,17 @@ export class Browser extends React.Component<Props, State, {}> {
|
||||||
let newSelected = Map<string, boolean>();
|
let newSelected = Map<string, boolean>();
|
||||||
const someSelected = this.state.selectedItems.size === 0 ? true : false;
|
const someSelected = this.state.selectedItems.size === 0 ? true : false;
|
||||||
if (someSelected) {
|
if (someSelected) {
|
||||||
this.props.items.forEach((item) => {
|
this.props.browser.items.forEach((item) => {
|
||||||
newSelected = newSelected.set(item.name, true);
|
newSelected = newSelected.set(item.name, true);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
this.props.items.forEach((item) => {
|
this.props.browser.items.forEach((item) => {
|
||||||
newSelected = newSelected.delete(item.name);
|
newSelected = newSelected.delete(item.name);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
selectedSrc: this.props.dirPath.join("/"),
|
selectedSrc: this.props.browser.dirPath.join("/"),
|
||||||
selectedItems: newSelected,
|
selectedItems: newSelected,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -240,7 +248,7 @@ export class Browser extends React.Component<Props, State, {}> {
|
||||||
.addSharing()
|
.addSharing()
|
||||||
.then((ok) => {
|
.then((ok) => {
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
alertMsg("failed to enable sharing");
|
alertMsg(this.props.msg.pkg.get("browser.share.add.fail"));
|
||||||
} else {
|
} else {
|
||||||
updater().setSharing(true);
|
updater().setSharing(true);
|
||||||
return this.listSharings();
|
return this.listSharings();
|
||||||
|
@ -256,7 +264,7 @@ export class Browser extends React.Component<Props, State, {}> {
|
||||||
.deleteSharing(dirPath)
|
.deleteSharing(dirPath)
|
||||||
.then((ok) => {
|
.then((ok) => {
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
alertMsg("failed to disable sharing");
|
alertMsg(this.props.msg.pkg.get("browser.share.del.fail"));
|
||||||
} else {
|
} else {
|
||||||
updater().setSharing(false);
|
updater().setSharing(false);
|
||||||
return this.listSharings();
|
return this.listSharings();
|
||||||
|
@ -278,13 +286,15 @@ export class Browser extends React.Component<Props, State, {}> {
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const breadcrumb = this.props.dirPath.map(
|
const breadcrumb = this.props.browser.dirPath.map(
|
||||||
(pathPart: string, key: number) => {
|
(pathPart: string, key: number) => {
|
||||||
return (
|
return (
|
||||||
<span key={pathPart}>
|
<span key={pathPart}>
|
||||||
<button
|
<button
|
||||||
type="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"
|
className="white-font margin-r-m"
|
||||||
style={{ backgroundColor: "rgba(0, 0, 0, 0.7)" }}
|
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-${
|
const nameCellClass = `item-name item-name-${
|
||||||
this.props.isVertical ? "vertical" : "horizontal"
|
this.props.browser.isVertical ? "vertical" : "horizontal"
|
||||||
} pointer`;
|
} pointer`;
|
||||||
const sizeCellClass = this.props.isVertical ? `hidden margin-s` : ``;
|
const sizeCellClass = this.props.browser.isVertical
|
||||||
const modTimeCellClass = this.props.isVertical ? `hidden margin-s` : ``;
|
? `hidden margin-s`
|
||||||
|
: ``;
|
||||||
|
const modTimeCellClass = this.props.browser.isVertical
|
||||||
|
? `hidden margin-s`
|
||||||
|
: ``;
|
||||||
|
|
||||||
const ops = (
|
const ops = (
|
||||||
<div>
|
<div>
|
||||||
|
@ -310,13 +324,13 @@ export class Browser extends React.Component<Props, State, {}> {
|
||||||
onChange={this.onInputChange}
|
onChange={this.onInputChange}
|
||||||
value={this.state.inputValue}
|
value={this.state.inputValue}
|
||||||
className="black0-font margin-r-m"
|
className="black0-font margin-r-m"
|
||||||
placeholder="folder name"
|
placeholder={this.props.msg.pkg.get("browser.folder.name")}
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
onClick={this.onMkDir}
|
onClick={this.onMkDir}
|
||||||
className="grey1-bg white-font margin-r-m"
|
className="grey1-bg white-font margin-r-m"
|
||||||
>
|
>
|
||||||
Create Folder
|
{this.props.msg.pkg.get("browser.folder.add")}
|
||||||
</button>
|
</button>
|
||||||
</span>
|
</span>
|
||||||
<span className="inline-block margin-t-m margin-b-m">
|
<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}
|
onClick={this.onClickUpload}
|
||||||
className="green0-bg white-font"
|
className="green0-bg white-font"
|
||||||
>
|
>
|
||||||
Upload Files
|
{this.props.msg.pkg.get("browser.upload")}
|
||||||
</button>
|
</button>
|
||||||
<input
|
<input
|
||||||
type="file"
|
type="file"
|
||||||
onChange={this.addUploads}
|
onChange={this.addUploads}
|
||||||
multiple={true}
|
multiple={true}
|
||||||
value={this.props.uploadValue}
|
value={this.props.browser.uploadValue}
|
||||||
ref={this.assignInput}
|
ref={this.assignInput}
|
||||||
className="black0-font hidden"
|
className="black0-font hidden"
|
||||||
/>
|
/>
|
||||||
|
@ -345,24 +359,24 @@ export class Browser extends React.Component<Props, State, {}> {
|
||||||
onClick={() => this.delete()}
|
onClick={() => this.delete()}
|
||||||
className="red0-bg white-font margin-t-m margin-b-m margin-r-m"
|
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>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => this.moveHere()}
|
onClick={() => this.moveHere()}
|
||||||
className="grey1-bg white-font margin-t-m margin-b-m margin-r-m"
|
className="grey1-bg white-font margin-t-m margin-b-m margin-r-m"
|
||||||
>
|
>
|
||||||
Paste
|
{this.props.msg.pkg.get("browser.paste")}
|
||||||
</button>
|
</button>
|
||||||
{this.props.isSharing ? (
|
{this.props.browser.isSharing ? (
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => {
|
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"
|
className="red0-bg white-font margin-t-m margin-b-m"
|
||||||
>
|
>
|
||||||
Stop Sharing
|
{this.props.msg.pkg.get("browser.share.del")}
|
||||||
</button>
|
</button>
|
||||||
) : (
|
) : (
|
||||||
<button
|
<button
|
||||||
|
@ -370,16 +384,16 @@ export class Browser extends React.Component<Props, State, {}> {
|
||||||
onClick={this.addSharing}
|
onClick={this.addSharing}
|
||||||
className="green0-bg white-font margin-t-m margin-b-m"
|
className="green0-bg white-font margin-t-m margin-b-m"
|
||||||
>
|
>
|
||||||
Share Folder
|
{this.props.msg.pkg.get("browser.share.add")}
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</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 isSelected = this.state.selectedItems.has(item.name);
|
||||||
const dirPath = this.props.dirPath.join("/");
|
const dirPath = this.props.browser.dirPath.join("/");
|
||||||
const itemPath = dirPath.endsWith("/")
|
const itemPath = dirPath.endsWith("/")
|
||||||
? `${dirPath}${item.name}`
|
? `${dirPath}${item.name}`
|
||||||
: `${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"}`}
|
className={`white-font ${isSelected ? "blue0-bg" : "grey1-bg"}`}
|
||||||
style={{ width: "8rem", display: "inline-block" }}
|
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>
|
</button>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
|
@ -435,7 +451,9 @@ export class Browser extends React.Component<Props, State, {}> {
|
||||||
className={`white-font ${isSelected ? "blue0-bg" : "grey1-bg"}`}
|
className={`white-font ${isSelected ? "blue0-bg" : "grey1-bg"}`}
|
||||||
style={{ width: "8rem", display: "inline-block" }}
|
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>
|
</button>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
|
@ -443,43 +461,45 @@ export class Browser extends React.Component<Props, State, {}> {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
const uploadingList = this.props.uploadings.map((uploading: UploadInfo) => {
|
const uploadingList = this.props.browser.uploadings.map(
|
||||||
const pathParts = uploading.realFilePath.split("/");
|
(uploading: UploadInfo) => {
|
||||||
const fileName = pathParts[pathParts.length - 1];
|
const pathParts = uploading.realFilePath.split("/");
|
||||||
|
const fileName = pathParts[pathParts.length - 1];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div key={fileName} className="flex-list-container">
|
<div key={fileName} className="flex-list-container">
|
||||||
<span className="flex-list-item-l">
|
<span className="flex-list-item-l">
|
||||||
<span className="vbar blue2-bg"></span>
|
<span className="vbar blue2-bg"></span>
|
||||||
<div className={nameCellClass}>
|
<div className={nameCellClass}>
|
||||||
<span className="bold">{fileName}</span>
|
<span className="bold">{fileName}</span>
|
||||||
<div className="grey1-font">
|
<div className="grey1-font">
|
||||||
{FileSize(uploading.uploaded, { round: 0 })}
|
{FileSize(uploading.uploaded, { round: 0 })}
|
||||||
/ {FileSize(uploading.size, { round: 0 })}
|
/ {FileSize(uploading.size, { round: 0 })}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</span>
|
||||||
</span>
|
<span className="flex-list-item-r padding-r-m">
|
||||||
<span className="flex-list-item-r padding-r-m">
|
<div className="item-op">
|
||||||
<div className="item-op">
|
<button
|
||||||
<button
|
onClick={() => this.stopUploading(uploading.realFilePath)}
|
||||||
onClick={() => this.stopUploading(uploading.realFilePath)}
|
className="grey1-bg white-font margin-r-m"
|
||||||
className="grey1-bg white-font margin-r-m"
|
>
|
||||||
>
|
{this.props.msg.pkg.get("browser.stop")}
|
||||||
Stop
|
</button>
|
||||||
</button>
|
<button
|
||||||
<button
|
onClick={() => this.deleteUpload(uploading.realFilePath)}
|
||||||
onClick={() => this.deleteUpload(uploading.realFilePath)}
|
className="grey1-bg white-font"
|
||||||
className="grey1-bg white-font"
|
>
|
||||||
>
|
{this.props.msg.pkg.get("browser.delete")}
|
||||||
Delete
|
</button>
|
||||||
</button>
|
</div>
|
||||||
</div>
|
</span>
|
||||||
</span>
|
</div>
|
||||||
</div>
|
);
|
||||||
);
|
}
|
||||||
});
|
);
|
||||||
|
|
||||||
const sharingList = this.props.sharings.map((dirPath: string) => {
|
const sharingList = this.props.browser.sharings.map((dirPath: string) => {
|
||||||
return (
|
return (
|
||||||
<div key={dirPath} className="flex-list-container">
|
<div key={dirPath} className="flex-list-container">
|
||||||
<span className="flex-list-item-l">
|
<span className="flex-list-item-l">
|
||||||
|
@ -501,7 +521,7 @@ export class Browser extends React.Component<Props, State, {}> {
|
||||||
}}
|
}}
|
||||||
className="grey1-bg white-font"
|
className="grey1-bg white-font"
|
||||||
>
|
>
|
||||||
Disable
|
{this.props.msg.pkg.get("browser.share.del")}
|
||||||
</button>
|
</button>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
@ -525,17 +545,17 @@ export class Browser extends React.Component<Props, State, {}> {
|
||||||
borderRadius: "0.5rem",
|
borderRadius: "0.5rem",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Location:
|
{this.props.msg.pkg.get("browser.location")}
|
||||||
</span>
|
</span>
|
||||||
{breadcrumb}
|
{breadcrumb}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{this.props.uploadings.size === 0 ? null : (
|
{this.props.browser.uploadings.size === 0 ? null : (
|
||||||
<div className="container">
|
<div className="container">
|
||||||
<div className="flex-list-container bold">
|
<div className="flex-list-container bold">
|
||||||
<span className="flex-list-item-l">
|
<span className="flex-list-item-l">
|
||||||
<span className="dot black-bg"></span>
|
<span className="dot black-bg"></span>
|
||||||
<span>Uploading Files</span>
|
<span>{this.props.msg.pkg.get("browser.upload.title")}</span>
|
||||||
</span>
|
</span>
|
||||||
<span className="flex-list-item-r padding-r-m"></span>
|
<span className="flex-list-item-r padding-r-m"></span>
|
||||||
</div>
|
</div>
|
||||||
|
@ -543,12 +563,12 @@ export class Browser extends React.Component<Props, State, {}> {
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{this.props.sharings.size === 0 ? null : (
|
{this.props.browser.sharings.size === 0 ? null : (
|
||||||
<div className="container">
|
<div className="container">
|
||||||
<div className="flex-list-container bold">
|
<div className="flex-list-container bold">
|
||||||
<span className="flex-list-item-l">
|
<span className="flex-list-item-l">
|
||||||
<span className="dot black-bg"></span>
|
<span className="dot black-bg"></span>
|
||||||
<span>Sharing Folders</span>
|
<span>{this.props.msg.pkg.get("browser.share.title")}</span>
|
||||||
</span>
|
</span>
|
||||||
<span className="flex-list-item-r padding-r-m"></span>
|
<span className="flex-list-item-r padding-r-m"></span>
|
||||||
</div>
|
</div>
|
||||||
|
@ -560,9 +580,7 @@ export class Browser extends React.Component<Props, State, {}> {
|
||||||
<div className="flex-list-container bold">
|
<div className="flex-list-container bold">
|
||||||
<span className="flex-list-item-l">
|
<span className="flex-list-item-l">
|
||||||
<span className="dot black-bg"></span>
|
<span className="dot black-bg"></span>
|
||||||
<span>Name</span>
|
<span>{this.props.msg.pkg.get("browser.item.title")}</span>
|
||||||
{/* <span>File Size</span>
|
|
||||||
<span>Mod Time</span> */}
|
|
||||||
</span>
|
</span>
|
||||||
<span className="flex-list-item-r padding-r-m">
|
<span className="flex-list-item-r padding-r-m">
|
||||||
<button
|
<button
|
||||||
|
@ -570,7 +588,7 @@ export class Browser extends React.Component<Props, State, {}> {
|
||||||
className={`grey1-bg white-font`}
|
className={`grey1-bg white-font`}
|
||||||
style={{ width: "8rem", display: "inline-block" }}
|
style={{ width: "8rem", display: "inline-block" }}
|
||||||
>
|
>
|
||||||
Select All
|
{this.props.msg.pkg.get("browser.selectAll")}
|
||||||
</button>
|
</button>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -4,16 +4,20 @@ import BgWorker from "../worker/upload.bg.worker";
|
||||||
import { FgWorker } from "../worker/upload.fg.worker";
|
import { FgWorker } from "../worker/upload.fg.worker";
|
||||||
|
|
||||||
// import { Props as PanelProps } from "./root_frame";
|
// import { Props as PanelProps } from "./root_frame";
|
||||||
import { Props as BrowserProps } from "./browser";
|
import { BrowserProps } from "./browser";
|
||||||
import { PanesProps as PanesProps } from "./panes";
|
import { PanesProps } from "./panes";
|
||||||
import { Props as LoginProps } from "./pane_login";
|
import { LoginProps } from "./pane_login";
|
||||||
import { Props as AdminProps } from "./pane_admin";
|
import { AdminProps } from "./pane_admin";
|
||||||
import { Props as SettingsProps } from "./pane_settings";
|
|
||||||
|
|
||||||
|
import { MsgPackage } from "../i18n/msger";
|
||||||
import { Item } from "./browser";
|
import { Item } from "./browser";
|
||||||
import { UploadInfo, User } from "../client";
|
import { UploadInfo, User } from "../client";
|
||||||
import { initUploadMgr, IWorker } from "../worker/upload_mgr";
|
import { initUploadMgr, IWorker } from "../worker/upload_mgr";
|
||||||
|
|
||||||
|
export interface MsgProps {
|
||||||
|
lan: string;
|
||||||
|
pkg: Map<string, string>;
|
||||||
|
}
|
||||||
export interface ICoreState {
|
export interface ICoreState {
|
||||||
// panel: PanelProps;
|
// panel: PanelProps;
|
||||||
isVertical: boolean;
|
isVertical: boolean;
|
||||||
|
@ -21,6 +25,7 @@ export interface ICoreState {
|
||||||
panes: PanesProps;
|
panes: PanesProps;
|
||||||
login: LoginProps;
|
login: LoginProps;
|
||||||
admin: AdminProps;
|
admin: AdminProps;
|
||||||
|
msg: MsgProps;
|
||||||
// settings: SettingsProps;
|
// settings: SettingsProps;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,6 +67,10 @@ export function initState(): ICoreState {
|
||||||
users: Map<string, User>(),
|
users: Map<string, User>(),
|
||||||
roles: Set<string>(),
|
roles: Set<string>(),
|
||||||
},
|
},
|
||||||
|
msg: {
|
||||||
|
lan: "en_US",
|
||||||
|
pkg: MsgPackage.get("en_US"),
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,19 @@
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { Map, Set } from "immutable";
|
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 { User, Quota } from "../client";
|
||||||
import { updater } from "./state_updater";
|
import { updater } from "./state_updater";
|
||||||
|
|
||||||
export interface Props {
|
export interface AdminProps {
|
||||||
users: Map<string, User>;
|
users: Map<string, User>;
|
||||||
roles: Set<string>;
|
roles: Set<string>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Props {
|
||||||
|
admin: AdminProps;
|
||||||
|
msg: MsgProps;
|
||||||
update?: (updater: (prevState: ICoreState) => ICoreState) => void;
|
update?: (updater: (prevState: ICoreState) => ICoreState) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,6 +24,7 @@ export interface UserFormProps {
|
||||||
role: string;
|
role: string;
|
||||||
quota: Quota;
|
quota: Quota;
|
||||||
roles: Set<string>;
|
roles: Set<string>;
|
||||||
|
msg: MsgProps;
|
||||||
update?: (updater: (prevState: ICoreState) => ICoreState) => void;
|
update?: (updater: (prevState: ICoreState) => ICoreState) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,7 +97,7 @@ export class UserForm extends React.Component<
|
||||||
|
|
||||||
setPwd = () => {
|
setPwd = () => {
|
||||||
if (this.state.newPwd1 !== this.state.newPwd2) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,9 +105,9 @@ export class UserForm extends React.Component<
|
||||||
.forceSetPwd(this.state.id, this.state.newPwd1)
|
.forceSetPwd(this.state.id, this.state.newPwd1)
|
||||||
.then((ok: boolean) => {
|
.then((ok: boolean) => {
|
||||||
if (ok) {
|
if (ok) {
|
||||||
alert("password is updated");
|
alertMsg(this.props.msg.pkg.get("update.ok"));
|
||||||
} else {
|
} else {
|
||||||
alert("failed to update password");
|
alertMsg(this.props.msg.pkg.get("update.fail"));
|
||||||
}
|
}
|
||||||
this.setState({
|
this.setState({
|
||||||
newPwd1: "",
|
newPwd1: "",
|
||||||
|
@ -114,9 +121,9 @@ export class UserForm extends React.Component<
|
||||||
.setUser(this.props.id, this.state.role, this.state.quota)
|
.setUser(this.props.id, this.state.role, this.state.quota)
|
||||||
.then((ok: boolean) => {
|
.then((ok: boolean) => {
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
alert("failed to set user");
|
alertMsg(this.props.msg.pkg.get("update.fail"));
|
||||||
} else {
|
} else {
|
||||||
alert("user is updated");
|
alertMsg(this.props.msg.pkg.get("update.ok"));
|
||||||
}
|
}
|
||||||
return updater().listUsers();
|
return updater().listUsers();
|
||||||
})
|
})
|
||||||
|
@ -130,7 +137,7 @@ export class UserForm extends React.Component<
|
||||||
.delUser(this.state.id)
|
.delUser(this.state.id)
|
||||||
.then((ok: boolean) => {
|
.then((ok: boolean) => {
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
alert("failed to delete user");
|
alertMsg(this.props.msg.pkg.get("delete.fail"));
|
||||||
}
|
}
|
||||||
return updater().listUsers();
|
return updater().listUsers();
|
||||||
})
|
})
|
||||||
|
@ -155,8 +162,12 @@ export class UserForm extends React.Component<
|
||||||
}}
|
}}
|
||||||
className="bold item-name"
|
className="bold item-name"
|
||||||
>
|
>
|
||||||
<div>ID: {this.props.id}</div>
|
<div>
|
||||||
<div>Name: {this.props.name}</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>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -172,7 +183,7 @@ export class UserForm extends React.Component<
|
||||||
onClick={this.delUser}
|
onClick={this.delUser}
|
||||||
className="grey1-bg white-font margin-r-m"
|
className="grey1-bg white-font margin-r-m"
|
||||||
>
|
>
|
||||||
Delete User
|
{this.props.msg.pkg.get("delete")}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -196,7 +207,7 @@ export class UserForm extends React.Component<
|
||||||
|
|
||||||
<div className="margin-t-m">
|
<div className="margin-t-m">
|
||||||
<div className="margin-r-m font-size-s grey1-font">
|
<div className="margin-r-m font-size-s grey1-font">
|
||||||
Space Limit
|
{this.props.msg.pkg.get("spaceLimit")}
|
||||||
</div>
|
</div>
|
||||||
<input
|
<input
|
||||||
name={`${this.props.id}-spaceLimit`}
|
name={`${this.props.id}-spaceLimit`}
|
||||||
|
@ -210,7 +221,7 @@ export class UserForm extends React.Component<
|
||||||
|
|
||||||
<div className="margin-t-m">
|
<div className="margin-t-m">
|
||||||
<div className="margin-r-m font-size-s grey1-font">
|
<div className="margin-r-m font-size-s grey1-font">
|
||||||
Upload Speed Limit
|
{this.props.msg.pkg.get("uploadLimit")}
|
||||||
</div>
|
</div>
|
||||||
<input
|
<input
|
||||||
name={`${this.props.id}-uploadSpeedLimit`}
|
name={`${this.props.id}-uploadSpeedLimit`}
|
||||||
|
@ -224,7 +235,7 @@ export class UserForm extends React.Component<
|
||||||
|
|
||||||
<div className="margin-t-m">
|
<div className="margin-t-m">
|
||||||
<div className="margin-r-m font-size-s grey1-font">
|
<div className="margin-r-m font-size-s grey1-font">
|
||||||
Download Speed Limit
|
{this.props.msg.pkg.get("downloadLimit")}
|
||||||
</div>
|
</div>
|
||||||
<input
|
<input
|
||||||
name={`${this.props.id}-downloadSpeedLimit`}
|
name={`${this.props.id}-downloadSpeedLimit`}
|
||||||
|
@ -242,7 +253,7 @@ export class UserForm extends React.Component<
|
||||||
onClick={this.setUser}
|
onClick={this.setUser}
|
||||||
className="grey1-bg white-font margin-r-m"
|
className="grey1-bg white-font margin-r-m"
|
||||||
>
|
>
|
||||||
Update User
|
{this.props.msg.pkg.get("update")}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -262,7 +273,7 @@ export class UserForm extends React.Component<
|
||||||
onChange={this.changePwd1}
|
onChange={this.changePwd1}
|
||||||
value={this.state.newPwd1}
|
value={this.state.newPwd1}
|
||||||
className="black0-font margin-b-m"
|
className="black0-font margin-b-m"
|
||||||
placeholder="new password"
|
placeholder={this.props.msg.pkg.get("settings.pwd.new1")}
|
||||||
/>
|
/>
|
||||||
<input
|
<input
|
||||||
name={`${this.props.id}-pwd2`}
|
name={`${this.props.id}-pwd2`}
|
||||||
|
@ -270,7 +281,7 @@ export class UserForm extends React.Component<
|
||||||
onChange={this.changePwd2}
|
onChange={this.changePwd2}
|
||||||
value={this.state.newPwd2}
|
value={this.state.newPwd2}
|
||||||
className="black0-font margin-b-m"
|
className="black0-font margin-b-m"
|
||||||
placeholder="repeat password"
|
placeholder={this.props.msg.pkg.get("settings.pwd.new2")}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -279,7 +290,7 @@ export class UserForm extends React.Component<
|
||||||
onClick={this.setPwd}
|
onClick={this.setPwd}
|
||||||
className="grey1-bg white-font margin-r-m"
|
className="grey1-bg white-font margin-r-m"
|
||||||
>
|
>
|
||||||
Update
|
{this.props.msg.pkg.get("update")}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -328,7 +339,9 @@ export class AdminPane extends React.Component<Props, State, {}> {
|
||||||
.addRole(this.state.newRole)
|
.addRole(this.state.newRole)
|
||||||
.then((ok: boolean) => {
|
.then((ok: boolean) => {
|
||||||
if (!ok) {
|
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();
|
return updater().listRoles();
|
||||||
})
|
})
|
||||||
|
@ -340,7 +353,7 @@ export class AdminPane extends React.Component<Props, State, {}> {
|
||||||
delRole = (role: string) => {
|
delRole = (role: string) => {
|
||||||
if (
|
if (
|
||||||
!confirm(
|
!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;
|
return;
|
||||||
|
@ -350,7 +363,9 @@ export class AdminPane extends React.Component<Props, State, {}> {
|
||||||
.delRole(role)
|
.delRole(role)
|
||||||
.then((ok: boolean) => {
|
.then((ok: boolean) => {
|
||||||
if (!ok) {
|
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();
|
return updater().listRoles();
|
||||||
})
|
})
|
||||||
|
@ -361,7 +376,7 @@ export class AdminPane extends React.Component<Props, State, {}> {
|
||||||
|
|
||||||
addUser = () => {
|
addUser = () => {
|
||||||
if (this.state.newUserPwd1 !== this.state.newUserPwd2) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -375,7 +390,9 @@ export class AdminPane extends React.Component<Props, State, {}> {
|
||||||
})
|
})
|
||||||
.then((ok: boolean) => {
|
.then((ok: boolean) => {
|
||||||
if (!ok) {
|
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({
|
this.setState({
|
||||||
newUserName: "",
|
newUserName: "",
|
||||||
|
@ -391,7 +408,7 @@ export class AdminPane extends React.Component<Props, State, {}> {
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const userList = this.props.users.valueSeq().map((user: User) => {
|
const userList = this.props.admin.users.valueSeq().map((user: User) => {
|
||||||
return (
|
return (
|
||||||
<div key={user.id} className="margin-t-m">
|
<div key={user.id} className="margin-t-m">
|
||||||
<UserForm
|
<UserForm
|
||||||
|
@ -400,14 +417,15 @@ export class AdminPane extends React.Component<Props, State, {}> {
|
||||||
name={user.name}
|
name={user.name}
|
||||||
role={user.role}
|
role={user.role}
|
||||||
quota={user.quota}
|
quota={user.quota}
|
||||||
roles={this.props.roles}
|
roles={this.props.admin.roles}
|
||||||
|
msg={this.props.msg}
|
||||||
update={this.props.update}
|
update={this.props.update}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
const roleList = this.props.roles.valueSeq().map((role: string) => {
|
const roleList = this.props.admin.roles.valueSeq().map((role: string) => {
|
||||||
return (
|
return (
|
||||||
<div key={role} className="flex-list-container margin-b-m">
|
<div key={role} className="flex-list-container margin-b-m">
|
||||||
<div className="flex-list-item-l">
|
<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"
|
className="grey1-bg white-font margin-r-m"
|
||||||
>
|
>
|
||||||
Delete
|
{this.props.msg.pkg.get("delete")}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -434,7 +452,7 @@ export class AdminPane extends React.Component<Props, State, {}> {
|
||||||
<div className="flex-list-container bold">
|
<div className="flex-list-container bold">
|
||||||
<span className="flex-list-item-l">
|
<span className="flex-list-item-l">
|
||||||
<span className="dot black-bg"></span>
|
<span className="dot black-bg"></span>
|
||||||
<span>Add New User</span>
|
<span>{this.props.msg.pkg.get("user.add")}</span>
|
||||||
</span>
|
</span>
|
||||||
<span className="flex-list-item-r padding-r-m"></span>
|
<span className="flex-list-item-r padding-r-m"></span>
|
||||||
</div>
|
</div>
|
||||||
|
@ -452,28 +470,28 @@ export class AdminPane extends React.Component<Props, State, {}> {
|
||||||
onChange={this.onChangeUserName}
|
onChange={this.onChangeUserName}
|
||||||
value={this.state.newUserName}
|
value={this.state.newUserName}
|
||||||
className="black0-font margin-b-m"
|
className="black0-font margin-b-m"
|
||||||
placeholder="new user name"
|
placeholder={this.props.msg.pkg.get("user.name")}
|
||||||
/>
|
/>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
onChange={this.onChangeUserRole}
|
onChange={this.onChangeUserRole}
|
||||||
value={this.state.newUserRole}
|
value={this.state.newUserRole}
|
||||||
className="black0-font margin-b-m"
|
className="black0-font margin-b-m"
|
||||||
placeholder="new user role"
|
placeholder={this.props.msg.pkg.get("user.role")}
|
||||||
/>
|
/>
|
||||||
<input
|
<input
|
||||||
type="password"
|
type="password"
|
||||||
onChange={this.onChangeUserPwd1}
|
onChange={this.onChangeUserPwd1}
|
||||||
value={this.state.newUserPwd1}
|
value={this.state.newUserPwd1}
|
||||||
className="black0-font margin-b-m"
|
className="black0-font margin-b-m"
|
||||||
placeholder="password"
|
placeholder={this.props.msg.pkg.get("user.password")}
|
||||||
/>
|
/>
|
||||||
<input
|
<input
|
||||||
type="password"
|
type="password"
|
||||||
onChange={this.onChangeUserPwd2}
|
onChange={this.onChangeUserPwd2}
|
||||||
value={this.state.newUserPwd2}
|
value={this.state.newUserPwd2}
|
||||||
className="black0-font margin-b-m"
|
className="black0-font margin-b-m"
|
||||||
placeholder="repeat password"
|
placeholder={this.props.msg.pkg.get("settings.pwd.new2")}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex-list-item-r">
|
<div className="flex-list-item-r">
|
||||||
|
@ -481,7 +499,7 @@ export class AdminPane extends React.Component<Props, State, {}> {
|
||||||
onClick={this.addUser}
|
onClick={this.addUser}
|
||||||
className="grey1-bg white-font margin-r-m"
|
className="grey1-bg white-font margin-r-m"
|
||||||
>
|
>
|
||||||
Create User
|
{this.props.msg.pkg.get("add")}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -492,7 +510,7 @@ export class AdminPane extends React.Component<Props, State, {}> {
|
||||||
<div className="flex-list-container bold">
|
<div className="flex-list-container bold">
|
||||||
<span className="flex-list-item-l">
|
<span className="flex-list-item-l">
|
||||||
<span className="dot black-bg"></span>
|
<span className="dot black-bg"></span>
|
||||||
<span>Users</span>
|
<span>{this.props.msg.pkg.get("admin.users")}</span>
|
||||||
</span>
|
</span>
|
||||||
<span className="flex-list-item-r padding-r-m"></span>
|
<span className="flex-list-item-r padding-r-m"></span>
|
||||||
</div>
|
</div>
|
||||||
|
@ -504,7 +522,7 @@ export class AdminPane extends React.Component<Props, State, {}> {
|
||||||
<div className="flex-list-container bold">
|
<div className="flex-list-container bold">
|
||||||
<span className="flex-list-item-l">
|
<span className="flex-list-item-l">
|
||||||
<span className="dot black-bg"></span>
|
<span className="dot black-bg"></span>
|
||||||
<span>Add New Role</span>
|
<span>{this.props.msg.pkg.get("role.add")}</span>
|
||||||
</span>
|
</span>
|
||||||
<span className="flex-list-item-r padding-r-m"></span>
|
<span className="flex-list-item-r padding-r-m"></span>
|
||||||
</div>
|
</div>
|
||||||
|
@ -517,7 +535,7 @@ export class AdminPane extends React.Component<Props, State, {}> {
|
||||||
onChange={this.onChangeRole}
|
onChange={this.onChangeRole}
|
||||||
value={this.state.newRole}
|
value={this.state.newRole}
|
||||||
className="black0-font margin-r-m"
|
className="black0-font margin-r-m"
|
||||||
placeholder="new role name"
|
placeholder={this.props.msg.pkg.get("role.name")}
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
@ -526,7 +544,7 @@ export class AdminPane extends React.Component<Props, State, {}> {
|
||||||
onClick={this.addRole}
|
onClick={this.addRole}
|
||||||
className="grey1-bg white-font margin-r-m"
|
className="grey1-bg white-font margin-r-m"
|
||||||
>
|
>
|
||||||
Create Role
|
{this.props.msg.pkg.get("add")}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -537,7 +555,7 @@ export class AdminPane extends React.Component<Props, State, {}> {
|
||||||
<div className="flex-list-container bold margin-b-m">
|
<div className="flex-list-container bold margin-b-m">
|
||||||
<span className="flex-list-item-l">
|
<span className="flex-list-item-l">
|
||||||
<span className="dot black-bg"></span>
|
<span className="dot black-bg"></span>
|
||||||
<span>Roles</span>
|
<span>{this.props.msg.pkg.get("admin.roles")}</span>
|
||||||
</span>
|
</span>
|
||||||
<span className="flex-list-item-r padding-r-m"></span>
|
<span className="flex-list-item-r padding-r-m"></span>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,14 +1,19 @@
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { List } from "immutable";
|
import { List } from "immutable";
|
||||||
|
|
||||||
import { ICoreState } 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";
|
||||||
|
|
||||||
export interface Props {
|
export interface LoginProps {
|
||||||
userRole: string;
|
userRole: string;
|
||||||
authed: boolean;
|
authed: boolean;
|
||||||
captchaID: string;
|
captchaID: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Props {
|
||||||
|
login: LoginProps;
|
||||||
|
msg: MsgProps;
|
||||||
update?: (updater: (prevState: ICoreState) => ICoreState) => void;
|
update?: (updater: (prevState: ICoreState) => ICoreState) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,7 +52,7 @@ export class AuthPane extends React.Component<Props, State, {}> {
|
||||||
.login(
|
.login(
|
||||||
this.state.user,
|
this.state.user,
|
||||||
this.state.pwd,
|
this.state.pwd,
|
||||||
this.props.captchaID,
|
this.props.login.captchaID,
|
||||||
this.state.captchaInput
|
this.state.captchaInput
|
||||||
)
|
)
|
||||||
.then((ok: boolean): Promise<any> => {
|
.then((ok: boolean): Promise<any> => {
|
||||||
|
@ -85,7 +90,7 @@ export class AuthPane extends React.Component<Props, State, {}> {
|
||||||
if (ok) {
|
if (ok) {
|
||||||
this.update(updater().updateLogin);
|
this.update(updater().updateLogin);
|
||||||
} else {
|
} 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>
|
<span>
|
||||||
<div
|
<div
|
||||||
className="container"
|
className="container"
|
||||||
style={{ display: this.props.authed ? "none" : "block" }}
|
style={{ display: this.props.login.authed ? "none" : "block" }}
|
||||||
>
|
>
|
||||||
<div className="padding-l">
|
<div className="padding-l">
|
||||||
<div className="flex-list-container">
|
<div className="flex-list-container">
|
||||||
|
@ -114,7 +119,7 @@ export class AuthPane extends React.Component<Props, State, {}> {
|
||||||
onChange={this.changeUser}
|
onChange={this.changeUser}
|
||||||
value={this.state.user}
|
value={this.state.user}
|
||||||
className="black0-font margin-t-m margin-b-m margin-r-m"
|
className="black0-font margin-t-m margin-b-m margin-r-m"
|
||||||
placeholder="user name"
|
placeholder={this.props.msg.pkg.get("login.username")}
|
||||||
/>
|
/>
|
||||||
<input
|
<input
|
||||||
name="pwd"
|
name="pwd"
|
||||||
|
@ -122,7 +127,7 @@ export class AuthPane extends React.Component<Props, State, {}> {
|
||||||
onChange={this.changePwd}
|
onChange={this.changePwd}
|
||||||
value={this.state.pwd}
|
value={this.state.pwd}
|
||||||
className="black0-font margin-t-m margin-b-m"
|
className="black0-font margin-t-m margin-b-m"
|
||||||
placeholder="password"
|
placeholder={this.props.msg.pkg.get("login.pwd")}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex-list-item-r">
|
<div className="flex-list-item-r">
|
||||||
|
@ -130,7 +135,7 @@ export class AuthPane extends React.Component<Props, State, {}> {
|
||||||
onClick={this.login}
|
onClick={this.login}
|
||||||
className="green0-bg white-font margin-t-m margin-b-m"
|
className="green0-bg white-font margin-t-m margin-b-m"
|
||||||
>
|
>
|
||||||
Log in
|
{this.props.msg.pkg.get("login.login")}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -143,10 +148,10 @@ export class AuthPane extends React.Component<Props, State, {}> {
|
||||||
onChange={this.changeCaptcha}
|
onChange={this.changeCaptcha}
|
||||||
value={this.state.captchaInput}
|
value={this.state.captchaInput}
|
||||||
className="black0-font margin-t-m margin-b-m margin-r-m"
|
className="black0-font margin-t-m margin-b-m margin-r-m"
|
||||||
placeholder="captcha"
|
placeholder={this.props.msg.pkg.get("login.captcha")}
|
||||||
/>
|
/>
|
||||||
<img
|
<img
|
||||||
src={`/v1/captchas/imgs?capid=${this.props.captchaID}`}
|
src={`/v1/captchas/imgs?capid=${this.props.login.captchaID}`}
|
||||||
className="captcha"
|
className="captcha"
|
||||||
onClick={this.refreshCaptcha}
|
onClick={this.refreshCaptcha}
|
||||||
/>
|
/>
|
||||||
|
@ -156,9 +161,9 @@ export class AuthPane extends React.Component<Props, State, {}> {
|
||||||
</div>
|
</div>
|
||||||
</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">
|
<button onClick={this.logout} className="grey1-bg white-font">
|
||||||
Log out
|
{this.props.msg.pkg.get("login.logout")}
|
||||||
</button>
|
</button>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
|
|
||||||
import { ICoreState } from "./core_state";
|
import { ICoreState, MsgProps } from "./core_state";
|
||||||
import { AuthPane, Props as LoginProps } from "./pane_login";
|
import { AuthPane, LoginProps } from "./pane_login";
|
||||||
import { updater } from "./state_updater";
|
import { updater } from "./state_updater";
|
||||||
import { alertMsg } from "../common/env";
|
import { alertMsg } from "../common/env";
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
login: LoginProps;
|
login: LoginProps;
|
||||||
|
msg: MsgProps;
|
||||||
update?: (updater: (prevState: ICoreState) => ICoreState) => void;
|
update?: (updater: (prevState: ICoreState) => ICoreState) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,19 +40,19 @@ export class PaneSettings extends React.Component<Props, State, {}> {
|
||||||
|
|
||||||
setPwd = () => {
|
setPwd = () => {
|
||||||
if (this.state.newPwd1 !== this.state.newPwd2) {
|
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 == "") {
|
} 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) {
|
} 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 {
|
} else {
|
||||||
updater()
|
updater()
|
||||||
.setPwd(this.state.oldPwd, this.state.newPwd1)
|
.setPwd(this.state.oldPwd, this.state.newPwd1)
|
||||||
.then((ok: boolean) => {
|
.then((ok: boolean) => {
|
||||||
if (ok) {
|
if (ok) {
|
||||||
alertMsg("Password is updated");
|
alertMsg(this.props.msg.pkg.get("settings.pwd.updated"));
|
||||||
} else {
|
} else {
|
||||||
alertMsg("Failed to update password");
|
alertMsg(this.props.msg.pkg.get("settings.pwd.fail"));
|
||||||
}
|
}
|
||||||
this.setState({
|
this.setState({
|
||||||
oldPwd: "",
|
oldPwd: "",
|
||||||
|
@ -64,36 +64,6 @@ export class PaneSettings extends React.Component<Props, State, {}> {
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
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 (
|
return (
|
||||||
<div className="container">
|
<div className="container">
|
||||||
<div className="padding-l">
|
<div className="padding-l">
|
||||||
|
@ -104,7 +74,7 @@ export class PaneSettings extends React.Component<Props, State, {}> {
|
||||||
</div>
|
</div>
|
||||||
<div className="flex-list-item-r">
|
<div className="flex-list-item-r">
|
||||||
<button onClick={this.setPwd} className="grey1-bg white-font">
|
<button onClick={this.setPwd} className="grey1-bg white-font">
|
||||||
Update
|
{this.props.msg.pkg.get("update")}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -116,7 +86,7 @@ export class PaneSettings extends React.Component<Props, State, {}> {
|
||||||
onChange={this.changeOldPwd}
|
onChange={this.changeOldPwd}
|
||||||
value={this.state.oldPwd}
|
value={this.state.oldPwd}
|
||||||
className="black0-font margin-t-m margin-b-m"
|
className="black0-font margin-t-m margin-b-m"
|
||||||
placeholder="old password"
|
placeholder={this.props.msg.pkg.get("settings.pwd.old")}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
@ -126,7 +96,7 @@ export class PaneSettings extends React.Component<Props, State, {}> {
|
||||||
onChange={this.changeNewPwd1}
|
onChange={this.changeNewPwd1}
|
||||||
value={this.state.newPwd1}
|
value={this.state.newPwd1}
|
||||||
className="black0-font margin-t-m margin-b-m margin-r-m"
|
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
|
<input
|
||||||
name="new_pwd2"
|
name="new_pwd2"
|
||||||
|
@ -134,7 +104,7 @@ export class PaneSettings extends React.Component<Props, State, {}> {
|
||||||
onChange={this.changeNewPwd2}
|
onChange={this.changeNewPwd2}
|
||||||
value={this.state.newPwd2}
|
value={this.state.newPwd2}
|
||||||
className="black0-font margin-t-m margin-b-m"
|
className="black0-font margin-t-m margin-b-m"
|
||||||
placeholder="new password again"
|
placeholder={this.props.msg.pkg.get("settings.pwd.new2")}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -148,9 +118,8 @@ export class PaneSettings extends React.Component<Props, State, {}> {
|
||||||
</div>
|
</div>
|
||||||
<div className="flex-list-item-r">
|
<div className="flex-list-item-r">
|
||||||
<AuthPane
|
<AuthPane
|
||||||
userRole={this.props.login.userRole}
|
login={this.props.login}
|
||||||
authed={this.props.login.authed}
|
msg={this.props.msg}
|
||||||
captchaID={this.props.login.captchaID}
|
|
||||||
update={this.update}
|
update={this.update}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -2,10 +2,10 @@ import * as React from "react";
|
||||||
import { Set, Map } from "immutable";
|
import { Set, Map } from "immutable";
|
||||||
|
|
||||||
import { updater } from "./state_updater";
|
import { updater } from "./state_updater";
|
||||||
import { ICoreState } from "./core_state";
|
import { ICoreState, MsgProps } from "./core_state";
|
||||||
import { PaneSettings } from "./pane_settings";
|
import { PaneSettings } from "./pane_settings";
|
||||||
import { AdminPane, Props as AdminPaneProps } from "./pane_admin";
|
import { AdminPane, AdminProps } from "./pane_admin";
|
||||||
import { AuthPane, Props as AuthPaneProps } from "./pane_login";
|
import { AuthPane, LoginProps } from "./pane_login";
|
||||||
|
|
||||||
export interface PanesProps {
|
export interface PanesProps {
|
||||||
displaying: string;
|
displaying: string;
|
||||||
|
@ -13,8 +13,9 @@ export interface PanesProps {
|
||||||
}
|
}
|
||||||
export interface Props {
|
export interface Props {
|
||||||
panes: PanesProps;
|
panes: PanesProps;
|
||||||
login: AuthPaneProps;
|
login: LoginProps;
|
||||||
admin: AdminPaneProps;
|
admin: AdminProps;
|
||||||
|
msg: MsgProps;
|
||||||
update?: (updater: (prevState: ICoreState) => ICoreState) => void;
|
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({
|
let panesMap: Map<string, JSX.Element> = Map({
|
||||||
settings: (
|
settings: (
|
||||||
<PaneSettings login={this.props.login} update={this.props.update} />
|
<PaneSettings
|
||||||
|
login={this.props.login}
|
||||||
|
msg={this.props.msg}
|
||||||
|
update={this.props.update}
|
||||||
|
/>
|
||||||
),
|
),
|
||||||
login: (
|
login: (
|
||||||
<AuthPane
|
<AuthPane
|
||||||
userRole={this.props.login.userRole}
|
login={this.props.login}
|
||||||
authed={this.props.login.authed}
|
|
||||||
captchaID={this.props.login.captchaID}
|
|
||||||
update={this.props.update}
|
update={this.props.update}
|
||||||
|
msg={this.props.msg}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
|
@ -57,8 +61,8 @@ export class Panes extends React.Component<Props, State, {}> {
|
||||||
panesMap = panesMap.set(
|
panesMap = panesMap.set(
|
||||||
"admin",
|
"admin",
|
||||||
<AdminPane
|
<AdminPane
|
||||||
users={this.props.admin.users}
|
admin={this.props.admin}
|
||||||
roles={this.props.admin.roles}
|
msg={this.props.msg}
|
||||||
update={this.props.update}
|
update={this.props.update}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -86,7 +90,7 @@ export class Panes extends React.Component<Props, State, {}> {
|
||||||
onClick={this.closePane}
|
onClick={this.closePane}
|
||||||
className={`red0-bg white-font ${btnClass}`}
|
className={`red0-bg white-font ${btnClass}`}
|
||||||
>
|
>
|
||||||
Close
|
{this.props.msg.pkg.get("panes.close")}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,14 +1,18 @@
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
|
|
||||||
import { ICoreState } from "./core_state";
|
import { ICoreState, MsgProps } from "./core_state";
|
||||||
import { Browser, Props as BrowserProps } from "./browser";
|
import { Browser, BrowserProps } from "./browser";
|
||||||
import { Props as PaneLoginProps } from "./pane_login";
|
import { LoginProps } from "./pane_login";
|
||||||
import { Panes, Props as PanesProps } from "./panes";
|
import { Panes, PanesProps } from "./panes";
|
||||||
|
import { AdminProps } from "./pane_admin";
|
||||||
import { TopBar } from "./topbar";
|
import { TopBar } from "./topbar";
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
browser: BrowserProps;
|
browser: BrowserProps;
|
||||||
panes: PanesProps;
|
panes: PanesProps;
|
||||||
|
admin: AdminProps;
|
||||||
|
login: LoginProps;
|
||||||
|
msg: MsgProps;
|
||||||
update?: (updater: (prevState: ICoreState) => ICoreState) => void;
|
update?: (updater: (prevState: ICoreState) => ICoreState) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,25 +27,24 @@ export class RootFrame extends React.Component<Props, State, {}> {
|
||||||
<div className="theme-white desktop">
|
<div className="theme-white desktop">
|
||||||
<div id="bg" className="bg bg-img font-m">
|
<div id="bg" className="bg bg-img font-m">
|
||||||
<Panes
|
<Panes
|
||||||
panes={this.props.panes.panes}
|
panes={this.props.panes}
|
||||||
login={this.props.panes.login}
|
login={this.props.login}
|
||||||
admin={this.props.panes.admin}
|
admin={this.props.admin}
|
||||||
|
msg={this.props.msg}
|
||||||
update={this.props.update}
|
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">
|
<div className="container-center">
|
||||||
<Browser
|
<Browser
|
||||||
dirPath={this.props.browser.dirPath}
|
browser={this.props.browser}
|
||||||
items={this.props.browser.items}
|
msg={this.props.msg}
|
||||||
uploadings={this.props.browser.uploadings}
|
|
||||||
sharings={this.props.browser.sharings}
|
|
||||||
isSharing={this.props.browser.isSharing}
|
|
||||||
update={this.props.update}
|
update={this.props.update}
|
||||||
uploadFiles={this.props.browser.uploadFiles}
|
|
||||||
uploadValue={this.props.browser.uploadValue}
|
|
||||||
isVertical={this.props.browser.isVertical}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -56,7 +56,7 @@ export class StateMgr extends React.Component<Props, State, {}> {
|
||||||
})
|
})
|
||||||
.then((ok: boolean) => {
|
.then((ok: boolean) => {
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
alertMsg("failed to get captcha id");
|
alertMsg(this.state.msg.pkg.get("stateMgr.cap.fail"));
|
||||||
} else {
|
} else {
|
||||||
this.update(updater().updateLogin);
|
this.update(updater().updateLogin);
|
||||||
}
|
}
|
||||||
|
@ -114,11 +114,10 @@ export class StateMgr extends React.Component<Props, State, {}> {
|
||||||
return (
|
return (
|
||||||
<RootFrame
|
<RootFrame
|
||||||
browser={this.state.browser}
|
browser={this.state.browser}
|
||||||
panes={{
|
msg={this.state.msg}
|
||||||
panes: this.state.panes,
|
panes={this.state.panes}
|
||||||
login: this.state.login,
|
login={this.state.login}
|
||||||
admin: this.state.admin,
|
admin={this.state.admin}
|
||||||
}}
|
|
||||||
update={this.update}
|
update={this.update}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
|
@ -18,6 +18,8 @@ import { UploadEntry } from "../worker/interface";
|
||||||
import { Up } from "../worker/upload_mgr";
|
import { Up } from "../worker/upload_mgr";
|
||||||
import { alertMsg } from "../common/env";
|
import { alertMsg } from "../common/env";
|
||||||
|
|
||||||
|
import { MsgPackage } from "../i18n/msger";
|
||||||
|
|
||||||
export class Updater {
|
export class Updater {
|
||||||
props: ICoreState;
|
props: ICoreState;
|
||||||
private usersClient: IUsersClient = new UsersClient("");
|
private usersClient: IUsersClient = new UsersClient("");
|
||||||
|
@ -220,7 +222,11 @@ export class Updater {
|
||||||
return resp.status === 200;
|
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);
|
const resp = await this.usersClient.setUser(userID, role, quota);
|
||||||
return resp.status === 200;
|
return resp.status === 200;
|
||||||
};
|
};
|
||||||
|
@ -306,11 +312,9 @@ export class Updater {
|
||||||
};
|
};
|
||||||
|
|
||||||
initIsAuthed = async (): Promise<void> => {
|
initIsAuthed = async (): Promise<void> => {
|
||||||
return this
|
return this.isAuthed().then((isAuthed) => {
|
||||||
.isAuthed()
|
updater().setAuthed(isAuthed);
|
||||||
.then((isAuthed) => {
|
});
|
||||||
updater().setAuthed(isAuthed);
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
setAuthed = (isAuthed: boolean) => {
|
setAuthed = (isAuthed: boolean) => {
|
||||||
|
@ -331,6 +335,21 @@ export class Updater {
|
||||||
return resp.status === 200;
|
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 => {
|
updateBrowser = (prevState: ICoreState): ICoreState => {
|
||||||
return {
|
return {
|
||||||
...prevState,
|
...prevState,
|
||||||
|
@ -358,6 +377,13 @@ export class Updater {
|
||||||
admin: { ...prevState.admin, ...this.props.admin },
|
admin: { ...prevState.admin, ...this.props.admin },
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
updateMsg = (prevState: ICoreState): ICoreState => {
|
||||||
|
return {
|
||||||
|
...prevState,
|
||||||
|
msg: { ...prevState.msg, ...this.props.msg },
|
||||||
|
};
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export let coreUpdater = new Updater();
|
export let coreUpdater = new Updater();
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
|
|
||||||
import { ICoreState } from "./core_state";
|
import { ICoreState, MsgProps } from "./core_state";
|
||||||
import { Props as LoginProps } from "./pane_login";
|
import { LoginProps } from "./pane_login";
|
||||||
import { updater } from "./state_updater";
|
import { updater } from "./state_updater";
|
||||||
|
|
||||||
export interface State {}
|
export interface State {}
|
||||||
export interface Props {
|
export interface Props {
|
||||||
login: LoginProps;
|
login: LoginProps;
|
||||||
|
msg: MsgProps;
|
||||||
update?: (updater: (prevState: ICoreState) => ICoreState) => void;
|
update?: (updater: (prevState: ICoreState) => ICoreState) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,13 +58,13 @@ export class TopBar extends React.Component<Props, State, {}> {
|
||||||
onClick={this.showSettings}
|
onClick={this.showSettings}
|
||||||
className="grey1-bg white-font margin-r-m"
|
className="grey1-bg white-font margin-r-m"
|
||||||
>
|
>
|
||||||
Settings
|
{this.props.msg.pkg.get("settings")}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={this.showAdmin}
|
onClick={this.showAdmin}
|
||||||
className="grey1-bg white-font margin-r-m"
|
className="grey1-bg white-font margin-r-m"
|
||||||
>
|
>
|
||||||
Admin
|
{this.props.msg.pkg.get("admin")}
|
||||||
</button>
|
</button>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,8 +1,64 @@
|
||||||
import { Map } from "immutable";
|
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({
|
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>) {
|
constructor(msgs: Map<string, string>) {
|
||||||
this.msgs = msgs;
|
this.msgs = msgs;
|
||||||
}
|
}
|
||||||
getMsg(key: string): string {
|
m(key: string): string {
|
||||||
return this.msgs.get(key, "");
|
return this.msgs.get(key, "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class MsgPackage {
|
export class MsgPackage {
|
||||||
static getPkg(key: string): Map<string, string> {
|
static get(key: string): Map<string, string> {
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case "en-US":
|
case "en-US":
|
||||||
return Map(enMsgs);
|
return Map(enMsgs);
|
||||||
|
|
|
@ -1,8 +1,63 @@
|
||||||
import { Map } from "immutable";
|
import { Map } from "immutable";
|
||||||
|
|
||||||
const adContent = `
|
|
||||||
发现bug等, 可至下方github库提交issue, 不过周末可能不上班😎.`;
|
|
||||||
|
|
||||||
export const msgs: Map<string, string> = Map({
|
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