fix(ui): refactor core state into a flat structure

This commit is contained in:
hexxa 2021-08-23 14:52:37 +08:00 committed by Hexxa
parent 8013c401f3
commit 9b67a85d97
11 changed files with 333 additions and 597 deletions

View file

@ -22,262 +22,262 @@ import { MetadataResp, UploadInfo } from "../../client";
import { MockWorker, UploadEntry } from "../../worker/interface";
import { UploadMgr, setUploadMgr } from "../../worker/upload_mgr";
describe("Browser", () => {
const mockWorkerClass = mock(MockWorker);
const mockWorker = instance(mockWorkerClass);
// describe("Browser", () => {
// const mockWorkerClass = mock(MockWorker);
// const mockWorker = instance(mockWorkerClass);
test("Updater: addUploads: add each files to UploadMgr", async () => {
let coreState = initState();
const UploadMgrClass = mock(UploadMgr);
const uploadMgr = instance(UploadMgrClass);
setUploadMgr(uploadMgr);
// test("Updater: addUploads: add each files to UploadMgr", async () => {
// 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);
// const filePaths = ["./file1", "./file2"];
// const fileList = mockFileList(filePaths);
// // 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);
// filePaths.forEach((filePath, i) => {
// verify(UploadMgrClass.add(anything(), filePath)).once();
// });
});
// // 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);
// // filePaths.forEach((filePath, i) => {
// // verify(UploadMgrClass.add(anything(), filePath)).once();
// // });
// });
test("Updater: deleteUploads: call UploadMgr and api to delete", async () => {
let coreState = initState();
const UploadMgrClass = mock(UploadMgr);
const uploadMgr = instance(UploadMgrClass);
setUploadMgr(uploadMgr);
// test("Updater: deleteUploads: call UploadMgr and api to delete", async () => {
// let coreState = initState();
// const UploadMgrClass = mock(UploadMgr);
// const uploadMgr = instance(UploadMgrClass);
// setUploadMgr(uploadMgr);
// const updater = new Updater();
const filesClientClass = mock(FilesClient);
when(filesClientClass.deleteUploading(anyString())).thenResolve({
status: 200,
statusText: "",
data: "",
});
const filesClient = instance(filesClientClass);
const usersClientClass = mock(UsersClient);
const usersClient = instance(usersClientClass);
updater().init(coreState);
updater().setClients(usersClient, filesClient);
// // const updater = new Updater();
// const filesClientClass = mock(FilesClient);
// when(filesClientClass.deleteUploading(anyString())).thenResolve({
// status: 200,
// statusText: "",
// data: "",
// });
// const filesClient = instance(filesClientClass);
// const usersClientClass = mock(UsersClient);
// const usersClient = instance(usersClientClass);
// updater().init(coreState);
// updater().setClients(usersClient, filesClient);
const filePath = "./path/file";
updater().deleteUpload(filePath);
// const filePath = "./path/file";
// updater().deleteUpload(filePath);
verify(filesClientClass.deleteUploading(filePath)).once();
verify(UploadMgrClass.delete(filePath)).once();
});
// verify(filesClientClass.deleteUploading(filePath)).once();
// verify(UploadMgrClass.delete(filePath)).once();
// });
test("Updater: delete", async () => {
const tests = [
{
dirPath: "path/path2",
items: [
{
name: "file",
size: 1,
modTime: "1-1",
isDir: false,
},
{
name: "folder",
size: 0,
modTime: "1-1",
isDir: true,
},
],
selected: {
file: true,
},
listResp: {
status: 200,
statusText: "",
data: {
metadatas: [
{
name: "folder",
size: 0,
modTime: "1-1",
isDir: true,
},
],
},
},
filePath: "path/file",
},
];
// test("Updater: delete", async () => {
// const tests = [
// {
// dirPath: "path/path2",
// items: [
// {
// name: "file",
// size: 1,
// modTime: "1-1",
// isDir: false,
// },
// {
// name: "folder",
// size: 0,
// modTime: "1-1",
// isDir: true,
// },
// ],
// selected: {
// file: true,
// },
// listResp: {
// status: 200,
// statusText: "",
// data: {
// metadatas: [
// {
// name: "folder",
// size: 0,
// modTime: "1-1",
// isDir: true,
// },
// ],
// },
// },
// filePath: "path/file",
// },
// ];
const usersClient = new MockUsersClient("");
const filesClient = new MockFilesClient("");
for (let i = 0; i < tests.length; i++) {
const tc = tests[i];
// const updater = new Updater();
updater().setClients(usersClient, filesClient);
filesClient.listMock(makePromise(tc.listResp));
filesClient.deleteMock(makeNumberResponse(200));
const coreState = newWithWorker(mockWorker);
updater().init(coreState);
// const usersClient = new MockUsersClient("");
// const filesClient = new MockFilesClient("");
// for (let i = 0; i < tests.length; i++) {
// const tc = tests[i];
// // const updater = new Updater();
// updater().setClients(usersClient, filesClient);
// filesClient.listMock(makePromise(tc.listResp));
// filesClient.deleteMock(makeNumberResponse(200));
// const coreState = newWithWorker(mockWorker);
// updater().init(coreState);
await updater().delete(
List<string>(tc.dirPath.split("/")),
List<MetadataResp>(tc.items),
Map(tc.selected)
);
// await updater().delete(
// List<string>(tc.dirPath.split("/")),
// List<MetadataResp>(tc.items),
// Map(tc.selected)
// );
const newState = updater().updateBrowser(coreState);
// const newState = updater().updateBrowser(coreState);
// TODO: check inputs of delete
newState.panel.browser.items.forEach((item, i) => {
expect(item.name).toEqual(tc.listResp.data.metadatas[i].name);
expect(item.size).toEqual(tc.listResp.data.metadatas[i].size);
expect(item.modTime).toEqual(tc.listResp.data.metadatas[i].modTime);
expect(item.isDir).toEqual(tc.listResp.data.metadatas[i].isDir);
});
}
});
// // TODO: check inputs of delete
// newState.panel.browser.items.forEach((item, i) => {
// expect(item.name).toEqual(tc.listResp.data.metadatas[i].name);
// expect(item.size).toEqual(tc.listResp.data.metadatas[i].size);
// expect(item.modTime).toEqual(tc.listResp.data.metadatas[i].modTime);
// expect(item.isDir).toEqual(tc.listResp.data.metadatas[i].isDir);
// });
// }
// });
test("Updater: setItems", async () => {
const tests = [
{
listResp: {
status: 200,
statusText: "",
data: {
metadatas: [
{
name: "file",
size: 1,
modTime: "1-1",
isDir: false,
},
{
name: "folder",
size: 0,
modTime: "1-1",
isDir: true,
},
],
},
},
filePath: "path/file",
},
];
// test("Updater: setItems", async () => {
// const tests = [
// {
// listResp: {
// status: 200,
// statusText: "",
// data: {
// metadatas: [
// {
// name: "file",
// size: 1,
// modTime: "1-1",
// isDir: false,
// },
// {
// name: "folder",
// size: 0,
// modTime: "1-1",
// isDir: true,
// },
// ],
// },
// },
// filePath: "path/file",
// },
// ];
const usersClient = new MockUsersClient("");
const filesClient = new MockFilesClient("");
// const usersClient = new MockUsersClient("");
// const filesClient = new MockFilesClient("");
for (let i = 0; i < tests.length; i++) {
const tc = tests[i];
// for (let i = 0; i < tests.length; i++) {
// const tc = tests[i];
filesClient.listMock(makePromise(tc.listResp));
updater().setClients(usersClient, filesClient);
const coreState = newWithWorker(mockWorker);
updater().init(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);
// 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);
expect(item.size).toEqual(tc.listResp.data.metadatas[i].size);
expect(item.modTime).toEqual(tc.listResp.data.metadatas[i].modTime);
expect(item.isDir).toEqual(tc.listResp.data.metadatas[i].isDir);
});
}
});
// newState.panel.browser.items.forEach((item, i) => {
// expect(item.name).toEqual(tc.listResp.data.metadatas[i].name);
// expect(item.size).toEqual(tc.listResp.data.metadatas[i].size);
// expect(item.modTime).toEqual(tc.listResp.data.metadatas[i].modTime);
// expect(item.isDir).toEqual(tc.listResp.data.metadatas[i].isDir);
// });
// }
// });
test("Updater: moveHere", async () => {
const tests = [
{
dirPath1: "path/path1",
dirPath2: "path/path2",
selected: {
file1: true,
file2: true,
},
listResp: {
status: 200,
statusText: "",
data: {
metadatas: [
{
name: "file1",
size: 1,
modTime: "1-1",
isDir: false,
},
{
name: "file2",
size: 2,
modTime: "1-1",
isDir: false,
},
],
},
},
},
];
// test("Updater: moveHere", async () => {
// const tests = [
// {
// dirPath1: "path/path1",
// dirPath2: "path/path2",
// selected: {
// file1: true,
// file2: true,
// },
// listResp: {
// status: 200,
// statusText: "",
// data: {
// metadatas: [
// {
// name: "file1",
// size: 1,
// modTime: "1-1",
// isDir: false,
// },
// {
// name: "file2",
// size: 2,
// modTime: "1-1",
// isDir: false,
// },
// ],
// },
// },
// },
// ];
const usersClient = new MockUsersClient("");
const filesClient = new MockFilesClient("");
for (let i = 0; i < tests.length; i++) {
const tc = tests[i];
// const usersClient = new MockUsersClient("");
// const filesClient = new MockFilesClient("");
// for (let i = 0; i < tests.length; i++) {
// const tc = tests[i];
filesClient.listMock(makePromise(tc.listResp));
filesClient.moveMock(makeNumberResponse(200));
updater().setClients(usersClient, filesClient);
// filesClient.listMock(makePromise(tc.listResp));
// filesClient.moveMock(makeNumberResponse(200));
// updater().setClients(usersClient, filesClient);
const coreState = newWithWorker(mockWorker);
updater().init(coreState);
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().updateBrowser(coreState);
// const newState = updater().updateBrowser(coreState);
// TODO: check inputs of move
newState.panel.browser.items.forEach((item, i) => {
expect(item.name).toEqual(tc.listResp.data.metadatas[i].name);
expect(item.size).toEqual(tc.listResp.data.metadatas[i].size);
expect(item.modTime).toEqual(tc.listResp.data.metadatas[i].modTime);
expect(item.isDir).toEqual(tc.listResp.data.metadatas[i].isDir);
});
}
});
// // TODO: check inputs of move
// newState.panel.browser.items.forEach((item, i) => {
// expect(item.name).toEqual(tc.listResp.data.metadatas[i].name);
// expect(item.size).toEqual(tc.listResp.data.metadatas[i].size);
// expect(item.modTime).toEqual(tc.listResp.data.metadatas[i].modTime);
// expect(item.isDir).toEqual(tc.listResp.data.metadatas[i].isDir);
// });
// }
// });
test("Browser: deleteUpload: tell uploader to deleteUpload and refreshUploadings", async () => {
let coreState = initState();
addMockUpdate(coreState.panel.browser);
const component = new Browser(coreState.panel.browser);
const UpdaterClass = mock(Updater);
const mockUpdater = instance(UpdaterClass);
setUpdater(mockUpdater);
when(UpdaterClass.setItems(anything())).thenResolve();
when(UpdaterClass.deleteUpload(anyString())).thenResolve(true);
when(UpdaterClass.refreshUploadings()).thenResolve(true);
// test("Browser: deleteUpload: tell uploader to deleteUpload and refreshUploadings", async () => {
// let coreState = initState();
// addMockUpdate(coreState.panel.browser);
// const component = new Browser(coreState.panel.browser);
// const UpdaterClass = mock(Updater);
// const mockUpdater = instance(UpdaterClass);
// setUpdater(mockUpdater);
// when(UpdaterClass.setItems(anything())).thenResolve();
// when(UpdaterClass.deleteUpload(anyString())).thenResolve(true);
// when(UpdaterClass.refreshUploadings()).thenResolve(true);
const filePath = "filePath";
await component.deleteUpload(filePath);
// const filePath = "filePath";
// await component.deleteUpload(filePath);
verify(UpdaterClass.deleteUpload(filePath)).once();
verify(UpdaterClass.refreshUploadings()).once();
});
// verify(UpdaterClass.deleteUpload(filePath)).once();
// verify(UpdaterClass.refreshUploadings()).once();
// });
test("Browser: stopUploading: tell updater to stopUploading", async () => {
let coreState = initState();
addMockUpdate(coreState.panel.browser);
const component = new Browser(coreState.panel.browser);
const UpdaterClass = mock(Updater);
const mockUpdater = instance(UpdaterClass);
setUpdater(mockUpdater);
when(UpdaterClass.stopUploading(anyString())).thenReturn();
// test("Browser: stopUploading: tell updater to stopUploading", async () => {
// let coreState = initState();
// addMockUpdate(coreState.panel.browser);
// const component = new Browser(coreState.panel.browser);
// const UpdaterClass = mock(Updater);
// const mockUpdater = instance(UpdaterClass);
// setUpdater(mockUpdater);
// when(UpdaterClass.stopUploading(anyString())).thenReturn();
const filePath = "filePath";
component.stopUploading(filePath);
// const filePath = "filePath";
// component.stopUploading(filePath);
verify(UpdaterClass.stopUploading(filePath)).once();
});
});
// verify(UpdaterClass.stopUploading(filePath)).once();
// });
// });

