mirror of
https://github.com/superseriousbusiness/gotosocial.git
synced 2024-10-31 22:40:01 +00:00
use redux state for profile form
This commit is contained in:
parent
3ce9dfe7d6
commit
2bd18790cf
5 changed files with 71 additions and 45 deletions
|
@ -18,6 +18,7 @@
|
|||
"browserlist": "^1.0.1",
|
||||
"create-error": "^0.3.1",
|
||||
"css-extract": "^2.0.0",
|
||||
"dotty": "^0.1.2",
|
||||
"eslint-plugin-react": "^7.24.0",
|
||||
"express": "^4.18.1",
|
||||
"factor-bundle": "^2.5.0",
|
||||
|
|
|
@ -19,10 +19,11 @@
|
|||
"use strict";
|
||||
|
||||
const Promise = require("bluebird");
|
||||
const d = require("dotty");
|
||||
|
||||
const user = require("../../redux/reducers/user").actions;
|
||||
|
||||
module.exports = function({apiCall}) {
|
||||
module.exports = function ({ apiCall }) {
|
||||
return {
|
||||
fetchAccount: function fetchAccount() {
|
||||
return function (dispatch, _getState) {
|
||||
|
@ -33,10 +34,34 @@ module.exports = function({apiCall}) {
|
|||
});
|
||||
};
|
||||
},
|
||||
updateAccount: function updateAccount(newAccount) {
|
||||
return function (dispatch, _getSate) {
|
||||
updateAccount: function updateAccount() {
|
||||
const formKeys = ["display_name", "locked"];
|
||||
const renamedKeys = [["note", "source.note"]];
|
||||
const fileKeys = ["header", "avatar"];
|
||||
|
||||
return function (dispatch, getState) {
|
||||
return Promise.try(() => {
|
||||
return dispatch(apiCall("PATCH", "/api/v1/accounts/update_credentials", newAccount, "form"));
|
||||
const { account } = getState().user;
|
||||
|
||||
const update = {};
|
||||
|
||||
formKeys.forEach((key) => {
|
||||
d.put(update, key, d.get(account, key));
|
||||
update[key] = account[key];
|
||||
});
|
||||
|
||||
renamedKeys.forEach(([sendKey, intKey]) => {
|
||||
d.put(update, sendKey, d.get(account, intKey));
|
||||
});
|
||||
|
||||
fileKeys.forEach((key) => {
|
||||
let file = d.get(account, `${key}File`);
|
||||
if (file != undefined) {
|
||||
d.put(update, key, file);
|
||||
}
|
||||
});
|
||||
|
||||
return dispatch(apiCall("PATCH", "/api/v1/accounts/update_credentials", update, "form"));
|
||||
}).then((account) => {
|
||||
console.log(account);
|
||||
return dispatch(user.setAccount(account));
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
"use strict";
|
||||
|
||||
const {createSlice} = require("@reduxjs/toolkit");
|
||||
const d = require("dotty");
|
||||
|
||||
module.exports = createSlice({
|
||||
name: "user",
|
||||
|
@ -27,6 +28,9 @@ module.exports = createSlice({
|
|||
reducers: {
|
||||
setAccount: (state, {payload}) => {
|
||||
state.account = payload;
|
||||
},
|
||||
setAccountVal: (state, {payload: [key, val]}) => {
|
||||
d.put(state.account, key, val);
|
||||
}
|
||||
}
|
||||
});
|
|
@ -21,10 +21,12 @@
|
|||
const Promise = require("bluebird");
|
||||
const React = require("react");
|
||||
const Redux = require("react-redux");
|
||||
const d = require("dotty");
|
||||
|
||||
const Submit = require("../components/submit");
|
||||
|
||||
const api = require("../lib/api");
|
||||
const user = require("../redux/reducers/user").actions;
|
||||
|
||||
module.exports = function UserProfile() {
|
||||
const dispatch = Redux.useDispatch();
|
||||
|
@ -33,29 +35,30 @@ module.exports = function UserProfile() {
|
|||
const [errorMsg, setError] = React.useState("");
|
||||
const [statusMsg, setStatus] = React.useState("");
|
||||
|
||||
const [headerFile, setHeaderFile] = React.useState(undefined);
|
||||
const [avatarFile, setAvatarFile] = React.useState(undefined);
|
||||
|
||||
const [displayName, setDisplayName] = React.useState("");
|
||||
const [bio, setBio] = React.useState("");
|
||||
const [locked, setLocked] = React.useState(false);
|
||||
|
||||
React.useEffect(() => {
|
||||
|
||||
setDisplayName(account.display_name);
|
||||
setBio(account.source ? account.source.note : "");
|
||||
setLocked(account.locked);
|
||||
}, []);
|
||||
|
||||
const headerOnChange = (e) => {
|
||||
setHeaderFile(e.target.files[0]);
|
||||
// setHeaderSrc(URL.createObjectURL(e.target.files[0]));
|
||||
function onTextChange(key) {
|
||||
return function (e) {
|
||||
dispatch(user.setAccountVal([key, e.target.value]));
|
||||
};
|
||||
}
|
||||
|
||||
const avatarOnChange = (e) => {
|
||||
setAvatarFile(e.target.files[0]);
|
||||
// setAvatarSrc(URL.createObjectURL(e.target.files[0]));
|
||||
function onCheckChange(key) {
|
||||
return function (e) {
|
||||
dispatch(user.setAccountVal([key, e.target.checked]));
|
||||
};
|
||||
}
|
||||
|
||||
function onFileChange(key) {
|
||||
return function (e) {
|
||||
let old = d.get(account, key);
|
||||
if (old != undefined) {
|
||||
URL.revokeObjectURL(old); // no error revoking a non-Object URL as provided by instance
|
||||
}
|
||||
let file = e.target.files[0];
|
||||
let objectURL = URL.createObjectURL(file);
|
||||
dispatch(user.setAccountVal([key, objectURL]));
|
||||
dispatch(user.setAccountVal([`${key}File`, file]));
|
||||
};
|
||||
}
|
||||
|
||||
const submit = (e) => {
|
||||
e.preventDefault();
|
||||
|
@ -63,21 +66,7 @@ module.exports = function UserProfile() {
|
|||
setStatus("PATCHing");
|
||||
setError("");
|
||||
return Promise.try(() => {
|
||||
let payload = {
|
||||
display_name: displayName,
|
||||
note: bio,
|
||||
locked: locked
|
||||
};
|
||||
|
||||
if (headerFile) {
|
||||
payload.header = headerFile;
|
||||
}
|
||||
|
||||
if (avatarFile) {
|
||||
payload.avatar = avatarFile;
|
||||
}
|
||||
|
||||
return dispatch(api.user.updateAccount(payload));
|
||||
return dispatch(api.user.updateAccount());
|
||||
}).then(() => {
|
||||
setStatus("Saved!");
|
||||
}).catch((e) => {
|
||||
|
@ -105,26 +94,28 @@ module.exports = function UserProfile() {
|
|||
<div>
|
||||
<h3>Header</h3>
|
||||
<label htmlFor="header" className="file-input button">Browse…</label>
|
||||
<span>{headerFile ? headerFile.name : "no file selected"}</span>
|
||||
<span>{account.headerFile ? account.headerFile.name : "no file selected"}</span>
|
||||
<input className="hidden" id="header" type="file" accept="image/*" onChange={onFileChange("header")}/>
|
||||
</div>
|
||||
<div>
|
||||
<h3>Avatar</h3>
|
||||
<label htmlFor="avatar" className="file-input button">Browse…</label>
|
||||
<span>{avatarFile ? avatarFile.name : "no file selected"}</span>
|
||||
<span>{account.avatarFile ? account.avatarFile.name : "no file selected"}</span>
|
||||
<input className="hidden" id="avatar" type="file" accept="image/*" onChange={onFileChange("avatar")}/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="labelinput">
|
||||
<label htmlFor="displayname">Name</label>
|
||||
<input id="displayname" type="text" value={displayName} onChange={(e) => setDisplayName(e.target.value)} placeholder="A GoToSocial user"/>
|
||||
<input id="displayname" type="text" value={account.display_name} onChange={onTextChange("display_name")} placeholder="A GoToSocial user"/>
|
||||
</div>
|
||||
<div className="labelinput">
|
||||
<label htmlFor="bio">Bio</label>
|
||||
<textarea id="bio" value={bio} onChange={(e) => setBio(e.target.value)} placeholder="Just trying out GoToSocial, my pronouns are they/them and I like sloths."/>
|
||||
<textarea id="bio" value={account.source.note} onChange={onTextChange("source.note")} placeholder="Just trying out GoToSocial, my pronouns are they/them and I like sloths."/>
|
||||
</div>
|
||||
<div className="labelcheckbox">
|
||||
<label htmlFor="locked">Manually approve follow requests?</label>
|
||||
<input id="locked" type="checkbox" checked={locked} onChange={(e) => setLocked(e.target.checked)}/>
|
||||
<input id="locked" type="checkbox" checked={account.locked} onChange={onCheckChange("locked")}/>
|
||||
</div>
|
||||
<Submit onClick={submit} label="Save profile info" errorMsg={errorMsg} statusMsg={statusMsg}/>
|
||||
</div>
|
||||
|
|
|
@ -2528,6 +2528,11 @@ domain-browser@^1.2.0:
|
|||
resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda"
|
||||
integrity sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==
|
||||
|
||||
dotty@^0.1.2:
|
||||
version "0.1.2"
|
||||
resolved "https://registry.yarnpkg.com/dotty/-/dotty-0.1.2.tgz#512d44cc4111a724931226259297f235e8484f6f"
|
||||
integrity sha512-V0EWmKeH3DEhMwAZ+8ZB2Ao4OK6p++Z0hsDtZq3N0+0ZMVqkzrcEGROvOnZpLnvBg5PTNG23JEDLAm64gPaotQ==
|
||||
|
||||
duplexer2@^0.1.2, duplexer2@~0.1.0, duplexer2@~0.1.2, duplexer2@~0.1.4:
|
||||
version "0.1.4"
|
||||
resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.1.4.tgz#8b12dab878c0d69e3e7891051662a32fc6bddcc1"
|
||||
|
|
Loading…
Reference in a new issue