Skip to content

Commit f725815

Browse files
committed
feat: enhance config editor and template editor actions
- Refactored action buttons to use a dropdown menu for better organization. - Updated styles for action buttons and added a footer for persistent action visibility. - Removed the ConfigProfileDetailHeaderWidget - Improved mobile responsiveness for action groups in both config and template editors.
1 parent 4d40482 commit f725815

File tree

14 files changed

+294
-384
lines changed

14 files changed

+294
-384
lines changed

public/locales/en/remnawave.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,8 @@
6868
"copy-all-content": "Copy all content",
6969
"select-all": "Select all",
7070
"cut-selection": "Cut selection",
71-
"paste-from-clipboard": "Paste from clipboard"
71+
"paste-from-clipboard": "Paste from clipboard",
72+
"generate-keypair": "Generate Keypair"
7273
}
7374
},
7475
"use-bandwidth-table-columns": {

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

Lines changed: 121 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,15 @@ import {
33
TbClipboardText,
44
TbCut,
55
TbDownload,
6+
TbMenu2,
67
TbSelectAll,
78
TbTools
89
} from 'react-icons/tb'
9-
import { ActionIcon, Button, Group, Text, Tooltip } from '@mantine/core'
10-
import { PiCheckSquareOffset, PiFloppyDisk } from 'react-icons/pi'
10+
import { PiCheck, PiCheckSquareOffset, PiCopy, PiFloppyDisk } from 'react-icons/pi'
11+
import { ActionIcon, Button, CopyButton, Group, Menu, Text } from '@mantine/core'
12+
import { useClipboard, useMediaQuery } from '@mantine/hooks'
1113
import { notifications } from '@mantine/notifications'
1214
import { useTranslation } from 'react-i18next'
13-
import { useClipboard } from '@mantine/hooks'
1415
import { modals } from '@mantine/modals'
1516
import consola from 'consola/browser'
1617

@@ -26,6 +27,7 @@ export function ConfigEditorActionsFeature(props: Props) {
2627
props
2728
const { t } = useTranslation()
2829

30+
const isMobile = useMediaQuery('(max-width: 48em)')
2931
const clipboard = useClipboard({ timeout: 500 })
3032

3133
const { mutate: updateConfig, isPending: isUpdating } = useUpdateConfigProfile({
@@ -156,110 +158,147 @@ export function ConfigEditorActionsFeature(props: Props) {
156158
}
157159

158160
return (
159-
<Group grow preventGrowOverflow={false} wrap="wrap">
160-
<Button
161-
leftSection={<PiCheckSquareOffset size={16} />}
162-
mb="md"
163-
onClick={formatDocument}
164-
>
165-
{t('config-editor-actions.feature.format')}
166-
</Button>
167-
161+
<Group grow={isMobile} preventGrowOverflow={false} wrap="wrap">
168162
<Button
169163
color="teal"
170164
disabled={!isConfigValid}
171165
leftSection={<PiFloppyDisk size={16} />}
172166
loading={isUpdating}
173-
mb="md"
174167
onClick={handleSave}
168+
radius="md"
169+
variant="light"
175170
>
176171
{t('config-editor-actions.feature.save')}
177172
</Button>
178173

179-
<Button
180-
color="red"
181-
disabled={isConfigValid || isUpdating}
182-
leftSection={<PiFloppyDisk size={16} />}
183-
loading={isUpdating}
184-
mb="md"
185-
onClick={() => {
186-
modals.openConfirmModal({
187-
title: t('config-editor-actions.feature.save-anyway-title'),
188-
children: (
189-
<Text>
190-
{t('config-editor-actions.feature.save-anyway-description')}
191-
</Text>
192-
),
193-
centered: true,
194-
labels: {
195-
confirm: t('config-editor-actions.feature.save'),
196-
cancel: t('config-editor-actions.feature.cancel')
197-
},
198-
confirmProps: {
199-
color: 'red'
200-
},
201-
onConfirm: handleSave
202-
})
203-
}}
204-
>
205-
{t('config-editor-actions.feature.save-anyway')}
206-
</Button>
207-
208-
<Group>
174+
{!isConfigValid && !isUpdating && (
209175
<Button
210-
leftSection={<TbTools size={16} />}
211-
mb="md"
176+
color="red"
177+
disabled={isConfigValid || isUpdating}
178+
leftSection={<PiFloppyDisk size={16} />}
179+
loading={isUpdating}
212180
onClick={() => {
213-
modals.open({
214-
title: t('config-editor-actions.feature.tools'),
181+
modals.openConfirmModal({
182+
title: t('config-editor-actions.feature.save-anyway-title'),
183+
children: (
184+
<Text>
185+
{t('config-editor-actions.feature.save-anyway-description')}
186+
</Text>
187+
),
215188
centered: true,
216-
children: <KeypairGeneratorWidget />
189+
labels: {
190+
confirm: t('config-editor-actions.feature.save'),
191+
cancel: t('config-editor-actions.feature.cancel')
192+
},
193+
confirmProps: {
194+
color: 'red'
195+
},
196+
onConfirm: handleSave
217197
})
218198
}}
199+
radius="md"
200+
variant="light"
201+
>
202+
{t('config-editor-actions.feature.save-anyway')}
203+
</Button>
204+
)}
205+
206+
<Group gap={0} wrap="nowrap">
207+
<Button
208+
leftSection={<PiCheckSquareOffset size={16} />}
209+
onClick={formatDocument}
210+
radius="md"
211+
style={{
212+
borderTopRightRadius: 0,
213+
borderBottomRightRadius: 0,
214+
borderRight: 0,
215+
width: '100%'
216+
}}
217+
variant="default"
219218
>
220-
{t('config-editor-actions.feature.tools')}
219+
{t('config-editor-actions.feature.format')}
221220
</Button>
222221

223-
<ActionIcon.Group mb="md">
224-
<Tooltip label={t('config-editor-actions.feature.copy-all-content')}>
222+
<Menu radius="sm" shadow="md" withinPortal>
223+
<Menu.Target>
225224
<ActionIcon
226-
color={clipboard.copied ? 'teal' : 'cyan'}
227-
onClick={handleCopyConfig}
228-
size="input-sm"
229-
variant="outline"
225+
radius="md"
226+
size={36}
227+
style={{
228+
borderTopLeftRadius: 0,
229+
borderBottomLeftRadius: 0,
230+
border: '1px solid var(--mantine-color-gray-7)'
231+
}}
232+
variant="default"
230233
>
231-
<TbClipboardCopy size={20} />
234+
<TbMenu2 size={20} />
232235
</ActionIcon>
233-
</Tooltip>
236+
</Menu.Target>
237+
238+
<Menu.Dropdown>
239+
<CopyButton timeout={2000} value={configProfile.uuid}>
240+
{({ copied, copy }) => (
241+
<Menu.Item
242+
color={copied ? 'teal' : undefined}
243+
leftSection={
244+
copied ? <PiCheck size={14} /> : <PiCopy size={14} />
245+
}
246+
onClick={copy}
247+
>
248+
{t('config-profiles-grid.widget.copy-uuid')}
249+
</Menu.Item>
250+
)}
251+
</CopyButton>
252+
253+
<Menu.Item
254+
color={clipboard.copied ? 'teal' : undefined}
255+
leftSection={<TbClipboardCopy size={14} />}
256+
onClick={handleCopyConfig}
257+
>
258+
{t('config-editor-actions.feature.copy-all-content')}
259+
</Menu.Item>
234260

235-
<Tooltip label={t('config-editor-actions.feature.select-all')}>
236-
<ActionIcon onClick={handleSelectAll} size="input-sm" variant="outline">
237-
<TbSelectAll size={20} />
238-
</ActionIcon>
239-
</Tooltip>
261+
<Menu.Item
262+
leftSection={<TbSelectAll size={14} />}
263+
onClick={handleSelectAll}
264+
>
265+
{t('config-editor-actions.feature.select-all')}
266+
</Menu.Item>
240267

241-
<Tooltip label={t('config-editor-actions.feature.cut-selection')}>
242-
<ActionIcon onClick={handleCut} size="input-sm" variant="outline">
243-
<TbCut size={20} />
244-
</ActionIcon>
245-
</Tooltip>
268+
<Menu.Item leftSection={<TbCut size={14} />} onClick={handleCut}>
269+
{t('config-editor-actions.feature.cut-selection')}
270+
</Menu.Item>
246271

247-
<Tooltip label={t('config-editor-actions.feature.paste-from-clipboard')}>
248-
<ActionIcon onClick={handlePaste} size="input-sm" variant="outline">
249-
<TbClipboardText size={20} />
250-
</ActionIcon>
251-
</Tooltip>
252-
</ActionIcon.Group>
272+
<Menu.Item
273+
leftSection={<TbClipboardText size={14} />}
274+
onClick={handlePaste}
275+
>
276+
{t('config-editor-actions.feature.paste-from-clipboard')}
277+
</Menu.Item>
278+
279+
<Menu.Divider />
280+
281+
<Menu.Item
282+
leftSection={<TbTools size={14} />}
283+
onClick={() => {
284+
modals.open({
285+
title: t('config-editor-actions.feature.tools'),
286+
centered: true,
287+
children: <KeypairGeneratorWidget />
288+
})
289+
}}
290+
>
291+
{t('config-editor-actions.feature.generate-keypair')}
292+
</Menu.Item>
253293

254-
<Button
255-
leftSection={<TbDownload size={16} />}
256-
loading={isUpdating}
257-
mb="md"
258-
onClick={openDownloadModal}
259-
variant="light"
260-
>
261-
{t('config-editor-actions.feature.load-from-github')}
262-
</Button>
294+
<Menu.Item
295+
leftSection={<TbDownload size={14} />}
296+
onClick={openDownloadModal}
297+
>
298+
{t('config-editor-actions.feature.load-from-github')}
299+
</Menu.Item>
300+
</Menu.Dropdown>
301+
</Menu>
263302
</Group>
264303
</Group>
265304
)

0 commit comments

Comments
 (0)