mirror of
1
Fork 0

refactor admin settings

This commit is contained in:
f0x 2023-01-08 16:14:46 +00:00
parent df9e980a24
commit 85e7f2ccb5
7 changed files with 124 additions and 49 deletions

View File

@ -19,88 +19,103 @@
"use strict"; "use strict";
const React = require("react"); const React = require("react");
const Redux = require("react-redux");
const Submit = require("../components/submit"); const query = require("../lib/query");
const api = require("../lib/api"); const {
const submit = require("../lib/submit"); useTextInput,
useFileInput
} = require("../lib/form");
const adminActions = require("../redux/reducers/instances").actions; const useFormSubmit = require("../lib/form/submit");
const { const {
TextInput, TextInput,
TextArea, TextArea,
File FileInput
} = require("../components/form-fields").formFields(adminActions.setAdminSettingsVal, (state) => state.instances.adminSettings); } = require("../components/form/inputs");
const FormWithData = require("../lib/form/form-with-data");
const MutationButton = require("../components/form/mutation-button");
module.exports = function AdminSettings() { module.exports = function AdminSettings() {
const dispatch = Redux.useDispatch(); return (
const instance = Redux.useSelector(state => state.instances.adminSettings); <FormWithData
dataQuery={query.useInstanceQuery}
const [errorMsg, setError] = React.useState(""); DataForm={AdminSettingsForm}
const [statusMsg, setStatus] = React.useState(""); />
const updateSettings = submit(
() => dispatch(api.admin.updateInstance()),
{setStatus, setError}
); );
};
function AdminSettingsForm({data: instance}) {
const form = {
title: useTextInput("title", {defaultValue: instance.title}),
thumbnail: useFileInput("thumbnail", {withPreview: true}),
thumbnailDesc: useTextInput("thumbnail_description", {defaultValue: instance.thumbnail_description}),
shortDesc: useTextInput("short_description", {defaultValue: instance.short_description}),
description: useTextInput("description", {defaultValue: instance.description}),
contactUser: useTextInput("contact_username", {defaultValue: instance.contact_account?.username}),
contactEmail: useTextInput("contact_email", {defaultValue: instance.email}),
terms: useTextInput("terms", {defaultValue: instance.terms})
};
const [result, submitForm] = useFormSubmit(form, query.useUpdateInstanceMutation());
return ( return (
<div> <form onSubmit={submitForm}>
<h1>Instance Settings</h1> <h1>Instance Settings</h1>
<TextInput <TextInput
id="title" field={form.title}
name="Title" label="Title"
placeHolder="My GoToSocial instance" placeholder="My GoToSocial instance"
/> />
<div className="file-upload"> <div className="file-upload">
<h3>Instance thumbnail</h3> <h3>Instance thumbnail</h3>
<div> <div>
<img className="preview avatar" src={instance.thumbnail} alt={instance.thumbnail ? `Thumbnail image for the instance` : "No instance thumbnail image set"} /> <img className="preview avatar" src={form.thumbnail.previewValue ?? instance.thumbnail} alt={form.thumbnailDesc.value ?? (instance.thumbnail ? `Thumbnail image for the instance` : "No instance thumbnail image set")} />
<File <FileInput
id="thumbnail" field={form.thumbnail}
fileType="image/*" accept="image/*"
/> />
</div> </div>
</div> </div>
<TextInput <TextInput
id="thumbnail_description" field={form.thumbnailDesc}
name="Instance thumbnail description" label="Instance thumbnail description"
placeHolder="A cute little picture of a smiling sloth." placeholder="A cute drawing of a smiling sloth."
/> />
<TextArea <TextArea
id="short_description" field={form.shortDesc}
name="Short description" label="Short description"
placeHolder="A small testing instance for the GoToSocial alpha." placeholder="A small testing instance for the GoToSocial alpha software."
/> />
<TextArea <TextArea
id="description" field={form.description}
name="Full description" label="Full description"
placeHolder="A small testing instance for the GoToSocial alpha." placeholder="A small testing instance for the GoToSocial alpha software. Just trying it out, my main instance is https://example.com"
/> />
<TextInput <TextInput
id="contact_account.username" field={form.contactUser}
name="Contact user (local account username)" label="Contact user (local account username)"
placeHolder="admin" placeholder="admin"
/> />
<TextInput <TextInput
id="email" field={form.contactEmail}
name="Contact email" label="Contact email"
placeHolder="admin@example.com" placeholder="admin@example.com"
/> />
<TextArea <TextArea
id="terms" field={form.terms}
name="Terms & Conditions" label="Terms & Conditions"
placeHolder="" placeholder=""
/> />
<Submit onClick={updateSettings} label="Save" errorMsg={errorMsg} statusMsg={statusMsg} /> <MutationButton text="Save" result={result}/>
</div> </form>
); );
}; }

View File

@ -0,0 +1,17 @@
"use strict";
const React = require("react");
const Loading = require("../../components/loading");
// Wrap Form component inside component that fires the RTK Query call,
// so Form will only be rendered when data is available to generate form-fields for
module.exports = function FormWithData({dataQuery, DataForm}) {
const {data, isLoading} = dataQuery();
if (isLoading) {
return <Loading/>;
} else {
return <DataForm data={data}/>;
}
};

View File

@ -0,0 +1,36 @@
/*
GoToSocial
Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"use strict";
const { updateCacheOnMutation } = require("./lib");
const base = require("./base");
const endpoints = (build) => ({
updateInstance: build.mutation({
query: (formData) => ({
method: "PATCH",
url: `/api/v1/instance`,
asForm: true,
body: formData
}),
...updateCacheOnMutation("instance")
})
});
module.exports = base.injectEndpoints({endpoints});

View File

@ -51,5 +51,11 @@ module.exports = createApi({
reducerPath: "api", reducerPath: "api",
baseQuery: instanceBasedQuery, baseQuery: instanceBasedQuery,
tagTypes: ["Emojis", "User"], tagTypes: ["Emojis", "User"],
endpoints: () => ({}) endpoints: (build) => ({
instance: build.query({
query: () => ({
url: `/api/v1/instance`
})
})
})
}); });

View File

@ -21,5 +21,6 @@
module.exports = { module.exports = {
...require("./base"), ...require("./base"),
...require("./custom-emoji.js"), ...require("./custom-emoji.js"),
...require("./user-settings") ...require("./user"),
...require("./admin")
}; };

View File

@ -66,8 +66,8 @@ function UserProfileForm({profile}) {
*/ */
const form = { const form = {
avatar: useFileInput("avatar", {withPreview: true, }), avatar: useFileInput("avatar", {withPreview: true}),
header: useFileInput("header", {withPreview: true, }), header: useFileInput("header", {withPreview: true}),
displayName: useTextInput("display_name", {defaultValue: profile.display_name}), displayName: useTextInput("display_name", {defaultValue: profile.display_name}),
note: useTextInput("note", {defaultValue: profile.source?.note}), note: useTextInput("note", {defaultValue: profile.source?.note}),
customCSS: useTextInput("custom_css", {defaultValue: profile.custom_css}), customCSS: useTextInput("custom_css", {defaultValue: profile.custom_css}),