mirror of
https://github.com/BrenBroZAYT/gameyfin.git
synced 2026-06-13 16:40:01 +00:00
Fix #635
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
import {Card, Dropdown, DropdownItem, DropdownMenu, DropdownTrigger, useDisclosure} from "@heroui/react";
|
||||
import {DotsThreeVertical} from "@phosphor-icons/react";
|
||||
import {useAuth} from "Frontend/util/auth";
|
||||
import {useEffect, useState} from "react";
|
||||
import {MessageEndpoint, PasswordResetEndpoint, UserEndpoint} from "Frontend/generated/endpoints";
|
||||
import {AvatarEndpoint} from "Frontend/endpoints/endpoints";
|
||||
@@ -20,7 +19,6 @@ export function UserManagementCard({user}: { user: UserInfoDto }) {
|
||||
const [disabledKeys, setDisabledKeys] = useState<string[]>([]);
|
||||
const [dropdownItems, setDropdownItems] = useState<any[]>([]);
|
||||
const [passwordResetToken, setPasswordResetToken] = useState<TokenDto>();
|
||||
const auth = useAuth();
|
||||
|
||||
useEffect(() => {
|
||||
setUserEnabled(user.enabled);
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
import React, {useEffect, useState} from "react";
|
||||
import {addToast, Button, Input, Modal, ModalBody, ModalContent, ModalFooter, ModalHeader} from "@heroui/react";
|
||||
import {RegistrationEndpoint, UserEndpoint} from "Frontend/generated/endpoints";
|
||||
import {addToast, Button, Modal, ModalBody, ModalContent, ModalFooter, ModalHeader, Snippet} from "@heroui/react";
|
||||
import {MessageEndpoint, RegistrationEndpoint, UserEndpoint} from "Frontend/generated/endpoints";
|
||||
import TokenDto from "Frontend/generated/org/gameyfin/app/shared/token/TokenDto";
|
||||
import {Form, Formik, FormikErrors} from "formik";
|
||||
import Input from "Frontend/components/general/input/Input";
|
||||
import * as Yup from "yup";
|
||||
|
||||
interface InviteUserModalProps {
|
||||
isOpen: boolean;
|
||||
@@ -8,56 +12,88 @@ interface InviteUserModalProps {
|
||||
}
|
||||
|
||||
export default function InviteUserModal({isOpen, onOpenChange}: InviteUserModalProps) {
|
||||
const [email, setEmail] = useState<string | null>();
|
||||
const [error, setError] = useState<string | null>();
|
||||
const [token, setToken] = useState<TokenDto | null>(null);
|
||||
const [isMessageServiceEnabled, setIsMessageServiceEnabled] = useState<boolean>(false);
|
||||
|
||||
useEffect(() => {
|
||||
setEmail(null);
|
||||
setError(null);
|
||||
}, []);
|
||||
setToken(null);
|
||||
MessageEndpoint.isEnabled().then(enabled => {
|
||||
setIsMessageServiceEnabled(enabled);
|
||||
});
|
||||
}, [isOpen]);
|
||||
|
||||
async function inviteUser(onClose: () => void) {
|
||||
async function inviteUser(email: string, setErrors: (errors: FormikErrors<any>) => void, onClose: () => void) {
|
||||
if (!email) return;
|
||||
|
||||
if (await UserEndpoint.existsByMail(email)) {
|
||||
setError("User with this email already exists");
|
||||
setErrors({email: "User with this email already exists"});
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await RegistrationEndpoint.createInvitation(email);
|
||||
addToast({
|
||||
title: "Invitation sent",
|
||||
description: "The user will receive an email with further instructions shortly.",
|
||||
color: "success"
|
||||
});
|
||||
onClose();
|
||||
} catch (e) {
|
||||
setError("Failed to create invitation");
|
||||
if (!isMessageServiceEnabled) {
|
||||
let token = await RegistrationEndpoint.createInvitation(email);
|
||||
setToken(token);
|
||||
return;
|
||||
}
|
||||
|
||||
await RegistrationEndpoint.createInvitation(email);
|
||||
addToast({
|
||||
title: "Invitation sent",
|
||||
description: "The user will receive an email with further instructions shortly.",
|
||||
color: "success"
|
||||
});
|
||||
onClose();
|
||||
}
|
||||
|
||||
return (
|
||||
<Modal isOpen={isOpen} onOpenChange={onOpenChange} backdrop="opaque" size="lg">
|
||||
<Modal isOpen={isOpen} onOpenChange={onOpenChange} backdrop="opaque" size="4xl">
|
||||
<ModalContent>
|
||||
{(onClose) => (
|
||||
<>
|
||||
<ModalHeader className="flex flex-col gap-1">Invite a new user</ModalHeader>
|
||||
<ModalBody>
|
||||
<p>Enter the email address of the user you want to invite:</p>
|
||||
<Input errorMessage={error} onChange={(e) => setEmail(e.target.value)} type="email"/>
|
||||
{error && <small className="text-danger">{error}</small>}
|
||||
</ModalBody>
|
||||
<ModalFooter>
|
||||
<Button variant="light" onPress={onClose}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button color="success" onPress={() => inviteUser(onClose)}
|
||||
isDisabled={email === null || email === undefined || email.length < 1}>
|
||||
Send invitation
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
</>
|
||||
<Formik
|
||||
initialValues={{email: ""}}
|
||||
isInitialValid={false}
|
||||
validationSchema={Yup.object({
|
||||
email: Yup.string()
|
||||
.email("Invalid email address")
|
||||
.required("Email is required")
|
||||
})}
|
||||
onSubmit={async (values: any, {setErrors}) => {
|
||||
await inviteUser(values.email, setErrors, onClose);
|
||||
}}
|
||||
>
|
||||
{(formik) => (
|
||||
<Form>
|
||||
<ModalHeader className="flex flex-col gap-1">Invite a new user</ModalHeader>
|
||||
<ModalBody>
|
||||
<p>Enter the email address of the user you want to invite:</p>
|
||||
<Input label="E-Mail" name="email" type="email"/>
|
||||
|
||||
{token && (
|
||||
<div className="flex flex-col gap-2">
|
||||
<p>The user can accept the invitation using the following link:</p>
|
||||
<Snippet symbol="">
|
||||
{`${document.baseURI}accept-invitation?token=${token.secret}`}
|
||||
</Snippet>
|
||||
</div>
|
||||
)}
|
||||
</ModalBody>
|
||||
<ModalFooter>
|
||||
<Button variant="light" onPress={onClose}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button color="success"
|
||||
type="submit"
|
||||
isLoading={formik.isSubmitting}
|
||||
isDisabled={!formik.isValid || token !== null}>
|
||||
{isMessageServiceEnabled ?
|
||||
<p>Send invitation</p> :
|
||||
<p>Generate invitation link</p>
|
||||
}
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
</Form>
|
||||
)}
|
||||
</Formik>
|
||||
)}
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
|
||||
Reference in New Issue
Block a user