Skip to content

Commit a577c04

Browse files
committed
feat: enhance config editor with validation and save confirmation
- Added validation to check for valid JSON before saving configurations in the ConfigEditorActionsFeature. - Introduced a "Save anyway" button with a confirmation modal for saving invalid configurations. - Updated localization files for English, Persian, and Russian to include new messages related to save confirmation and error handling.
1 parent 68fe928 commit a577c04

File tree

4 files changed

+64
-4
lines changed

4 files changed

+64
-4
lines changed

public/locales/en/remnawave.json

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,13 @@
5353
"feature": {
5454
"save": "Save",
5555
"format": "Format",
56-
"copy-config": "Copy config"
56+
"copy-config": "Copy config",
57+
"failed-to-save-invalid-json": "Failed to save, invalid JSON.",
58+
"error": "Error",
59+
"save-anyway": "Save anyway",
60+
"save-anyway-description": "Are you sure you want to save invalid XRay config? This action\n can lead to unexpected behavior. Continue only if you know what\n you are doing.",
61+
"cancel": "Cancel",
62+
"save-anyway-title": "Confirm action"
5763
}
5864
},
5965
"use-bandwidth-table-columns": {

public/locales/fa/remnawave.json

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,13 @@
5353
"feature": {
5454
"save": "ذخیره",
5555
"format": "فرمت",
56-
"copy-config": "کپی"
56+
"copy-config": "کپی",
57+
"save-anyway-description": "Are you sure you want to save invalid XRay config? This action\n can lead to unexpected behavior. Continue only if you know what\n you are doing.",
58+
"cancel": "Cancel",
59+
"save-anyway-title": "Confirm action",
60+
"error": "Error",
61+
"failed-to-save-invalid-json": "Failed to save, invalid JSON.",
62+
"save-anyway": "Save anyway"
5763
}
5864
},
5965
"use-bandwidth-table-columns": {

public/locales/ru/remnawave.json

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,13 @@
5353
"feature": {
5454
"save": "Сохранить",
5555
"format": "Форматировать",
56-
"copy-config": "Скопировать"
56+
"copy-config": "Скопировать",
57+
"save-anyway-description": "Are you sure you want to save invalid XRay config? This action\n can lead to unexpected behavior. Continue only if you know what\n you are doing.",
58+
"cancel": "Cancel",
59+
"save-anyway-title": "Confirm action",
60+
"error": "Error",
61+
"failed-to-save-invalid-json": "Failed to save, invalid JSON.",
62+
"save-anyway": "Save anyway"
5763
}
5864
},
5965
"use-bandwidth-table-columns": {

src/features/dashboard/config/config-editor-actions/config-editor-actions.feature.tsx

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import { PiCheck, PiCheckSquareOffset, PiCopy, PiFloppyDisk } from 'react-icons/pi'
2+
import { notifications } from '@mantine/notifications'
3+
import { Button, Group, Text } from '@mantine/core'
24
import { useTranslation } from 'react-i18next'
3-
import { Button, Group } from '@mantine/core'
45
import { useClipboard } from '@mantine/hooks'
6+
import { modals } from '@mantine/modals'
57

68
import { useUpdateConfig } from '@shared/api/hooks'
79

@@ -24,6 +26,17 @@ export function ConfigEditorActionsFeature(props: Props) {
2426

2527
const currentValue = editorRef.current.getValue()
2628

29+
try {
30+
JSON.parse(currentValue)
31+
} catch (error) {
32+
notifications.show({
33+
color: 'red',
34+
message: t('config-editor-actions.feature.failed-to-save-invalid-json'),
35+
title: t('config-editor-actions.feature.error')
36+
})
37+
return
38+
}
39+
2740
if (currentValue) {
2841
updateConfig({
2942
variables: JSON.parse(currentValue),
@@ -84,6 +97,35 @@ export function ConfigEditorActionsFeature(props: Props) {
8497
>
8598
{t('config-editor-actions.feature.save')}
8699
</Button>
100+
101+
<Button
102+
color="red"
103+
disabled={isConfigValid || isUpdating}
104+
leftSection={<PiFloppyDisk size={16} />}
105+
loading={isUpdating}
106+
mb="md"
107+
onClick={() => {
108+
modals.openConfirmModal({
109+
title: t('config-editor-actions.feature.save-anyway-title'),
110+
children: (
111+
<Text>
112+
{t('config-editor-actions.feature.save-anyway-description')}
113+
</Text>
114+
),
115+
centered: true,
116+
labels: {
117+
confirm: t('config-editor-actions.feature.save'),
118+
cancel: t('config-editor-actions.feature.cancel')
119+
},
120+
confirmProps: {
121+
color: 'red'
122+
},
123+
onConfirm: handleSave
124+
})
125+
}}
126+
>
127+
{t('config-editor-actions.feature.save-anyway')}
128+
</Button>
87129
</Group>
88130
)
89131
}

0 commit comments

Comments
 (0)