fix(updater): merge all updater as one updater
This commit is contained in:
parent
369b769952
commit
ee056aa193
15 changed files with 704 additions and 450 deletions
|
@ -2,7 +2,7 @@ import * as React from "react";
|
|||
import { List, Map } from "immutable";
|
||||
import { mock, instance, anyString, anything, when, verify } from "ts-mockito";
|
||||
|
||||
import { ICoreState, initWithWorker, mockState } from "../core_state";
|
||||
import { ICoreState, newWithWorker, initState } from "../core_state";
|
||||
import {
|
||||
makePromise,
|
||||
makeNumberResponse,
|
||||
|
@ -11,7 +11,9 @@ import {
|
|||
mockFileList,
|
||||
} from "../../test/helpers";
|
||||
import { Browser } from "../browser";
|
||||
import { Updater, setUpdater } from "../browser.updater";
|
||||
// import { Updater, setUpdater } from "../browser.updater";
|
||||
|
||||
import { updater, Updater, setUpdater } from "../state_updater";
|
||||
import { MockUsersClient } from "../../client/users_mock";
|
||||
import { UsersClient } from "../../client/users";
|
||||
import { FilesClient } from "../../client/files";
|
||||
|
@ -25,18 +27,18 @@ describe("Browser", () => {
|
|||
const mockWorker = instance(mockWorkerClass);
|
||||
|
||||
test("Updater: addUploads: add each files to UploadMgr", async () => {
|
||||
let coreState = mockState();
|
||||
let coreState = initState();
|
||||
const UploadMgrClass = mock(UploadMgr);
|
||||
const uploadMgr = instance(UploadMgrClass);
|
||||
setUploadMgr(uploadMgr);
|
||||
|
||||
const filePaths = ["./file1", "./file2"];
|
||||
const fileList = mockFileList(filePaths);
|
||||
const updater = new Updater();
|
||||
updater.setUploadings = (infos: Map<string, UploadEntry>) => {};
|
||||
updater.init(coreState.panel.browser);
|
||||
// const updater = new Updater();
|
||||
updater().setUploadings = (infos: Map<string, UploadEntry>) => {};
|
||||
updater().init(coreState);
|
||||
|
||||
updater.addUploads(fileList);
|
||||
updater().addUploads(fileList);
|
||||
|
||||
// it seems that new File will do some file path escaping, so just check call time here
|
||||
verify(UploadMgrClass.add(anything(), anything())).times(filePaths.length);
|
||||
|
@ -46,12 +48,12 @@ describe("Browser", () => {
|
|||
});
|
||||
|
||||
test("Updater: deleteUploads: call UploadMgr and api to delete", async () => {
|
||||
let coreState = mockState();
|
||||
let coreState = initState();
|
||||
const UploadMgrClass = mock(UploadMgr);
|
||||
const uploadMgr = instance(UploadMgrClass);
|
||||
setUploadMgr(uploadMgr);
|
||||
|
||||
const updater = new Updater();
|
||||
// const updater = new Updater();
|
||||
const filesClientClass = mock(FilesClient);
|
||||
when(filesClientClass.deleteUploading(anyString())).thenResolve({
|
||||
status: 200,
|
||||
|
@ -61,11 +63,11 @@ describe("Browser", () => {
|
|||
const filesClient = instance(filesClientClass);
|
||||
const usersClientClass = mock(UsersClient);
|
||||
const usersClient = instance(usersClientClass);
|
||||
updater.init(coreState.panel.browser);
|
||||
updater.setClients(usersClient, filesClient);
|
||||
updater().init(coreState);
|
||||
updater().setClients(usersClient, filesClient);
|
||||
|
||||
const filePath = "./path/file";
|
||||
updater.deleteUpload(filePath);
|
||||
updater().deleteUpload(filePath);
|
||||
|
||||
verify(filesClientClass.deleteUploading(filePath)).once();
|
||||
verify(UploadMgrClass.delete(filePath)).once();
|
||||
|
@ -114,20 +116,20 @@ describe("Browser", () => {
|
|||
const filesClient = new MockFilesClient("");
|
||||
for (let i = 0; i < tests.length; i++) {
|
||||
const tc = tests[i];
|
||||
const updater = new Updater();
|
||||
updater.setClients(usersClient, filesClient);
|
||||
// const updater = new Updater();
|
||||
updater().setClients(usersClient, filesClient);
|
||||
filesClient.listMock(makePromise(tc.listResp));
|
||||
filesClient.deleteMock(makeNumberResponse(200));
|
||||
const coreState = initWithWorker(mockWorker);
|
||||
updater.init(coreState.panel.browser);
|
||||
const coreState = newWithWorker(mockWorker);
|
||||
updater().init(coreState);
|
||||
|
||||
await updater.delete(
|
||||
await updater().delete(
|
||||
List<string>(tc.dirPath.split("/")),
|
||||
List<MetadataResp>(tc.items),
|
||||
Map(tc.selected)
|
||||
);
|
||||
|
||||
const newState = updater.setBrowser(coreState);
|
||||
const newState = updater().updateBrowser(coreState);
|
||||
|
||||
// TODO: check inputs of delete
|
||||
newState.panel.browser.items.forEach((item, i) => {
|
||||
|
@ -171,14 +173,14 @@ describe("Browser", () => {
|
|||
|
||||
for (let i = 0; i < tests.length; i++) {
|
||||
const tc = tests[i];
|
||||
const updater = new Updater();
|
||||
filesClient.listMock(makePromise(tc.listResp));
|
||||
updater.setClients(usersClient, filesClient);
|
||||
const coreState = initWithWorker(mockWorker);
|
||||
updater.init(coreState.panel.browser);
|
||||
|
||||
await updater.setItems(List<string>(tc.filePath.split("/")));
|
||||
const newState = updater.setBrowser(coreState);
|
||||
filesClient.listMock(makePromise(tc.listResp));
|
||||
updater().setClients(usersClient, filesClient);
|
||||
const coreState = newWithWorker(mockWorker);
|
||||
updater().init(coreState);
|
||||
|
||||
await updater().setItems(List<string>(tc.filePath.split("/")));
|
||||
const newState = updater().updateBrowser(coreState);
|
||||
|
||||
newState.panel.browser.items.forEach((item, i) => {
|
||||
expect(item.name).toEqual(tc.listResp.data.metadatas[i].name);
|
||||
|
@ -225,17 +227,16 @@ describe("Browser", () => {
|
|||
const filesClient = new MockFilesClient("");
|
||||
for (let i = 0; i < tests.length; i++) {
|
||||
const tc = tests[i];
|
||||
const updater = new Updater();
|
||||
|
||||
filesClient.listMock(makePromise(tc.listResp));
|
||||
filesClient.moveMock(makeNumberResponse(200));
|
||||
updater.setClients(usersClient, filesClient);
|
||||
updater().setClients(usersClient, filesClient);
|
||||
|
||||
const coreState = initWithWorker(mockWorker);
|
||||
updater.init(coreState.panel.browser);
|
||||
await updater.moveHere(tc.dirPath1, tc.dirPath2, Map(tc.selected));
|
||||
const coreState = newWithWorker(mockWorker);
|
||||
updater().init(coreState);
|
||||
await updater().moveHere(tc.dirPath1, tc.dirPath2, Map(tc.selected));
|
||||
|
||||
const newState = updater.setBrowser(coreState);
|
||||
const newState = updater().updateBrowser(coreState);
|
||||
|
||||
// TODO: check inputs of move
|
||||
newState.panel.browser.items.forEach((item, i) => {
|
||||
|
@ -248,7 +249,7 @@ describe("Browser", () => {
|
|||
});
|
||||
|
||||
test("Browser: deleteUpload: tell uploader to deleteUpload and refreshUploadings", async () => {
|
||||
let coreState = mockState();
|
||||
let coreState = initState();
|
||||
addMockUpdate(coreState.panel.browser);
|
||||
const component = new Browser(coreState.panel.browser);
|
||||
const UpdaterClass = mock(Updater);
|
||||
|
@ -266,7 +267,7 @@ describe("Browser", () => {
|
|||
});
|
||||
|
||||
test("Browser: stopUploading: tell updater to stopUploading", async () => {
|
||||
let coreState = mockState();
|
||||
let coreState = initState();
|
||||
addMockUpdate(coreState.panel.browser);
|
||||
const component = new Browser(coreState.panel.browser);
|
||||
const UpdaterClass = mock(Updater);
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
import { mock, instance } from "ts-mockito";
|
||||
|
||||
import { initWithWorker } from "../core_state";
|
||||
import { Updater } from "../pane_login";
|
||||
import { newWithWorker } from "../core_state";
|
||||
import { updater } from "../state_updater";
|
||||
import { MockUsersClient } from "../../client/users_mock";
|
||||
import { FilesClient } from "../../client/files_mock";
|
||||
import { Response } from "../../client";
|
||||
import { MockWorker } from "../../worker/interface";
|
||||
|
||||
|
@ -41,20 +42,21 @@ describe("AuthPane", () => {
|
|||
},
|
||||
];
|
||||
|
||||
const client = new MockUsersClient("");
|
||||
const usersClient = new MockUsersClient("");
|
||||
const filesClient = new FilesClient("");
|
||||
for (let i = 0; i < tests.length; i++) {
|
||||
const tc = tests[i];
|
||||
|
||||
client.loginMock(makeNumberResponse(tc.loginStatus));
|
||||
client.logoutMock(makeNumberResponse(tc.logoutStatus));
|
||||
client.isAuthedMock(makeNumberResponse(tc.isAuthedStatus));
|
||||
client.setPwdMock(makeNumberResponse(tc.setPwdStatus));
|
||||
usersClient.loginMock(makeNumberResponse(tc.loginStatus));
|
||||
usersClient.logoutMock(makeNumberResponse(tc.logoutStatus));
|
||||
usersClient.isAuthedMock(makeNumberResponse(tc.isAuthedStatus));
|
||||
usersClient.setPwdMock(makeNumberResponse(tc.setPwdStatus));
|
||||
|
||||
const coreState = initWithWorker(mockWorker);
|
||||
Updater.setClient(client);
|
||||
Updater.init(coreState.panel.authPane);
|
||||
await Updater.initIsAuthed();
|
||||
const newState = Updater.setAuthPane(coreState);
|
||||
const coreState = newWithWorker(mockWorker);
|
||||
updater().setClients(usersClient, filesClient);
|
||||
updater().init(coreState);
|
||||
await updater().initIsAuthed();
|
||||
const newState = updater().updateAuthPane(coreState);
|
||||
|
||||
expect(newState.panel.authPane.authed).toEqual(tc.isAuthed);
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
import { Set } from "immutable";
|
||||
|
||||
import { ICoreState, mockState } from "../core_state";
|
||||
import { Panes, Updater } from "../panes";
|
||||
import { ICoreState, initState } from "../core_state";
|
||||
import { Panes } from "../panes";
|
||||
import { mockUpdate } from "../../test/helpers";
|
||||
import { updater } from "../state_updater";
|
||||
|
||||
describe("Panes", () => {
|
||||
test("Panes: closePane", async () => {
|
||||
|
@ -36,14 +37,14 @@ describe("Panes", () => {
|
|||
};
|
||||
|
||||
tcs.forEach((tc: TestCase) => {
|
||||
const preState = setState(tc.preState, mockState());
|
||||
const postState = setState(tc.postState, mockState());
|
||||
const preState = setState(tc.preState, initState());
|
||||
const postState = setState(tc.postState, initState());
|
||||
|
||||
const component = new Panes(preState.panel.panes);
|
||||
Updater.init(preState.panel.panes);
|
||||
updater().init(preState);
|
||||
|
||||
component.closePane();
|
||||
expect(Updater.props).toEqual(postState.panel.panes);
|
||||
expect(updater().props).toEqual(postState);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import { Set } from "immutable";
|
||||
// import { mock, instance } from "ts-mockito";
|
||||
|
||||
import { ICoreState, mockState } from "../core_state";
|
||||
import { ICoreState, initState } from "../core_state";
|
||||
import { RootFrame } from "../root_frame";
|
||||
import { Updater } from "../panes";
|
||||
// import { Updater } from "../panes";
|
||||
import { updater } from "../state_updater";
|
||||
|
||||
describe("RootFrame", () => {
|
||||
xdescribe("RootFrame", () => {
|
||||
test("component: showSettings", async () => {
|
||||
interface TestCase {
|
||||
preState: ICoreState;
|
||||
|
@ -39,14 +39,14 @@ describe("RootFrame", () => {
|
|||
};
|
||||
|
||||
tcs.forEach((tc: TestCase) => {
|
||||
const preState = setState(tc.preState, mockState());
|
||||
const postState = setState(tc.postState, mockState());
|
||||
const preState = setState(tc.preState, initState());
|
||||
const postState = setState(tc.postState, initState());
|
||||
|
||||
const component = new RootFrame(preState.panel);
|
||||
Updater.init(preState.panel.panes);
|
||||
updater().init(preState);
|
||||
|
||||
component.showSettings();
|
||||
expect(Updater.props).toEqual(postState.panel.panes);
|
||||
// component.showSettings();
|
||||
expect(updater().props).toEqual(postState);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -3,13 +3,10 @@ import * as ReactDOM from "react-dom";
|
|||
import { List, Map } from "immutable";
|
||||
import FileSize from "filesize";
|
||||
|
||||
import { Layouter } from "./layouter";
|
||||
import { alertMsg, comfirmMsg } from "../common/env";
|
||||
import { updater } from "./browser.updater";
|
||||
import { updater } from "./state_updater";
|
||||
import { ICoreState } from "./core_state";
|
||||
import {
|
||||
IUsersClient,
|
||||
IFilesClient,
|
||||
MetadataResp,
|
||||
UploadInfo,
|
||||
} from "../client";
|
||||
|
@ -88,7 +85,7 @@ export class Browser extends React.Component<Props, State, {}> {
|
|||
fileList = fileList.push(event.target.files[i]);
|
||||
}
|
||||
updater().addUploads(fileList);
|
||||
this.update(updater().setBrowser);
|
||||
this.update(updater().updateBrowser);
|
||||
};
|
||||
|
||||
deleteUpload = (filePath: string): Promise<void> => {
|
||||
|
@ -101,13 +98,13 @@ export class Browser extends React.Component<Props, State, {}> {
|
|||
return updater().refreshUploadings();
|
||||
})
|
||||
.then(() => {
|
||||
this.update(updater().setBrowser);
|
||||
this.update(updater().updateBrowser);
|
||||
});
|
||||
};
|
||||
|
||||
stopUploading = (filePath: string) => {
|
||||
updater().stopUploading(filePath);
|
||||
this.update(updater().setBrowser);
|
||||
this.update(updater().updateBrowser);
|
||||
};
|
||||
|
||||
onMkDir = () => {
|
||||
|
@ -127,7 +124,7 @@ export class Browser extends React.Component<Props, State, {}> {
|
|||
return updater().setItems(this.props.dirPath);
|
||||
})
|
||||
.then(() => {
|
||||
this.update(updater().setBrowser);
|
||||
this.update(updater().updateBrowser);
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -149,7 +146,7 @@ export class Browser extends React.Component<Props, State, {}> {
|
|||
updater()
|
||||
.delete(this.props.dirPath, this.props.items, this.state.selectedItems)
|
||||
.then(() => {
|
||||
this.update(updater().setBrowser);
|
||||
this.update(updater().updateBrowser);
|
||||
this.setState({
|
||||
selectedSrc: "",
|
||||
selectedItems: Map<string, boolean>(),
|
||||
|
@ -172,7 +169,7 @@ export class Browser extends React.Component<Props, State, {}> {
|
|||
this.state.selectedItems
|
||||
)
|
||||
.then(() => {
|
||||
this.update(updater().setBrowser);
|
||||
this.update(updater().updateBrowser);
|
||||
this.setState({
|
||||
selectedSrc: "",
|
||||
selectedItems: Map<string, boolean>(),
|
||||
|
@ -198,7 +195,7 @@ export class Browser extends React.Component<Props, State, {}> {
|
|||
return updater().isSharing(dirPath.join("/"));
|
||||
})
|
||||
.then(() => {
|
||||
this.update(updater().setBrowser);
|
||||
this.update(updater().updateBrowser);
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -207,7 +204,7 @@ export class Browser extends React.Component<Props, State, {}> {
|
|||
updater()
|
||||
.setItems(this.props.dirPath)
|
||||
.then(() => {
|
||||
this.update(updater().setBrowser);
|
||||
this.update(updater().updateBrowser);
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -253,7 +250,7 @@ export class Browser extends React.Component<Props, State, {}> {
|
|||
}
|
||||
})
|
||||
.then(() => {
|
||||
this.props.update(updater().setBrowser);
|
||||
this.props.update(updater().updateBrowser);
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -269,7 +266,7 @@ export class Browser extends React.Component<Props, State, {}> {
|
|||
}
|
||||
})
|
||||
.then(() => {
|
||||
this.props.update(updater().setBrowser);
|
||||
this.props.update(updater().updateBrowser);
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -278,7 +275,7 @@ export class Browser extends React.Component<Props, State, {}> {
|
|||
.listSharings()
|
||||
.then((ok) => {
|
||||
if (ok) {
|
||||
this.update(updater().setBrowser);
|
||||
this.update(updater().updateBrowser);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
|
|
@ -8,35 +8,24 @@ import { Item } from "./browser";
|
|||
import { UploadInfo, User } from "../client";
|
||||
import { initUploadMgr, IWorker } from "../worker/upload_mgr";
|
||||
|
||||
export class BaseUpdater {
|
||||
public static props: any;
|
||||
public static init = (props: any) => (BaseUpdater.props = { ...props });
|
||||
public static apply = (prevState: ICoreState): ICoreState => {
|
||||
throw Error("apply is not implemented");
|
||||
};
|
||||
}
|
||||
|
||||
export interface ICoreState {
|
||||
panel: PanelProps;
|
||||
isVertical: boolean;
|
||||
}
|
||||
|
||||
export function initWithWorker(worker: IWorker): ICoreState {
|
||||
export function newWithWorker(worker: IWorker): ICoreState {
|
||||
initUploadMgr(worker);
|
||||
return initState();
|
||||
}
|
||||
|
||||
export function init(): ICoreState {
|
||||
export function newState(): ICoreState {
|
||||
const worker = Worker == null ? new FgWorker() : new BgWorker();
|
||||
initUploadMgr(worker);
|
||||
|
||||
return initState();
|
||||
}
|
||||
|
||||
export function isVertical(): boolean {
|
||||
return window.innerWidth <= window.innerHeight;
|
||||
}
|
||||
|
||||
export function initState(): ICoreState {
|
||||
return {
|
||||
isVertical: isVertical(),
|
||||
|
@ -73,38 +62,7 @@ export function initState(): ICoreState {
|
|||
};
|
||||
}
|
||||
|
||||
export function mockState(): ICoreState {
|
||||
return {
|
||||
isVertical: false,
|
||||
panel: {
|
||||
displaying: "browser",
|
||||
authPane: {
|
||||
authed: false,
|
||||
captchaID: "",
|
||||
},
|
||||
browser: {
|
||||
isVertical: false,
|
||||
dirPath: List<string>(["."]),
|
||||
items: List<Item>([]),
|
||||
sharings: List<string>([]),
|
||||
isSharing: false,
|
||||
uploadings: List<UploadInfo>([]),
|
||||
uploadValue: "",
|
||||
uploadFiles: List<File>([]),
|
||||
},
|
||||
panes: {
|
||||
userRole: "",
|
||||
displaying: "",
|
||||
paneNames: Set<string>(["settings", "login", "admin"]),
|
||||
login: {
|
||||
authed: false,
|
||||
captchaID: "",
|
||||
},
|
||||
admin: {
|
||||
users: Map<string, User>(),
|
||||
roles: Set<string>(),
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function isVertical(): boolean {
|
||||
return window.innerWidth <= window.innerHeight;
|
||||
}
|
|
@ -3,7 +3,7 @@ import { Map, Set } from "immutable";
|
|||
|
||||
import { ICoreState } from "./core_state";
|
||||
import { User, Quota } from "../client";
|
||||
import { Updater as PanesUpdater } from "./panes";
|
||||
import { updater } from "./state_updater";
|
||||
|
||||
export interface Props {
|
||||
users: Map<string, User>;
|
||||
|
@ -94,8 +94,9 @@ export class UserForm extends React.Component<
|
|||
return;
|
||||
}
|
||||
|
||||
PanesUpdater.forceSetPwd(this.state.id, this.state.newPwd1).then(
|
||||
(ok: boolean) => {
|
||||
updater()
|
||||
.forceSetPwd(this.state.id, this.state.newPwd1)
|
||||
.then((ok: boolean) => {
|
||||
if (ok) {
|
||||
alert("password is updated");
|
||||
} else {
|
||||
|
@ -105,22 +106,22 @@ export class UserForm extends React.Component<
|
|||
newPwd1: "",
|
||||
newPwd2: "",
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
setUser = () => {};
|
||||
|
||||
delUser = () => {
|
||||
PanesUpdater.delUser(this.state.id)
|
||||
updater()
|
||||
.delUser(this.state.id)
|
||||
.then((ok: boolean) => {
|
||||
if (!ok) {
|
||||
alert("failed to delete user");
|
||||
}
|
||||
return PanesUpdater.listUsers();
|
||||
return updater().listUsers();
|
||||
})
|
||||
.then((_: boolean) => {
|
||||
this.props.update(PanesUpdater.updateState);
|
||||
this.props.update(updater().updatePanes);
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -311,15 +312,16 @@ export class AdminPane extends React.Component<Props, State, {}> {
|
|||
};
|
||||
|
||||
addRole = () => {
|
||||
PanesUpdater.addRole(this.state.newRole)
|
||||
updater()
|
||||
.addRole(this.state.newRole)
|
||||
.then((ok: boolean) => {
|
||||
if (!ok) {
|
||||
alert("failed to add role");
|
||||
}
|
||||
return PanesUpdater.listRoles();
|
||||
return updater().listRoles();
|
||||
})
|
||||
.then(() => {
|
||||
this.props.update(PanesUpdater.updateState);
|
||||
this.props.update(updater().updatePanes);
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -332,15 +334,16 @@ export class AdminPane extends React.Component<Props, State, {}> {
|
|||
return;
|
||||
}
|
||||
|
||||
PanesUpdater.delRole(role)
|
||||
updater()
|
||||
.delRole(role)
|
||||
.then((ok: boolean) => {
|
||||
if (!ok) {
|
||||
alert("failed to delete role");
|
||||
}
|
||||
return PanesUpdater.listRoles();
|
||||
return updater().listRoles();
|
||||
})
|
||||
.then(() => {
|
||||
this.props.update(PanesUpdater.updateState);
|
||||
this.props.update(updater().updatePanes);
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -350,13 +353,14 @@ export class AdminPane extends React.Component<Props, State, {}> {
|
|||
return;
|
||||
}
|
||||
|
||||
PanesUpdater.addUser({
|
||||
id: "", // backend will fill it
|
||||
name: this.state.newUserName,
|
||||
pwd: this.state.newUserPwd1,
|
||||
role: this.state.newUserRole,
|
||||
quota: undefined,
|
||||
})
|
||||
updater()
|
||||
.addUser({
|
||||
id: "", // backend will fill it
|
||||
name: this.state.newUserName,
|
||||
pwd: this.state.newUserPwd1,
|
||||
role: this.state.newUserRole,
|
||||
quota: undefined,
|
||||
})
|
||||
.then((ok: boolean) => {
|
||||
if (!ok) {
|
||||
alert("failed to add user");
|
||||
|
@ -367,10 +371,10 @@ export class AdminPane extends React.Component<Props, State, {}> {
|
|||
newUserPwd2: "",
|
||||
newUserRole: "",
|
||||
});
|
||||
return PanesUpdater.listUsers();
|
||||
return updater().listUsers();
|
||||
})
|
||||
.then(() => {
|
||||
this.props.update(PanesUpdater.updateState);
|
||||
this.props.update(updater().updatePanes);
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
@ -2,11 +2,7 @@ import * as React from "react";
|
|||
import { List } from "immutable";
|
||||
|
||||
import { ICoreState } from "./core_state";
|
||||
import { IUsersClient } from "../client";
|
||||
import { UsersClient } from "../client/users";
|
||||
import { Updater as PanesUpdater } from "./panes";
|
||||
import { updater as BrowserUpdater } from "./browser.updater";
|
||||
import { Layouter } from "./layouter";
|
||||
import { updater } from "./state_updater";
|
||||
|
||||
export interface Props {
|
||||
authed: boolean;
|
||||
|
@ -14,66 +10,6 @@ export interface Props {
|
|||
update?: (updater: (prevState: ICoreState) => ICoreState) => void;
|
||||
}
|
||||
|
||||
export class Updater {
|
||||
private static props: Props;
|
||||
private static client: IUsersClient;
|
||||
|
||||
static init = (props: Props) => (Updater.props = { ...props });
|
||||
|
||||
static setClient = (client: IUsersClient): void => {
|
||||
Updater.client = client;
|
||||
};
|
||||
|
||||
static login = async (
|
||||
user: string,
|
||||
pwd: string,
|
||||
captchaID: string,
|
||||
captchaInput: string
|
||||
): Promise<boolean> => {
|
||||
const resp = await Updater.client.login(user, pwd, captchaID, captchaInput);
|
||||
Updater.setAuthed(resp.status === 200);
|
||||
return resp.status === 200;
|
||||
};
|
||||
|
||||
static logout = async (): Promise<boolean> => {
|
||||
const resp = await Updater.client.logout();
|
||||
Updater.setAuthed(false);
|
||||
return resp.status === 200;
|
||||
};
|
||||
|
||||
static isAuthed = async (): Promise<boolean> => {
|
||||
const resp = await Updater.client.isAuthed();
|
||||
return resp.status === 200;
|
||||
};
|
||||
|
||||
static initIsAuthed = async (): Promise<void> => {
|
||||
return Updater.isAuthed().then((isAuthed) => {
|
||||
Updater.setAuthed(isAuthed);
|
||||
});
|
||||
};
|
||||
|
||||
static setAuthed = (isAuthed: boolean) => {
|
||||
Updater.props.authed = isAuthed;
|
||||
};
|
||||
|
||||
static getCaptchaID = async (): Promise<boolean> => {
|
||||
return Updater.client.getCaptchaID().then((resp) => {
|
||||
if (resp.status === 200) {
|
||||
Updater.props.captchaID = resp.data.id;
|
||||
}
|
||||
return resp.status === 200;
|
||||
});
|
||||
};
|
||||
|
||||
static setAuthPane = (preState: ICoreState): ICoreState => {
|
||||
preState.panel.authPane = {
|
||||
...preState.panel.authPane,
|
||||
...Updater.props,
|
||||
};
|
||||
return preState;
|
||||
};
|
||||
}
|
||||
|
||||
export interface State {
|
||||
user: string;
|
||||
pwd: string;
|
||||
|
@ -84,8 +20,6 @@ export class AuthPane extends React.Component<Props, State, {}> {
|
|||
private update: (updater: (prevState: ICoreState) => ICoreState) => void;
|
||||
constructor(p: Props) {
|
||||
super(p);
|
||||
Updater.init(p);
|
||||
Updater.setClient(new UsersClient(""));
|
||||
this.update = p.update;
|
||||
this.state = {
|
||||
user: "",
|
||||
|
@ -109,53 +43,56 @@ export class AuthPane extends React.Component<Props, State, {}> {
|
|||
};
|
||||
|
||||
initIsAuthed = () => {
|
||||
Updater.initIsAuthed().then(() => {
|
||||
this.update(Updater.setAuthPane);
|
||||
});
|
||||
updater()
|
||||
.initIsAuthed()
|
||||
.then(() => {
|
||||
this.update(updater().updateAuthPane);
|
||||
});
|
||||
};
|
||||
|
||||
login = () => {
|
||||
Updater.login(
|
||||
this.state.user,
|
||||
this.state.pwd,
|
||||
this.props.captchaID,
|
||||
this.state.captchaInput
|
||||
)
|
||||
updater()
|
||||
.login(
|
||||
this.state.user,
|
||||
this.state.pwd,
|
||||
this.props.captchaID,
|
||||
this.state.captchaInput
|
||||
)
|
||||
.then((ok: boolean) => {
|
||||
if (ok) {
|
||||
this.update(Updater.setAuthPane);
|
||||
this.update(updater().updateAuthPane);
|
||||
this.setState({ user: "", pwd: "" });
|
||||
// close all the panes
|
||||
PanesUpdater.displayPane("");
|
||||
this.update(PanesUpdater.updateState);
|
||||
updater().displayPane("");
|
||||
this.update(updater().updatePanes);
|
||||
|
||||
// refresh
|
||||
return BrowserUpdater().setHomeItems();
|
||||
return updater().setHomeItems();
|
||||
} else {
|
||||
this.setState({ user: "", pwd: "" });
|
||||
alert("Failed to login.");
|
||||
}
|
||||
})
|
||||
.then(() => {
|
||||
return BrowserUpdater().refreshUploadings();
|
||||
return updater().refreshUploadings();
|
||||
})
|
||||
.then(() => {
|
||||
return BrowserUpdater().isSharing(
|
||||
BrowserUpdater().props.dirPath.join("/")
|
||||
return updater().isSharing(
|
||||
updater().props.panel.browser.dirPath.join("/")
|
||||
);
|
||||
})
|
||||
.then(() => {
|
||||
return BrowserUpdater().listSharings();
|
||||
return updater().listSharings();
|
||||
})
|
||||
.then((_: boolean) => {
|
||||
this.update(BrowserUpdater().setBrowser);
|
||||
this.update(updater().updateBrowser);
|
||||
});
|
||||
};
|
||||
|
||||
logout = () => {
|
||||
Updater.logout().then((ok: boolean) => {
|
||||
updater().logout().then((ok: boolean) => {
|
||||
if (ok) {
|
||||
this.update(Updater.setAuthPane);
|
||||
this.update(updater().updateAuthPane);
|
||||
} else {
|
||||
alert("Failed to logout.");
|
||||
}
|
||||
|
|
|
@ -1,37 +1,14 @@
|
|||
import * as React from "react";
|
||||
|
||||
import { ICoreState } from "./core_state";
|
||||
import { IUsersClient } from "../client";
|
||||
import { AuthPane, Props as LoginProps } from "./pane_login";
|
||||
import { UsersClient } from "../client/users";
|
||||
import { updater } from "./state_updater";
|
||||
|
||||
export interface Props {
|
||||
login: LoginProps;
|
||||
update?: (updater: (prevState: ICoreState) => ICoreState) => void;
|
||||
}
|
||||
|
||||
export class Updater {
|
||||
private static props: Props;
|
||||
private static usersClient: IUsersClient;
|
||||
|
||||
static init = (props: Props) => (Updater.props = { ...props });
|
||||
static setClient(usersClient: IUsersClient) {
|
||||
Updater.usersClient = usersClient;
|
||||
}
|
||||
|
||||
static setPwd = async (oldPwd: string, newPwd: string): Promise<boolean> => {
|
||||
const resp = await Updater.usersClient.setPwd(oldPwd, newPwd);
|
||||
return resp.status === 200;
|
||||
};
|
||||
|
||||
static updateState = (prevState: ICoreState): ICoreState => {
|
||||
return {
|
||||
...prevState,
|
||||
panel: { ...prevState.panel, ...Updater.props },
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export interface State {
|
||||
oldPwd: string;
|
||||
newPwd1: string;
|
||||
|
@ -52,8 +29,6 @@ export class PaneSettings extends React.Component<Props, State, {}> {
|
|||
|
||||
constructor(p: Props) {
|
||||
super(p);
|
||||
Updater.init(p);
|
||||
Updater.setClient(new UsersClient(""));
|
||||
this.update = p.update;
|
||||
this.state = {
|
||||
oldPwd: "",
|
||||
|
@ -70,8 +45,9 @@ export class PaneSettings extends React.Component<Props, State, {}> {
|
|||
} else if (this.state.oldPwd == this.state.newPwd1) {
|
||||
alert("old and new passwords are same");
|
||||
} else {
|
||||
Updater.setPwd(this.state.oldPwd, this.state.newPwd1).then(
|
||||
(ok: boolean) => {
|
||||
updater()
|
||||
.setPwd(this.state.oldPwd, this.state.newPwd1)
|
||||
.then((ok: boolean) => {
|
||||
if (ok) {
|
||||
alert("Password is updated");
|
||||
} else {
|
||||
|
@ -82,8 +58,7 @@ export class PaneSettings extends React.Component<Props, State, {}> {
|
|||
newPwd1: "",
|
||||
newPwd2: "",
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
import * as React from "react";
|
||||
import { Set, Map } from "immutable";
|
||||
|
||||
import { IUsersClient, User, ListUsersResp, ListRolesResp } from "../client";
|
||||
import { UsersClient } from "../client/users";
|
||||
import { updater } from "./state_updater";
|
||||
// import { IUsersClient, User, ListUsersResp, ListRolesResp } from "../client";
|
||||
// import { UsersClient } from "../client/users";
|
||||
import { ICoreState } from "./core_state";
|
||||
import { PaneSettings } from "./pane_settings";
|
||||
import { AdminPane, Props as AdminPaneProps } from "./pane_admin";
|
||||
|
@ -17,128 +18,126 @@ export interface Props {
|
|||
update?: (updater: (prevState: ICoreState) => ICoreState) => void;
|
||||
}
|
||||
|
||||
export class Updater {
|
||||
static props: Props;
|
||||
private static client: IUsersClient;
|
||||
// export class Updater {
|
||||
// static props: Props;
|
||||
// private static client: IUsersClient;
|
||||
|
||||
static init = (props: Props) => (Updater.props = { ...props });
|
||||
static setClient = (client: IUsersClient): void => {
|
||||
Updater.client = client;
|
||||
};
|
||||
// static init = (props: Props) => (Updater.props = { ...props });
|
||||
// static setClient = (client: IUsersClient): void => {
|
||||
// Updater.client = client;
|
||||
// };
|
||||
|
||||
static displayPane = (paneName: string) => {
|
||||
if (paneName === "") {
|
||||
// hide all panes
|
||||
Updater.props.displaying = "";
|
||||
} else {
|
||||
const pane = Updater.props.paneNames.get(paneName);
|
||||
if (pane != null) {
|
||||
Updater.props.displaying = paneName;
|
||||
} else {
|
||||
alert(`dialgos: pane (${paneName}) not found`);
|
||||
}
|
||||
}
|
||||
};
|
||||
// static displayPane = (paneName: string) => {
|
||||
// if (paneName === "") {
|
||||
// // hide all panes
|
||||
// Updater.props.displaying = "";
|
||||
// } else {
|
||||
// const pane = Updater.props.paneNames.get(paneName);
|
||||
// if (pane != null) {
|
||||
// Updater.props.displaying = paneName;
|
||||
// } else {
|
||||
// alert(`dialgos: pane (${paneName}) not found`);
|
||||
// }
|
||||
// }
|
||||
// };
|
||||
|
||||
static self = async (): Promise<boolean> => {
|
||||
const resp = await Updater.client.self();
|
||||
if (resp.status === 200) {
|
||||
Updater.props.userRole = resp.data.role;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
// static self = async (): Promise<boolean> => {
|
||||
// const resp = await Updater.client.self();
|
||||
// if (resp.status === 200) {
|
||||
// Updater.props.userRole = resp.data.role;
|
||||
// return true;
|
||||
// }
|
||||
// return false;
|
||||
// };
|
||||
|
||||
static addUser = async (user: User): Promise<boolean> => {
|
||||
const resp = await Updater.client.addUser(user.name, user.pwd, user.role);
|
||||
// TODO: should return uid instead
|
||||
return resp.status === 200;
|
||||
};
|
||||
// static addUser = async (user: User): Promise<boolean> => {
|
||||
// const resp = await Updater.client.addUser(user.name, user.pwd, user.role);
|
||||
// // TODO: should return uid instead
|
||||
// return resp.status === 200;
|
||||
// };
|
||||
|
||||
static delUser = async (userID: string): Promise<boolean> => {
|
||||
const resp = await Updater.client.delUser(userID);
|
||||
return resp.status === 200;
|
||||
};
|
||||
// static delUser = async (userID: string): Promise<boolean> => {
|
||||
// const resp = await Updater.client.delUser(userID);
|
||||
// return resp.status === 200;
|
||||
// };
|
||||
|
||||
static setRole = async (userID: string, role: string): Promise<boolean> => {
|
||||
const resp = await Updater.client.delUser(userID);
|
||||
return resp.status === 200;
|
||||
};
|
||||
// static setRole = async (userID: string, role: string): Promise<boolean> => {
|
||||
// const resp = await Updater.client.delUser(userID);
|
||||
// return resp.status === 200;
|
||||
// };
|
||||
|
||||
static forceSetPwd = async (
|
||||
userID: string,
|
||||
pwd: string
|
||||
): Promise<boolean> => {
|
||||
const resp = await Updater.client.forceSetPwd(userID, pwd);
|
||||
return resp.status === 200;
|
||||
};
|
||||
// static forceSetPwd = async (
|
||||
// userID: string,
|
||||
// pwd: string
|
||||
// ): Promise<boolean> => {
|
||||
// const resp = await Updater.client.forceSetPwd(userID, pwd);
|
||||
// return resp.status === 200;
|
||||
// };
|
||||
|
||||
static listUsers = async (): Promise<boolean> => {
|
||||
const resp = await Updater.client.listUsers();
|
||||
if (resp.status !== 200) {
|
||||
return false;
|
||||
}
|
||||
// static listUsers = async (): Promise<boolean> => {
|
||||
// const resp = await Updater.client.listUsers();
|
||||
// if (resp.status !== 200) {
|
||||
// return false;
|
||||
// }
|
||||
|
||||
const lsRes = resp.data as ListUsersResp;
|
||||
let users = Map<User>({});
|
||||
lsRes.users.forEach((user: User) => {
|
||||
users = users.set(user.name, user);
|
||||
});
|
||||
Updater.props.admin.users = users;
|
||||
// const lsRes = resp.data as ListUsersResp;
|
||||
// let users = Map<User>({});
|
||||
// lsRes.users.forEach((user: User) => {
|
||||
// users = users.set(user.name, user);
|
||||
// });
|
||||
// Updater.props.admin.users = users;
|
||||
|
||||
return true;
|
||||
};
|
||||
// return true;
|
||||
// };
|
||||
|
||||
static addRole = async (role: string): Promise<boolean> => {
|
||||
const resp = await Updater.client.addRole(role);
|
||||
// TODO: should return uid instead
|
||||
return resp.status === 200;
|
||||
};
|
||||
// static addRole = async (role: string): Promise<boolean> => {
|
||||
// const resp = await Updater.client.addRole(role);
|
||||
// // TODO: should return uid instead
|
||||
// return resp.status === 200;
|
||||
// };
|
||||
|
||||
static delRole = async (role: string): Promise<boolean> => {
|
||||
const resp = await Updater.client.delRole(role);
|
||||
return resp.status === 200;
|
||||
};
|
||||
// static delRole = async (role: string): Promise<boolean> => {
|
||||
// const resp = await Updater.client.delRole(role);
|
||||
// return resp.status === 200;
|
||||
// };
|
||||
|
||||
static listRoles = async (): Promise<boolean> => {
|
||||
const resp = await Updater.client.listRoles();
|
||||
if (resp.status !== 200) {
|
||||
return false;
|
||||
}
|
||||
// static listRoles = async (): Promise<boolean> => {
|
||||
// const resp = await Updater.client.listRoles();
|
||||
// if (resp.status !== 200) {
|
||||
// return false;
|
||||
// }
|
||||
|
||||
const lsRes = resp.data as ListRolesResp;
|
||||
let roles = Set<string>();
|
||||
Object.keys(lsRes.roles).forEach((role: string) => {
|
||||
roles = roles.add(role);
|
||||
});
|
||||
Updater.props.admin.roles = roles;
|
||||
// const lsRes = resp.data as ListRolesResp;
|
||||
// let roles = Set<string>();
|
||||
// Object.keys(lsRes.roles).forEach((role: string) => {
|
||||
// roles = roles.add(role);
|
||||
// });
|
||||
// Updater.props.admin.roles = roles;
|
||||
|
||||
return true;
|
||||
};
|
||||
// return true;
|
||||
// };
|
||||
|
||||
static updateState = (prevState: ICoreState): ICoreState => {
|
||||
return {
|
||||
...prevState,
|
||||
panel: {
|
||||
...prevState.panel,
|
||||
panes: { ...prevState.panel.panes, ...Updater.props },
|
||||
},
|
||||
};
|
||||
};
|
||||
}
|
||||
// static updateState = (prevState: ICoreState): ICoreState => {
|
||||
// return {
|
||||
// ...prevState,
|
||||
// panel: {
|
||||
// ...prevState.panel,
|
||||
// panes: { ...prevState.panel.panes, ...Updater.props },
|
||||
// },
|
||||
// };
|
||||
// };
|
||||
// }
|
||||
|
||||
export interface State {}
|
||||
export class Panes extends React.Component<Props, State, {}> {
|
||||
constructor(p: Props) {
|
||||
super(p);
|
||||
Updater.init(p);
|
||||
Updater.setClient(new UsersClient(""));
|
||||
}
|
||||
|
||||
closePane = () => {
|
||||
if (this.props.displaying !== "login") {
|
||||
Updater.displayPane("");
|
||||
this.props.update(Updater.updateState);
|
||||
updater().displayPane("");
|
||||
this.props.update(updater().updatePanes);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -146,6 +145,7 @@ export class Panes extends React.Component<Props, State, {}> {
|
|||
let displaying = this.props.displaying;
|
||||
if (!this.props.login.authed) {
|
||||
// TODO: use constant instead
|
||||
// TODO: control this with props
|
||||
displaying = "login";
|
||||
}
|
||||
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
import * as React from "react";
|
||||
|
||||
import { ICoreState, BaseUpdater } from "./core_state";
|
||||
import { ICoreState } from "./core_state";
|
||||
import { Browser, Props as BrowserProps } from "./browser";
|
||||
import { Props as PaneLoginProps } from "./pane_login";
|
||||
import { Panes, Props as PanesProps, Updater as PanesUpdater } from "./panes";
|
||||
import { Panes, Props as PanesProps } from "./panes";
|
||||
import { TopBar } from "./topbar";
|
||||
|
||||
export interface Props {
|
||||
displaying: string;
|
||||
|
@ -13,37 +14,13 @@ export interface Props {
|
|||
update?: (updater: (prevState: ICoreState) => ICoreState) => void;
|
||||
}
|
||||
|
||||
export class Updater {
|
||||
public static props: Props;
|
||||
public static init = (props: Props) => (BaseUpdater.props = { ...props });
|
||||
public static apply = (prevState: ICoreState): ICoreState => {
|
||||
return {
|
||||
...prevState,
|
||||
panel: { ...prevState.panel, ...Updater.props },
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export interface State {}
|
||||
export class RootFrame extends React.Component<Props, State, {}> {
|
||||
constructor(p: Props) {
|
||||
super(p);
|
||||
Updater.init(p);
|
||||
}
|
||||
|
||||
showSettings = () => {
|
||||
PanesUpdater.displayPane("settings");
|
||||
this.props.update(PanesUpdater.updateState);
|
||||
};
|
||||
|
||||
showAdmin = () => {
|
||||
PanesUpdater.displayPane("admin");
|
||||
this.props.update(PanesUpdater.updateState);
|
||||
};
|
||||
|
||||
render() {
|
||||
const update = this.props.update;
|
||||
|
||||
return (
|
||||
<div className="theme-white desktop">
|
||||
<div id="bg" className="bg bg-img font-m">
|
||||
|
@ -53,36 +30,10 @@ export class RootFrame extends React.Component<Props, State, {}> {
|
|||
paneNames={this.props.panes.paneNames}
|
||||
login={this.props.authPane}
|
||||
admin={this.props.panes.admin}
|
||||
update={update}
|
||||
update={this.props.update}
|
||||
/>
|
||||
|
||||
<div
|
||||
id="top-bar"
|
||||
className="top-bar cyan1-font padding-t-m padding-b-m padding-l-l padding-r-l"
|
||||
>
|
||||
<div className="flex-2col-parent">
|
||||
<a
|
||||
href="https://github.com/ihexxa/quickshare"
|
||||
className="flex-13col h5"
|
||||
>
|
||||
Quickshare
|
||||
</a>
|
||||
<span className="flex-23col text-right">
|
||||
<button
|
||||
onClick={this.showSettings}
|
||||
className="grey1-bg white-font margin-r-m"
|
||||
>
|
||||
Settings
|
||||
</button>
|
||||
<button
|
||||
onClick={this.showAdmin}
|
||||
className="grey1-bg white-font margin-r-m"
|
||||
>
|
||||
Admin
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<TopBar update={this.props.update}></TopBar>
|
||||
|
||||
<div className="container-center">
|
||||
<Browser
|
||||
|
@ -91,7 +42,7 @@ export class RootFrame extends React.Component<Props, State, {}> {
|
|||
uploadings={this.props.browser.uploadings}
|
||||
sharings={this.props.browser.sharings}
|
||||
isSharing={this.props.browser.isSharing}
|
||||
update={update}
|
||||
update={this.props.update}
|
||||
uploadFiles={this.props.browser.uploadFiles}
|
||||
uploadValue={this.props.browser.uploadValue}
|
||||
isVertical={this.props.browser.isVertical}
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
import * as React from "react";
|
||||
import { List } from "immutable";
|
||||
|
||||
import { updater as BrowserUpdater } from "./browser.updater";
|
||||
import { Updater as PanesUpdater } from "./panes";
|
||||
import { ICoreState, init } from "./core_state";
|
||||
import { updater } from "./state_updater";
|
||||
import { ICoreState, newState } from "./core_state";
|
||||
import { RootFrame } from "./root_frame";
|
||||
import { FilesClient } from "../client/files";
|
||||
import { UsersClient } from "../client/users";
|
||||
import { Updater as LoginPaneUpdater } from "./pane_login";
|
||||
// import { Updater as LoginPaneUpdater } from "./pane_login";
|
||||
|
||||
export interface Props {}
|
||||
export interface State extends ICoreState {}
|
||||
|
@ -15,68 +14,67 @@ export interface State extends ICoreState {}
|
|||
export class StateMgr extends React.Component<Props, State, {}> {
|
||||
constructor(p: Props) {
|
||||
super(p);
|
||||
this.state = init();
|
||||
this.state = newState();
|
||||
this.initUpdaters(this.state);
|
||||
}
|
||||
|
||||
initUpdaters = (state: ICoreState) => {
|
||||
BrowserUpdater().init(state.panel.browser);
|
||||
BrowserUpdater().setClients(new UsersClient(""), new FilesClient(""));
|
||||
updater().init(state);
|
||||
updater().setClients(new UsersClient(""), new FilesClient(""));
|
||||
|
||||
const params = new URLSearchParams(document.location.search.substring(1));
|
||||
updater()
|
||||
.getCaptchaID()
|
||||
.then((ok: boolean) => {
|
||||
if (!ok) {
|
||||
alert("failed to get captcha id");
|
||||
} else {
|
||||
this.update(updater().updateAuthPane);
|
||||
}
|
||||
});
|
||||
|
||||
LoginPaneUpdater.init(state.panel.authPane);
|
||||
LoginPaneUpdater.setClient(new UsersClient(""));
|
||||
LoginPaneUpdater.getCaptchaID().then((ok: boolean) => {
|
||||
if (!ok) {
|
||||
alert("failed to get captcha id");
|
||||
} else {
|
||||
this.update(LoginPaneUpdater.setAuthPane);
|
||||
}
|
||||
});
|
||||
|
||||
BrowserUpdater()
|
||||
updater()
|
||||
.refreshUploadings()
|
||||
.then(() => {
|
||||
const dir = params.get("dir");
|
||||
if (dir != null && dir !== "") {
|
||||
const dirPath = List(dir.split("/"));
|
||||
return BrowserUpdater().setItems(dirPath);
|
||||
return updater().setItems(dirPath);
|
||||
} else {
|
||||
return BrowserUpdater().setHomeItems();
|
||||
return updater().setHomeItems();
|
||||
}
|
||||
})
|
||||
.then(() => {
|
||||
return BrowserUpdater().initUploads();
|
||||
return updater().initUploads();
|
||||
})
|
||||
.then(() => {
|
||||
return BrowserUpdater().isSharing(
|
||||
BrowserUpdater().props.dirPath.join("/")
|
||||
return updater().isSharing(
|
||||
updater().props.panel.browser.dirPath.join("/")
|
||||
);
|
||||
})
|
||||
.then(() => {
|
||||
return BrowserUpdater().listSharings();
|
||||
return updater().listSharings();
|
||||
})
|
||||
.then(() => {
|
||||
this.update(BrowserUpdater().setBrowser);
|
||||
this.update(updater().updateBrowser);
|
||||
})
|
||||
.then(() => {
|
||||
return PanesUpdater.self();
|
||||
return updater().self();
|
||||
})
|
||||
.then(() => {
|
||||
if (PanesUpdater.props.userRole === "admin") {
|
||||
if (updater().props.panel.panes.userRole === "admin") {
|
||||
// TODO: remove hardcode
|
||||
return PanesUpdater.listRoles();
|
||||
return updater().listRoles();
|
||||
}
|
||||
})
|
||||
.then(() => {
|
||||
if (PanesUpdater.props.userRole === "admin") {
|
||||
if (updater().props.panel.panes.userRole === "admin") {
|
||||
// TODO: remove hardcode
|
||||
return PanesUpdater.listUsers();
|
||||
return updater().listUsers();
|
||||
}
|
||||
})
|
||||
.then(() => {
|
||||
this.update(PanesUpdater.updateState);
|
||||
this.update(updater().updatePanes);
|
||||
});
|
||||
};
|
||||
|
||||
|
|
373
src/client/web/src/components/state_updater.ts
Normal file
373
src/client/web/src/components/state_updater.ts
Normal file
|
@ -0,0 +1,373 @@
|
|||
import { List, Map, Set } from "immutable";
|
||||
|
||||
import { ICoreState } from "./core_state";
|
||||
import { getItemPath } from "./browser";
|
||||
import {
|
||||
User,
|
||||
ListUsersResp,
|
||||
ListRolesResp,
|
||||
IUsersClient,
|
||||
IFilesClient,
|
||||
MetadataResp,
|
||||
UploadInfo,
|
||||
} from "../client";
|
||||
import { FilesClient } from "../client/files";
|
||||
import { UsersClient } from "../client/users";
|
||||
import { UploadEntry } from "../worker/interface";
|
||||
import { Up } from "../worker/upload_mgr";
|
||||
|
||||
export class Updater {
|
||||
props: ICoreState;
|
||||
private usersClient: IUsersClient = new UsersClient("");
|
||||
private filesClient: IFilesClient = new FilesClient("");
|
||||
|
||||
init = (props: ICoreState) => (this.props = { ...props });
|
||||
setClients(usersClient: IUsersClient, filesClient: IFilesClient) {
|
||||
this.usersClient = usersClient;
|
||||
this.filesClient = filesClient;
|
||||
}
|
||||
|
||||
initUploads = () => {
|
||||
this.props.panel.browser.uploadings.forEach((entry) => {
|
||||
Up().addStopped(entry.realFilePath, entry.uploaded, entry.size);
|
||||
});
|
||||
// this.setUploadings(Up().list());
|
||||
};
|
||||
|
||||
addUploads = (fileList: List<File>) => {
|
||||
fileList.forEach((file) => {
|
||||
const filePath = getItemPath(
|
||||
this.props.panel.browser.dirPath.join("/"),
|
||||
file.name
|
||||
);
|
||||
// do not wait for the promise
|
||||
Up().add(file, filePath);
|
||||
});
|
||||
this.setUploadings(Up().list());
|
||||
};
|
||||
|
||||
deleteUpload = async (filePath: string): Promise<boolean> => {
|
||||
Up().delete(filePath);
|
||||
const resp = await this.filesClient.deleteUploading(filePath);
|
||||
return resp.status === 200;
|
||||
};
|
||||
|
||||
setUploadings = (infos: Map<string, UploadEntry>) => {
|
||||
this.props.panel.browser.uploadings = List<UploadInfo>(
|
||||
infos.valueSeq().map((v: UploadEntry): UploadInfo => {
|
||||
return {
|
||||
realFilePath: v.filePath,
|
||||
size: v.size,
|
||||
uploaded: v.uploaded,
|
||||
};
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
addSharing = async (): Promise<boolean> => {
|
||||
const dirPath = this.props.panel.browser.dirPath.join("/");
|
||||
const resp = await this.filesClient.addSharing(dirPath);
|
||||
return resp.status === 200;
|
||||
};
|
||||
|
||||
deleteSharing = async (dirPath: string): Promise<boolean> => {
|
||||
const resp = await this.filesClient.deleteSharing(dirPath);
|
||||
return resp.status === 200;
|
||||
};
|
||||
|
||||
isSharing = async (dirPath: string): Promise<boolean> => {
|
||||
const resp = await this.filesClient.isSharing(dirPath);
|
||||
this.props.panel.browser.isSharing = resp.status === 200;
|
||||
return resp.status === 200; // TODO: differentiate 404 and error
|
||||
};
|
||||
|
||||
setSharing = (shared: boolean) => {
|
||||
this.props.panel.browser.isSharing = shared;
|
||||
};
|
||||
|
||||
listSharings = async (): Promise<boolean> => {
|
||||
const resp = await this.filesClient.listSharings();
|
||||
this.props.panel.browser.sharings =
|
||||
resp.status === 200
|
||||
? List<string>(resp.data.sharingDirs)
|
||||
: this.props.panel.browser.sharings;
|
||||
return resp.status === 200;
|
||||
};
|
||||
|
||||
refreshUploadings = async (): Promise<boolean> => {
|
||||
const luResp = await this.filesClient.listUploadings();
|
||||
|
||||
this.props.panel.browser.uploadings =
|
||||
luResp.status === 200
|
||||
? List<UploadInfo>(luResp.data.uploadInfos)
|
||||
: this.props.panel.browser.uploadings;
|
||||
return luResp.status === 200;
|
||||
};
|
||||
|
||||
stopUploading = (filePath: string) => {
|
||||
Up().stop(filePath);
|
||||
};
|
||||
|
||||
mkDir = async (dirPath: string): Promise<void> => {
|
||||
const resp = await this.filesClient.mkdir(dirPath);
|
||||
if (resp.status !== 200) {
|
||||
alert(`failed to make dir ${dirPath}`);
|
||||
}
|
||||
};
|
||||
|
||||
delete = async (
|
||||
dirParts: List<string>,
|
||||
items: List<MetadataResp>,
|
||||
selectedItems: Map<string, boolean>
|
||||
): Promise<void> => {
|
||||
const delRequests = items
|
||||
.filter((item) => {
|
||||
return selectedItems.has(item.name);
|
||||
})
|
||||
.map(async (selectedItem: MetadataResp): Promise<string> => {
|
||||
const itemPath = getItemPath(dirParts.join("/"), selectedItem.name);
|
||||
const resp = await this.filesClient.delete(itemPath);
|
||||
return resp.status === 200 ? "" : selectedItem.name;
|
||||
});
|
||||
|
||||
const failedFiles = await Promise.all(delRequests);
|
||||
failedFiles.forEach((failedFile) => {
|
||||
if (failedFile !== "") {
|
||||
alert(`failed to delete ${failedFile}`);
|
||||
}
|
||||
});
|
||||
return this.setItems(dirParts);
|
||||
};
|
||||
|
||||
setItems = async (dirParts: List<string>): Promise<void> => {
|
||||
const dirPath = dirParts.join("/");
|
||||
const listResp = await this.filesClient.list(dirPath);
|
||||
|
||||
this.props.panel.browser.dirPath = dirParts;
|
||||
this.props.panel.browser.items =
|
||||
listResp.status === 200
|
||||
? List<MetadataResp>(listResp.data.metadatas)
|
||||
: this.props.panel.browser.items;
|
||||
};
|
||||
|
||||
setHomeItems = async (): Promise<void> => {
|
||||
const listResp = await this.filesClient.listHome();
|
||||
|
||||
this.props.panel.browser.dirPath = List<string>(
|
||||
listResp.data.cwd.split("/")
|
||||
);
|
||||
this.props.panel.browser.items =
|
||||
listResp.status === 200
|
||||
? List<MetadataResp>(listResp.data.metadatas)
|
||||
: this.props.panel.browser.items;
|
||||
};
|
||||
|
||||
moveHere = async (
|
||||
srcDir: string,
|
||||
dstDir: string,
|
||||
selectedItems: Map<string, boolean>
|
||||
): Promise<void> => {
|
||||
const moveRequests = List<string>(selectedItems.keys()).map(
|
||||
async (itemName: string): Promise<string> => {
|
||||
const oldPath = getItemPath(srcDir, itemName);
|
||||
const newPath = getItemPath(dstDir, itemName);
|
||||
const resp = await this.filesClient.move(oldPath, newPath);
|
||||
return resp.status === 200 ? "" : itemName;
|
||||
}
|
||||
);
|
||||
|
||||
const failedFiles = await Promise.all(moveRequests);
|
||||
failedFiles.forEach((failedItem) => {
|
||||
if (failedItem !== "") {
|
||||
alert(`failed to move ${failedItem}`);
|
||||
}
|
||||
});
|
||||
|
||||
return this.setItems(List<string>(dstDir.split("/")));
|
||||
};
|
||||
|
||||
displayPane = (paneName: string) => {
|
||||
if (paneName === "") {
|
||||
// hide all panes
|
||||
this.props.panel.panes.displaying = "";
|
||||
} else {
|
||||
const pane = this.props.panel.panes.paneNames.get(paneName);
|
||||
if (pane != null) {
|
||||
this.props.panel.panes.displaying = paneName;
|
||||
} else {
|
||||
alert(`dialgos: pane (${paneName}) not found`);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
self = async (): Promise<boolean> => {
|
||||
const resp = await this.usersClient.self();
|
||||
if (resp.status === 200) {
|
||||
this.props.panel.panes.userRole = resp.data.role;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
addUser = async (user: User): Promise<boolean> => {
|
||||
const resp = await this.usersClient.addUser(user.name, user.pwd, user.role);
|
||||
// TODO: should return uid instead
|
||||
return resp.status === 200;
|
||||
};
|
||||
|
||||
delUser = async (userID: string): Promise<boolean> => {
|
||||
const resp = await this.usersClient.delUser(userID);
|
||||
return resp.status === 200;
|
||||
};
|
||||
|
||||
setRole = async (userID: string, role: string): Promise<boolean> => {
|
||||
const resp = await this.usersClient.delUser(userID);
|
||||
return resp.status === 200;
|
||||
};
|
||||
|
||||
forceSetPwd = async (userID: string, pwd: string): Promise<boolean> => {
|
||||
const resp = await this.usersClient.forceSetPwd(userID, pwd);
|
||||
return resp.status === 200;
|
||||
};
|
||||
|
||||
listUsers = async (): Promise<boolean> => {
|
||||
const resp = await this.usersClient.listUsers();
|
||||
if (resp.status !== 200) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const lsRes = resp.data as ListUsersResp;
|
||||
let users = Map<User>({});
|
||||
lsRes.users.forEach((user: User) => {
|
||||
users = users.set(user.name, user);
|
||||
});
|
||||
this.props.panel.panes.admin.users = users;
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
addRole = async (role: string): Promise<boolean> => {
|
||||
const resp = await this.usersClient.addRole(role);
|
||||
// TODO: should return uid instead
|
||||
return resp.status === 200;
|
||||
};
|
||||
|
||||
delRole = async (role: string): Promise<boolean> => {
|
||||
const resp = await this.usersClient.delRole(role);
|
||||
return resp.status === 200;
|
||||
};
|
||||
|
||||
listRoles = async (): Promise<boolean> => {
|
||||
const resp = await this.usersClient.listRoles();
|
||||
if (resp.status !== 200) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const lsRes = resp.data as ListRolesResp;
|
||||
let roles = Set<string>();
|
||||
Object.keys(lsRes.roles).forEach((role: string) => {
|
||||
roles = roles.add(role);
|
||||
});
|
||||
this.props.panel.panes.admin.roles = roles;
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
login = async (
|
||||
user: string,
|
||||
pwd: string,
|
||||
captchaID: string,
|
||||
captchaInput: string
|
||||
): Promise<boolean> => {
|
||||
const resp = await this.usersClient.login(
|
||||
user,
|
||||
pwd,
|
||||
captchaID,
|
||||
captchaInput
|
||||
);
|
||||
updater().setAuthed(resp.status === 200);
|
||||
return resp.status === 200;
|
||||
};
|
||||
|
||||
logout = async (): Promise<boolean> => {
|
||||
const resp = await this.usersClient.logout();
|
||||
updater().setAuthed(false);
|
||||
return resp.status === 200;
|
||||
};
|
||||
|
||||
isAuthed = async (): Promise<boolean> => {
|
||||
const resp = await this.usersClient.isAuthed();
|
||||
return resp.status === 200;
|
||||
};
|
||||
|
||||
initIsAuthed = async (): Promise<void> => {
|
||||
return updater()
|
||||
.isAuthed()
|
||||
.then((isAuthed) => {
|
||||
updater().setAuthed(isAuthed);
|
||||
});
|
||||
};
|
||||
|
||||
setAuthed = (isAuthed: boolean) => {
|
||||
this.props.panel.authPane.authed = isAuthed;
|
||||
};
|
||||
|
||||
getCaptchaID = async (): Promise<boolean> => {
|
||||
return this.usersClient.getCaptchaID().then((resp) => {
|
||||
if (resp.status === 200) {
|
||||
this.props.panel.authPane.captchaID = resp.data.id;
|
||||
}
|
||||
return resp.status === 200;
|
||||
});
|
||||
};
|
||||
|
||||
setPwd = async (oldPwd: string, newPwd: string): Promise<boolean> => {
|
||||
const resp = await this.usersClient.setPwd(oldPwd, newPwd);
|
||||
return resp.status === 200;
|
||||
};
|
||||
|
||||
updateBrowser = (prevState: ICoreState): ICoreState => {
|
||||
return {
|
||||
...prevState,
|
||||
panel: {
|
||||
...prevState.panel,
|
||||
browser: {
|
||||
dirPath: this.props.panel.browser.dirPath,
|
||||
isSharing: this.props.panel.browser.isSharing,
|
||||
items: this.props.panel.browser.items,
|
||||
uploadings: this.props.panel.browser.uploadings,
|
||||
sharings: this.props.panel.browser.sharings,
|
||||
uploadFiles: this.props.panel.browser.uploadFiles,
|
||||
uploadValue: this.props.panel.browser.uploadValue,
|
||||
isVertical: this.props.panel.browser.isVertical,
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
updatePanes = (prevState: ICoreState): ICoreState => {
|
||||
return {
|
||||
...prevState,
|
||||
panel: {
|
||||
...prevState.panel,
|
||||
panes: { ...prevState.panel.panes, ...this.props.panel.panes },
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
updateAuthPane = (preState: ICoreState): ICoreState => {
|
||||
preState.panel.authPane = {
|
||||
...preState.panel.authPane,
|
||||
...this.props.panel.authPane,
|
||||
};
|
||||
return preState;
|
||||
};
|
||||
}
|
||||
|
||||
export let coreUpdater = new Updater();
|
||||
export const updater = (): Updater => {
|
||||
return coreUpdater;
|
||||
};
|
||||
export const setUpdater = (updater: Updater) => {
|
||||
coreUpdater = updater;
|
||||
};
|
57
src/client/web/src/components/topbar.tsx
Normal file
57
src/client/web/src/components/topbar.tsx
Normal file
|
@ -0,0 +1,57 @@
|
|||
import * as React from "react";
|
||||
|
||||
import { ICoreState } from "./core_state";
|
||||
import { updater } from "./state_updater";
|
||||
|
||||
export interface State {}
|
||||
export interface Props {
|
||||
update?: (updater: (prevState: ICoreState) => ICoreState) => void;
|
||||
}
|
||||
|
||||
export class TopBar extends React.Component<Props, State, {}> {
|
||||
constructor(p: Props) {
|
||||
super(p);
|
||||
}
|
||||
|
||||
showSettings = () => {
|
||||
updater().displayPane("settings");
|
||||
this.props.update(updater().updatePanes);
|
||||
};
|
||||
|
||||
showAdmin = () => {
|
||||
updater().displayPane("admin");
|
||||
this.props.update(updater().updatePanes);
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div
|
||||
id="top-bar"
|
||||
className="top-bar cyan1-font padding-t-m padding-b-m padding-l-l padding-r-l"
|
||||
>
|
||||
<div className="flex-2col-parent">
|
||||
<a
|
||||
href="https://github.com/ihexxa/quickshare"
|
||||
className="flex-13col h5"
|
||||
>
|
||||
Quickshare
|
||||
</a>
|
||||
<span className="flex-23col text-right">
|
||||
<button
|
||||
onClick={this.showSettings}
|
||||
className="grey1-bg white-font margin-r-m"
|
||||
>
|
||||
Settings
|
||||
</button>
|
||||
<button
|
||||
onClick={this.showAdmin}
|
||||
className="grey1-bg white-font margin-r-m"
|
||||
>
|
||||
Admin
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
import { Response } from "../client";
|
||||
import { ICoreState, mockState } from "../components/core_state";
|
||||
import { ICoreState, initState } from "../components/core_state";
|
||||
import { List } from "immutable";
|
||||
|
||||
export const makePromise = (ret: any): Promise<any> => {
|
||||
|
@ -19,7 +19,7 @@ export const makeNumberResponse = (status: number): Promise<Response> => {
|
|||
export const mockUpdate = (
|
||||
apply: (prevState: ICoreState) => ICoreState
|
||||
): void => {
|
||||
apply(mockState());
|
||||
apply(initState());
|
||||
};
|
||||
|
||||
export const addMockUpdate = (subState: any) => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue