+ );
+}
+
+interface DomainPermFormProps {
+ defaultDomain: string;
+ perm?: DomainPerm;
+ permType: PermType;
+ baseUrl: string;
+}
+
+function DomainPermForm({ defaultDomain, perm, permType, baseUrl }: DomainPermFormProps) {
+ const isExistingPerm = perm !== undefined;
+ const disabledForm = isExistingPerm
+ ? {
+ disabled: true,
+ title: "Domain permissions currently cannot be edited."
+ }
+ : {
+ disabled: false,
+ title: "",
+ };
+
+ const form = {
+ domain: useTextInput("domain", { source: perm, defaultValue: defaultDomain }),
+ obfuscate: useBoolInput("obfuscate", { source: perm }),
+ commentPrivate: useTextInput("private_comment", { source: perm }),
+ commentPublic: useTextInput("public_comment", { source: perm })
+ };
+
+ // Check which perm type we're meant to be handling
+ // here, and use appropriate mutations and results.
+ // We can't call these hooks conditionally because
+ // react is like "weh" (mood), but we can decide
+ // which ones to use conditionally.
+ const [ addBlock, addBlockResult ] = useAddDomainBlockMutation();
+ const [ removeBlock, removeBlockResult] = useRemoveDomainBlockMutation({ fixedCacheKey: perm?.id });
+ const [ addAllow, addAllowResult ] = useAddDomainAllowMutation();
+ const [ removeAllow, removeAllowResult ] = useRemoveDomainAllowMutation({ fixedCacheKey: perm?.id });
+
+ const [
+ addTrigger,
+ addResult,
+ removeTrigger,
+ removeResult,
+ ] = useMemo(() => {
+ return permType == "block"
+ ? [
+ addBlock,
+ addBlockResult,
+ removeBlock,
+ removeBlockResult,
+ ]
+ : [
+ addAllow,
+ addAllowResult,
+ removeAllow,
+ removeAllowResult,
+ ];
+ }, [permType,
+ addBlock, addBlockResult, removeBlock, removeBlockResult,
+ addAllow, addAllowResult, removeAllow, removeAllowResult,
+ ]);
+
+ // Use appropriate submission params for this permType.
+ const [submitForm, submitFormResult] = useFormSubmit(form, [addTrigger, addResult], { changedOnly: false });
+
+ // Uppercase first letter of given permType.
+ const permTypeUpper = useMemo(() => {
+ return permType.charAt(0).toUpperCase() + permType.slice(1);
+ }, [permType]);
+
+ const [location, setLocation] = useLocation();
+
+ function verifyUrlThenSubmit(e) {
+ // Adding a new domain permissions happens on a url like
+ // "/settings/admin/domain-permissions/:permType/domain.com",
+ // but if domain input changes, that doesn't match anymore
+ // and causes issues later on so, before submitting the form,
+ // silently change url, and THEN submit.
+ let correctUrl = `${baseUrl}/${form.domain.value}`;
+ if (location != correctUrl) {
+ setLocation(correctUrl);
+ }
+ return submitForm(e);
+ }
+
+ return (
+
+ );
+}
diff --git a/web/source/settings/admin/federation/import-export/export-format-table.jsx b/web/source/settings/admin/domain-permissions/export-format-table.jsx
similarity index 100%
rename from web/source/settings/admin/federation/import-export/export-format-table.jsx
rename to web/source/settings/admin/domain-permissions/export-format-table.jsx
diff --git a/web/source/settings/admin/federation/import-export/form.jsx b/web/source/settings/admin/domain-permissions/form.tsx
similarity index 62%
rename from web/source/settings/admin/federation/import-export/form.jsx
rename to web/source/settings/admin/domain-permissions/form.tsx
index 2086739e37..fb639202db 100644
--- a/web/source/settings/admin/federation/import-export/form.jsx
+++ b/web/source/settings/admin/domain-permissions/form.tsx
@@ -17,34 +17,57 @@
along with this program. If not, see .
*/
-const React = require("react");
+import React from "react";
-const query = require("../../../lib/query");
-const useFormSubmit = require("../../../lib/form/submit");
+import { useEffect } from "react";
-const {
+import { useExportDomainListMutation } from "../../lib/query/admin/domain-permissions/export";
+import useFormSubmit from "../../lib/form/submit";
+
+import {
+ RadioGroup,
TextArea,
Select,
-} = require("../../../components/form/inputs");
+} from "../../components/form/inputs";
+
+import MutationButton from "../../components/form/mutation-button";
+
+import { Error } from "../../components/error";
+import ExportFormatTable from "./export-format-table";
-const MutationButton = require("../../../components/form/mutation-button");
+import type {
+ FormSubmitFunction,
+ FormSubmitResult,
+ RadioFormInputHook,
+ TextFormInputHook,
+} from "../../lib/form/types";
-const { Error } = require("../../../components/error");
-const ExportFormatTable = require("./export-format-table");
+export interface ImportExportFormProps {
+ form: {
+ domains: TextFormInputHook;
+ exportType: TextFormInputHook;
+ permType: RadioFormInputHook;
+ };
+ submitParse: FormSubmitFunction;
+ parseResult: FormSubmitResult;
+}
-module.exports = function ImportExportForm({ form, submitParse, parseResult }) {
- const [submitExport, exportResult] = useFormSubmit(form, query.useExportDomainListMutation());
+export default function ImportExportForm({ form, submitParse, parseResult }: ImportExportFormProps) {
+ const [submitExport, exportResult] = useFormSubmit(form, useExportDomainListMutation());
function fileChanged(e) {
const reader = new FileReader();
reader.onload = function (read) {
- form.domains.value = read.target.result;
- submitParse();
+ const res = read.target?.result;
+ if (typeof res === "string") {
+ form.domains.value = res;
+ submitParse();
+ }
};
reader.readAsText(e.target.files[0]);
}
- React.useEffect(() => {
+ useEffect(() => {
if (exportResult.isSuccess) {
form.domains.setter(exportResult.data);
}
@@ -53,12 +76,10 @@ module.exports = function ImportExportForm({ form, submitParse, parseResult }) {
return (
<>
-
Import / Export suspended domains
-
- This page can be used to import and export lists of domains to suspend.
- Exports can be done in various formats, with varying functionality and support in other software.
- Imports will automatically detect what format is being processed.
-
+
Import / Export domain permissions
+
This page can be used to import and export lists of domain permissions.
+
Exports can be done in various formats, with varying functionality and support in other software.
+
Imports will automatically detect what format is being processed.
- );
-};
-
-function DomainBlockForm({ defaultDomain, block = {}, baseUrl }) {
- const isExistingBlock = block.domain != undefined;
-
- const disabledForm = isExistingBlock
- ? {
- disabled: true,
- title: "Domain suspensions currently cannot be edited."
- }
- : {};
-
- const form = {
- domain: useTextInput("domain", { source: block, defaultValue: defaultDomain }),
- obfuscate: useBoolInput("obfuscate", { source: block }),
- commentPrivate: useTextInput("private_comment", { source: block }),
- commentPublic: useTextInput("public_comment", { source: block })
- };
-
- const [submitForm, addResult] = useFormSubmit(form, query.useAddInstanceBlockMutation(), { changedOnly: false });
-
- const [removeBlock, removeResult] = query.useRemoveInstanceBlockMutation({ fixedCacheKey: block.id });
-
- const [location, setLocation] = useLocation();
-
- function verifyUrlThenSubmit(e) {
- // Adding a new block happens on /settings/admin/federation/domain.com
- // but if domain input changes, that doesn't match anymore and causes issues later on
- // so, before submitting the form, silently change url, then submit
- let correctUrl = `${baseUrl}/${form.domain.value}`;
- if (location != correctUrl) {
- setLocation(correctUrl);
- }
- return submitForm(e);
- }
-
- return (
-
- );
-}
\ No newline at end of file
diff --git a/web/source/settings/admin/federation/import-export/index.jsx b/web/source/settings/admin/federation/import-export/index.jsx
deleted file mode 100644
index bff14b9394..0000000000
--- a/web/source/settings/admin/federation/import-export/index.jsx
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- GoToSocial
- Copyright (C) GoToSocial Authors admin@gotosocial.org
- SPDX-License-Identifier: AGPL-3.0-or-later
-
- 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 .
-*/
-
-const React = require("react");
-const { Switch, Route, Redirect, useLocation } = require("wouter");
-
-const query = require("../../../lib/query");
-
-const {
- useTextInput,
-} = require("../../../lib/form");
-
-const useFormSubmit = require("../../../lib/form/submit");
-
-const ProcessImport = require("./process");
-const ImportExportForm = require("./form");
-
-module.exports = function ImportExport({ baseUrl }) {
- const form = {
- domains: useTextInput("domains"),
- exportType: useTextInput("exportType", { defaultValue: "plain", dontReset: true })
- };
-
- const [submitParse, parseResult] = useFormSubmit(form, query.useProcessDomainListMutation(), { changedOnly: false });
-
- const [_location, setLocation] = useLocation();
-
- return (
-
-
- {parseResult.isSuccess ? (
- <>
-
-
- >
- ) : }
-
-
-
- {!parseResult.isSuccess ? (
-
- ) : }
-
-
- );
-};
\ No newline at end of file
diff --git a/web/source/settings/admin/federation/overview.js b/web/source/settings/admin/federation/overview.js
deleted file mode 100644
index c09289284c..0000000000
--- a/web/source/settings/admin/federation/overview.js
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- GoToSocial
- Copyright (C) GoToSocial Authors admin@gotosocial.org
- SPDX-License-Identifier: AGPL-3.0-or-later
-
- 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 .
-*/
-
-const React = require("react");
-const { Link, useLocation } = require("wouter");
-const { matchSorter } = require("match-sorter");
-
-const { useTextInput } = require("../../lib/form");
-
-const { TextInput } = require("../../components/form/inputs");
-
-const query = require("../../lib/query");
-
-const Loading = require("../../components/loading");
-
-module.exports = function InstanceOverview({ baseUrl }) {
- const { data: blockedInstances = [], isLoading } = query.useInstanceBlocksQuery();
-
- const [_location, setLocation] = useLocation();
-
- const filterField = useTextInput("filter");
- const filter = filterField.value;
-
- const blockedInstancesList = React.useMemo(() => {
- return Object.values(blockedInstances);
- }, [blockedInstances]);
-
- const filteredInstances = React.useMemo(() => {
- return matchSorter(blockedInstancesList, filter, { keys: ["domain"] });
- }, [blockedInstancesList, filter]);
-
- let filtered = blockedInstancesList.length - filteredInstances.length;
-
- function filterFormSubmit(e) {
- e.preventDefault();
- setLocation(`${baseUrl}/${filter}`);
- }
-
- if (isLoading) {
- return ;
- }
-
- return (
- <>
-
Federation
-
-
-
Suspended instances
-
- Suspending a domain blocks all current and future accounts on that instance. Stored content will be removed,
- and no more data is sent to the remote server.
- This extends to all subdomains as well, so blocking 'example.com' also includes 'social.example.com'.
-