mirror of
https://github.com/remnawave/frontend.git
synced 2026-08-27 04:15:49 +00:00
feat: display raw subscription
This commit is contained in:
parent
e4c0004edf
commit
bcb9bd8a62
5 changed files with 127 additions and 12 deletions
|
|
@ -1,4 +1,6 @@
|
|||
import { CodeHighlight } from '@mantine/code-highlight'
|
||||
import { Button, Card, Group, Paper, Stack, Switch, Text, Transition } from '@mantine/core'
|
||||
import { modals } from '@mantine/modals'
|
||||
import { notifications } from '@mantine/notifications'
|
||||
import { GetExternalSquadByUuidCommand } from '@remnawave/backend-contract'
|
||||
import { RemarksManager } from '@widgets/dashboard/subscription-settings/settings/cards/managers/remarks-manager.widget'
|
||||
|
|
@ -9,6 +11,7 @@ import { TbDeviceFloppy, TbDevices2, TbListLetters, TbX } from 'react-icons/tb'
|
|||
|
||||
import { queryClient } from '@shared/api'
|
||||
import { QueryKeys, useUpdateExternalSquad } from '@shared/api/hooks'
|
||||
import { BaseOverlayHeader } from '@shared/ui/overlays/base-overlay-header'
|
||||
|
||||
interface IProps {
|
||||
externalSquad: GetExternalSquadByUuidCommand.Response['response']
|
||||
|
|
@ -108,6 +111,23 @@ export const ExternalSquadsCustomRemarksTabWidget = (props: IProps) => {
|
|||
data
|
||||
)
|
||||
}
|
||||
},
|
||||
onError: (error) => {
|
||||
if ((error.cause as unknown as { errorCode: string })?.errorCode === 'A231') {
|
||||
modals.open({
|
||||
centered: true,
|
||||
size: 'auto',
|
||||
title: (
|
||||
<BaseOverlayHeader
|
||||
iconColor="red"
|
||||
IconComponent={TbX}
|
||||
iconVariant="soft"
|
||||
title={t('subscription-settings.widget.validation-error')}
|
||||
/>
|
||||
),
|
||||
children: <CodeHighlight language="json" code={error.message} />
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -9,9 +9,13 @@ import {
|
|||
Stack,
|
||||
TextInput,
|
||||
ThemeIcon,
|
||||
Text
|
||||
Text,
|
||||
Box,
|
||||
Button
|
||||
} from '@mantine/core'
|
||||
import { modals } from '@mantine/modals'
|
||||
import { githubDarkTheme } from 'json-edit-react'
|
||||
import { JsonEditor } from 'json-edit-react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import {
|
||||
PiEyeSlashDuotone,
|
||||
|
|
@ -23,9 +27,10 @@ import {
|
|||
PiEmptyDuotone,
|
||||
PiQrCodeDuotone
|
||||
} from 'react-icons/pi'
|
||||
import { TbJson } from 'react-icons/tb'
|
||||
|
||||
import { useNiceMantineModal } from '@shared/_modals/use-nice-modal'
|
||||
import { useGetConnectionKeysByUuid } from '@shared/api/hooks'
|
||||
import { useGetConnectionKeysByUuid, useGetRawSubscription } from '@shared/api/hooks'
|
||||
import { LoaderModalShared } from '@shared/ui/loader-modal'
|
||||
import { BaseOverlayHeader } from '@shared/ui/overlays/base-overlay-header'
|
||||
import { QrCodeBuilder } from '@shared/ui/qr-code-builder'
|
||||
|
|
@ -34,10 +39,11 @@ import { SectionCardSection } from '@shared/ui/section-card/section-card.section
|
|||
|
||||
interface IProps {
|
||||
userUuid: string
|
||||
shortUuid: string
|
||||
}
|
||||
|
||||
export const ConnectionKeysDrawer = NiceModal.create((props: IProps) => {
|
||||
const { userUuid } = props
|
||||
const { userUuid, shortUuid } = props
|
||||
const { t } = useTranslation()
|
||||
|
||||
const modal = useModal()
|
||||
|
|
@ -52,6 +58,10 @@ export const ConnectionKeysDrawer = NiceModal.create((props: IProps) => {
|
|||
}
|
||||
})
|
||||
|
||||
const { data: rawSubscription, isLoading: isRawSubscriptionLoading } = useGetRawSubscription({
|
||||
route: { shortUuid }
|
||||
})
|
||||
|
||||
const renderQrCode = (link: string, remark: string) => {
|
||||
modals.open({
|
||||
centered: true,
|
||||
|
|
@ -169,6 +179,44 @@ export const ConnectionKeysDrawer = NiceModal.create((props: IProps) => {
|
|||
)
|
||||
}
|
||||
|
||||
const renderRawSubscription = () => {
|
||||
modals.open({
|
||||
centered: true,
|
||||
size: 'xl',
|
||||
title: (
|
||||
<BaseOverlayHeader
|
||||
iconColor="teal"
|
||||
IconComponent={TbJson}
|
||||
iconVariant="soft"
|
||||
title="Raw Subscription"
|
||||
/>
|
||||
),
|
||||
children: (
|
||||
<Box>
|
||||
<JsonEditor
|
||||
collapse={({ path }) => {
|
||||
if (path.length === 0) return false
|
||||
if (path[0] !== 'resolvedProxyConfigs') return true
|
||||
return path.length > 2
|
||||
}}
|
||||
data={JSON.parse(JSON.stringify(rawSubscription))}
|
||||
indent={4}
|
||||
keySort={([a], [b]) => {
|
||||
if (a === 'resolvedProxyConfigs') return -1
|
||||
if (b === 'resolvedProxyConfigs') return 1
|
||||
return 0
|
||||
}}
|
||||
maxWidth="100%"
|
||||
rootName=""
|
||||
theme={githubDarkTheme}
|
||||
viewOnly
|
||||
jsonStringify={(data) => JSON.stringify(data)}
|
||||
/>
|
||||
</Box>
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<Drawer
|
||||
{...modalProps}
|
||||
|
|
@ -184,13 +232,24 @@ export const ConnectionKeysDrawer = NiceModal.create((props: IProps) => {
|
|||
/>
|
||||
}
|
||||
>
|
||||
{isLoading ? (
|
||||
<LoaderModalShared
|
||||
text={t('get-user-subscription-links.feature.loading-subscription-links')}
|
||||
/>
|
||||
) : (
|
||||
<Stack>{renderLinks()}</Stack>
|
||||
)}
|
||||
<Stack>
|
||||
<Button
|
||||
fullWidth
|
||||
onClick={renderRawSubscription}
|
||||
leftSection={<TbJson size="16px" />}
|
||||
variant="soft"
|
||||
loading={isRawSubscriptionLoading}
|
||||
>
|
||||
Raw Subscription
|
||||
</Button>
|
||||
{isLoading ? (
|
||||
<LoaderModalShared
|
||||
text={t('get-user-subscription-links.feature.loading-subscription-links')}
|
||||
/>
|
||||
) : (
|
||||
<Stack>{renderLinks()}</Stack>
|
||||
)}
|
||||
</Stack>
|
||||
</Drawer>
|
||||
)
|
||||
})
|
||||
|
|
|
|||
|
|
@ -6,7 +6,8 @@ import {
|
|||
GetUserAccessibleNodesCommand,
|
||||
GetUserByUuidCommand,
|
||||
GetUserMetadataCommand,
|
||||
GetUserSubscriptionRequestHistoryCommand
|
||||
GetUserSubscriptionRequestHistoryCommand,
|
||||
GetRawSubscriptionByShortUuidCommand
|
||||
} from '@remnawave/backend-contract'
|
||||
import { keepPreviousData } from '@tanstack/react-query'
|
||||
|
||||
|
|
@ -24,6 +25,9 @@ export const usersQueryKeys = createQueryKeys('users', {
|
|||
getConnectionKeysByUuid: (route: GetConnectionKeysByUuidCommand.RequestParam) => ({
|
||||
queryKey: [route]
|
||||
}),
|
||||
getRawSubscription: (route: GetRawSubscriptionByShortUuidCommand.RequestParam) => ({
|
||||
queryKey: [route]
|
||||
}),
|
||||
getUserTags: {
|
||||
queryKey: null
|
||||
},
|
||||
|
|
@ -119,3 +123,13 @@ export const useGetUserMetadata = createGetQueryHook({
|
|||
staleTime: sToMs(60)
|
||||
}
|
||||
})
|
||||
|
||||
export const useGetRawSubscription = createGetQueryHook({
|
||||
endpoint: GetRawSubscriptionByShortUuidCommand.TSQ_url,
|
||||
responseSchema: GetRawSubscriptionByShortUuidCommand.ResponseSchema,
|
||||
routeParamsSchema: GetRawSubscriptionByShortUuidCommand.RequestParamSchema,
|
||||
getQueryKey: ({ route }) => usersQueryKeys.getRawSubscription(route!).queryKey,
|
||||
rQueryParams: {
|
||||
staleTime: sToMs(60)
|
||||
}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -181,7 +181,8 @@ export const UserIdentificationCard = memo((props: IProps) => {
|
|||
color="teal"
|
||||
onClick={() => {
|
||||
showModal('users_connectionKeysDrawer', {
|
||||
userUuid: user.uuid
|
||||
userUuid: user.uuid,
|
||||
shortUuid: user.shortUuid
|
||||
})
|
||||
}}
|
||||
size="lg"
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
import { CodeHighlight } from '@mantine/code-highlight'
|
||||
import { Button, Card, Group, Stack } from '@mantine/core'
|
||||
import { useForm, schemaResolver } from '@mantine/form'
|
||||
import { modals } from '@mantine/modals'
|
||||
import { notifications } from '@mantine/notifications'
|
||||
import { UpdateSubscriptionSettingsCommand } from '@remnawave/backend-contract'
|
||||
import { useState } from 'react'
|
||||
|
|
@ -10,6 +12,7 @@ import Masonry from 'react-layout-masonry'
|
|||
|
||||
import { queryClient } from '@shared/api'
|
||||
import { QueryKeys, useUpdateSubscriptionSettings } from '@shared/api/hooks'
|
||||
import { BaseOverlayHeader } from '@shared/ui/overlays/base-overlay-header'
|
||||
import { SettingsCardShared } from '@shared/ui/settings-card'
|
||||
import { handleFormErrors } from '@shared/utils/misc'
|
||||
|
||||
|
|
@ -77,6 +80,24 @@ export const SubscriptionUserRemarksCardWidget = (props: IProps) => {
|
|||
},
|
||||
|
||||
onError(error) {
|
||||
if ((error.cause as unknown as { errorCode: string })?.errorCode === 'A231') {
|
||||
modals.open({
|
||||
centered: true,
|
||||
size: 'auto',
|
||||
title: (
|
||||
<BaseOverlayHeader
|
||||
iconColor="red"
|
||||
IconComponent={TbX}
|
||||
iconVariant="soft"
|
||||
title={t('subscription-settings.widget.validation-error')}
|
||||
/>
|
||||
),
|
||||
children: <CodeHighlight language="json" code={error.message} />
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
handleFormErrors(form, error)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue