diff --git a/web/source/css/base.css b/web/source/css/base.css
index 98c16acdd..ddca1efa8 100644
--- a/web/source/css/base.css
+++ b/web/source/css/base.css
@@ -83,6 +83,11 @@ header, footer {
align-self: start;
}
+header {
+ display: flex;
+ justify-content: center;
+}
+
header a {
margin: 2rem;
/* background: $header-bg; */
diff --git a/web/source/package.json b/web/source/package.json
index 412c92329..8b0bde878 100644
--- a/web/source/package.json
+++ b/web/source/package.json
@@ -1,6 +1,6 @@
{
"name": "gotosocial-frontend",
- "version": "0.3.8",
+ "version": "0.5.0",
"description": "GoToSocial frontend sources",
"main": "index.js",
"author": "f0x",
diff --git a/web/source/settings-panel/admin/federation.js b/web/source/settings-panel/admin/federation.js
index 4c97ebb8e..6898de602 100644
--- a/web/source/settings-panel/admin/federation.js
+++ b/web/source/settings-panel/admin/federation.js
@@ -18,6 +18,65 @@
"use strict";
-module.exports = function Federation() {
- return "federation";
+const Promise = require("bluebird");
+const React = require("react");
+const Redux = require("react-redux");
+
+const Submit = require("../components/submit");
+
+const api = require("../lib/api");
+const adminActions = require("../redux/reducers/instances").actions;
+
+const {
+ TextInput,
+ TextArea,
+ File
+} = require("../components/form-fields").formFields(adminActions.setAdminSettingsVal, (state) => state.instances.adminSettings);
+
+module.exports = function AdminSettings() {
+ const dispatch = Redux.useDispatch();
+ const instance = Redux.useSelector(state => state.instances.adminSettings);
+
+ const [loaded, setLoaded] = React.useState(false);
+
+ const [errorMsg, setError] = React.useState("");
+ const [statusMsg, setStatus] = React.useState("");
+
+ React.useEffect(() => {
+ Promise.try(() => {
+ return dispatch(api.admin.fetchDomainBlocks());
+ }).then(() => {
+ setLoaded(true);
+ }).catch((e) => {
+ console.log(e);
+ });
+ }, []);
+
+ function submit() {
+ setStatus("PATCHing");
+ setError("");
+ return Promise.try(() => {
+ return dispatch(api.admin.updateInstance());
+ }).then(() => {
+ setStatus("Saved!");
+ }).catch((e) => {
+ setError(e.message);
+ setStatus("");
+ });
+ }
+
+ if (!loaded) {
+ return (
+
+
Federation
+ Loading instance blocks...
+
+ );
+ }
+
+ return (
+
+
Federation
+
+ );
};
\ No newline at end of file
diff --git a/web/source/settings-panel/components/form-fields.jsx b/web/source/settings-panel/components/form-fields.jsx
index 30f209f13..67c6b883a 100644
--- a/web/source/settings-panel/components/form-fields.jsx
+++ b/web/source/settings-panel/components/form-fields.jsx
@@ -71,7 +71,7 @@ function get(state, id) {
module.exports = {
formFields: function formFields(setter, selector) {
- function FormField({type, id, name, className="", placeHolder="", fileType="", children=null, options={}}) {
+ function FormField({type, id, name, className="", placeHolder="", fileType="", children=null, options=null}) {
const dispatch = Redux.useDispatch();
let state = Redux.useSelector(selector);
let {
@@ -111,7 +111,6 @@ module.exports = {
}
let label = ;
-
return (
{defaultLabel ? label : null}
diff --git a/web/source/settings-panel/index.js b/web/source/settings-panel/index.js
index be0af56e7..8083807bb 100644
--- a/web/source/settings-panel/index.js
+++ b/web/source/settings-panel/index.js
@@ -28,6 +28,8 @@ const { PersistGate } = require("redux-persist/integration/react");
const { store, persistor } = require("./redux");
const api = require("./lib/api");
+const oauth = require("./redux/reducers/oauth").actions;
+const { AuthenticationError } = require("./lib/errors");
const Login = require("./components/login");
@@ -40,6 +42,7 @@ const nav = {
"Settings": require("./user/settings.js"),
},
"Admin": {
+ adminOnly: true,
"Instance Settings": require("./admin/settings.js"),
"Federation": require("./admin/federation.js"),
"Custom Emoji": require("./admin/emoji.js"),
@@ -47,15 +50,16 @@ const nav = {
}
};
-// Generate component tree from `nav` object once, as it won't change
-const { sidebar, panelRouter } = require("./lib/generate-views")(nav);
+const { sidebar, panelRouter } = require("./lib/get-views")(nav);
function App() {
const dispatch = Redux.useDispatch();
- const { loginState } = Redux.useSelector((state) => state.oauth);
+
+ const { loginState, isAdmin } = Redux.useSelector((state) => state.oauth);
const reduxTempStatus = Redux.useSelector((state) => state.temporary.status);
- const [ errorMsg, setErrorMsg ] = React.useState();
- const [ tokenChecked, setTokenChecked ] = React.useState(false);
+
+ const [errorMsg, setErrorMsg] = React.useState();
+ const [tokenChecked, setTokenChecked] = React.useState(false);
React.useEffect(() => {
if (loginState == "login" || loginState == "callback") {
@@ -64,7 +68,7 @@ function App() {
if (loginState == "callback") {
let urlParams = new URLSearchParams(window.location.search);
let code = urlParams.get("code");
-
+
if (code == undefined) {
setErrorMsg(new Error("Waiting for OAUTH callback but no ?code= provided. You can try logging in again:"));
} else {
@@ -79,7 +83,13 @@ function App() {
return dispatch(api.user.fetchAccount());
}).then(() => {
setTokenChecked(true);
+
+ return dispatch(api.oauth.checkIfAdmin());
}).catch((e) => {
+ if (e instanceof AuthenticationError) {
+ dispatch(oauth.remove());
+ e.message = "Stored OAUTH token no longer valid, please log in again.";
+ }
setErrorMsg(e);
console.error(e.message);
});
@@ -97,7 +107,7 @@ function App() {
}
const LogoutElement = (
-