mirror of
https://github.com/Myzel394/kleckrelay-website.git
synced 2025-06-19 15:55:26 +02:00
improvements
This commit is contained in:
parent
c0e48cb62a
commit
64a8ae3096
@ -10,6 +10,7 @@ export default function ErrorSnack({message}: ErrorSnackProps): ReactElement {
|
|||||||
const [open, setOpen] = useState<boolean>(true)
|
const [open, setOpen] = useState<boolean>(true)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
setOpen(false)
|
||||||
setOpen(Boolean(message))
|
setOpen(Boolean(message))
|
||||||
}, [message])
|
}, [message])
|
||||||
|
|
||||||
|
@ -12,13 +12,14 @@ export default function SuccessSnack({
|
|||||||
const [open, setOpen] = useState<boolean>(true)
|
const [open, setOpen] = useState<boolean>(true)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
setOpen(false)
|
||||||
setOpen(Boolean(message))
|
setOpen(Boolean(message))
|
||||||
}, [message])
|
}, [message])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Snackbar
|
<Snackbar
|
||||||
open={open}
|
open={open}
|
||||||
autoHideDuration={5000}
|
autoHideDuration={2000}
|
||||||
onClose={() => setOpen(false)}
|
onClose={() => setOpen(false)}
|
||||||
>
|
>
|
||||||
<Alert severity="success" variant="filled">
|
<Alert severity="success" variant="filled">
|
||||||
|
@ -240,11 +240,12 @@ export default function AliasNotesForm({
|
|||||||
<IconButton
|
<IconButton
|
||||||
edge="end"
|
edge="end"
|
||||||
aria-label="delete"
|
aria-label="delete"
|
||||||
onClick={() =>
|
onClick={async () => {
|
||||||
arrayHelpers.remove(
|
arrayHelpers.remove(
|
||||||
index,
|
index,
|
||||||
)
|
)
|
||||||
}
|
await formik.submitForm()
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<TiDelete />
|
<TiDelete />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
@ -260,7 +261,9 @@ export default function AliasNotesForm({
|
|||||||
</Grid>
|
</Grid>
|
||||||
</form>
|
</form>
|
||||||
<ErrorSnack message={formik.errors.detail} />
|
<ErrorSnack message={formik.errors.detail} />
|
||||||
<SuccessSnack message={isSuccess && "Update Alias notes!"} />
|
<SuccessSnack
|
||||||
|
message={isSuccess && "Updated notes successfully!"}
|
||||||
|
/>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,68 @@
|
|||||||
|
import {ReactElement, useEffect, useState} from "react"
|
||||||
|
import {AxiosError} from "axios"
|
||||||
|
|
||||||
|
import {Switch} from "@mui/material"
|
||||||
|
import {useMutation} from "@tanstack/react-query"
|
||||||
|
|
||||||
|
import {Alias} from "~/server-types"
|
||||||
|
import {UpdateAliasData, updateAlias} from "~/apis"
|
||||||
|
import {parseFastAPIError} from "~/utils"
|
||||||
|
import {ErrorSnack, SuccessSnack} from "~/components"
|
||||||
|
|
||||||
|
export interface ChangeAliasActivationStatusSwitchProps {
|
||||||
|
id: string
|
||||||
|
isActive: boolean
|
||||||
|
|
||||||
|
onChanged: () => void
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function ChangeAliasActivationStatusSwitch({
|
||||||
|
id,
|
||||||
|
isActive,
|
||||||
|
onChanged,
|
||||||
|
}: ChangeAliasActivationStatusSwitchProps): ReactElement {
|
||||||
|
const [isActiveUIState, setIsActiveUIState] = useState<boolean>(true)
|
||||||
|
|
||||||
|
const [successMessage, setSuccessMessage] = useState<string>("")
|
||||||
|
const [errorMessage, setErrorMessage] = useState<string>("")
|
||||||
|
|
||||||
|
const {mutateAsync, isLoading} = useMutation<
|
||||||
|
Alias,
|
||||||
|
AxiosError,
|
||||||
|
UpdateAliasData
|
||||||
|
>(values => updateAlias(id, values), {
|
||||||
|
onSuccess: onChanged,
|
||||||
|
onError: error =>
|
||||||
|
setErrorMessage(parseFastAPIError(error).detail as string),
|
||||||
|
})
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setIsActiveUIState(isActive)
|
||||||
|
}, [isActive])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Switch
|
||||||
|
checked={isActiveUIState}
|
||||||
|
disabled={isActiveUIState === null || isLoading}
|
||||||
|
onChange={async () => {
|
||||||
|
setIsActiveUIState(!isActiveUIState)
|
||||||
|
|
||||||
|
try {
|
||||||
|
await mutateAsync({
|
||||||
|
isActive: !isActiveUIState,
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!isActiveUIState) {
|
||||||
|
setSuccessMessage("Alias activated successfully!")
|
||||||
|
} else {
|
||||||
|
setSuccessMessage("Alias deactivated successfully!")
|
||||||
|
}
|
||||||
|
} catch {}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<SuccessSnack message={successMessage} />
|
||||||
|
<ErrorSnack message={errorMessage} />
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
@ -1,23 +1,18 @@
|
|||||||
import {ReactElement, useContext, useState} from "react"
|
import {ReactElement, useContext} from "react"
|
||||||
import {useParams} from "react-router-dom"
|
import {useParams} from "react-router-dom"
|
||||||
import {AxiosError} from "axios"
|
import {AxiosError} from "axios"
|
||||||
|
|
||||||
import {useMutation, useQuery} from "@tanstack/react-query"
|
import {useQuery} from "@tanstack/react-query"
|
||||||
import {Grid, Switch, Typography} from "@mui/material"
|
import {Grid, Typography} from "@mui/material"
|
||||||
|
|
||||||
import {UpdateAliasData, getAlias, updateAlias} from "~/apis"
|
import {getAlias} from "~/apis"
|
||||||
import {Alias, DecryptedAlias} from "~/server-types"
|
import {Alias, DecryptedAlias} from "~/server-types"
|
||||||
import {
|
import {AliasTypeIndicator, QueryResult, SimplePage} from "~/components"
|
||||||
AliasTypeIndicator,
|
import {decryptAliasNotes} from "~/utils"
|
||||||
ErrorSnack,
|
|
||||||
QueryResult,
|
|
||||||
SimplePage,
|
|
||||||
SuccessSnack,
|
|
||||||
} from "~/components"
|
|
||||||
import {decryptAliasNotes, parseFastAPIError} from "~/utils"
|
|
||||||
import AliasNotesForm from "~/route-widgets/AliasDetailRoute/AliasNotesForm"
|
import AliasNotesForm from "~/route-widgets/AliasDetailRoute/AliasNotesForm"
|
||||||
import AliasPreferencesForm from "~/route-widgets/AliasDetailRoute/AliasPreferencesForm"
|
import AliasPreferencesForm from "~/route-widgets/AliasDetailRoute/AliasPreferencesForm"
|
||||||
import AuthContext from "~/AuthContext/AuthContext"
|
import AuthContext from "~/AuthContext/AuthContext"
|
||||||
|
import ChangeAliasActivationStatusSwitch from "~/route-widgets/AliasDetailRoute/ChangeAliasActivationStatusSwitch"
|
||||||
import DecryptionPasswordMissingAlert from "~/components/DecryptionPasswordMissingAlert"
|
import DecryptionPasswordMissingAlert from "~/components/DecryptionPasswordMissingAlert"
|
||||||
|
|
||||||
export default function AliasDetailRoute(): ReactElement {
|
export default function AliasDetailRoute(): ReactElement {
|
||||||
@ -25,10 +20,6 @@ export default function AliasDetailRoute(): ReactElement {
|
|||||||
const {user, _decryptUsingMasterPassword} = useContext(AuthContext)
|
const {user, _decryptUsingMasterPassword} = useContext(AuthContext)
|
||||||
const address = atob(params.addressInBase64 as string)
|
const address = atob(params.addressInBase64 as string)
|
||||||
|
|
||||||
const [successMessage, setSuccessMessage] = useState<string>("")
|
|
||||||
const [errorMessage, setErrorMessage] = useState<string>("")
|
|
||||||
|
|
||||||
const [isActive, setIsActive] = useState<boolean>(true)
|
|
||||||
const query = useQuery<Alias | DecryptedAlias, AxiosError>(
|
const query = useQuery<Alias | DecryptedAlias, AxiosError>(
|
||||||
["get_alias", params.addressInBase64],
|
["get_alias", params.addressInBase64],
|
||||||
async () => {
|
async () => {
|
||||||
@ -41,121 +32,87 @@ export default function AliasDetailRoute(): ReactElement {
|
|||||||
return getAlias(address)
|
return getAlias(address)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
onSuccess: alias => setIsActive(alias.isActive),
|
|
||||||
},
|
|
||||||
)
|
|
||||||
const {mutateAsync} = useMutation<Alias, AxiosError, UpdateAliasData>(
|
|
||||||
values => updateAlias(query.data!.id, values),
|
|
||||||
{
|
|
||||||
onSuccess: () => query.refetch(),
|
|
||||||
onError: error =>
|
|
||||||
setErrorMessage(parseFastAPIError(error).detail as string),
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<SimplePage title="Alias Details">
|
||||||
<SimplePage title="Alias Details">
|
<QueryResult<Alias | DecryptedAlias> query={query}>
|
||||||
<QueryResult<Alias | DecryptedAlias> query={query}>
|
{alias => (
|
||||||
{alias => (
|
<Grid container spacing={4}>
|
||||||
<Grid container spacing={4}>
|
<Grid item>
|
||||||
<Grid item>
|
<Grid
|
||||||
<Grid
|
container
|
||||||
container
|
spacing={1}
|
||||||
spacing={1}
|
direction="row"
|
||||||
direction="row"
|
alignItems="center"
|
||||||
alignItems="center"
|
>
|
||||||
>
|
<Grid item>
|
||||||
<Grid item>
|
<AliasTypeIndicator type={alias.type} />
|
||||||
<AliasTypeIndicator type={alias.type} />
|
|
||||||
</Grid>
|
|
||||||
<Grid item>
|
|
||||||
<Typography variant="subtitle1">
|
|
||||||
{address}
|
|
||||||
</Typography>
|
|
||||||
</Grid>
|
|
||||||
<Grid item>
|
|
||||||
<Switch
|
|
||||||
checked={isActive}
|
|
||||||
onChange={async () => {
|
|
||||||
setIsActive(!isActive)
|
|
||||||
|
|
||||||
try {
|
|
||||||
await mutateAsync({
|
|
||||||
isActive,
|
|
||||||
})
|
|
||||||
|
|
||||||
if (isActive) {
|
|
||||||
setSuccessMessage(
|
|
||||||
"Alias activated successfully!",
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
setSuccessMessage(
|
|
||||||
"Alias deactivated successfully!",
|
|
||||||
)
|
|
||||||
}
|
|
||||||
} catch {}
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
<Grid item>
|
||||||
<Grid item width="100%">
|
<Typography variant="subtitle1">
|
||||||
<Grid container direction="column" spacing={4}>
|
{address}
|
||||||
<Grid item>
|
</Typography>
|
||||||
<Typography variant="h6" component="h3">
|
|
||||||
Notes
|
|
||||||
</Typography>
|
|
||||||
</Grid>
|
|
||||||
<Grid item>
|
|
||||||
{user?.encryptedPassword &&
|
|
||||||
(alias as DecryptedAlias).notes ? (
|
|
||||||
<AliasNotesForm
|
|
||||||
id={alias.id}
|
|
||||||
notes={
|
|
||||||
(alias as DecryptedAlias)
|
|
||||||
.notes
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<DecryptionPasswordMissingAlert />
|
|
||||||
)}
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
<Grid item>
|
||||||
<Grid item>
|
<ChangeAliasActivationStatusSwitch
|
||||||
<Grid container spacing={4}>
|
id={alias.id}
|
||||||
<Grid item>
|
isActive={alias.isActive}
|
||||||
<Typography variant="h6" component="h3">
|
onChanged={query.refetch}
|
||||||
Settings
|
/>
|
||||||
</Typography>
|
|
||||||
</Grid>
|
|
||||||
<Grid item>
|
|
||||||
<Typography variant="body1">
|
|
||||||
These settings apply to this alias
|
|
||||||
only. You can either set a value
|
|
||||||
manually or refer to your defaults
|
|
||||||
settings. Note that this does change
|
|
||||||
in behavior. When you set a value to
|
|
||||||
refer to your default setting, the
|
|
||||||
alias will always use the latest
|
|
||||||
value. So when you change your
|
|
||||||
default setting, the alias will
|
|
||||||
automatically use the new value.
|
|
||||||
</Typography>
|
|
||||||
</Grid>
|
|
||||||
<Grid item>
|
|
||||||
<AliasPreferencesForm alias={alias} />
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
)}
|
<Grid item width="100%">
|
||||||
</QueryResult>
|
<Grid container direction="column" spacing={4}>
|
||||||
</SimplePage>
|
<Grid item>
|
||||||
<SuccessSnack message={successMessage} />
|
<Typography variant="h6" component="h3">
|
||||||
<ErrorSnack message={errorMessage} />
|
Notes
|
||||||
</>
|
</Typography>
|
||||||
|
</Grid>
|
||||||
|
<Grid item>
|
||||||
|
{user?.encryptedPassword &&
|
||||||
|
(alias as DecryptedAlias).notes ? (
|
||||||
|
<AliasNotesForm
|
||||||
|
id={alias.id}
|
||||||
|
notes={
|
||||||
|
(alias as DecryptedAlias).notes
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<DecryptionPasswordMissingAlert />
|
||||||
|
)}
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
<Grid item>
|
||||||
|
<Grid container spacing={4}>
|
||||||
|
<Grid item>
|
||||||
|
<Typography variant="h6" component="h3">
|
||||||
|
Settings
|
||||||
|
</Typography>
|
||||||
|
</Grid>
|
||||||
|
<Grid item>
|
||||||
|
<Typography variant="body1">
|
||||||
|
These settings apply to this alias only.
|
||||||
|
You can either set a value manually or
|
||||||
|
refer to your defaults settings. Note
|
||||||
|
that this does change in behavior. When
|
||||||
|
you set a value to refer to your default
|
||||||
|
setting, the alias will always use the
|
||||||
|
latest value. So when you change your
|
||||||
|
default setting, the alias will
|
||||||
|
automatically use the new value.
|
||||||
|
</Typography>
|
||||||
|
</Grid>
|
||||||
|
<Grid item>
|
||||||
|
<AliasPreferencesForm alias={alias} />
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
)}
|
||||||
|
</QueryResult>
|
||||||
|
</SimplePage>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user