From 80c05825ab6616175fcd004d959d861a7d66a500 Mon Sep 17 00:00:00 2001 From: f0x Date: Thu, 15 Sep 2022 21:16:18 +0200 Subject: [PATCH] federation block routing --- web/source/settings-panel/admin/federation.js | 110 +++++++++++++----- .../settings-panel/components/nav-button.jsx | 2 +- web/source/settings-panel/lib/api/admin.js | 3 + web/source/settings-panel/lib/api/oauth.js | 9 +- web/source/settings-panel/lib/get-views.js | 23 ++-- web/source/settings-panel/redux/index.js | 1 + .../settings-panel/redux/reducers/admin.js | 49 ++++++++ 7 files changed, 150 insertions(+), 47 deletions(-) create mode 100644 web/source/settings-panel/redux/reducers/admin.js diff --git a/web/source/settings-panel/admin/federation.js b/web/source/settings-panel/admin/federation.js index 6898de602..23117be9f 100644 --- a/web/source/settings-panel/admin/federation.js +++ b/web/source/settings-panel/admin/federation.js @@ -21,62 +21,108 @@ const Promise = require("bluebird"); const React = require("react"); const Redux = require("react-redux"); +const {Switch, Route, Link, useRoute} = require("wouter"); 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); +const base = "/settings/admin/federation"; + +// 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 instance = Redux.useSelector(state => state.instances.adminSettings); + const { blockedInstances } = Redux.useSelector(state => state.admin); 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); - }); - }, []); + const [loaded, setLoaded] = React.useState(false); - function submit() { - setStatus("PATCHing"); - setError(""); - return Promise.try(() => { - return dispatch(api.admin.updateInstance()); - }).then(() => { - setStatus("Saved!"); - }).catch((e) => { - setError(e.message); - setStatus(""); - }); - } + React.useEffect(() => { + if (blockedInstances != undefined) { + setLoaded(true); + } else { + return Promise.try(() => { + return dispatch(api.admin.fetchDomainBlocks()); + }).then(() => { + setLoaded(true); + }); + } + }, []); if (!loaded) { return (

Federation

