diff options
author | 2025-01-08 11:29:40 +0100 | |
---|---|---|
committer | 2025-01-08 11:29:40 +0100 | |
commit | 451803b230084d5553962c2b3e3b2a921e9545e8 (patch) | |
tree | 9fde24ef1d70d77b7545c2a62126ea19ead2fb2a /web/source | |
parent | [chore] replace statuses.updated_at column with statuses.edited_at (#3636) (diff) | |
download | gotosocial-451803b230084d5553962c2b3e3b2a921e9545e8.tar.xz |
[feature] Fetch + create domain permissions from subscriptions nightly (#3635)
* peepeepoopoo
* test domain perm subs
* swagger
* envparsing
* dries your wets
* start on docs
* finish up docs
* copy paste errors
* rename actions package
* rename force -> skipCache
* move obfuscate parse nearer to where err is checked
* make higherPrios a simple slice
* don't use receiver for permsFrom funcs
* add more context to error logs
* defer finished log
* use switch for permType instead of if/else
* thanks linter, love you <3
* validate csv headers before full read
* use bufio scanner
Diffstat (limited to 'web/source')
4 files changed, 104 insertions, 5 deletions
diff --git a/web/source/settings/components/pageable-list.tsx b/web/source/settings/components/pageable-list.tsx index 3571fb1cd..92c5e220d 100644 --- a/web/source/settings/components/pageable-list.tsx +++ b/web/source/settings/components/pageable-list.tsx @@ -30,7 +30,7 @@ export interface PageableListProps<T> { items?: T[]; itemToEntry: (_item: T) => ReactNode; isLoading: boolean; - isFetching: boolean; + isFetching?: boolean; isError: boolean; error: FetchBaseQueryError | SerializedError | undefined; emptyMessage: ReactNode; diff --git a/web/source/settings/lib/query/admin/domain-permissions/subscriptions.ts b/web/source/settings/lib/query/admin/domain-permissions/subscriptions.ts index f065aaf54..fef512a56 100644 --- a/web/source/settings/lib/query/admin/domain-permissions/subscriptions.ts +++ b/web/source/settings/lib/query/admin/domain-permissions/subscriptions.ts @@ -20,6 +20,7 @@ import { gtsApi } from "../../gts-api"; import type { + DomainPerm, DomainPermSub, DomainPermSubCreateUpdateParams, DomainPermSubSearchParams, @@ -120,6 +121,13 @@ const extended = gtsApi.injectEndpoints({ asForm: true, body: { remove_children: remove_children }, }), + }), + + testDomainPermissionSubscription: build.mutation<{ error: string } | DomainPerm[], string>({ + query: (id) => ({ + method: "POST", + url: `/api/v1/admin/domain_permission_subscriptions/${id}/test`, + }), }) }), }); @@ -154,6 +162,11 @@ const useUpdateDomainPermissionSubscriptionMutation = extended.useUpdateDomainPe */ const useRemoveDomainPermissionSubscriptionMutation = extended.useRemoveDomainPermissionSubscriptionMutation; +/** + * Test a domain permission subscription to see if data can be fetched + parsed. + */ +const useTestDomainPermissionSubscriptionMutation = extended.useTestDomainPermissionSubscriptionMutation; + export { useLazySearchDomainPermissionSubscriptionsQuery, useGetDomainPermissionSubscriptionQuery, @@ -161,4 +174,5 @@ export { useGetDomainPermissionSubscriptionsPreviewQuery, useUpdateDomainPermissionSubscriptionMutation, useRemoveDomainPermissionSubscriptionMutation, + useTestDomainPermissionSubscriptionMutation, }; diff --git a/web/source/settings/style.css b/web/source/settings/style.css index bbb8fd61c..75e7e7e3f 100644 --- a/web/source/settings/style.css +++ b/web/source/settings/style.css @@ -1426,6 +1426,18 @@ button.tab-button { } } +.domain-permission-subscription-details { + > .list > .entries > .perm-preview { + gap: 0.5rem; + } + + > .perm-issue > b > code { + background: $info-bg; + padding: 0; + } +} + + .domain-permission-subscription-title { font-size: 1.2rem; font-weight: bold; @@ -1451,7 +1463,8 @@ button.tab-button { } } -.domain-permission-subscription-remove { +.domain-permission-subscription-remove, +.domain-permission-subscription-test { gap: 1rem; } diff --git a/web/source/settings/views/moderation/domain-permissions/subscriptions/detail.tsx b/web/source/settings/views/moderation/domain-permissions/subscriptions/detail.tsx index 408d81b92..06f1582ae 100644 --- a/web/source/settings/views/moderation/domain-permissions/subscriptions/detail.tsx +++ b/web/source/settings/views/moderation/domain-permissions/subscriptions/detail.tsx @@ -17,19 +17,20 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ -import React, { useState } from "react"; +import React, { ReactNode, useState } from "react"; import { useLocation, useParams } from "wouter"; import { useBaseUrl } from "../../../../lib/navigation/util"; import BackButton from "../../../../components/back-button"; -import { useGetDomainPermissionSubscriptionQuery, useRemoveDomainPermissionSubscriptionMutation, useUpdateDomainPermissionSubscriptionMutation } from "../../../../lib/query/admin/domain-permissions/subscriptions"; +import { useGetDomainPermissionSubscriptionQuery, useRemoveDomainPermissionSubscriptionMutation, useTestDomainPermissionSubscriptionMutation, useUpdateDomainPermissionSubscriptionMutation } from "../../../../lib/query/admin/domain-permissions/subscriptions"; import { useBoolInput, useNumberInput, useTextInput } from "../../../../lib/form"; import FormWithData from "../../../../lib/form/form-with-data"; -import { DomainPermSub } from "../../../../lib/types/domain-permission"; +import { DomainPerm, DomainPermSub } from "../../../../lib/types/domain-permission"; import MutationButton from "../../../../components/form/mutation-button"; import { Checkbox, NumberInput, Select, TextInput } from "../../../../components/form/inputs"; import useFormSubmit from "../../../../lib/form/submit"; import UsernameLozenge from "../../../../components/username-lozenge"; import { urlValidator } from "../../../../lib/util/formvalidators"; +import { PageableList } from "../../../../components/pageable-list"; export default function DomainPermissionSubscriptionDetail() { const params = useParams(); @@ -56,6 +57,7 @@ function DomainPermSubForm({ data: permSub }: { data: DomainPermSub }) { <h1><BackButton to={backLocation} /> Domain Permission Subscription Detail</h1> <DomainPermSubDetails permSub={permSub} /> <UpdateDomainPermSub permSub={permSub} /> + <TestDomainPermSub permSub={permSub} /> <DeleteDomainPermSub permSub={permSub} backLocation={backLocation} /> </div> ); @@ -382,3 +384,73 @@ function DeleteDomainPermSub({ permSub, backLocation }: { permSub: DomainPermSub </form> ); } + +function TestDomainPermSub({ permSub }: { permSub: DomainPermSub }) { + const permType = permSub.permission_type; + if (!permType) { + throw "permission_type was undefined"; + } + + const [ testSub, testRes ] = useTestDomainPermissionSubscriptionMutation(); + const onSubmit = (e) => { + e.preventDefault(); + testSub(permSub.id); + }; + + // Function to map an item to a list entry. + function itemToEntry(perm: DomainPerm): ReactNode { + return ( + <span className="text-cutoff entry perm-preview"> + <strong>{ perm.domain }</strong> + { perm.public_comment && <>({ perm.public_comment })</> } + </span> + ); + } + + return ( + <> + <form + className="domain-permission-subscription-test" + onSubmit={onSubmit} + > + <h2>Test Subscription</h2> + Click the "test" button to instruct your instance to do a test + fetch and parse of the {permType} list at the subscription URI. + <br/> + If the fetch is successful, you will see a list of {permType}s + (or {permType} drafts) that *would* be created by this subscription, + along with the public comment for each {permType} (if applicable). + <br/> + The test does not actually create those {permType}s in your database. + <MutationButton + disabled={false} + label={"Test"} + result={testRes} + /> + </form> + { testRes.data && "error" in testRes.data + ? <div className="info perm-issue"> + <i className="fa fa-fw fa-exclamation-circle" aria-hidden="true"></i> + <b> + The following issue was encountered when doing a fetch + parse: + <br/><code>{ testRes.data.error }</code> + <br/>This may be due to a temporary outage at the remote URL, + or you may wish to check your subscription settings and test again. + </b> + </div> + : <> + { testRes.data && `${testRes.data?.length} ${permType}s would be created by this subscription:`} + <PageableList + isLoading={testRes.isLoading} + isSuccess={testRes.isSuccess} + items={testRes.data} + itemToEntry={itemToEntry} + isError={testRes.isError} + error={testRes.error} + emptyMessage={<b>No entries!</b>} + /> + </> + } + </> + ); +} |