View file

@ -56,9 +56,9 @@ describe("AuthPane", () => {
updater().setClients(usersClient, filesClient);
updater().init(coreState);
await updater().initIsAuthed();
const newState = updater().updateAuthPane(coreState);
const newState = updater().updateLogin(coreState);
expect(newState.panel.authPane.authed).toEqual(tc.isAuthed);
expect(newState.login.authed).toEqual(tc.isAuthed);
}
});
});

View file

@ -32,7 +32,7 @@ describe("Panes", () => {
];
const setState = (patch: any, state: ICoreState): ICoreState => {
state.panel.panes = patch.panes;
state.panes = patch.panes;
return state;
};
@ -40,7 +40,12 @@ describe("Panes", () => {
const preState = setState(tc.preState, initState());
const postState = setState(tc.postState, initState());
const component = new Panes(preState.panel.panes);
const component = new Panes({
panes: preState.panes,
admin: preState.admin,
login: preState.login,
update: mockUpdate,
});
updater().init(preState);
component.closePane();

View file

@ -1,52 +0,0 @@
import { Set } from "immutable";
import { ICoreState, initState } from "../core_state";
import { RootFrame } from "../root_frame";
// import { Updater } from "../panes";
import { updater } from "../state_updater";
xdescribe("RootFrame", () => {
test("component: showSettings", async () => {
interface TestCase {
preState: ICoreState;
postState: ICoreState;
}
const mockUpdate = (apply: (prevState: ICoreState) => ICoreState): void => {};
const tcs: any = [
{
preState: {
displaying: "",
panes: {
displaying: "",
paneNames: Set<string>(["settings", "login"]),
},
update: mockUpdate,
},
postState: {
displaying: "settings",
panes: {
displaying: "settings",
paneNames: Set<string>(["settings", "login"]),
},
update: mockUpdate,
},
},
];
const setState = (patch: any, state: ICoreState): ICoreState => {
return { ...state, panel: { ...state.panel, ...patch } };
};
tcs.forEach((tc: TestCase) => {
const preState = setState(tc.preState, initState());
const postState = setState(tc.postState, initState());
const component = new RootFrame(preState.panel);
updater().init(preState);
// component.showSettings();
expect(updater().props).toEqual(postState);
});
});
});

View file

@ -1,207 +0,0 @@
import { List, Map } from "immutable";
import { ICoreState } from "./core_state";
import { Props, getItemPath } from "./browser";
import {
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: Props;
private usersClient: IUsersClient = new UsersClient("");
private filesClient: IFilesClient = new FilesClient("");
init = (props: Props) => (this.props = { ...props });
setClients(usersClient: IUsersClient, filesClient: IFilesClient) {
this.usersClient = usersClient;
this.filesClient = filesClient;
}
initUploads = () => {
this.props.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.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.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.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.isSharing = resp.status === 200;
return resp.status === 200; // TODO: differentiate 404 and error
};
setSharing = (shared: boolean) => {
this.props.isSharing = shared;
};
listSharings = async (): Promise<boolean> => {
const resp = await this.filesClient.listSharings();
this.props.sharings =
resp.status === 200
? List<string>(resp.data.sharingDirs)
: this.props.sharings;
return resp.status === 200;
};
refreshUploadings = async (): Promise<boolean> => {
const luResp = await this.filesClient.listUploadings();
this.props.uploadings =
luResp.status === 200
? List<UploadInfo>(luResp.data.uploadInfos)
: this.props.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.dirPath = dirParts;
this.props.items =
listResp.status === 200
? List<MetadataResp>(listResp.data.metadatas)
: this.props.items;
};
setHomeItems = async (): Promise<void> => {
const listResp = await this.filesClient.listHome();
this.props.dirPath = List<string>(listResp.data.cwd.split("/"));
this.props.items =
listResp.status === 200
? List<MetadataResp>(listResp.data.metadatas)
: this.props.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("/")));
};
setBrowser = (prevState: ICoreState): ICoreState => {
return {
...prevState,
panel: {
...prevState.panel,
browser: {
dirPath: this.props.dirPath,
isSharing: this.props.isSharing,
items: this.props.items,
uploadings: this.props.uploadings,
sharings: this.props.sharings,
uploadFiles: this.props.uploadFiles,
uploadValue: this.props.uploadValue,
isVertical: this.props.isVertical,
},
},
};
};
}
export let browserUpdater = new Updater();
export const updater = (): Updater => {
return browserUpdater;
};
export const setUpdater = (updater: Updater) => {
browserUpdater = updater;
};

View file

@ -3,15 +3,25 @@ import { List, Set, Map } from "immutable";
import BgWorker from "../worker/upload.bg.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 { PanesProps as PanesProps } from "./panes";
import { Props as LoginProps } from "./pane_login";
import { Props as AdminProps } from "./pane_admin";
import { Props as SettingsProps } from "./pane_settings";
import { Item } from "./browser";
import { UploadInfo, User } from "../client";
import { initUploadMgr, IWorker } from "../worker/upload_mgr";
export interface ICoreState {
panel: PanelProps;
// panel: PanelProps;
isVertical: boolean;
browser: BrowserProps;
panes: PanesProps;
login: LoginProps;
admin: AdminProps;
// settings: SettingsProps;
}
export function newWithWorker(worker: IWorker): ICoreState {
@ -29,40 +39,32 @@ export function newState(): ICoreState {
export function initState(): ICoreState {
return {
isVertical: isVertical(),
panel: {
browser: {
isVertical: isVertical(),
dirPath: List<string>(["."]),
items: List<Item>([]),
sharings: List<string>([]),
isSharing: false,
uploadings: List<UploadInfo>([]),
uploadValue: "",
uploadFiles: List<File>([]),
},
panes: {
userRole: "",
displaying: "browser",
authPane: {
authed: false,
captchaID: "",
},
browser: {
isVertical: isVertical(),
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>(),
},
},
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;
}
}

View file

@ -46,7 +46,7 @@ export class AuthPane extends React.Component<Props, State, {}> {
updater()
.initIsAuthed()
.then(() => {
this.update(updater().updateAuthPane);
this.update(updater().updateLogin);
});
};
@ -60,7 +60,7 @@ export class AuthPane extends React.Component<Props, State, {}> {
)
.then((ok: boolean) => {
if (ok) {
this.update(updater().updateAuthPane);
this.update(updater().updateLogin);
this.setState({ user: "", pwd: "" });
// close all the panes
updater().displayPane("");
@ -78,7 +78,7 @@ export class AuthPane extends React.Component<Props, State, {}> {
})
.then(() => {
return updater().isSharing(
updater().props.panel.browser.dirPath.join("/")
updater().props.browser.dirPath.join("/")
);
})
.then(() => {
@ -92,7 +92,7 @@ export class AuthPane extends React.Component<Props, State, {}> {
logout = () => {
updater().logout().then((ok: boolean) => {
if (ok) {
this.update(updater().updateAuthPane);
this.update(updater().updateLogin);
} else {
alert("Failed to logout.");
}

View file

@ -7,10 +7,13 @@ import { PaneSettings } from "./pane_settings";
import { AdminPane, Props as AdminPaneProps } from "./pane_admin";
import { AuthPane, Props as AuthPaneProps } from "./pane_login";
export interface Props {
userRole: string;
export interface PanesProps {
displaying: string;
userRole: string;
paneNames: Set<string>;
}
export interface Props {
panes: PanesProps;
login: AuthPaneProps;
admin: AdminPaneProps;
update?: (updater: (prevState: ICoreState) => ICoreState) => void;
@ -23,14 +26,14 @@ export class Panes extends React.Component<Props, State, {}> {
}
closePane = () => {
if (this.props.displaying !== "login") {
if (this.props.panes.displaying !== "login") {
updater().displayPane("");
this.props.update(updater().updatePanes);
}
};
render() {
let displaying = this.props.displaying;
let displaying = this.props.panes.displaying;
if (!this.props.login.authed) {
// TODO: use constant instead
// TODO: control this with props
@ -50,7 +53,7 @@ export class Panes extends React.Component<Props, State, {}> {
),
});
if (this.props.userRole === "admin") {
if (this.props.panes.userRole === "admin") {
panesMap = panesMap.set(
"admin",
<AdminPane

View file

@ -7,9 +7,7 @@ import { Panes, Props as PanesProps } from "./panes";
import { TopBar } from "./topbar";
export interface Props {
displaying: string;
browser: BrowserProps;
authPane: PaneLoginProps;
panes: PanesProps;
update?: (updater: (prevState: ICoreState) => ICoreState) => void;
}
@ -25,10 +23,8 @@ export class RootFrame extends React.Component<Props, State, {}> {
<div className="theme-white desktop">
<div id="bg" className="bg bg-img font-m">
<Panes
userRole={this.props.panes.userRole}
displaying={this.props.panes.displaying}
paneNames={this.props.panes.paneNames}
login={this.props.authPane}
panes={this.props.panes.panes}
login={this.props.panes.login}
admin={this.props.panes.admin}
update={this.props.update}
/>

View file

@ -29,7 +29,7 @@ export class StateMgr extends React.Component<Props, State, {}> {
if (!ok) {
alert("failed to get captcha id");
} else {
this.update(updater().updateAuthPane);
this.update(updater().updateLogin);
}
});
@ -48,9 +48,7 @@ export class StateMgr extends React.Component<Props, State, {}> {
return updater().initUploads();
})
.then(() => {
return updater().isSharing(
updater().props.panel.browser.dirPath.join("/")
);
return updater().isSharing(updater().props.browser.dirPath.join("/"));
})
.then(() => {
return updater().listSharings();
@ -62,13 +60,13 @@ export class StateMgr extends React.Component<Props, State, {}> {
return updater().self();
})
.then(() => {
if (updater().props.panel.panes.userRole === "admin") {
if (updater().props.panes.userRole === "admin") {
// TODO: remove hardcode
return updater().listRoles();
}
})
.then(() => {
if (updater().props.panel.panes.userRole === "admin") {
if (updater().props.panes.userRole === "admin") {
// TODO: remove hardcode
return updater().listUsers();
}
@ -85,11 +83,13 @@ export class StateMgr extends React.Component<Props, State, {}> {
render() {
return (
<RootFrame
authPane={this.state.panel.authPane}
displaying={this.state.panel.displaying}
browser={this.state.browser}
panes={{
panes: this.state.panes,
login: this.state.login,
admin: this.state.admin,
}}
update={this.update}
browser={this.state.panel.browser}
panes={this.state.panel.panes}
/>
);
}

View file

@ -28,7 +28,7 @@ export class Updater {
}
initUploads = () => {
this.props.panel.browser.uploadings.forEach((entry) => {
this.props.browser.uploadings.forEach((entry) => {
Up().addStopped(entry.realFilePath, entry.uploaded, entry.size);
});
// this.setUploadings(Up().list());
@ -37,7 +37,7 @@ export class Updater {
addUploads = (fileList: List<File>) => {
fileList.forEach((file) => {
const filePath = getItemPath(
this.props.panel.browser.dirPath.join("/"),
this.props.browser.dirPath.join("/"),
file.name
);
// do not wait for the promise
@ -53,7 +53,7 @@ export class Updater {
};
setUploadings = (infos: Map<string, UploadEntry>) => {
this.props.panel.browser.uploadings = List<UploadInfo>(
this.props.browser.uploadings = List<UploadInfo>(
infos.valueSeq().map((v: UploadEntry): UploadInfo => {
return {
realFilePath: v.filePath,
@ -65,7 +65,7 @@ export class Updater {
};
addSharing = async (): Promise<boolean> => {
const dirPath = this.props.panel.browser.dirPath.join("/");
const dirPath = this.props.browser.dirPath.join("/");
const resp = await this.filesClient.addSharing(dirPath);
return resp.status === 200;
};
@ -77,30 +77,30 @@ export class Updater {
isSharing = async (dirPath: string): Promise<boolean> => {
const resp = await this.filesClient.isSharing(dirPath);
this.props.panel.browser.isSharing = resp.status === 200;
this.props.browser.isSharing = resp.status === 200;
return resp.status === 200; // TODO: differentiate 404 and error
};
setSharing = (shared: boolean) => {
this.props.panel.browser.isSharing = shared;
this.props.browser.isSharing = shared;
};
listSharings = async (): Promise<boolean> => {
const resp = await this.filesClient.listSharings();
this.props.panel.browser.sharings =
this.props.browser.sharings =
resp.status === 200
? List<string>(resp.data.sharingDirs)
: this.props.panel.browser.sharings;
: this.props.browser.sharings;
return resp.status === 200;
};
refreshUploadings = async (): Promise<boolean> => {
const luResp = await this.filesClient.listUploadings();
this.props.panel.browser.uploadings =
this.props.browser.uploadings =
luResp.status === 200
? List<UploadInfo>(luResp.data.uploadInfos)
: this.props.panel.browser.uploadings;
: this.props.browser.uploadings;
return luResp.status === 200;
};
@ -143,23 +143,21 @@ export class Updater {
const dirPath = dirParts.join("/");
const listResp = await this.filesClient.list(dirPath);
this.props.panel.browser.dirPath = dirParts;
this.props.panel.browser.items =
this.props.browser.dirPath = dirParts;
this.props.browser.items =
listResp.status === 200
? List<MetadataResp>(listResp.data.metadatas)
: this.props.panel.browser.items;
: this.props.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 =
this.props.browser.dirPath = List<string>(listResp.data.cwd.split("/"));
this.props.browser.items =
listResp.status === 200
? List<MetadataResp>(listResp.data.metadatas)
: this.props.panel.browser.items;
: this.props.browser.items;
};
moveHere = async (
@ -189,11 +187,11 @@ export class Updater {
displayPane = (paneName: string) => {
if (paneName === "") {
// hide all panes
this.props.panel.panes.displaying = "";
this.props.panes.displaying = "";
} else {
const pane = this.props.panel.panes.paneNames.get(paneName);
const pane = this.props.panes.paneNames.get(paneName);
if (pane != null) {
this.props.panel.panes.displaying = paneName;
this.props.panes.displaying = paneName;
} else {
alert(`dialgos: pane (${paneName}) not found`);
}
@ -203,7 +201,7 @@ export class Updater {
self = async (): Promise<boolean> => {
const resp = await this.usersClient.self();
if (resp.status === 200) {
this.props.panel.panes.userRole = resp.data.role;
this.props.panes.userRole = resp.data.role;
return true;
}
return false;
@ -241,7 +239,7 @@ export class Updater {
lsRes.users.forEach((user: User) => {
users = users.set(user.name, user);
});
this.props.panel.panes.admin.users = users;
this.props.admin.users = users;
return true;
};
@ -268,7 +266,7 @@ export class Updater {
Object.keys(lsRes.roles).forEach((role: string) => {
roles = roles.add(role);
});
this.props.panel.panes.admin.roles = roles;
this.props.admin.roles = roles;
return true;
};
@ -309,13 +307,13 @@ export class Updater {
};
setAuthed = (isAuthed: boolean) => {
this.props.panel.authPane.authed = isAuthed;
this.props.login.authed = isAuthed;
};
getCaptchaID = async (): Promise<boolean> => {
return this.usersClient.getCaptchaID().then((resp) => {
if (resp.status === 200) {
this.props.panel.authPane.captchaID = resp.data.id;
this.props.login.captchaID = resp.data.id;
}
return resp.status === 200;
});
@ -329,38 +327,29 @@ export class Updater {
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,
},
},
browser: { ...prevState.browser, ...this.props.browser },
};
};
updatePanes = (prevState: ICoreState): ICoreState => {
return {
...prevState,
panel: {
...prevState.panel,
panes: { ...prevState.panel.panes, ...this.props.panel.panes },
},
panes: { ...prevState.panes, ...this.props.panes },
};
};
updateAuthPane = (preState: ICoreState): ICoreState => {
preState.panel.authPane = {
...preState.panel.authPane,
...this.props.panel.authPane,
updateLogin = (prevState: ICoreState): ICoreState => {
return {
...prevState,
login: { ...prevState.login, ...this.props.login },
};
};
updateAdmin = (prevState: ICoreState): ICoreState => {
return {
...prevState,
admin: { ...prevState.admin, ...this.props.admin },
};
return preState;
};
}