- Loading instance blocks... + Loading...
); } return (
-

Federation

+ + + + + +
); -}; \ No newline at end of file +}; + +function InstanceOverview({blockedInstances}) { + return ( +
+

Federation

+ {blockedInstances.map((entry) => { + return ( + + {entry.domain} + + ); + })} +
+ ); +} + +function BackButton() { + return ( + + < back + + ); +} + +function InstancePage({blockedInstances}) { + let [_match, {domain}] = useRoute(`${base}/:domain`); + let [status, setStatus] = React.useState(""); + let [entry, setEntry] = React.useState(() => { + let entry = blockedInstances.find((a) => a.domain == domain); + + if (entry == undefined) { + setStatus(`No block entry found for ${domain}, but you can create one below:`); + return { + private_comment: "" + }; + } else { + return entry; + } + }); + + return ( +
+ {status} +

Federation settings for: {domain}

+
{entry.private_comment}
+
+ ); +} \ No newline at end of file diff --git a/web/source/settings-panel/components/nav-button.jsx b/web/source/settings-panel/components/nav-button.jsx index d806400fb..3c76711fb 100644 --- a/web/source/settings-panel/components/nav-button.jsx +++ b/web/source/settings-panel/components/nav-button.jsx @@ -22,7 +22,7 @@ const React = require("react"); const { Link, useRoute } = require("wouter"); module.exports = function NavButton({href, name}) { - const [isActive] = useRoute(href); + const [isActive] = useRoute(`${href}/:anything?`); return ( diff --git a/web/source/settings-panel/lib/api/admin.js b/web/source/settings-panel/lib/api/admin.js index cfc243fd0..cf44fc6ef 100644 --- a/web/source/settings-panel/lib/api/admin.js +++ b/web/source/settings-panel/lib/api/admin.js @@ -21,6 +21,7 @@ const Promise = require("bluebird"); const instance = require("../../redux/reducers/instances").actions; +const admin = require("../../redux/reducers/admin").actions; module.exports = function ({ apiCall, getChanges }) { return { @@ -45,6 +46,8 @@ module.exports = function ({ apiCall, getChanges }) { return function (dispatch, _getState) { return Promise.try(() => { return dispatch(apiCall("GET", "/api/v1/admin/domain_blocks")); + }).then((data) => { + return dispatch(admin.setBlockedInstances(data)); }); }; } diff --git a/web/source/settings-panel/lib/api/oauth.js b/web/source/settings-panel/lib/api/oauth.js index 604bdcc37..4067f5a75 100644 --- a/web/source/settings-panel/lib/api/oauth.js +++ b/web/source/settings-panel/lib/api/oauth.js @@ -24,7 +24,7 @@ const { OAUTHError, AuthenticationError } = require("../errors"); const oauth = require("../../redux/reducers/oauth").actions; const temporary = require("../../redux/reducers/temporary").actions; -const user = require("../../redux/reducers/user").actions; +const admin = require("../../redux/reducers/admin").actions; module.exports = function oauthAPI({ apiCall, getCurrentUrl }) { return { @@ -103,8 +103,11 @@ module.exports = function oauthAPI({ apiCall, getCurrentUrl }) { // no role info, try fetching an admin-only route and see if we get an error return Promise.try(() => { return dispatch(apiCall("GET", "/api/v1/admin/domain_blocks")); - }).then(() => { - return dispatch(oauth.setAdmin(true)); + }).then((data) => { + return Promise.all([ + dispatch(oauth.setAdmin(true)), + dispatch(admin.setBlockedInstances(data)) + ]); }).catch(AuthenticationError, () => { return dispatch(oauth.setAdmin(false)); }).catch((e) => { diff --git a/web/source/settings-panel/lib/get-views.js b/web/source/settings-panel/lib/get-views.js index 5c68e832c..01031747e 100644 --- a/web/source/settings-panel/lib/get-views.js +++ b/web/source/settings-panel/lib/get-views.js @@ -64,11 +64,11 @@ module.exports = function getViews(struct) { let url = `${base}/${urlSafe(name)}`; if (firstRoute == undefined) { - firstRoute = `${base}/${urlSafe(name)}`; + firstRoute = url; } - routes.push(( - + panelRouterEl.push(( + { }}> {/* FIXME: implement onReset */} @@ -87,14 +87,15 @@ module.exports = function getViews(struct) { ); - let childrenPath = `${base}/:section`; - panelRouterEl.push( - - - {routes} - - - ); + // let childrenPath = `${base}/:section`; + // panelRouterEl.push(...routes); + console.log(panelRouterEl); + // + // + // {routes} + // + // + // ); sidebarEl.push( diff --git a/web/source/settings-panel/redux/index.js b/web/source/settings-panel/redux/index.js index ab2694223..e0dbe9b23 100644 --- a/web/source/settings-panel/redux/index.js +++ b/web/source/settings-panel/redux/index.js @@ -36,6 +36,7 @@ const combinedReducers = combineReducers({ instances: require("./reducers/instances").reducer, temporary: require("./reducers/temporary").reducer, user: require("./reducers/user").reducer, + admin: require("./reducers/admin").reducer, }); const persistedReducer = persistReducer(persistConfig, combinedReducers); diff --git a/web/source/settings-panel/redux/reducers/admin.js b/web/source/settings-panel/redux/reducers/admin.js new file mode 100644 index 000000000..f8f4e994e --- /dev/null +++ b/web/source/settings-panel/redux/reducers/admin.js @@ -0,0 +1,49 @@ +/* + 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 . +*/ + +"use strict"; + +const {createSlice} = require("@reduxjs/toolkit"); +// const d = require("dotty"); + +function sortBlocks(blocks) { + return blocks.sort((a, b) => { // alphabetical sort + return a.domain.localeCompare(b.domain); + }); +} + +// function deduplicateBlocks(blocks) { +// let a = new Map(); +// blocks.forEach((block) => { +// a.set(block.id, block); +// }); +// return Array.from(a.values()); +// } + +module.exports = createSlice({ + name: "admin", + initialState: { + blockedInstances: undefined, + blockedInstancesMap: {} + }, + reducers: { + setBlockedInstances: (state, {payload}) => { + state.blockedInstances = sortBlocks(payload); + }, + } +}); \ No newline at end of file