| 
									
										
										
										
											2023-02-03 12:07:40 +01:00
										 |  |  | /* | 
					
						
							|  |  |  | 	GoToSocial | 
					
						
							| 
									
										
										
										
											2023-03-12 18:49:06 +01:00
										 |  |  | 	Copyright (C) GoToSocial Authors admin@gotosocial.org | 
					
						
							|  |  |  | 	SPDX-License-Identifier: AGPL-3.0-or-later | 
					
						
							| 
									
										
										
										
											2023-02-03 12:07:40 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	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/>.
 | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-17 12:46:06 +02:00
										 |  |  | import React from "react"; | 
					
						
							| 
									
										
										
										
											2023-02-03 12:07:40 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-17 12:46:06 +02:00
										 |  |  | import { memo, useMemo, useCallback, useEffect } from "react"; | 
					
						
							| 
									
										
										
										
											2023-02-03 12:07:40 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-17 12:46:06 +02:00
										 |  |  | import { isValidDomainPermission, hasBetterScope } from "../../lib/util/domain-permission"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import { | 
					
						
							| 
									
										
										
										
											2023-02-03 12:07:40 +01:00
										 |  |  | 	useTextInput, | 
					
						
							|  |  |  | 	useBoolInput, | 
					
						
							|  |  |  | 	useRadioInput, | 
					
						
							| 
									
										
										
										
											2023-10-17 12:46:06 +02:00
										 |  |  | 	useCheckListInput, | 
					
						
							|  |  |  | } from "../../lib/form"; | 
					
						
							| 
									
										
										
										
											2023-02-03 12:07:40 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-17 12:46:06 +02:00
										 |  |  | import { | 
					
						
							|  |  |  | 	Select, | 
					
						
							| 
									
										
										
										
											2023-02-03 12:07:40 +01:00
										 |  |  | 	TextArea, | 
					
						
							| 
									
										
										
										
											2023-10-17 12:46:06 +02:00
										 |  |  | 	RadioGroup, | 
					
						
							| 
									
										
										
										
											2023-02-03 12:07:40 +01:00
										 |  |  | 	Checkbox, | 
					
						
							| 
									
										
										
										
											2023-10-17 12:46:06 +02:00
										 |  |  | 	TextInput, | 
					
						
							|  |  |  | } from "../../components/form/inputs"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import useFormSubmit from "../../lib/form/submit"; | 
					
						
							| 
									
										
										
										
											2023-02-03 12:07:40 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-17 12:46:06 +02:00
										 |  |  | import CheckList from "../../components/check-list"; | 
					
						
							|  |  |  | import MutationButton from "../../components/form/mutation-button"; | 
					
						
							|  |  |  | import FormWithData from "../../lib/form/form-with-data"; | 
					
						
							| 
									
										
										
										
											2023-02-03 12:07:40 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-17 12:46:06 +02:00
										 |  |  | 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) { | 
					
						
							| 
									
										
										
										
											2023-02-03 12:07:40 +01:00
										 |  |  | 		return ( | 
					
						
							|  |  |  | 			<div className="without-border"> | 
					
						
							|  |  |  | 				<FormWithData | 
					
						
							| 
									
										
										
										
											2023-10-17 12:46:06 +02:00
										 |  |  | 					dataQuery={permType.value == "allow" | 
					
						
							|  |  |  | 						? useDomainAllowsQuery | 
					
						
							|  |  |  | 						: useDomainBlocksQuery | 
					
						
							|  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2023-02-03 12:07:40 +01:00
										 |  |  | 					DataForm={ImportList} | 
					
						
							| 
									
										
										
										
											2023-10-17 12:46:06 +02:00
										 |  |  | 					{...{ list, permType }} | 
					
						
							| 
									
										
										
										
											2023-02-03 12:07:40 +01:00
										 |  |  | 				/> | 
					
						
							|  |  |  | 			</div> | 
					
						
							|  |  |  | 		); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | ); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-17 12:46:06 +02:00
										 |  |  | export interface ImportListProps { | 
					
						
							|  |  |  | 	list: Array<DomainPerm>, | 
					
						
							|  |  |  | 	data: MappedDomainPerms, | 
					
						
							|  |  |  | 	permType: RadioFormInputHook, | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function ImportList({ list, data: domainPerms, permType }: ImportListProps) { | 
					
						
							|  |  |  | 	const hasComment = useMemo(() => { | 
					
						
							| 
									
										
										
										
											2023-02-03 12:07:40 +01:00
										 |  |  | 		let hasPublic = false; | 
					
						
							|  |  |  | 		let hasPrivate = false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		list.some((entry) => { | 
					
						
							| 
									
										
										
										
											2023-10-17 12:46:06 +02:00
										 |  |  | 			if (entry.public_comment) { | 
					
						
							| 
									
										
										
										
											2023-02-03 12:07:40 +01:00
										 |  |  | 				hasPublic = true; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-17 12:46:06 +02:00
										 |  |  | 			if (entry.private_comment) { | 
					
						
							| 
									
										
										
										
											2023-02-03 12:07:40 +01:00
										 |  |  | 				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 = { | 
					
						
							| 
									
										
										
										
											2023-10-17 12:46:06 +02:00
										 |  |  | 		domains: useCheckListInput("domains", { entries: list }), // DomainPerm is actually also a Checkable.
 | 
					
						
							| 
									
										
										
										
											2023-02-03 12:07:40 +01:00
										 |  |  | 		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" | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}), | 
					
						
							| 
									
										
										
										
											2023-10-17 12:46:06 +02:00
										 |  |  | 		permType: permType, | 
					
						
							| 
									
										
										
										
											2023-02-03 12:07:40 +01:00
										 |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-17 12:46:06 +02:00
										 |  |  | 	const [importDomains, importResult] = useFormSubmit(form, useImportDomainPermsMutation(), { changedOnly: false }); | 
					
						
							| 
									
										
										
										
											2023-02-03 12:07:40 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return ( | 
					
						
							|  |  |  | 		<> | 
					
						
							| 
									
										
										
										
											2023-10-17 12:46:06 +02:00
										 |  |  | 			<form | 
					
						
							|  |  |  | 				onSubmit={importDomains} | 
					
						
							|  |  |  | 				className="domain-perm-import-list" | 
					
						
							|  |  |  | 			> | 
					
						
							| 
									
										
										
										
											2023-02-03 12:07:40 +01:00
										 |  |  | 				<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> | 
					
						
							|  |  |  | 						</> | 
					
						
							|  |  |  | 					} /> | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-11 10:49:44 +01:00
										 |  |  | 				<div className="checkbox-list-wrapper"> | 
					
						
							|  |  |  | 					<DomainCheckList | 
					
						
							|  |  |  | 						field={form.domains} | 
					
						
							| 
									
										
										
										
											2023-10-17 12:46:06 +02:00
										 |  |  | 						domainPerms={domainPerms} | 
					
						
							|  |  |  | 						commentType={showComment.value as "public_comment" | "private_comment"} | 
					
						
							|  |  |  | 						permType={form.permType} | 
					
						
							| 
									
										
										
										
											2023-03-11 10:49:44 +01:00
										 |  |  | 					/> | 
					
						
							|  |  |  | 				</div> | 
					
						
							| 
									
										
										
										
											2023-02-03 12:07:40 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				<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" | 
					
						
							|  |  |  | 				/> | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-17 12:46:06 +02:00
										 |  |  | 				<MutationButton | 
					
						
							|  |  |  | 					label="Import" | 
					
						
							|  |  |  | 					disabled={false} | 
					
						
							|  |  |  | 					result={importResult} | 
					
						
							|  |  |  | 				/> | 
					
						
							| 
									
										
										
										
											2023-02-03 12:07:40 +01:00
										 |  |  | 			</form> | 
					
						
							|  |  |  | 		</> | 
					
						
							|  |  |  | 	); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-17 12:46:06 +02:00
										 |  |  | 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) => { | 
					
						
							| 
									
										
										
										
											2023-02-03 12:07:40 +01:00
										 |  |  | 		return { | 
					
						
							|  |  |  | 			comment: entry[commentType], | 
					
						
							| 
									
										
										
										
											2023-10-17 12:46:06 +02:00
										 |  |  | 			alreadyExists: entry.domain in domainPerms, | 
					
						
							|  |  |  | 			permType: permType, | 
					
						
							| 
									
										
										
										
											2023-02-03 12:07:40 +01:00
										 |  |  | 		}; | 
					
						
							| 
									
										
										
										
											2023-10-17 12:46:06 +02:00
										 |  |  | 	}, [domainPerms, commentType, permType]); | 
					
						
							| 
									
										
										
										
											2023-02-03 12:07:40 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-17 12:46:06 +02:00
										 |  |  | 	const entriesWithSuggestions = useMemo(() => { | 
					
						
							|  |  |  | 		const fieldValue = (field.value ?? {}) as { [k: string]: DomainPerm; }; | 
					
						
							|  |  |  | 		return Object.values(fieldValue).filter((entry) => entry.suggest); | 
					
						
							|  |  |  | 	}, [field.value]); | 
					
						
							| 
									
										
										
										
											2023-02-03 12:07:40 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return ( | 
					
						
							|  |  |  | 		<> | 
					
						
							|  |  |  | 			<CheckList | 
					
						
							| 
									
										
										
										
											2023-10-17 12:46:06 +02:00
										 |  |  | 				field={field as ChecklistInputHook} | 
					
						
							| 
									
										
										
										
											2023-02-03 12:07:40 +01:00
										 |  |  | 				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} | 
					
						
							|  |  |  | 			/> | 
					
						
							|  |  |  | 		</> | 
					
						
							|  |  |  | 	); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-17 12:46:06 +02:00
										 |  |  | interface UpdateHintProps { | 
					
						
							|  |  |  | 	entries, | 
					
						
							|  |  |  | 	updateEntry, | 
					
						
							|  |  |  | 	updateMultiple, | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const UpdateHint = memo( | 
					
						
							|  |  |  | 	function UpdateHint({ entries, updateEntry, updateMultiple }: UpdateHintProps) { | 
					
						
							| 
									
										
										
										
											2023-02-03 12:07:40 +01:00
										 |  |  | 		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> | 
					
						
							|  |  |  | 		); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | ); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-17 12:46:06 +02:00
										 |  |  | interface UpdateableEntryProps { | 
					
						
							|  |  |  | 	entry, | 
					
						
							|  |  |  | 	updateEntry, | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const UpdateableEntry = memo( | 
					
						
							|  |  |  | 	function UpdateableEntry({ entry, updateEntry }: UpdateableEntryProps) { | 
					
						
							| 
									
										
										
										
											2023-02-03 12:07:40 +01:00
										 |  |  | 		return ( | 
					
						
							|  |  |  | 			<> | 
					
						
							|  |  |  | 				<span className="text-cutoff">{entry.domain}</span> | 
					
						
							| 
									
										
										
										
											2023-02-06 09:19:56 +01:00
										 |  |  | 				<i className="fa fa-long-arrow-right" aria-hidden="true"></i> | 
					
						
							| 
									
										
										
										
											2023-02-03 12:07:40 +01:00
										 |  |  | 				<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"; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-17 12:46:06 +02:00
										 |  |  | interface DomainEntryProps { | 
					
						
							|  |  |  | 	entry; | 
					
						
							|  |  |  | 	onChange; | 
					
						
							|  |  |  | 	extraProps: { | 
					
						
							|  |  |  | 		alreadyExists: boolean; | 
					
						
							|  |  |  | 		comment: string; | 
					
						
							|  |  |  | 		permType: RadioFormInputHook; | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function DomainEntry({ entry, onChange, extraProps: { alreadyExists, comment, permType } }: DomainEntryProps) { | 
					
						
							| 
									
										
										
										
											2023-02-03 12:07:40 +01:00
										 |  |  | 	const domainField = useTextInput("domain", { | 
					
						
							|  |  |  | 		defaultValue: entry.domain, | 
					
						
							|  |  |  | 		showValidation: entry.checked, | 
					
						
							|  |  |  | 		initValidation: domainValidationError(entry.valid), | 
					
						
							| 
									
										
										
										
											2023-10-17 12:46:06 +02:00
										 |  |  | 		validator: (value) => domainValidationError(isValidDomainPermission(value)) | 
					
						
							| 
									
										
										
										
											2023-02-03 12:07:40 +01:00
										 |  |  | 	}); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-17 12:46:06 +02:00
										 |  |  | 	useEffect(() => { | 
					
						
							| 
									
										
										
										
											2023-02-03 12:07:40 +01:00
										 |  |  | 		if (entry.valid != domainField.valid) { | 
					
						
							|  |  |  | 			onChange({ valid: domainField.valid }); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}, [onChange, entry.valid, domainField.valid]); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-17 12:46:06 +02:00
										 |  |  | 	useEffect(() => { | 
					
						
							| 
									
										
										
										
											2023-02-03 12:07:40 +01:00
										 |  |  | 		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]); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-17 12:46:06 +02:00
										 |  |  | 	useEffect(() => { | 
					
						
							|  |  |  | 		onChange({ suggest: hasBetterScope(domainField.value ?? "") }); | 
					
						
							| 
									
										
										
										
											2023-02-03 12:07:40 +01:00
										 |  |  | 		// 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 ( | 
					
						
							|  |  |  | 		<> | 
					
						
							| 
									
										
										
										
											2023-03-11 10:49:44 +01:00
										 |  |  | 			<div className="domain-input"> | 
					
						
							|  |  |  | 				<TextInput | 
					
						
							|  |  |  | 					field={domainField} | 
					
						
							|  |  |  | 					onChange={(e) => { | 
					
						
							|  |  |  | 						domainField.onChange(e); | 
					
						
							|  |  |  | 						onChange({ domain: e.target.value, checked: true }); | 
					
						
							|  |  |  | 					}} | 
					
						
							|  |  |  | 				/> | 
					
						
							|  |  |  | 				<span id="icon" onClick={clickIcon}> | 
					
						
							| 
									
										
										
										
											2023-10-17 12:46:06 +02:00
										 |  |  | 					<DomainEntryIcon | 
					
						
							|  |  |  | 						alreadyExists={alreadyExists} | 
					
						
							|  |  |  | 						suggestion={entry.suggest} | 
					
						
							|  |  |  | 						permTypeString={permType.value?? ""} | 
					
						
							|  |  |  | 					/> | 
					
						
							| 
									
										
										
										
											2023-03-11 10:49:44 +01:00
										 |  |  | 				</span> | 
					
						
							|  |  |  | 			</div> | 
					
						
							| 
									
										
										
										
											2023-02-03 12:07:40 +01:00
										 |  |  | 			<p>{comment}</p> | 
					
						
							|  |  |  | 		</> | 
					
						
							|  |  |  | 	); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-17 12:46:06 +02:00
										 |  |  | interface DomainEntryIconProps { | 
					
						
							|  |  |  | 	alreadyExists: boolean; | 
					
						
							|  |  |  | 	suggestion: string; | 
					
						
							|  |  |  | 	permTypeString: string;  | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function DomainEntryIcon({ alreadyExists, suggestion, permTypeString }: DomainEntryIconProps) { | 
					
						
							| 
									
										
										
										
											2023-02-03 12:07:40 +01:00
										 |  |  | 	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) { | 
					
						
							| 
									
										
										
										
											2023-10-17 12:46:06 +02:00
										 |  |  | 		icon = "fa-history permission-already-exists"; | 
					
						
							|  |  |  | 		text = `Domain ${permTypeString} already exists.`; | 
					
						
							| 
									
										
										
										
											2023-02-03 12:07:40 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!icon) { | 
					
						
							|  |  |  | 		return null; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return ( | 
					
						
							|  |  |  | 		<> | 
					
						
							| 
									
										
										
										
											2023-03-11 10:49:44 +01:00
										 |  |  | 			<i className={`fa fa-fw ${icon}`} aria-hidden="true" title={text}></i> | 
					
						
							| 
									
										
										
										
											2023-02-03 12:07:40 +01:00
										 |  |  | 			<span className="sr-only">{text}</span> | 
					
						
							|  |  |  | 		</> | 
					
						
							|  |  |  | 	); | 
					
						
							|  |  |  | } |