From f151f47581f5496a5b39965a5301b412a3e088d7 Mon Sep 17 00:00:00 2001 From: hexxa Date: Sat, 9 Oct 2021 21:14:15 +0800 Subject: [PATCH] feat(settings): enable background settings --- configs/dev.yml | 2 +- src/client/web/src/client/settings.ts | 4 +- src/client/web/src/components/pane_admin.tsx | 169 +++++++++++++++++- src/client/web/src/components/pane_login.tsx | 1 + .../web/src/components/pane_settings.tsx | 9 +- src/client/web/src/components/panes.tsx | 4 +- src/client/web/src/components/root_frame.tsx | 1 + src/client/web/src/components/state_mgr.tsx | 1 + .../web/src/components/state_updater.ts | 22 ++- src/client/web/src/components/topbar.tsx | 11 +- src/client/web/src/i18n/en_US.ts | 8 + src/client/web/src/i18n/zh_CN.ts | 10 +- src/handlers/settings/handlers.go | 4 +- 13 files changed, 229 insertions(+), 17 deletions(-) diff --git a/configs/dev.yml b/configs/dev.yml index 085e859..512ca5b 100644 --- a/configs/dev.yml +++ b/configs/dev.yml @@ -42,7 +42,7 @@ site: siteName: "Quickshare" siteDesc: "quick and simple file sharing" bg: - url: "/static/img/textured_paper.png" + url: "/v1/fs/files?fp=qs/files/Screen%20Shot%202021-08-07%20at%2020.03.08%20PM.png" repeat: "repeat" position: "fixed" align: "center" diff --git a/src/client/web/src/client/settings.ts b/src/client/web/src/client/settings.ts index 43f0b84..6286bf4 100644 --- a/src/client/web/src/client/settings.ts +++ b/src/client/web/src/client/settings.ts @@ -25,7 +25,9 @@ export class SettingsClient extends BaseClient { return this.do({ method: "patch", url: `${this.url}/v1/settings/client`, - data: cfg, + data: { + clientCfg: cfg, + }, }); }; } diff --git a/src/client/web/src/components/pane_admin.tsx b/src/client/web/src/components/pane_admin.tsx index 70272ee..0c13c29 100644 --- a/src/client/web/src/components/pane_admin.tsx +++ b/src/client/web/src/components/pane_admin.tsx @@ -3,10 +3,11 @@ import { List, Map, Set } from "immutable"; import FileSize from "filesize"; import { alertMsg, confirmMsg } from "../common/env"; -import { ICoreState, MsgProps } from "./core_state"; +import { ICoreState, MsgProps, UIProps } from "./core_state"; import { User, Quota } from "../client"; import { updater } from "./state_updater"; import { Flexbox } from "./layout/flexbox"; +import { Flowgrid } from "./layout/flowgrid"; export interface AdminProps { users: Map; @@ -15,6 +16,7 @@ export interface AdminProps { export interface Props { admin: AdminProps; + ui: UIProps; msg: MsgProps; update?: (updater: (prevState: ICoreState) => ICoreState) => void; } @@ -458,6 +460,14 @@ export class AdminPane extends React.Component { return (
+
+ +
+
{ ); } } + +interface BgProps { + msg: MsgProps; + ui: UIProps; + update?: (updater: (prevState: ICoreState) => ICoreState) => void; +} + +interface BgState {} +export class BgCfg extends React.Component { + changeSiteName = (ev: React.ChangeEvent) => { + updater().setClientCfg({ ...this.props.ui, siteName: ev.target.value }); + this.props.update(updater().updateUI); + }; + changeSiteDesc = (ev: React.ChangeEvent) => { + updater().setClientCfg({ ...this.props.ui, siteDesc: ev.target.value }); + this.props.update(updater().updateUI); + }; + changeBgUrl = (ev: React.ChangeEvent) => { + updater().setClientCfg({ + ...this.props.ui, + bg: { ...this.props.ui.bg, url: ev.target.value }, + }); + this.props.update(updater().updateUI); + }; + changeBgRepeat = (ev: React.ChangeEvent) => { + updater().setClientCfg({ + ...this.props.ui, + bg: { ...this.props.ui.bg, repeat: ev.target.value }, + }); + this.props.update(updater().updateUI); + }; + changeBgPos = (ev: React.ChangeEvent) => { + updater().setClientCfg({ + ...this.props.ui, + bg: { ...this.props.ui.bg, position: ev.target.value }, + }); + this.props.update(updater().updateUI); + }; + changeBgAlign = (ev: React.ChangeEvent) => { + updater().setClientCfg({ + ...this.props.ui, + bg: { ...this.props.ui.bg, align: ev.target.value }, + }); + this.props.update(updater().updateUI); + }; + + constructor(p: BgProps) { + super(p); + } + + setClientCfg = async () => { + return updater().setClientCfgRemote({ + siteName: this.props.ui.siteName, + siteDesc: this.props.ui.siteDesc, + bg: this.props.ui.bg, + }); + }; + + resetClientCfg = () => { + // TODO: move this to backend + updater().setClientCfg({ + siteName: "Quickshare", + siteDesc: "Quickshare", + bg: { + url: "/static/img/textured_paper.png", + repeat: "repeat", + position: "fixed", + align: "center", + }, + }); + this.props.update(updater().updateUI); + }; + + render() { + return ( +
+ + {this.props.msg.pkg.get("cfg.bg")} + , + + + + + , + ])} + childrenStyles={List([{}, { justifyContent: "flex-end" }])} + /> + + +
+ {this.props.msg.pkg.get("cfg.bg.url")} +
+ +
, + +
+
+ {this.props.msg.pkg.get("cfg.bg.repeat")} +
+ +
, + +
+
+ {this.props.msg.pkg.get("cfg.bg.pos")} +
+ +
, + +
+
+ {this.props.msg.pkg.get("cfg.bg.align")} +
+ +
, + ])} + /> +
+ ); + } +} diff --git a/src/client/web/src/components/pane_login.tsx b/src/client/web/src/components/pane_login.tsx index c4a8afe..c09329f 100644 --- a/src/client/web/src/components/pane_login.tsx +++ b/src/client/web/src/components/pane_login.tsx @@ -78,6 +78,7 @@ export class AuthPane extends React.Component { this.update(updater().updateLogin); this.update(updater().updatePanes); this.update(updater().updateAdmin); + this.update(updater().updateUI); updater().initLan(); this.update(updater().updateMsg); diff --git a/src/client/web/src/components/pane_settings.tsx b/src/client/web/src/components/pane_settings.tsx index fcf2478..ce53093 100644 --- a/src/client/web/src/components/pane_settings.tsx +++ b/src/client/web/src/components/pane_settings.tsx @@ -1,15 +1,16 @@ import * as React from "react"; import FileSize from "filesize"; +import { List } from "immutable"; import { ICoreState, MsgProps } from "./core_state"; import { LoginProps } from "./pane_login"; import { Flexbox } from "./layout/flexbox"; import { updater } from "./state_updater"; import { alertMsg } from "../common/env"; -import { List } from "immutable"; export interface Props { login: LoginProps; msg: MsgProps; + update?: (updater: (prevState: ICoreState) => ICoreState) => void; } @@ -20,7 +21,6 @@ export interface State { } export class PaneSettings extends React.Component { - private update: (updater: (prevState: ICoreState) => ICoreState) => void; changeOldPwd = (ev: React.ChangeEvent) => { this.setState({ oldPwd: ev.target.value }); }; @@ -33,7 +33,6 @@ export class PaneSettings extends React.Component { constructor(p: Props) { super(p); - this.update = p.update; this.state = { oldPwd: "", newPwd1: "", @@ -130,9 +129,7 @@ export class PaneSettings extends React.Component {
-
-
{ />
-
-
ICoreState) => void; } @@ -88,6 +89,7 @@ export class Panes extends React.Component {
diff --git a/src/client/web/src/components/root_frame.tsx b/src/client/web/src/components/root_frame.tsx index 9c62068..f3ce692 100644 --- a/src/client/web/src/components/root_frame.tsx +++ b/src/client/web/src/components/root_frame.tsx @@ -44,6 +44,7 @@ export class RootFrame extends React.Component { panes={this.props.panes} login={this.props.login} admin={this.props.admin} + ui={this.props.ui} msg={this.props.msg} update={this.props.update} /> diff --git a/src/client/web/src/components/state_mgr.tsx b/src/client/web/src/components/state_mgr.tsx index 3e1ac1e..1293d3c 100644 --- a/src/client/web/src/components/state_mgr.tsx +++ b/src/client/web/src/components/state_mgr.tsx @@ -64,6 +64,7 @@ export class StateMgr extends React.Component { this.update(updater().updateLogin); this.update(updater().updatePanes); this.update(updater().updateAdmin); + this.update(updater().updateUI); updater().initLan(); this.update(updater().updateMsg); diff --git a/src/client/web/src/components/state_updater.ts b/src/client/web/src/components/state_updater.ts index 2dad3f6..ef5db01 100644 --- a/src/client/web/src/components/state_updater.ts +++ b/src/client/web/src/components/state_updater.ts @@ -350,6 +350,10 @@ export class Updater { .then(() => { return this.isSharing(this.props.browser.dirPath.join("/")); }) + .then(() => { + // init settings + return this.getClientCfg(); + }) .then(() => { // init panes return this.initPanes(); @@ -561,11 +565,20 @@ export class Updater { return resp.status === 200; }; - setClientCfg = async (cfg: ClientConfig): Promise => { + setClientCfgRemote = async (cfg: ClientConfig): Promise => { const resp = await this.settingsClient.setClientCfg(cfg); return resp.status; }; + setClientCfg = async (cfg: ClientConfig): Promise => { + this.props.ui = { + ...this.props.ui, + siteName: cfg.siteName, + siteDesc: cfg.siteDesc, + bg: cfg.bg, + }; + }; + getClientCfg = async (): Promise => { const resp = await this.settingsClient.getClientCfg(); if (resp.status === 200) { @@ -612,6 +625,13 @@ export class Updater { msg: { ...prevState.msg, ...this.props.msg }, }; }; + + updateUI = (prevState: ICoreState): ICoreState => { + return { + ...prevState, + ui: { ...prevState.ui, ...this.props.ui }, + }; + }; } export let coreUpdater = new Updater(); diff --git a/src/client/web/src/components/topbar.tsx b/src/client/web/src/components/topbar.tsx index 247bf7b..882d5e9 100644 --- a/src/client/web/src/components/topbar.tsx +++ b/src/client/web/src/components/topbar.tsx @@ -8,7 +8,7 @@ import { PanesProps } from "./panes"; import { updater } from "./state_updater"; import { Flexbox } from "./layout/flexbox"; -export interface State { } +export interface State {} export interface Props { login: LoginProps; panes: PanesProps; @@ -51,7 +51,9 @@ export class TopBar extends React.Component { .logout() .then((ok: boolean) => { if (ok) { - const params = new URLSearchParams(document.location.search.substring(1)); + const params = new URLSearchParams( + document.location.search.substring(1) + ); return updater().initAll(params); } else { alertMsg(this.props.msg.pkg.get("login.logout.fail")); @@ -65,6 +67,7 @@ export class TopBar extends React.Component { this.props.update(updater().updateLogin); this.props.update(updater().updatePanes); this.props.update(updater().updateAdmin); + this.props.update(updater().updateUI); updater().initLan(); this.props.update(updater().updateMsg); @@ -82,7 +85,9 @@ export class TopBar extends React.Component { render() { const showUserInfo = this.props.login.authed ? "" : "hidden"; const showLogin = this.props.login.authed ? "" : "hidden"; - const showSettings = this.props.panes.paneNames.get("settings") ? "" : "hidden"; + const showSettings = this.props.panes.paneNames.get("settings") + ? "" + : "hidden"; const showAdmin = this.props.panes.paneNames.get("admin") ? "" : "hidden"; return ( diff --git a/src/client/web/src/i18n/en_US.ts b/src/client/web/src/i18n/en_US.ts index 6f153f3..5f1a46d 100644 --- a/src/client/web/src/i18n/en_US.ts +++ b/src/client/web/src/i18n/en_US.ts @@ -87,4 +87,12 @@ export const msgs: Map = Map({ "user.downLimit": "Download Speed Limit", "user.upLimit": "Upload Speed Limit", "user.spaceLimit": "Space Limit", + "cfg.siteName": "Site Name", + "cfg.siteDesc": "Site Description", + "cfg.bg": "Background", + "cfg.bg.url": "Background URL", + "cfg.bg.repeat": "Repeat", + "cfg.bg.pos": "Position", + "cfg.bg.align": "Align", + reset: "Reset", }); diff --git a/src/client/web/src/i18n/zh_CN.ts b/src/client/web/src/i18n/zh_CN.ts index 1cba08a..ba1e958 100644 --- a/src/client/web/src/i18n/zh_CN.ts +++ b/src/client/web/src/i18n/zh_CN.ts @@ -79,11 +79,19 @@ export const msgs: Map = Map({ "pane.admin": "管理", "pane.settings": "设置", "logout.confirm": "确定登出吗?", - "unauthed": "未授权动作", + unauthed: "未授权动作", "err.tooManyUploads": "不可同时上传超过1000个文件", "login.role": "角色", "user.profile": "用户信息", "user.downLimit": "下载速度限制", "user.upLimit": "上传速度限制", "user.spaceLimit": "空间限制", + "cfg.siteName": "站点名字", + "cfg.siteDesc": "站点描述", + "cfg.bg": "背景设置", + "cfg.bg.url": "图片链接", + "cfg.bg.repeat": "重复", + "cfg.bg.pos": "位置", + "cfg.bg.align": "对齐", + reset: "重置", }); diff --git a/src/handlers/settings/handlers.go b/src/handlers/settings/handlers.go index 539489e..1768645 100644 --- a/src/handlers/settings/handlers.go +++ b/src/handlers/settings/handlers.go @@ -30,7 +30,7 @@ func (h *SettingsSvc) Health(c *gin.Context) { } type ClientCfgMsg struct { - ClientCfg *sitestore.ClientConfig + ClientCfg *sitestore.ClientConfig `json:"clientCfg"` } func (h *SettingsSvc) GetClientCfg(c *gin.Context) { @@ -51,6 +51,8 @@ func (h *SettingsSvc) SetClientCfg(c *gin.Context) { c.JSON(q.ErrResp(c, 400, err)) return } + h.deps.Log().Info(req.ClientCfg) + if err = validateClientCfg(req.ClientCfg); err != nil { c.JSON(q.ErrResp(c, 400, err)) return