mirror of
https://github.com/Myzel394/kleckrelay-website.git
synced 2025-06-19 07:55:25 +02:00
adding AliasDetailRoute.tsx
This commit is contained in:
parent
044c98f348
commit
7225dcc98c
@ -7,6 +7,7 @@ import {CssBaseline, ThemeProvider} from "@mui/material"
|
|||||||
import {queryClient} from "~/constants/react-query"
|
import {queryClient} from "~/constants/react-query"
|
||||||
import {lightTheme} from "~/constants/themes"
|
import {lightTheme} from "~/constants/themes"
|
||||||
import {getServerSettings} from "~/apis"
|
import {getServerSettings} from "~/apis"
|
||||||
|
import AliasDetailRoute from "~/routes/AliasDetailRoute"
|
||||||
import AliasesRoute from "~/routes/AliasesRoute"
|
import AliasesRoute from "~/routes/AliasesRoute"
|
||||||
import AuthContextProvider from "~/AuthContext/AuthContextProvider"
|
import AuthContextProvider from "~/AuthContext/AuthContextProvider"
|
||||||
import AuthenticateRoute from "~/routes/AuthenticateRoute"
|
import AuthenticateRoute from "~/routes/AuthenticateRoute"
|
||||||
@ -60,6 +61,10 @@ const router = createBrowserRouter([
|
|||||||
path: "/aliases",
|
path: "/aliases",
|
||||||
element: <AliasesRoute />,
|
element: <AliasesRoute />,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "/aliases/:addressInBase64",
|
||||||
|
element: <AliasDetailRoute />,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: "/settings",
|
path: "/settings",
|
||||||
element: <SettingsRoute />,
|
element: <SettingsRoute />,
|
||||||
|
@ -9,11 +9,12 @@ import {client} from "~/constants/axios-client"
|
|||||||
interface CreateAliasDataOther {
|
interface CreateAliasDataOther {
|
||||||
isActive?: boolean
|
isActive?: boolean
|
||||||
encryptedNotes?: string
|
encryptedNotes?: string
|
||||||
removeTrackers?: boolean
|
|
||||||
createMailReport?: boolean
|
prefRemoveTrackers?: boolean
|
||||||
proxyImages?: boolean
|
prefCreateMailReport?: boolean
|
||||||
imageProxyFormat?: ImageProxyFormatType
|
prefProxyImages?: boolean
|
||||||
imageProxyUserAgent?: ProxyUserAgentType
|
prefImageProxyFormat?: ImageProxyFormatType
|
||||||
|
prefImageProxyUserAgent?: ProxyUserAgentType
|
||||||
}
|
}
|
||||||
|
|
||||||
interface CreateAliasDataBase extends CreateAliasDataOther {
|
interface CreateAliasDataBase extends CreateAliasDataOther {
|
||||||
|
13
src/apis/get-alias.ts
Normal file
13
src/apis/get-alias.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import {client} from "~/constants/axios-client"
|
||||||
|
import {Alias} from "~/server-types"
|
||||||
|
|
||||||
|
export default async function getAlias(address: string): Promise<Alias> {
|
||||||
|
const {data} = await client.get(
|
||||||
|
`${import.meta.env.VITE_SERVER_BASE_URL}/alias/${address}`,
|
||||||
|
{
|
||||||
|
withCredentials: true,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
return data
|
||||||
|
}
|
@ -1,7 +1,9 @@
|
|||||||
import {Alias, PaginationResult} from "~/server-types"
|
import {AliasList, PaginationResult} from "~/server-types"
|
||||||
import {client} from "~/constants/axios-client"
|
import {client} from "~/constants/axios-client"
|
||||||
|
|
||||||
export default async function getAliases(): Promise<PaginationResult<Alias>> {
|
export default async function getAliases(): Promise<
|
||||||
|
PaginationResult<AliasList>
|
||||||
|
> {
|
||||||
const {data} = await client.get(
|
const {data} = await client.get(
|
||||||
`${import.meta.env.VITE_SERVER_BASE_URL}/alias`,
|
`${import.meta.env.VITE_SERVER_BASE_URL}/alias`,
|
||||||
{
|
{
|
||||||
|
@ -30,3 +30,5 @@ export * from "./get-reports"
|
|||||||
export {default as getReports} from "./get-reports"
|
export {default as getReports} from "./get-reports"
|
||||||
export * from "./get-report"
|
export * from "./get-report"
|
||||||
export {default as getReport} from "./get-report"
|
export {default as getReport} from "./get-report"
|
||||||
|
export * from "./get-alias"
|
||||||
|
export {default as getAlias} from "./get-alias"
|
||||||
|
22
src/constants/enum_mappings.ts
Normal file
22
src/constants/enum_mappings.ts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import {ImageProxyFormatType, ProxyUserAgentType} from "~/server-types"
|
||||||
|
|
||||||
|
export const IMAGE_PROXY_FORMAT_TYPE_NAME_MAP: Record<
|
||||||
|
ImageProxyFormatType,
|
||||||
|
string
|
||||||
|
> = {
|
||||||
|
[ImageProxyFormatType.JPEG]: "JPEG",
|
||||||
|
[ImageProxyFormatType.PNG]: "PNG",
|
||||||
|
[ImageProxyFormatType.WEBP]: "WebP",
|
||||||
|
}
|
||||||
|
|
||||||
|
export const IMAGE_PROXY_USER_AGENT_TYPE_NAME_MAP: Record<
|
||||||
|
ProxyUserAgentType,
|
||||||
|
string
|
||||||
|
> = {
|
||||||
|
[ProxyUserAgentType.APPLE_MAIL]: "Apple Mail",
|
||||||
|
[ProxyUserAgentType.GOOGLE_MAIL]: "Google Mail",
|
||||||
|
[ProxyUserAgentType.CHROME]: "Chrome Browser",
|
||||||
|
[ProxyUserAgentType.FIREFOX]: "Firefox Browser",
|
||||||
|
[ProxyUserAgentType.OUTLOOK_MACOS]: "Outlook / MacOS",
|
||||||
|
[ProxyUserAgentType.OUTLOOK_WINDOWS]: "Outlook / Windows",
|
||||||
|
}
|
140
src/route-widgets/AliasDetailRoute/AliasPreferencesForm.tsx
Normal file
140
src/route-widgets/AliasDetailRoute/AliasPreferencesForm.tsx
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
import * as yup from "yup"
|
||||||
|
import {ReactElement} from "react"
|
||||||
|
import {BsImage, BsShieldShaded} from "react-icons/bs"
|
||||||
|
import {useFormik} from "formik"
|
||||||
|
import {FaFile} from "react-icons/fa"
|
||||||
|
|
||||||
|
import {Collapse, Grid} from "@mui/material"
|
||||||
|
import {mdiTextBoxMultiple} from "@mdi/js/commonjs/mdi"
|
||||||
|
import Icon from "@mdi/react"
|
||||||
|
|
||||||
|
import {Alias, ImageProxyFormatType, ProxyUserAgentType} from "~/server-types"
|
||||||
|
import {LoadingButton} from "@mui/lab"
|
||||||
|
import {MdCheckCircle} from "react-icons/md"
|
||||||
|
import SelectField from "~/route-widgets/SettingsRoute/SelectField"
|
||||||
|
|
||||||
|
export interface AliasPreferencesFormProps {
|
||||||
|
alias: Alias
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Form {
|
||||||
|
removeTrackers: boolean
|
||||||
|
createMailReport: boolean
|
||||||
|
proxyImages: boolean
|
||||||
|
imageProxyFormat: ImageProxyFormatType
|
||||||
|
imageProxyUserAgent: ProxyUserAgentType
|
||||||
|
|
||||||
|
detail?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const SCHEMA = yup.object().shape({
|
||||||
|
removeTrackers: yup.boolean(),
|
||||||
|
createMailReport: yup.boolean(),
|
||||||
|
proxyImages: yup.boolean(),
|
||||||
|
imageProxyFormat: yup
|
||||||
|
.mixed<ImageProxyFormatType>()
|
||||||
|
.oneOf(Object.values(ImageProxyFormatType))
|
||||||
|
.required(),
|
||||||
|
imageProxyUserAgent: yup
|
||||||
|
.mixed<ProxyUserAgentType>()
|
||||||
|
.oneOf(Object.values(ProxyUserAgentType))
|
||||||
|
.required(),
|
||||||
|
})
|
||||||
|
|
||||||
|
export default function AliasPreferencesForm({
|
||||||
|
alias,
|
||||||
|
}: AliasPreferencesFormProps): ReactElement {
|
||||||
|
const formik = useFormik<Form>({
|
||||||
|
initialValues: {
|
||||||
|
removeTrackers: alias.prefRemoveTrackers,
|
||||||
|
createMailReport: alias.prefCreateMailReport,
|
||||||
|
proxyImages: alias.prefProxyImages,
|
||||||
|
imageProxyFormat: alias.prefImageProxyFormat,
|
||||||
|
imageProxyUserAgent: alias.prefImageProxyUserAgent,
|
||||||
|
},
|
||||||
|
validationSchema: SCHEMA,
|
||||||
|
onSubmit: () => null,
|
||||||
|
})
|
||||||
|
|
||||||
|
return (
|
||||||
|
<form onSubmit={formik.handleSubmit}>
|
||||||
|
<Grid
|
||||||
|
container
|
||||||
|
spacing={4}
|
||||||
|
flexDirection="column"
|
||||||
|
alignItems="center"
|
||||||
|
>
|
||||||
|
<Grid item>
|
||||||
|
<Grid container spacing={4}>
|
||||||
|
<Grid item xs={12} sm={6}>
|
||||||
|
<SelectField
|
||||||
|
label="Remove Trackers"
|
||||||
|
formik={formik}
|
||||||
|
icon={<BsShieldShaded />}
|
||||||
|
name="removeTrackers"
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12} sm={6}>
|
||||||
|
<SelectField
|
||||||
|
label="Create Reports"
|
||||||
|
formik={formik}
|
||||||
|
icon={
|
||||||
|
<Icon
|
||||||
|
path={mdiTextBoxMultiple}
|
||||||
|
size={0.8}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
name="createMailReport"
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<Grid container spacing={2}>
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<SelectField
|
||||||
|
label="Proxy Images"
|
||||||
|
formik={formik}
|
||||||
|
icon={<BsImage />}
|
||||||
|
name="proxyImages"
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<Collapse
|
||||||
|
in={formik.values.proxyImages !== false}
|
||||||
|
>
|
||||||
|
<Grid container spacing={4}>
|
||||||
|
<Grid item xs={12} sm={6}>
|
||||||
|
<SelectField
|
||||||
|
label="Image File Type"
|
||||||
|
formik={formik}
|
||||||
|
icon={<FaFile />}
|
||||||
|
name="imageProxyFormat"
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12} sm={6}>
|
||||||
|
<SelectField
|
||||||
|
label="Image Proxy User Agent"
|
||||||
|
formik={formik}
|
||||||
|
name="imageProxyUserAgent"
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</Collapse>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
<Grid item>
|
||||||
|
<LoadingButton
|
||||||
|
loading={formik.isSubmitting}
|
||||||
|
variant="contained"
|
||||||
|
type="submit"
|
||||||
|
startIcon={<MdCheckCircle />}
|
||||||
|
>
|
||||||
|
Save Settings
|
||||||
|
</LoadingButton>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</form>
|
||||||
|
)
|
||||||
|
}
|
@ -3,7 +3,7 @@ import {MdOutlineMoreVert} from "react-icons/md"
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
IconButton,
|
IconButton,
|
||||||
ListItem,
|
ListItemButton,
|
||||||
ListItemSecondaryAction,
|
ListItemSecondaryAction,
|
||||||
ListItemText,
|
ListItemText,
|
||||||
} from "@mui/material"
|
} from "@mui/material"
|
||||||
@ -17,14 +17,16 @@ export interface AliasListItemProps {
|
|||||||
export default function AliasListItem({
|
export default function AliasListItem({
|
||||||
alias,
|
alias,
|
||||||
}: AliasListItemProps): ReactElement {
|
}: AliasListItemProps): ReactElement {
|
||||||
|
const address = `${alias.local}@${alias.domain}`
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ListItem>
|
<ListItemButton href={`/aliases/${btoa(address)}`}>
|
||||||
<ListItemText primary={`${alias.local}@${alias.domain}`} />
|
<ListItemText primary={address} />
|
||||||
<ListItemSecondaryAction>
|
<ListItemSecondaryAction>
|
||||||
<IconButton edge="end">
|
<IconButton edge="end">
|
||||||
<MdOutlineMoreVert />
|
<MdOutlineMoreVert />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</ListItemSecondaryAction>
|
</ListItemSecondaryAction>
|
||||||
</ListItem>
|
</ListItemButton>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,10 @@ import {UpdatePreferencesData, updatePreferences} from "~/apis"
|
|||||||
import {useUser} from "~/hooks"
|
import {useUser} from "~/hooks"
|
||||||
import {parseFastAPIError} from "~/utils"
|
import {parseFastAPIError} from "~/utils"
|
||||||
import {SuccessSnack} from "~/components"
|
import {SuccessSnack} from "~/components"
|
||||||
|
import {
|
||||||
|
IMAGE_PROXY_FORMAT_TYPE_NAME_MAP,
|
||||||
|
IMAGE_PROXY_USER_AGENT_TYPE_NAME_MAP,
|
||||||
|
} from "~/constants/enum_mappings"
|
||||||
import AuthContext from "~/AuthContext/AuthContext"
|
import AuthContext from "~/AuthContext/AuthContext"
|
||||||
import ErrorSnack from "~/components/ErrorSnack"
|
import ErrorSnack from "~/components/ErrorSnack"
|
||||||
|
|
||||||
@ -57,22 +61,6 @@ const SCHEMA = yup.object().shape({
|
|||||||
.required(),
|
.required(),
|
||||||
})
|
})
|
||||||
|
|
||||||
const IMAGE_PROXY_FORMAT_TYPE_NAME_MAP: Record<ImageProxyFormatType, string> = {
|
|
||||||
[ImageProxyFormatType.JPEG]: "JPEG",
|
|
||||||
[ImageProxyFormatType.PNG]: "PNG",
|
|
||||||
[ImageProxyFormatType.WEBP]: "WebP",
|
|
||||||
}
|
|
||||||
|
|
||||||
const IMAGE_PROXY_USER_AGENT_TYPE_NAME_MAP: Record<ProxyUserAgentType, string> =
|
|
||||||
{
|
|
||||||
[ProxyUserAgentType.APPLE_MAIL]: "Apple Mail",
|
|
||||||
[ProxyUserAgentType.GOOGLE_MAIL]: "Google Mail",
|
|
||||||
[ProxyUserAgentType.CHROME]: "Chrome Browser",
|
|
||||||
[ProxyUserAgentType.FIREFOX]: "Firefox Browser",
|
|
||||||
[ProxyUserAgentType.OUTLOOK_MACOS]: "Outlook / MacOS",
|
|
||||||
[ProxyUserAgentType.OUTLOOK_WINDOWS]: "Outlook / Windows",
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function AliasesPreferencesForm(): ReactElement {
|
export default function AliasesPreferencesForm(): ReactElement {
|
||||||
const {_updateUser} = useContext(AuthContext)
|
const {_updateUser} = useContext(AuthContext)
|
||||||
const user = useUser()
|
const user = useUser()
|
||||||
|
64
src/route-widgets/SettingsRoute/SelectField.tsx
Normal file
64
src/route-widgets/SettingsRoute/SelectField.tsx
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
import {ReactElement, ReactNode} from "react"
|
||||||
|
|
||||||
|
import {
|
||||||
|
FormControl,
|
||||||
|
FormHelperText,
|
||||||
|
InputAdornment,
|
||||||
|
InputLabel,
|
||||||
|
MenuItem,
|
||||||
|
Select,
|
||||||
|
} from "@mui/material"
|
||||||
|
|
||||||
|
export interface SelectFieldProps {
|
||||||
|
label: string
|
||||||
|
formik: any
|
||||||
|
name: string
|
||||||
|
|
||||||
|
icon?: ReactElement
|
||||||
|
children?: ReactNode
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function SelectField({
|
||||||
|
label,
|
||||||
|
formik,
|
||||||
|
icon,
|
||||||
|
name,
|
||||||
|
children,
|
||||||
|
}: SelectFieldProps): ReactElement {
|
||||||
|
const labelId = `${name}-label`
|
||||||
|
|
||||||
|
return (
|
||||||
|
<FormControl fullWidth>
|
||||||
|
<InputLabel id={labelId}>{label}</InputLabel>
|
||||||
|
<Select
|
||||||
|
fullWidth
|
||||||
|
name={name}
|
||||||
|
id={name}
|
||||||
|
label={label}
|
||||||
|
labelId={labelId}
|
||||||
|
startAdornment={
|
||||||
|
icon ? (
|
||||||
|
<InputAdornment position="start">{icon}</InputAdornment>
|
||||||
|
) : undefined
|
||||||
|
}
|
||||||
|
value={(formik.values[name] ?? "null").toString()}
|
||||||
|
onChange={formik.handleChange}
|
||||||
|
disabled={formik.isSubmitting}
|
||||||
|
error={Boolean(formik.touched[name] && formik.errors[name])}
|
||||||
|
>
|
||||||
|
{children ?? (
|
||||||
|
<MenuItem value="null">
|
||||||
|
<i>{"<Default>"}</i>
|
||||||
|
</MenuItem>
|
||||||
|
)}
|
||||||
|
{children ?? <MenuItem value="true">Yes</MenuItem>}
|
||||||
|
{children ?? <MenuItem value="false">No</MenuItem>}
|
||||||
|
</Select>
|
||||||
|
<FormHelperText
|
||||||
|
error={Boolean(formik.touched[name] && formik.errors[name])}
|
||||||
|
>
|
||||||
|
{formik.touched[name] && formik.errors[name]}
|
||||||
|
</FormHelperText>
|
||||||
|
</FormControl>
|
||||||
|
)
|
||||||
|
}
|
60
src/routes/AliasDetailRoute.tsx
Normal file
60
src/routes/AliasDetailRoute.tsx
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
import {ReactElement} from "react"
|
||||||
|
import {useParams} from "react-router-dom"
|
||||||
|
import {AxiosError} from "axios"
|
||||||
|
|
||||||
|
import {useQuery} from "@tanstack/react-query"
|
||||||
|
import {Grid, Typography} from "@mui/material"
|
||||||
|
|
||||||
|
import {getAlias} from "~/apis"
|
||||||
|
import {Alias} from "~/server-types"
|
||||||
|
import AliasPreferencesForm from "~/route-widgets/AliasDetailRoute/AliasPreferencesForm"
|
||||||
|
import QueryResult from "~/components/QueryResult"
|
||||||
|
|
||||||
|
export default function AliasDetailRoute(): ReactElement {
|
||||||
|
const params = useParams()
|
||||||
|
const address = atob(params.addressInBase64 as string)
|
||||||
|
|
||||||
|
const query = useQuery<Alias, AxiosError>(
|
||||||
|
["get_alias", params.addressInBase64],
|
||||||
|
() => getAlias(address),
|
||||||
|
)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<QueryResult<Alias> query={query}>
|
||||||
|
{alias => (
|
||||||
|
<Grid container spacing={4}>
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<Typography variant="h4" component="h1">
|
||||||
|
Alias Details
|
||||||
|
</Typography>
|
||||||
|
</Grid>
|
||||||
|
<Grid item>
|
||||||
|
<Typography variant="subtitle1">{address}</Typography>
|
||||||
|
</Grid>
|
||||||
|
<Grid item>
|
||||||
|
<Grid container spacing={4}>
|
||||||
|
<Grid item>
|
||||||
|
<Typography variant="h6">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>
|
||||||
|
)
|
||||||
|
}
|
@ -82,11 +82,19 @@ export interface Alias {
|
|||||||
local: string
|
local: string
|
||||||
isActive: boolean
|
isActive: boolean
|
||||||
encryptedNotes: string
|
encryptedNotes: string
|
||||||
removeTrackers: boolean
|
|
||||||
createMailReport: boolean
|
prefRemoveTrackers: boolean
|
||||||
proxyImages: boolean
|
prefCreateMailReport: boolean
|
||||||
imageProxyFormat: ImageProxyFormatType
|
prefProxyImages: boolean
|
||||||
imageProxyUserAgent: ProxyUserAgentType
|
prefImageProxyFormat: ImageProxyFormatType
|
||||||
|
prefImageProxyUserAgent: ProxyUserAgentType
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AliasList {
|
||||||
|
id: string
|
||||||
|
domain: string
|
||||||
|
local: string
|
||||||
|
isActive: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Report {
|
export interface Report {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user