refactor admin settings
This commit is contained in:
parent
df9e980a24
commit
85e7f2ccb5
|
@ -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>
|
||||||
);
|
);
|
||||||
};
|
}
|
|
@ -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}/>;
|
||||||
|
}
|
||||||
|
};
|
|
@ -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});
|
|
@ -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`
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
});
|
});
|
|
@ -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")
|
||||||
};
|
};
|
|
@ -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}),
|
||||||
|
|
Loading…
Reference in New Issue