diff options
Diffstat (limited to 'web/source/settings/admin/domain-permissions')
7 files changed, 0 insertions, 1211 deletions
| diff --git a/web/source/settings/admin/domain-permissions/detail.tsx b/web/source/settings/admin/domain-permissions/detail.tsx deleted file mode 100644 index f74802666..000000000 --- a/web/source/settings/admin/domain-permissions/detail.tsx +++ /dev/null @@ -1,254 +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 <http://www.gnu.org/licenses/>. -*/ - -import React from "react"; - -import { useMemo } from "react"; -import { useLocation } from "wouter"; - -import { useTextInput, useBoolInput } from "../../lib/form"; - -import useFormSubmit from "../../lib/form/submit"; - -import { TextInput, Checkbox, TextArea } from "../../components/form/inputs"; - -import Loading from "../../components/loading"; -import BackButton from "../../components/back-button"; -import MutationButton from "../../components/form/mutation-button"; - -import { useDomainAllowsQuery, useDomainBlocksQuery } from "../../lib/query/admin/domain-permissions/get"; -import { useAddDomainAllowMutation, useAddDomainBlockMutation, useRemoveDomainAllowMutation, useRemoveDomainBlockMutation } from "../../lib/query/admin/domain-permissions/update"; -import { DomainPerm, PermType } from "../../lib/types/domain-permission"; -import { NoArg } from "../../lib/types/query"; -import { Error } from "../../components/error"; - -export interface DomainPermDetailProps { -	baseUrl: string; -	permType: PermType; -	domain: string; -} - -export default function DomainPermDetail({ baseUrl, permType, domain }: DomainPermDetailProps) { -	const { data: domainBlocks = {}, isLoading: isLoadingDomainBlocks } = useDomainBlocksQuery(NoArg, { skip: permType !== "block" }); -	const { data: domainAllows = {}, isLoading: isLoadingDomainAllows } = useDomainAllowsQuery(NoArg, { skip: permType !== "allow" }); - -	let isLoading; -	switch (permType) { -		case "block": -			isLoading = isLoadingDomainBlocks; -			break; -		case "allow": -			isLoading = isLoadingDomainAllows; -			break; -		default: -			throw "perm type unknown"; -	} - -	if (domain == "view") { -		// Retrieve domain from form field submission. -		domain = (new URL(document.location.toString())).searchParams.get("domain")?? "unknown"; -	} - -	if (domain == "unknown") { -		throw "unknown domain"; -	} - -	// Normalize / decode domain (it may be URL-encoded). -	domain = decodeURIComponent(domain); - -	// Check if we already have a perm of the desired type for this domain. -	const existingPerm: DomainPerm | undefined = useMemo(() => { -		if (permType == "block") { -			return domainBlocks[domain]; -		} else { -			return domainAllows[domain]; -		} -	}, [domainBlocks, domainAllows, domain, permType]); - -	let infoContent: React.JSX.Element; - -	if (isLoading) { -		infoContent = <Loading />; -	} else if (existingPerm == undefined) { -		infoContent = <span>No stored {permType} yet, you can add one below:</span>; -	} else { -		infoContent = ( -			<div className="info"> -				<i className="fa fa-fw fa-exclamation-triangle" aria-hidden="true"></i> -				<b>Editing domain permissions isn't implemented yet, <a href="https://github.com/superseriousbusiness/gotosocial/issues/1198" target="_blank" rel="noopener noreferrer">check here for progress</a></b> -			</div> -		); -	} - -	return ( -		<div> -			<h1 className="text-cutoff"><BackButton to={baseUrl} /> Domain {permType} for: <span title={domain}>{domain}</span></h1> -			{infoContent} -			<DomainPermForm -				defaultDomain={domain} -				perm={existingPerm} -				permType={permType} -				baseUrl={baseUrl} -			/> -		</div> -	); -} - -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 ( -		<form onSubmit={verifyUrlThenSubmit}> -			<TextInput -				field={form.domain} -				label="Domain" -				placeholder="example.com" -				{...disabledForm} -			/> - -			<Checkbox -				field={form.obfuscate} -				label="Obfuscate domain in public lists" -				{...disabledForm} -			/> - -			<TextArea -				field={form.commentPrivate} -				label="Private comment" -				rows={3} -				{...disabledForm} -			/> - -			<TextArea -				field={form.commentPublic} -				label="Public comment" -				rows={3} -				{...disabledForm} -			/> - -			<div className="action-buttons row"> -				<MutationButton -					label={permTypeUpper} -					result={submitFormResult} -					showError={false} -					{...disabledForm} -				/> - -				{ -					isExistingPerm && -					<MutationButton -						type="button" -						onClick={() => removeTrigger(perm.id?? "")} -						label="Remove" -						result={removeResult} -						className="button danger" -						showError={false} -						disabled={!isExistingPerm} -					/> -				} -			</div> - -			<> -				{addResult.error && <Error error={addResult.error} />} -				{removeResult.error && <Error error={removeResult.error} />} -			</> - -		</form> -	); -} diff --git a/web/source/settings/admin/domain-permissions/export-format-table.jsx b/web/source/settings/admin/domain-permissions/export-format-table.jsx deleted file mode 100644 index 7fcffa348..000000000 --- a/web/source/settings/admin/domain-permissions/export-format-table.jsx +++ /dev/null @@ -1,65 +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 <http://www.gnu.org/licenses/>. -*/ - -const React = require("react"); - -module.exports = function ExportFormatTable() { -	return ( -		<div className="export-format-table-wrapper without-border"> -			<table className="export-format-table"> -				<thead> -					<tr> -						<th rowSpan={2} /> -						<th colSpan={2}>Includes</th> -						<th colSpan={2}>Importable by</th> -					</tr> -					<tr> -						<th>Domain</th> -						<th>Public comment</th> -						<th>GoToSocial</th> -						<th>Mastodon</th> -					</tr> -				</thead> -				<tbody> -					<Format name="Text" info={[true, false, true, false]} /> -					<Format name="JSON" info={[true, true, true, false]} /> -					<Format name="CSV" info={[true, true, true, true]} /> -				</tbody> -			</table> -		</div> -	); -}; - -function Format({ name, info }) { -	return ( -		<tr> -			<td><b>{name}</b></td> -			{info.map((b, key) => <td key={key} className="bool">{bool(b)}</td>)} -		</tr> -	); -} - -function bool(val) { -	return ( -		<> -			<i className={`fa fa-${val ? "check" : "times"}`} aria-hidden="true"></i> -			<span className="sr-only">{val ? "Yes" : "No"}</span> -		</> -	); -}
\ No newline at end of file diff --git a/web/source/settings/admin/domain-permissions/form.tsx b/web/source/settings/admin/domain-permissions/form.tsx deleted file mode 100644 index 57502d6d9..000000000 --- a/web/source/settings/admin/domain-permissions/form.tsx +++ /dev/null @@ -1,153 +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 <http://www.gnu.org/licenses/>. -*/ - -import React from "react"; - -import { useEffect } from "react"; - -import { useExportDomainListMutation } from "../../lib/query/admin/domain-permissions/export"; -import useFormSubmit from "../../lib/form/submit"; - -import { -	RadioGroup, -	TextArea, -	Select, -} from "../../components/form/inputs"; - -import MutationButton from "../../components/form/mutation-button"; - -import { Error } from "../../components/error"; -import ExportFormatTable from "./export-format-table"; - -import type { -	FormSubmitFunction, -	FormSubmitResult, -	RadioFormInputHook, -	TextFormInputHook, -} from "../../lib/form/types"; - -export interface ImportExportFormProps { -	form: { -		domains: TextFormInputHook; -		exportType: TextFormInputHook; -		permType: RadioFormInputHook; -	}; -	submitParse: FormSubmitFunction; -	parseResult: FormSubmitResult; -}  - -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) { -			const res = read.target?.result; -			if (typeof res === "string") { -				form.domains.value = res; -				submitParse(); -			} -		}; -		reader.readAsText(e.target.files[0]); -	} - -	useEffect(() => { -		if (exportResult.isSuccess) { -			form.domains.setter(exportResult.data); -		} -		/* eslint-disable-next-line react-hooks/exhaustive-deps */ -	}, [exportResult]); - -	return ( -		<> -			<h1>Import / Export domain permissions</h1> -			<p>This page can be used to import and export lists of domain permissions.</p> -			<p>Exports can be done in various formats, with varying functionality and support in other software.</p> -			<p>Imports will automatically detect what format is being processed.</p> -			<ExportFormatTable /> -			<div className="import-export"> -				<TextArea -					field={form.domains} -					label="Domains" -					placeholder={`google.com\nfacebook.com`} -					rows={8} -				/> - -				<RadioGroup -					field={form.permType} -				/> - -				<div className="button-grid"> -					<MutationButton -						label="Import" -						type="button" -						onClick={() => submitParse()} -						result={parseResult} -						showError={false} -						disabled={form.permType.value === undefined || form.permType.value.length === 0} -					/> -					<label className={`button with-icon${form.permType.value === undefined || form.permType.value.length === 0 ? " disabled" : ""}`}> -						<i className="fa fa-fw " aria-hidden="true" /> -						Import file -						<input -							type="file" -							className="hidden" -							onChange={fileChanged} -							accept="application/json,text/plain,text/csv" -							disabled={form.permType.value === undefined || form.permType.value.length === 0} -						/> -					</label> -					<b /> {/* grid filler */} -					<MutationButton -						label="Export" -						type="button" -						onClick={() => submitExport("export")} -						result={exportResult} showError={false} -						disabled={form.permType.value === undefined || form.permType.value.length === 0} -					/> -					<MutationButton -						label="Export to file" -						wrapperClassName="export-file-button" -						type="button" -						onClick={() => submitExport("export-file")} -						result={exportResult} -						showError={false} -						disabled={form.permType.value === undefined || form.permType.value.length === 0} -					/> -					<div className="export-file"> -						<span> -							as -						</span> -						<Select -							field={form.exportType} -							options={<> -								<option value="plain">Text</option> -								<option value="json">JSON</option> -								<option value="csv">CSV</option> -							</>} -						/> -					</div> -				</div> - -				{parseResult.error && <Error error={parseResult.error} />} -				{exportResult.error && <Error error={exportResult.error} />} -			</div> -		</> -	); -} diff --git a/web/source/settings/admin/domain-permissions/import-export.tsx b/web/source/settings/admin/domain-permissions/import-export.tsx deleted file mode 100644 index 871bca131..000000000 --- a/web/source/settings/admin/domain-permissions/import-export.tsx +++ /dev/null @@ -1,90 +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 <http://www.gnu.org/licenses/>. -*/ - -import React from "react"; - -import { Switch, Route, Redirect, useLocation } from "wouter"; - -import { useProcessDomainPermissionsMutation } from "../../lib/query/admin/domain-permissions/process"; - -import { useTextInput, useRadioInput } from "../../lib/form"; - -import useFormSubmit from "../../lib/form/submit"; - -import { ProcessImport } from "./process"; -import ImportExportForm from "./form"; - -export default function ImportExport({ baseUrl }) { -	const form = { -		domains: useTextInput("domains"), -		exportType: useTextInput("exportType", { defaultValue: "plain", dontReset: true }), -		permType: useRadioInput("permType", {  -			options: { -				block: "Domain blocks", -				allow: "Domain allows", -			} -		}) -	}; - -	const [submitParse, parseResult] = useFormSubmit(form, useProcessDomainPermissionsMutation(), { changedOnly: false }); - -	const [_location, setLocation] = useLocation(); - -	return ( -		<Switch> -			<Route path={`${baseUrl}/process`}> -				{ -					parseResult.isSuccess  -						? ( -							<> -								<h1> -									<span -										className="button" -										onClick={() => { -											parseResult.reset(); -											setLocation(baseUrl); -										}} -									> -										< back -									</span> -									  Confirm import of domain {form.permType.value}s: -								</h1> -								<ProcessImport -									list={parseResult.data} -									permType={form.permType} -								/> -							</> -						) -						: <Redirect to={baseUrl} /> -				} -			</Route> -			<Route> -				{ -					parseResult.isSuccess -						? <Redirect to={`${baseUrl}/process`} /> -						: <ImportExportForm -							form={form} -							submitParse={submitParse} -							parseResult={parseResult} -						/> -				} -			</Route> -		</Switch> -	); -} diff --git a/web/source/settings/admin/domain-permissions/index.tsx b/web/source/settings/admin/domain-permissions/index.tsx deleted file mode 100644 index 7d790cfc8..000000000 --- a/web/source/settings/admin/domain-permissions/index.tsx +++ /dev/null @@ -1,49 +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 <http://www.gnu.org/licenses/>. -*/ - -import React from "react"; -import { Switch, Route } from "wouter"; - -import DomainPermissionsOverview from "./overview"; -import { PermType } from "../../lib/types/domain-permission"; -import DomainPermDetail from "./detail"; - -export default function DomainPermissions({ baseUrl }: { baseUrl: string }) { -	return ( -		<Switch> -			<Route path="/settings/admin/domain-permissions/:permType/:domain"> -				{params => ( -					<DomainPermDetail -						permType={params.permType as PermType} -						baseUrl={baseUrl} -						domain={params.domain} -					/> -				)} -			</Route> -			<Route path="/settings/admin/domain-permissions/:permType"> -				{params => ( -					<DomainPermissionsOverview -						permType={params.permType as PermType} -						baseUrl={baseUrl} -					/> -				)} -			</Route> -		</Switch> -	); -} diff --git a/web/source/settings/admin/domain-permissions/overview.tsx b/web/source/settings/admin/domain-permissions/overview.tsx deleted file mode 100644 index bdfd214bc..000000000 --- a/web/source/settings/admin/domain-permissions/overview.tsx +++ /dev/null @@ -1,198 +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 <http://www.gnu.org/licenses/>. -*/ - -import React from "react"; - -import { useMemo } from "react"; -import { Link, useLocation } from "wouter"; -import { matchSorter } from "match-sorter"; - -import { useTextInput } from "../../lib/form"; - -import { TextInput } from "../../components/form/inputs"; - -import Loading from "../../components/loading"; -import { useDomainAllowsQuery, useDomainBlocksQuery } from "../../lib/query/admin/domain-permissions/get"; -import type { MappedDomainPerms, PermType } from "../../lib/types/domain-permission"; -import { NoArg } from "../../lib/types/query"; - -export interface DomainPermissionsOverviewProps { -	// Params injected by -	// the wouter router. -	permType: PermType; -	baseUrl: string, -} - -export default function DomainPermissionsOverview({ permType, baseUrl }: DomainPermissionsOverviewProps) {	 -	if (permType !== "block" && permType !== "allow") { -		throw "unrecognized perm type " + permType; -	} - -	// Uppercase first letter of given permType. -	const permTypeUpper = useMemo(() => { -		return permType.charAt(0).toUpperCase() + permType.slice(1);  -	}, [permType]); - -	// Fetch / wait for desired perms to load. -	const { data: blocks, isLoading: isLoadingBlocks } = useDomainBlocksQuery(NoArg, { skip: permType !== "block" }); -	const { data: allows, isLoading: isLoadingAllows } = useDomainAllowsQuery(NoArg, { skip: permType !== "allow" }); -	 -	let data: MappedDomainPerms | undefined; -	let isLoading: boolean; - -	if (permType == "block") { -		data = blocks; -		isLoading = isLoadingBlocks; -	} else { -		data = allows; -		isLoading = isLoadingAllows; -	} - -	if (isLoading || data === undefined) { -		return <Loading />; -	} -	 -	return ( -		<div> -			<h1>Domain {permTypeUpper}s</h1> -			{ permType == "block" ? <BlockHelperText/> : <AllowHelperText/> } -			<DomainPermsList -				data={data} -				baseUrl={baseUrl} -				permType={permType} -				permTypeUpper={permTypeUpper} -			/> -			<Link to="/settings/admin/domain-permissions/import-export"> -				<a>Or use the bulk import/export interface</a> -			</Link> -		</div> -	); -} - -interface DomainPermsListProps { -	data: MappedDomainPerms; -	baseUrl: string; -	permType: PermType; -	permTypeUpper: string; -} - -function DomainPermsList({ data, baseUrl, permType, permTypeUpper }: DomainPermsListProps) { -	// Format perms into a list. -	const perms = useMemo(() => { -		return Object.values(data); -	}, [data]); - -	const [_location, setLocation] = useLocation(); -	const filterField = useTextInput("filter"); -	 -	function filterFormSubmit(e) { -		e.preventDefault(); -		setLocation(`${baseUrl}/${filter}`); -	} -	 -	const filter = filterField.value ?? ""; -	const filteredPerms = useMemo(() => { -		return matchSorter(perms, filter, { keys: ["domain"] }); -	}, [perms, filter]); -	const filtered = perms.length - filteredPerms.length; -	 -	const filterInfo = ( -		<span> -			{perms.length} {permType}ed domain{perms.length != 1 ? "s" : ""} {filtered > 0 && `(${filtered} filtered by search)`} -		</span> -	); - -	const entries = filteredPerms.map((entry) => { -		return ( -			<Link key={entry.domain} to={`${baseUrl}/${entry.domain}`}> -				<a className="entry nounderline"> -					<span id="domain">{entry.domain}</span> -					<span id="date">{new Date(entry.created_at ?? "").toLocaleString()}</span> -				</a> -			</Link> -		); -	}); - -	return ( -		<div className="domain-permissions-list"> -			<form className="filter" role="search" onSubmit={filterFormSubmit}> -				<TextInput -					field={filterField} -					placeholder="example.org" -					label={`Search or add domain ${permType}`} -				/> -				<Link to={`${baseUrl}/${filter}`}> -					<a className="button">{permTypeUpper} {filter}</a> -				</Link> -			</form> -			<div> -				{filterInfo} -				<div className="list"> -					<div className="entries scrolling"> -						{entries} -					</div> -				</div> -			</div> -		</div> -	); -} - -function BlockHelperText() { -	return ( -		<p> -			Blocking a domain blocks interaction between your instance, and all current and future accounts on -			instance(s) running on the blocked domain. 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 blocks 'social.example.com'. -			<br/> -			<a -				href="https://docs.gotosocial.org/en/latest/admin/domain_blocks/" -				target="_blank" -				className="docslink" -				rel="noreferrer" -			> -				Learn more about domain blocks (opens in a new tab) -			</a> -			<br/> -		</p> -	); -} - -function AllowHelperText() { -	return ( -		<p> -			Allowing a domain explicitly allows instance(s) running on that domain to interact with your instance. -			If you're running in allowlist mode, this is how you "allow" instances through. -			If you're running in blocklist mode (the default federation mode), you can use explicit domain allows -			to override domain blocks. In blocklist mode, explicitly allowed instances will be able to interact with -			your instance regardless of any domain blocks in place.  This extends to all subdomains as well, so allowing -			'example.com' also allows 'social.example.com'. This is useful when you're importing a block list but -			there are some domains on the list you don't want to block: just create an explicit allow for those domains -			before importing the list. -			<br/> -			<a -				href="https://docs.gotosocial.org/en/latest/admin/federation_modes/" -				target="_blank" -				className="docslink" -				rel="noreferrer" -			> -				Learn more about federation modes (opens in a new tab) -			</a> -		</p> -	); -} diff --git a/web/source/settings/admin/domain-permissions/process.tsx b/web/source/settings/admin/domain-permissions/process.tsx deleted file mode 100644 index bb9411b9d..000000000 --- a/web/source/settings/admin/domain-permissions/process.tsx +++ /dev/null @@ -1,402 +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 <http://www.gnu.org/licenses/>. -*/ - -import React from "react"; - -import { memo, useMemo, useCallback, useEffect } from "react"; - -import { isValidDomainPermission, hasBetterScope } from "../../lib/util/domain-permission"; - -import { -	useTextInput, -	useBoolInput, -	useRadioInput, -	useCheckListInput, -} from "../../lib/form"; - -import { -	Select, -	TextArea, -	RadioGroup, -	Checkbox, -	TextInput, -} from "../../components/form/inputs"; - -import useFormSubmit from "../../lib/form/submit"; - -import CheckList from "../../components/check-list"; -import MutationButton from "../../components/form/mutation-button"; -import FormWithData from "../../lib/form/form-with-data"; - -import { useImportDomainPermsMutation } from "../../lib/query/admin/domain-permissions/import"; -import { -	useDomainAllowsQuery, -	useDomainBlocksQuery -} from "../../lib/query/admin/domain-permissions/get"; - -import type { DomainPerm, MappedDomainPerms } from "../../lib/types/domain-permission"; -import type { ChecklistInputHook, RadioFormInputHook } from "../../lib/form/types"; - -export interface ProcessImportProps { -	list: DomainPerm[], -	permType: RadioFormInputHook, -} - -export const ProcessImport = memo( -	function ProcessImport({ list, permType }: ProcessImportProps) { -		return ( -			<div className="without-border"> -				<FormWithData -					dataQuery={permType.value == "allow" -						? useDomainAllowsQuery -						: useDomainBlocksQuery -					} -					DataForm={ImportList} -					{...{ list, permType }} -				/> -			</div> -		); -	} -); - -export interface ImportListProps { -	list: Array<DomainPerm>, -	data: MappedDomainPerms, -	permType: RadioFormInputHook, -} - -function ImportList({ list, data: domainPerms, permType }: ImportListProps) { -	const hasComment = useMemo(() => { -		let hasPublic = false; -		let hasPrivate = false; - -		list.some((entry) => { -			if (entry.public_comment) { -				hasPublic = true; -			} - -			if (entry.private_comment) { -				hasPrivate = true; -			} - -			return hasPublic && hasPrivate; -		}); - -		if (hasPublic && hasPrivate) { -			return { both: true }; -		} else if (hasPublic) { -			return { type: "public_comment" }; -		} else if (hasPrivate) { -			return { type: "private_comment" }; -		} else { -			return {}; -		} -	}, [list]); - -	const showComment = useTextInput("showComment", { defaultValue: hasComment.type ?? "public_comment" }); - -	const form = { -		domains: useCheckListInput("domains", { entries: list }), // DomainPerm is actually also a Checkable. -		obfuscate: useBoolInput("obfuscate"), -		privateComment: useTextInput("private_comment", { -			defaultValue: `Imported on ${new Date().toLocaleString()}` -		}), -		privateCommentBehavior: useRadioInput("private_comment_behavior", { -			defaultValue: "append", -			options: { -				append: "Append to", -				replace: "Replace" -			} -		}), -		publicComment: useTextInput("public_comment"), -		publicCommentBehavior: useRadioInput("public_comment_behavior", { -			defaultValue: "append", -			options: { -				append: "Append to", -				replace: "Replace" -			} -		}), -		permType: permType, -	}; - -	const [importDomains, importResult] = useFormSubmit(form, useImportDomainPermsMutation(), { changedOnly: false }); - -	return ( -		<> -			<form -				onSubmit={importDomains} -				className="domain-perm-import-list" -			> -				<span>{list.length} domain{list.length != 1 ? "s" : ""} in this list</span> - -				{hasComment.both && -					<Select field={showComment} options={ -						<> -							<option value="public_comment">Show public comments</option> -							<option value="private_comment">Show private comments</option> -						</> -					} /> -				} - -				<div className="checkbox-list-wrapper"> -					<DomainCheckList -						field={form.domains} -						domainPerms={domainPerms} -						commentType={showComment.value as "public_comment" | "private_comment"} -						permType={form.permType} -					/> -				</div> - -				<TextArea -					field={form.privateComment} -					label="Private comment" -					rows={3} -				/> -				<RadioGroup -					field={form.privateCommentBehavior} -					label="imported private comment" -				/> - -				<TextArea -					field={form.publicComment} -					label="Public comment" -					rows={3} -				/> -				<RadioGroup -					field={form.publicCommentBehavior} -					label="imported public comment" -				/> - -				<Checkbox -					field={form.obfuscate} -					label="Obfuscate domains in public lists" -				/> - -				<MutationButton -					label="Import" -					disabled={false} -					result={importResult} -				/> -			</form> -		</> -	); -} - -interface DomainCheckListProps { -	field: ChecklistInputHook, -	domainPerms: MappedDomainPerms, -	commentType: "public_comment" | "private_comment", -	permType: RadioFormInputHook, -} - -function DomainCheckList({ field, domainPerms, commentType, permType }: DomainCheckListProps) { -	const getExtraProps = useCallback((entry: DomainPerm) => { -		return { -			comment: entry[commentType], -			alreadyExists: entry.domain in domainPerms, -			permType: permType, -		}; -	}, [domainPerms, commentType, permType]); - -	const entriesWithSuggestions = useMemo(() => { -		const fieldValue = (field.value ?? {}) as { [k: string]: DomainPerm; }; -		return Object.values(fieldValue).filter((entry) => entry.suggest); -	}, [field.value]); - -	return ( -		<> -			<CheckList -				field={field as ChecklistInputHook} -				header={<> -					<b>Domain</b> -					<b> -						{commentType == "public_comment" && "Public comment"} -						{commentType == "private_comment" && "Private comment"} -					</b> -				</>} -				EntryComponent={DomainEntry} -				getExtraProps={getExtraProps} -			/> -			<UpdateHint -				entries={entriesWithSuggestions} -				updateEntry={field.onChange} -				updateMultiple={field.updateMultiple} -			/> -		</> -	); -} - -interface UpdateHintProps { -	entries, -	updateEntry, -	updateMultiple, -} - -const UpdateHint = memo( -	function UpdateHint({ entries, updateEntry, updateMultiple }: UpdateHintProps) { -		if (entries.length == 0) { -			return null; -		} - -		function changeAll() { -			updateMultiple( -				entries.map((entry) => [entry.key, { domain: entry.suggest, suggest: null }]) -			); -		} - -		return ( -			<div className="update-hints"> -				<p> -					{entries.length} {entries.length == 1 ? "entry uses" : "entries use"} a specific subdomain, -					which you might want to change to the main domain, as that includes all it's (future) subdomains. -				</p> -				<div className="hints"> -					{entries.map((entry) => ( -						<UpdateableEntry key={entry.key} entry={entry} updateEntry={updateEntry} /> -					))} -				</div> -				{entries.length > 0 && <a onClick={changeAll}>change all</a>} -			</div> -		); -	} -); - -interface UpdateableEntryProps { -	entry, -	updateEntry, -} - -const UpdateableEntry = memo( -	function UpdateableEntry({ entry, updateEntry }: UpdateableEntryProps) { -		return ( -			<> -				<span className="text-cutoff">{entry.domain}</span> -				<i className="fa fa-long-arrow-right" aria-hidden="true"></i> -				<span>{entry.suggest}</span> -				<a role="button" onClick={() => -					updateEntry(entry.key, { domain: entry.suggest, suggest: null }) -				}>change</a> -			</> -		); -	} -); - -function domainValidationError(isValid) { -	return isValid ? "" : "Invalid domain"; -} - -interface DomainEntryProps { -	entry; -	onChange; -	extraProps: { -		alreadyExists: boolean; -		comment: string; -		permType: RadioFormInputHook; -	}; -} - -function DomainEntry({ entry, onChange, extraProps: { alreadyExists, comment, permType } }: DomainEntryProps) { -	const domainField = useTextInput("domain", { -		defaultValue: entry.domain, -		showValidation: entry.checked, -		initValidation: domainValidationError(entry.valid), -		validator: (value) => domainValidationError(isValidDomainPermission(value)) -	}); - -	useEffect(() => { -		if (entry.valid != domainField.valid) { -			onChange({ valid: domainField.valid }); -		} -	}, [onChange, entry.valid, domainField.valid]); - -	useEffect(() => { -		if (entry.domain != domainField.value) { -			domainField.setter(entry.domain); -		} -		// domainField.setter is enough, eslint wants domainField -		// eslint-disable-next-line react-hooks/exhaustive-deps -	}, [entry.domain, domainField.setter]); - -	useEffect(() => { -		onChange({ suggest: hasBetterScope(domainField.value ?? "") }); -		// only need this update if it's the entry.checked that updated, not onChange -		// eslint-disable-next-line react-hooks/exhaustive-deps -	}, [domainField.value]); - -	function clickIcon(e) { -		if (entry.suggest) { -			e.stopPropagation(); -			e.preventDefault(); -			domainField.setter(entry.suggest); -			onChange({ domain: entry.suggest, checked: true }); -		} -	} - -	return ( -		<> -			<div className="domain-input"> -				<TextInput -					field={domainField} -					onChange={(e) => { -						domainField.onChange(e); -						onChange({ domain: e.target.value, checked: true }); -					}} -				/> -				<span id="icon" onClick={clickIcon}> -					<DomainEntryIcon -						alreadyExists={alreadyExists} -						suggestion={entry.suggest} -						permTypeString={permType.value?? ""} -					/> -				</span> -			</div> -			<p>{comment}</p> -		</> -	); -} - -interface DomainEntryIconProps { -	alreadyExists: boolean; -	suggestion: string; -	permTypeString: string;  -} - -function DomainEntryIcon({ alreadyExists, suggestion, permTypeString }: DomainEntryIconProps) { -	let icon; -	let text; - -	if (suggestion) { -		icon = "fa-info-circle suggest-changes"; -		text = `Entry targets a specific subdomain, consider changing it to '${suggestion}'.`; -	} else if (alreadyExists) { -		icon = "fa-history permission-already-exists"; -		text = `Domain ${permTypeString} already exists.`; -	} - -	if (!icon) { -		return null; -	} - -	return ( -		<> -			<i className={`fa fa-fw ${icon}`} aria-hidden="true" title={text}></i> -			<span className="sr-only">{text}</span> -		</> -	); -}
\ No newline at end of file | 
