diff --git a/src/shared/_modals/external-squads/external-squads-drawer/tabs/external-squads-custom-remarks.widget.tsx b/src/shared/_modals/external-squads/external-squads-drawer/tabs/external-squads-custom-remarks.widget.tsx
index b397c6a2..19194d18 100644
--- a/src/shared/_modals/external-squads/external-squads-drawer/tabs/external-squads-custom-remarks.widget.tsx
+++ b/src/shared/_modals/external-squads/external-squads-drawer/tabs/external-squads-custom-remarks.widget.tsx
@@ -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: (
+
+ ),
+ children:
+ })
+ }
}
}
})
diff --git a/src/shared/_modals/users/connection-keys-drawer/connection-keys.drawer.tsx b/src/shared/_modals/users/connection-keys-drawer/connection-keys.drawer.tsx
index 39cd52ea..a584d799 100644
--- a/src/shared/_modals/users/connection-keys-drawer/connection-keys.drawer.tsx
+++ b/src/shared/_modals/users/connection-keys-drawer/connection-keys.drawer.tsx
@@ -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: (
+
+ ),
+ children: (
+
+ {
+ 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)}
+ />
+
+ )
+ })
+ }
+
return (
{
/>
}
>
- {isLoading ? (
-
- ) : (
- {renderLinks()}
- )}
+
+ }
+ variant="soft"
+ loading={isRawSubscriptionLoading}
+ >
+ Raw Subscription
+
+ {isLoading ? (
+
+ ) : (
+ {renderLinks()}
+ )}
+
)
})
diff --git a/src/shared/api/hooks/users/users.query.hooks.ts b/src/shared/api/hooks/users/users.query.hooks.ts
index ebece094..8b5bb9b5 100644
--- a/src/shared/api/hooks/users/users.query.hooks.ts
+++ b/src/shared/api/hooks/users/users.query.hooks.ts
@@ -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)
+ }
+})
diff --git a/src/shared/ui/forms/users/forms-components/user-identification-card.tsx b/src/shared/ui/forms/users/forms-components/user-identification-card.tsx
index 2bcc005d..4226b39e 100644
--- a/src/shared/ui/forms/users/forms-components/user-identification-card.tsx
+++ b/src/shared/ui/forms/users/forms-components/user-identification-card.tsx
@@ -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"
diff --git a/src/widgets/dashboard/subscription-settings/settings/cards/subscription-user-remarks-card.widget.tsx b/src/widgets/dashboard/subscription-settings/settings/cards/subscription-user-remarks-card.widget.tsx
index 7c8f39c8..a7039060 100644
--- a/src/widgets/dashboard/subscription-settings/settings/cards/subscription-user-remarks-card.widget.tsx
+++ b/src/widgets/dashboard/subscription-settings/settings/cards/subscription-user-remarks-card.widget.tsx
@@ -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: (
+
+ ),
+ children:
+ })
+
+ return
+ }
+
handleFormErrors(form, error)
}
}