diff --git a/web/source/.eslintrc.js b/web/source/.eslintrc.js index 81a2c39f9..0d30f742c 100644 --- a/web/source/.eslintrc.js +++ b/web/source/.eslintrc.js @@ -22,6 +22,7 @@ module.exports = { "extends": ["@joepie91/eslint-config/react"], "plugins": ["license-header"], "rules": { - "license-header/header": ["error", __dirname + "/.license-header.js"] + "license-header/header": ["error", __dirname + "/.license-header.js"], + "no-console": 'error' } }; \ No newline at end of file diff --git a/web/source/package.json b/web/source/package.json index 9e7951620..4f7221eb1 100644 --- a/web/source/package.json +++ b/web/source/package.json @@ -14,6 +14,7 @@ "@reduxjs/toolkit": "^1.8.6", "ariakit": "^2.0.0-next.41", "bluebird": "^3.7.2", + "get-by-dot": "^1.0.2", "is-valid-domain": "^0.1.6", "js-file-download": "^0.4.12", "langs": "^2.0.0", diff --git a/web/source/settings/admin/emoji/local/detail.js b/web/source/settings/admin/emoji/local/detail.js index cecd36869..8fcb5510c 100644 --- a/web/source/settings/admin/emoji/local/detail.js +++ b/web/source/settings/admin/emoji/local/detail.js @@ -54,7 +54,7 @@ module.exports = function EmojiDetailRoute() { function EmojiDetailForm({ data: emoji }) { const form = { id: useValue("id", emoji.id), - category: useComboBoxInput("category", { defaultValue: emoji.category }), + category: useComboBoxInput("category", { source: emoji }), image: useFileInput("image", { withPreview: true, maxSize: 50 * 1024 // TODO: get from instance api diff --git a/web/source/settings/admin/federation/detail.js b/web/source/settings/admin/federation/detail.js index ecace90cd..ea9109720 100644 --- a/web/source/settings/admin/federation/detail.js +++ b/web/source/settings/admin/federation/detail.js @@ -19,7 +19,7 @@ "use strict"; const React = require("react"); -const { useRoute, Redirect } = require("wouter"); +const { useRoute, Redirect, useLocation } = require("wouter"); const query = require("../../lib/query"); @@ -69,12 +69,12 @@ module.exports = function InstanceDetail({ baseUrl }) {

Federation settings for: {domain}

{infoContent} - +
); }; -function DomainBlockForm({ defaultDomain, block = {} }) { +function DomainBlockForm({ defaultDomain, block = {}, baseUrl }) { const isExistingBlock = block.domain != undefined; const disabledForm = isExistingBlock @@ -85,18 +85,31 @@ function DomainBlockForm({ defaultDomain, block = {} }) { : {}; const form = { - domain: useTextInput("domain", { defaultValue: block.domain ?? defaultDomain }), - obfuscate: useBoolInput("obfuscate", { defaultValue: block.obfuscate }), - commentPrivate: useTextInput("private_comment", { defaultValue: block.private_comment }), - commentPublic: useTextInput("public_comment", { defaultValue: block.public_comment }) + 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 ( -
+

Import / Export suspended domains

diff --git a/web/source/settings/admin/federation/import-export/index.jsx b/web/source/settings/admin/federation/import-export/index.jsx index 3039b98f3..ca55296f8 100644 --- a/web/source/settings/admin/federation/import-export/index.jsx +++ b/web/source/settings/admin/federation/import-export/index.jsx @@ -40,7 +40,7 @@ module.exports = function ImportExport() { exportType: useTextInput("exportType", { defaultValue: "plain", dontReset: true }) }; - const [submitParse, parseResult] = useFormSubmit(form, query.useProcessDomainListMutation()); + const [submitParse, parseResult] = useFormSubmit(form, query.useProcessDomainListMutation(), { changedOnly: false }); const [_location, setLocation] = useLocation(); diff --git a/web/source/settings/admin/federation/import-export/process.jsx b/web/source/settings/admin/federation/import-export/process.jsx index 0b2d10099..6b9d98f01 100644 --- a/web/source/settings/admin/federation/import-export/process.jsx +++ b/web/source/settings/admin/federation/import-export/process.jsx @@ -234,7 +234,7 @@ const UpdateableEntry = React.memo( return ( <> {entry.domain} - + {entry.suggest} updateEntry(entry.key, { domain: entry.suggest, suggest: null }) diff --git a/web/source/settings/admin/settings.js b/web/source/settings/admin/settings.js index c0a9eabbe..fa0085946 100644 --- a/web/source/settings/admin/settings.js +++ b/web/source/settings/admin/settings.js @@ -49,14 +49,17 @@ module.exports = function AdminSettings() { function AdminSettingsForm({ data: instance }) { const form = { - title: useTextInput("title", { defaultValue: instance.title }), + title: useTextInput("title", { + source: instance, + validator: (val) => val.length <= 40 ? "" : "Instance title must be 40 characters or less" + }), thumbnail: useFileInput("thumbnail", { withPreview: true }), - thumbnailDesc: useTextInput("thumbnail_description", { defaultValue: instance.thumbnail_description }), - shortDesc: useTextInput("short_description", { defaultValue: instance.short_description }), - description: useTextInput("description", { defaultValue: instance.description }), - contactUser: useTextInput("contact_username", { defaultValue: instance.contact_account?.username }), - contactEmail: useTextInput("contact_email", { defaultValue: instance.email }), - terms: useTextInput("terms", { defaultValue: instance.terms }) + thumbnailDesc: useTextInput("thumbnail_description", { source: instance }), + shortDesc: useTextInput("short_description", { source: instance }), + description: useTextInput("description", { source: instance }), + contactUser: useTextInput("contact_username", { source: instance, valueSelector: (s) => s.contact_account?.username }), + contactEmail: useTextInput("contact_email", { source: instance, valueSelector: (s) => s.email }), + terms: useTextInput("terms", { source: instance }) }; const [submitForm, result] = useFormSubmit(form, query.useUpdateInstanceMutation()); diff --git a/web/source/settings/components/form/inputs.jsx b/web/source/settings/components/form/inputs.jsx index 19386b6f2..8694d7b73 100644 --- a/web/source/settings/components/form/inputs.jsx +++ b/web/source/settings/components/form/inputs.jsx @@ -22,7 +22,6 @@ const React = require("react"); function TextInput({ label, field, ...inputProps }) { const { onChange, value, ref } = field; - console.log(field.name, field.valid, field.value); return (
@@ -93,13 +92,13 @@ function Checkbox({ label, field, ...inputProps }) { ); } -function Select({ label, field, options, ...inputProps }) { +function Select({ label, field, options, children, ...inputProps }) { const { onChange, value, ref } = field; return (