diff --git a/src/client/web/src/components/__test__/pane_login.test.tsx b/src/client/web/src/components/__test__/pane_login.test.tsx index c168144..4803d6a 100644 --- a/src/client/web/src/components/__test__/pane_login.test.tsx +++ b/src/client/web/src/components/__test__/pane_login.test.tsx @@ -3,7 +3,13 @@ import { List, Set, Map } from "immutable"; import { initMockWorker } from "../../test/helpers"; import { User, UploadInfo } from "../../client"; import { AuthPane } from "../pane_login"; -import { ICoreState, newState } from "../core_state"; +import { + ICoreState, + newState, + sharingCtrl, + ctrlOn, + ctrlOff, +} from "../core_state"; import { updater } from "../state_updater"; import { UploadState, UploadEntry } from "../../worker/interface"; import { MockUsersClient, resps as usersResps } from "../../client/users_mock"; @@ -16,7 +22,7 @@ import { settingsTabsCtrl } from "../dialog_settings"; describe("Login", () => { initMockWorker(); - test("login", async () => { + test("login as admin without sharing", async () => { const coreState = newState(); const pane = new AuthPane({ login: coreState.login, @@ -113,8 +119,9 @@ describe("Login", () => { control: { controls: Map({ [panelTabs]: "filesPanel", - [settingsDialogCtrl]: "off", + [settingsDialogCtrl]: ctrlOff, [settingsTabsCtrl]: "preferencePane", + [sharingCtrl]: ctrlOff, }), options: Map>({ [panelTabs]: Set([ @@ -122,8 +129,9 @@ describe("Login", () => { "uploadingsPanel", "sharingsPanel", ]), - [settingsDialogCtrl]: Set(["on", "off"]), + [settingsDialogCtrl]: Set([ctrlOn, ctrlOff]), [settingsTabsCtrl]: Set(["preferencePane", "managementPane"]), + [sharingCtrl]: Set([ctrlOn, ctrlOff]), }), }, }); diff --git a/src/client/web/src/components/__test__/state_mgr.test.tsx b/src/client/web/src/components/__test__/state_mgr.test.tsx index 6058f34..adbeb14 100644 --- a/src/client/web/src/components/__test__/state_mgr.test.tsx +++ b/src/client/web/src/components/__test__/state_mgr.test.tsx @@ -16,6 +16,7 @@ import { MsgPackage } from "../../i18n/msger"; describe("State Manager", () => { initMockWorker(); + const emptyQuery = new URLSearchParams(""); test("initUpdater for admin", async () => { const usersCl = new MockUsersClient(""); @@ -33,7 +34,7 @@ describe("State Manager", () => { }; const coreState = newState(); - await mgr.initUpdater(coreState); + await mgr.initUpdater(coreState, emptyQuery); // browser expect(coreState.filesInfo.dirPath.join("/")).toEqual("mock_home/files"); @@ -161,11 +162,14 @@ describe("State Manager", () => { mgr.update = (apply: (prevState: ICoreState) => ICoreState): void => { // no op }; - await mgr.initUpdater(coreState); + + const sharingPath = "sharingPath/files"; + const query = new URLSearchParams(`?dir=${sharingPath}`); + await mgr.initUpdater(coreState, query); // browser // TODO: mock query to get dir parm - expect(coreState.filesInfo.dirPath.join("/")).toEqual("mock_home/files"); + expect(coreState.filesInfo.dirPath.join("/")).toEqual(sharingPath); expect(coreState.filesInfo.isSharing).toEqual(true); expect(coreState.filesInfo.items).toEqual( List(filesResps.listHomeMockResp.data.metadatas) diff --git a/src/client/web/src/components/core_state.ts b/src/client/web/src/components/core_state.ts index 100de43..f3dcafd 100644 --- a/src/client/web/src/components/core_state.ts +++ b/src/client/web/src/components/core_state.ts @@ -1,7 +1,8 @@ import { List, Set, Map } from "immutable"; import { UploadEntry } from "../worker/interface"; - +import { MsgPackage } from "../i18n/msger"; +import { User, MetadataResp } from "../client"; import { settingsDialogCtrl } from "./layers"; import { FilesProps } from "./panel_files"; import { UploadingsProps } from "./panel_uploadings"; @@ -10,9 +11,11 @@ import { controlName as panelTabs } from "./root_frame"; import { settingsTabsCtrl } from "./dialog_settings"; import { LoginProps } from "./pane_login"; import { AdminProps } from "./pane_admin"; -import { MsgPackage } from "../i18n/msger"; -import { User, MetadataResp } from "../client"; +export const ctrlHidden = "hidden"; +export const ctrlOn = "on"; +export const ctrlOff = "off"; +export const sharingCtrl = "sharingCtrl"; export interface MsgProps { lan: string; pkg: Map; @@ -108,6 +111,7 @@ export function initState(): ICoreState { [panelTabs]: "filesPanel", [settingsDialogCtrl]: "off", [settingsTabsCtrl]: "preferencePane", + [sharingCtrl]: "off", }), options: Map>({ [panelTabs]: Set([ @@ -117,6 +121,7 @@ export function initState(): ICoreState { ]), [settingsDialogCtrl]: Set(["on", "off"]), [settingsTabsCtrl]: Set(["preferencePane", "managementPane"]), + [sharingCtrl]: Set(["on", "off"]), }), }, }, diff --git a/src/client/web/src/components/state_mgr.tsx b/src/client/web/src/components/state_mgr.tsx index f9e603e..cbd44e9 100644 --- a/src/client/web/src/components/state_mgr.tsx +++ b/src/client/web/src/components/state_mgr.tsx @@ -25,7 +25,9 @@ export class StateMgr extends React.Component { const worker = window.Worker == null ? new FgWorker() : new BgWorker(); initUploadMgr(worker); this.state = newState(); - this.initUpdater(this.state); // don't await + + const query = new URLSearchParams(document.location.search.substring(1)); + this.initUpdater(this.state, query); // don't await } setUsersClient = (client: IUsersClient) => { @@ -40,7 +42,10 @@ export class StateMgr extends React.Component { this.settingsClient = client; }; - initUpdater = async (state: ICoreState): Promise => { + initUpdater = async ( + state: ICoreState, + query: URLSearchParams + ): Promise => { updater().init(state); if ( this.usersClient == null || @@ -56,9 +61,8 @@ export class StateMgr extends React.Component { this.settingsClient ); - const params = new URLSearchParams(document.location.search.substring(1)); return updater() - .initAll(params) + .initAll(query) .then(() => { this.update(updater().updateFilesInfo); this.update(updater().updateUploadingsInfo); diff --git a/src/client/web/src/components/state_updater.ts b/src/client/web/src/components/state_updater.ts index 8e037ef..f5a6b8d 100644 --- a/src/client/web/src/components/state_updater.ts +++ b/src/client/web/src/components/state_updater.ts @@ -1,6 +1,12 @@ import { List, Map, Set } from "immutable"; -import { ICoreState } from "./core_state"; +import { + ICoreState, + sharingCtrl, + ctrlOn, + ctrlOff, + ctrlHidden, +} from "./core_state"; import { getItemPath } from "./browser"; import { User, @@ -26,6 +32,9 @@ import { UploadEntry, UploadState } from "../worker/interface"; import { Up } from "../worker/upload_mgr"; import { alertMsg } from "../common/env"; import { LocalStorage } from "../common/localstorage"; +import { controlName as panelTabs } from "./root_frame"; +import { settingsTabsCtrl } from "./dialog_settings"; +import { settingsDialogCtrl } from "./layers"; import { MsgPackage, isValidLanPack } from "../i18n/msger"; @@ -286,48 +295,135 @@ export class Updater { return this.setItems(List(dstDir.split("/"))); }; + initUITree = () => { + const isAuthed = this.props.login.authed; + const isSharing = + this.props.ui.control.controls.get(sharingCtrl) === ctrlOn; + + if (isAuthed) { + this.props.ui.control.controls = Map({ + [panelTabs]: "filesPanel", + [settingsDialogCtrl]: ctrlOff, + [settingsTabsCtrl]: "preferencePane", + [sharingCtrl]: isSharing ? ctrlOn : ctrlOff, + }); + this.props.ui.control.options = Map>({ + [panelTabs]: Set([ + "filesPanel", + "uploadingsPanel", + "sharingsPanel", + ]), + [settingsDialogCtrl]: Set([ctrlOn, ctrlOff]), + [settingsTabsCtrl]: Set(["preferencePane"]), + [sharingCtrl]: Set([ctrlOn, ctrlOff]), + }); + + if (this.props.login.userRole == roleAdmin) { + this.props.ui.control.options = this.props.ui.control.options.set( + settingsTabsCtrl, + Set(["preferencePane", "managementPane"]) + ); + } + } else { + if (isSharing) { + this.props.ui.control.controls = Map({ + [panelTabs]: "filesPanel", + [settingsDialogCtrl]: ctrlHidden, + [settingsTabsCtrl]: ctrlHidden, + [sharingCtrl]: ctrlOn, + }); + this.props.ui.control.options = Map>({ + [panelTabs]: Set(["filesPanel"]), + [settingsDialogCtrl]: Set([ctrlHidden]), + [settingsTabsCtrl]: Set([ctrlHidden]), + [sharingCtrl]: Set([ctrlOn]), + }); + } else { + this.props.ui.control.controls = Map({ + [panelTabs]: ctrlHidden, + [settingsDialogCtrl]: ctrlHidden, + [settingsTabsCtrl]: ctrlHidden, + [sharingCtrl]: ctrlOff, + }); + this.props.ui.control.options = Map>({ + [panelTabs]: Set([ctrlHidden]), + [settingsDialogCtrl]: Set([ctrlHidden]), + [settingsTabsCtrl]: Set([ctrlHidden]), + [sharingCtrl]: Set([ctrlOff]), + }); + } + } + }; + + initStateForVisitor = async (): Promise => { + // TOOD: status is ignored, should return alert + return Promise.all([ + this.getClientCfg(), + this.syncLan(), + this.isSharing(this.props.filesInfo.dirPath.join("/")), + ]); + }; + + initStateForAuthedUser = async (): Promise => { + // TOOD: status is ignored, should return alert + return Promise.all([ + this.refreshUploadings(), + this.initUploads(), + this.listSharings(), + ]); + }; + + initStateForAdmin = async (): Promise => { + return this.initStateForVisitor() + .then(() => { + return this.initStateForAuthedUser(); + }) + .then(() => { + return Promise.all([this.listRoles(), this.listUsers()]); + }); + }; + + syncCwd = async () => { + if (this.props.filesInfo.dirPath.size !== 0) { + return this.setItems(this.props.filesInfo.dirPath); + } + return this.setHomeItems(); + }; + + initCwd = async (params: URLSearchParams): Promise => { + const dir = params.get("dir"); + + if (dir != null && dir !== "") { + const dirPath = List(dir.split("/")); + this.props.ui.control.controls = this.props.ui.control.controls.set( + sharingCtrl, + ctrlOn + ); + this.props.filesInfo.dirPath = dirPath; + } else { + this.props.ui.control.controls = this.props.ui.control.controls.set( + sharingCtrl, + ctrlOff + ); + this.props.filesInfo.dirPath = List([]); + } + }; + initAll = async (params: URLSearchParams): Promise => { - return this.initIsAuthed() + return Promise.all([this.self(), this.initIsAuthed(), this.initCwd(params)]) .then(() => { - return this.self(); + this.initUITree(); }) .then(() => { - const dir = params.get("dir"); - if (dir != null && dir !== "") { - const dirPath = List(dir.split("/")); - return this.setItems(dirPath); - } else { - return this.setHomeItems(); - } + return this.syncCwd(); }) .then(() => { - return this.isSharing(this.props.filesInfo.dirPath.join("/")); - }) - .then(() => { - if (this.props.login.userRole !== roleVisitor) { - // init panels for authned users - return Promise.all([ - this.refreshUploadings(), - this.initUploads(), - this.listSharings(), - ]); - } - }) - .then(() => { - // init settings - return this.getClientCfg(); - }) - .then(() => { - // init i18n - // TOOD: status is ignored, should return alert - return this.fetchLanPack(); - }) - .then(() => { - // init admin content if (this.props.login.userRole === roleAdmin) { - return Promise.all([this.listRoles(), this.listUsers()]); + return this.initStateForAdmin(); + } else if (this.props.login.userRole === roleVisitor) { + return this.initStateForVisitor(); } - return; + return this.initStateForAuthedUser(); }); }; @@ -572,7 +668,7 @@ export class Updater { return resp.status; }; - fetchLanPack = async (): Promise => { + syncLan = async (): Promise => { const url = this.props.login.preferences.lanPackURL; if (url === "") { const lan = this.props.login.preferences.lan;