[feature] Admin accounts endpoints; approve/reject sign-ups (#2826)

* update settings panels, add pending overview + approve/deny functions

* add admin accounts get, approve, reject

* send approved/rejected emails

* use signup URL

* docs!

* email

* swagger

* web linting

* fix email tests

* wee lil fixerinos

* use new paging logic for GetAccounts() series of admin endpoints, small changes to query building

* shuffle useAccountIDIn check *before* adding to query

* fix parse from toot react error

* use `netip.Addr`

* put valid slices in globals

* optimistic updates for account state

---------

Co-authored-by: kim <grufwub@gmail.com>
This commit is contained in:
tobi 2024-04-13 13:25:10 +02:00 committed by GitHub
commit 89e0cfd874
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
74 changed files with 4102 additions and 545 deletions

View file

@ -17,29 +17,25 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
const React = require("react");
const { useRoute, Link, Redirect } = require("wouter");
import React, { useEffect } from "react";
import { useRoute, Link, Redirect } from "wouter";
const { useComboBoxInput, useFileInput, useValue } = require("../../../lib/form");
const { CategorySelect } = require("../category-select");
import { useComboBoxInput, useFileInput, useValue } from "../../../lib/form";
import { CategorySelect } from "../category-select";
const useFormSubmit = require("../../../lib/form/submit").default;
const { useBaseUrl } = require("../../../lib/navigation/util");
import useFormSubmit from "../../../lib/form/submit";
import { useBaseUrl } from "../../../lib/navigation/util";
const FakeToot = require("../../../components/fake-toot");
const FormWithData = require("../../../lib/form/form-with-data").default;
const Loading = require("../../../components/loading");
const { FileInput } = require("../../../components/form/inputs");
const MutationButton = require("../../../components/form/mutation-button");
const { Error } = require("../../../components/error");
import FakeToot from "../../../components/fake-toot";
import FormWithData from "../../../lib/form/form-with-data";
import Loading from "../../../components/loading";
import { FileInput } from "../../../components/form/inputs";
import MutationButton from "../../../components/form/mutation-button";
import { Error } from "../../../components/error";
const {
useGetEmojiQuery,
useEditEmojiMutation,
useDeleteEmojiMutation,
} = require("../../../lib/query/admin/custom-emoji");
import { useGetEmojiQuery, useEditEmojiMutation, useDeleteEmojiMutation } from "../../../lib/query/admin/custom-emoji";
module.exports = function EmojiDetailRoute({ }) {
export default function EmojiDetailRoute({ }) {
const baseUrl = useBaseUrl();
let [_match, params] = useRoute(`${baseUrl}/:emojiId`);
if (params?.emojiId == undefined) {
@ -52,7 +48,7 @@ module.exports = function EmojiDetailRoute({ }) {
</div>
);
}
};
}
function EmojiDetailForm({ data: emoji }) {
const baseUrl = useBaseUrl();
@ -68,7 +64,7 @@ function EmojiDetailForm({ data: emoji }) {
const [modifyEmoji, result] = useFormSubmit(form, useEditEmojiMutation());
// Automatic submitting of category change
React.useEffect(() => {
useEffect(() => {
if (
form.category.hasChanged() &&
!form.category.state.open &&

View file

@ -17,13 +17,13 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
const React = require("react");
const { Switch, Route } = require("wouter");
import React from "react";
import { Switch, Route } from "wouter";
const EmojiOverview = require("./overview");
const EmojiDetail = require("./detail");
import EmojiOverview from "./overview";
import EmojiDetail from "./detail";
module.exports = function CustomEmoji({ baseUrl }) {
export default function CustomEmoji({ baseUrl }) {
return (
<Switch>
<Route path={`${baseUrl}/:emojiId`}>
@ -32,4 +32,4 @@ module.exports = function CustomEmoji({ baseUrl }) {
<EmojiOverview />
</Switch>
);
};
}

View file

@ -17,31 +17,26 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
const React = require("react");
import React, { useMemo, useEffect } from "react";
const {
useFileInput,
useComboBoxInput
} = require("../../../lib/form");
const useShortcode = require("./use-shortcode");
import { useFileInput, useComboBoxInput } from "../../../lib/form";
import useShortcode from "./use-shortcode";
const useFormSubmit = require("../../../lib/form/submit").default;
import useFormSubmit from "../../../lib/form/submit";
const {
TextInput, FileInput
} = require("../../../components/form/inputs");
import { TextInput, FileInput } from "../../../components/form/inputs";
const { CategorySelect } = require('../category-select');
const FakeToot = require("../../../components/fake-toot");
const MutationButton = require("../../../components/form/mutation-button");
const { useAddEmojiMutation } = require("../../../lib/query/admin/custom-emoji");
const { useInstanceV1Query } = require("../../../lib/query");
import { CategorySelect } from '../category-select';
import FakeToot from "../../../components/fake-toot";
import MutationButton from "../../../components/form/mutation-button";
import { useAddEmojiMutation } from "../../../lib/query/admin/custom-emoji";
import { useInstanceV1Query } from "../../../lib/query";
module.exports = function NewEmojiForm() {
export default function NewEmojiForm() {
const shortcode = useShortcode();
const { data: instance } = useInstanceV1Query();
const emojiMaxSize = React.useMemo(() => {
const emojiMaxSize = useMemo(() => {
return instance?.configuration?.emojis?.emoji_size_limit ?? 50 * 1024;
}, [instance]);
@ -56,8 +51,8 @@ module.exports = function NewEmojiForm() {
shortcode, image, category
}, useAddEmojiMutation());
React.useEffect(() => {
if (shortcode.value.length == 0) {
useEffect(() => {
if (shortcode.value === undefined || shortcode.value.length == 0) {
if (image.value != undefined) {
let [name, _ext] = image.value.name.split(".");
shortcode.setter(name);
@ -71,7 +66,7 @@ module.exports = function NewEmojiForm() {
/* eslint-disable-next-line react-hooks/exhaustive-deps */
}, [image.value]);
let emojiOrShortcode = `:${shortcode.value}:`;
let emojiOrShortcode;
if (image.previewValue != undefined) {
emojiOrShortcode = <img
@ -80,6 +75,10 @@ module.exports = function NewEmojiForm() {
title={`:${shortcode.value}:`}
alt={shortcode.value}
/>;
} else if (shortcode.value !== undefined && shortcode.value.length > 0) {
emojiOrShortcode = `:${shortcode.value}:`;
} else {
emojiOrShortcode = `:your_emoji_here:`;
}
return (
@ -103,10 +102,15 @@ module.exports = function NewEmojiForm() {
<CategorySelect
field={category}
children={[]}
/>
<MutationButton label="Upload emoji" result={result} />
<MutationButton
disabled={image.previewValue === undefined}
label="Upload emoji"
result={result}
/>
</form>
</div>
);
};
}

View file

@ -22,7 +22,7 @@ const { Link } = require("wouter");
const syncpipe = require("syncpipe");
const { matchSorter } = require("match-sorter");
const NewEmojiForm = require("./new-emoji");
const NewEmojiForm = require("./new-emoji").default;
const { useTextInput } = require("../../../lib/form");
const { useEmojiByCategory } = require("../category-select");