mirror of
https://github.com/Myzel394/kleckrelay-website.git
synced 2025-06-19 07:55:25 +02:00
created ReservedAliasesRoute.tsx
This commit is contained in:
parent
dead769e88
commit
dac14af539
@ -280,6 +280,22 @@
|
||||
"title": "Log out",
|
||||
"description": "We are logging you out..."
|
||||
},
|
||||
"ReservedAliasesRoute": {
|
||||
"title": "Reserved Aliases",
|
||||
"pageActions": {
|
||||
"search": {
|
||||
"label": "Search",
|
||||
"placeholder": "Search for aliases"
|
||||
}
|
||||
},
|
||||
"actions": {
|
||||
"create": {
|
||||
"label": "Create new Reserved Alias"
|
||||
}
|
||||
},
|
||||
"userAmount_one": "Forwards to one user",
|
||||
"userAmount_other": "Forwards to {{count}} users"
|
||||
},
|
||||
"AdminRoute": {
|
||||
"title": "Site configuration",
|
||||
"forms": {
|
||||
|
@ -21,6 +21,7 @@ import LogoutRoute from "~/routes/LogoutRoute"
|
||||
import OverviewRoute from "~/routes/OverviewRoute"
|
||||
import ReportDetailRoute from "~/routes/ReportDetailRoute"
|
||||
import ReportsRoute from "~/routes/ReportsRoute"
|
||||
import ReservedAliasesRoute from "~/routes/ReservedAliasesRoute"
|
||||
import RootRoute from "~/routes/Root"
|
||||
import SettingsRoute from "~/routes/SettingsRoute"
|
||||
import SignupRoute from "~/routes/SignupRoute"
|
||||
@ -99,6 +100,10 @@ const router = createBrowserRouter([
|
||||
loader: getServerSettings,
|
||||
element: <EnterDecryptionPassword />,
|
||||
},
|
||||
{
|
||||
path: "/admin/reserved-aliases",
|
||||
element: <ReservedAliasesRoute />,
|
||||
},
|
||||
{
|
||||
path: "/admin/reserved-aliases/create",
|
||||
loader: getServerSettings,
|
||||
|
@ -4,7 +4,7 @@ import {MdMail} from "react-icons/md"
|
||||
import {useLoaderData} from "react-router"
|
||||
import {ServerSettings} from "~/server-types"
|
||||
import {useTranslation} from "react-i18next"
|
||||
import {BsArrowDown} from "react-icons/bs"
|
||||
import {BsArrowRight} from "react-icons/bs"
|
||||
import {FaMask} from "react-icons/fa"
|
||||
import {HiUsers} from "react-icons/hi"
|
||||
|
||||
@ -21,13 +21,14 @@ export default function AliasExplanation({local, emails}: AliasExplanationProps)
|
||||
return (
|
||||
<Grid
|
||||
container
|
||||
direction="column"
|
||||
direction="row"
|
||||
padding={4}
|
||||
gap={4}
|
||||
borderRadius={theme.shape.borderRadius}
|
||||
border={1}
|
||||
borderColor={theme.palette.text.disabled}
|
||||
bgcolor={theme.palette.background.default}
|
||||
flexWrap="nowrap"
|
||||
>
|
||||
<Grid item>
|
||||
<Grid container direction="column" spacing={1} alignItems="center">
|
||||
@ -35,7 +36,7 @@ export default function AliasExplanation({local, emails}: AliasExplanationProps)
|
||||
<MdMail size={24} />
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<Typography variant="caption" align="center">
|
||||
<Typography variant="caption" textAlign="center">
|
||||
{t("routes.AdminRoute.forms.reservedAliases.explanation.step1")}
|
||||
</Typography>
|
||||
</Grid>
|
||||
@ -44,10 +45,10 @@ export default function AliasExplanation({local, emails}: AliasExplanationProps)
|
||||
<Grid item>
|
||||
<Grid container direction="column" spacing={1} alignItems="center">
|
||||
<Grid item>
|
||||
<BsArrowDown size={24} />
|
||||
<BsArrowRight size={24} />
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<Typography variant="caption" align="center">
|
||||
<Typography variant="caption" textAlign="center">
|
||||
{t("routes.AdminRoute.forms.reservedAliases.explanation.step2")}
|
||||
</Typography>
|
||||
</Grid>
|
||||
@ -59,9 +60,11 @@ export default function AliasExplanation({local, emails}: AliasExplanationProps)
|
||||
<FaMask size={24} />
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<Typography variant="body1" align="center">
|
||||
<Typography variant="body1" textAlign="center">
|
||||
<span style={{display: "block"}}>{local}</span>
|
||||
<span style={{opacity: 0.4}}>@{serverSettings.mailDomain}</span>
|
||||
<span style={{opacity: 0.4, wordBreak: "break-word"}}>
|
||||
@{serverSettings.mailDomain}
|
||||
</span>
|
||||
</Typography>
|
||||
</Grid>
|
||||
</Grid>
|
||||
@ -69,10 +72,10 @@ export default function AliasExplanation({local, emails}: AliasExplanationProps)
|
||||
<Grid item>
|
||||
<Grid container direction="column" spacing={1} alignItems="center">
|
||||
<Grid item>
|
||||
<BsArrowDown size={24} />
|
||||
<BsArrowRight size={24} />
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<Typography variant="caption" align="center">
|
||||
<Typography variant="caption" textAlign="center">
|
||||
{t("routes.AdminRoute.forms.reservedAliases.explanation.step4")}
|
||||
</Typography>
|
||||
</Grid>
|
||||
|
@ -77,14 +77,13 @@ export default function CreateReservedAliasRoute(): ReactElement {
|
||||
})),
|
||||
})
|
||||
} catch (error) {
|
||||
console.log(parseFastAPIError(error as AxiosError))
|
||||
setErrors(parseFastAPIError(error as AxiosError))
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
return (
|
||||
<Grid container spacing={4} flexDirection="column" alignItems="center">
|
||||
<Grid container spacing={2} flexDirection="column" alignItems="center">
|
||||
<Grid item>
|
||||
<form onSubmit={formik.handleSubmit}>
|
||||
<SimpleForm
|
||||
@ -133,7 +132,10 @@ export default function CreateReservedAliasRoute(): ReactElement {
|
||||
</form>
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<AliasExplanation local={formik.values.local} emails={[]} />
|
||||
<AliasExplanation
|
||||
local={formik.values.local}
|
||||
emails={formik.values.users.map(user => user.email.address)}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
)
|
||||
|
113
src/routes/ReservedAliasesRoute.tsx
Normal file
113
src/routes/ReservedAliasesRoute.tsx
Normal file
@ -0,0 +1,113 @@
|
||||
import {ReactElement, useState, useTransition} from "react"
|
||||
import {AxiosError} from "axios"
|
||||
import {useTranslation} from "react-i18next"
|
||||
import {MdAdd, MdSearch} from "react-icons/md"
|
||||
import {Link} from "react-router-dom"
|
||||
|
||||
import {
|
||||
Button,
|
||||
InputAdornment,
|
||||
List,
|
||||
ListItemButton,
|
||||
ListItemSecondaryAction,
|
||||
ListItemText,
|
||||
Switch,
|
||||
TextField,
|
||||
} from "@mui/material"
|
||||
import {useQuery} from "@tanstack/react-query"
|
||||
|
||||
import {PaginationResult, ReservedAlias} from "~/server-types"
|
||||
import {getReservedAliases} from "~/apis"
|
||||
import {QueryResult, SimplePage} from "~/components"
|
||||
|
||||
export default function ReservedAliasesRoute(): ReactElement {
|
||||
const {t} = useTranslation()
|
||||
const [showSearch, setShowSearch] = useState<boolean>(false)
|
||||
const [searchValue, setSearchValue] = useState<string>("")
|
||||
const [queryValue, setQueryValue] = useState<string>("")
|
||||
const [, startTransition] = useTransition()
|
||||
const query = useQuery<PaginationResult<ReservedAlias>, AxiosError>(
|
||||
["getReservedAliases", {queryValue}],
|
||||
() =>
|
||||
getReservedAliases({
|
||||
query: queryValue,
|
||||
}),
|
||||
{
|
||||
onSuccess: () => {
|
||||
setShowSearch(true)
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
return (
|
||||
<SimplePage
|
||||
title={t("routes.ReservedAliasesRoute.title")}
|
||||
pageOptionsActions={
|
||||
showSearch && (
|
||||
<TextField
|
||||
key="search"
|
||||
fullWidth
|
||||
value={searchValue}
|
||||
onChange={event => {
|
||||
setSearchValue(event.target.value)
|
||||
startTransition(() => {
|
||||
setQueryValue(event.target.value)
|
||||
})
|
||||
}}
|
||||
label={t("routes.ReservedAliasesRoute.pageActions.search.label")}
|
||||
placeholder={t(
|
||||
"routes.ReservedAliasesRoute.pageActions.search.placeholder",
|
||||
)}
|
||||
id="search"
|
||||
InputProps={{
|
||||
startAdornment: (
|
||||
<InputAdornment position="start">
|
||||
<MdSearch />
|
||||
</InputAdornment>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}
|
||||
actions={
|
||||
<Button
|
||||
component={Link}
|
||||
startIcon={<MdAdd />}
|
||||
to="/admin/reserved-aliases/create"
|
||||
variant="contained"
|
||||
>
|
||||
{t("routes.ReservedAliasesRoute.actions.create.label")}
|
||||
</Button>
|
||||
}
|
||||
>
|
||||
<QueryResult<PaginationResult<ReservedAlias>, AxiosError> query={query}>
|
||||
{({items: aliases}) => (
|
||||
<List>
|
||||
{aliases.map(alias => (
|
||||
<ListItemButton
|
||||
to={`/admin/reserved-aliases/${alias.id}`}
|
||||
component={Link}
|
||||
key={alias.id}
|
||||
>
|
||||
<ListItemText
|
||||
primary={
|
||||
<>
|
||||
<span>{alias.local}</span>
|
||||
<span style={{opacity: 0.4}}>@{alias.domain}</span>
|
||||
</>
|
||||
}
|
||||
secondary={t("routes.ReservedAliasesRoute.userAmount", {
|
||||
count: alias.users.length,
|
||||
})}
|
||||
/>
|
||||
<ListItemSecondaryAction>
|
||||
<Switch checked={alias.isActive} />
|
||||
</ListItemSecondaryAction>
|
||||
</ListItemButton>
|
||||
))}
|
||||
</List>
|
||||
)}
|
||||
</QueryResult>
|
||||
</SimplePage>
|
||||
)
|
||||
}
|
@ -103,6 +103,7 @@ export interface Alias {
|
||||
|
||||
export interface ReservedAlias {
|
||||
id: string
|
||||
isActive: boolean
|
||||
domain: string
|
||||
local: string
|
||||
users: Array<{
|
||||
|
Loading…
x
Reference in New Issue
Block a user