Skip to content

Commit 605d358

Browse files
committed
Add edit functionality for NPUB management
- Add edit button to actions column with edit icon - Create edit user modal with tier and permission controls - Implement smart update logic that removes and re-adds entries for tier changes - Fix form integration with proper initialValues and delayed field setting - Add error handling with user-friendly messages
1 parent dcba69a commit 605d358

1 file changed

Lines changed: 141 additions & 8 deletions

File tree

src/components/allowed-users/components/NPubManagement/NPubManagement.tsx

Lines changed: 141 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React, { useState, useEffect } from 'react';
22
import { Button, Input, Table, Space, Modal, Form, Select, message, Popconfirm } from 'antd';
3-
import { PlusOutlined, UploadOutlined, DeleteOutlined, DownloadOutlined } from '@ant-design/icons';
3+
import { PlusOutlined, UploadOutlined, DeleteOutlined, DownloadOutlined, EditOutlined } from '@ant-design/icons';
44
import { useAllowedUsersNpubs, useAllowedUsersValidation } from '@app/hooks/useAllowedUsers';
55
import { AllowedUsersSettings, AllowedUsersMode } from '@app/types/allowedUsers.types';
66
import * as S from './NPubManagement.styles';
@@ -30,10 +30,13 @@ export const NPubManagement: React.FC<NPubManagementProps> = ({
3030
mode
3131
}) => {
3232
const [isAddModalVisible, setIsAddModalVisible] = useState(false);
33+
const [isEditModalVisible, setIsEditModalVisible] = useState(false);
3334
const [isBulkModalVisible, setIsBulkModalVisible] = useState(false);
3435
const [bulkText, setBulkText] = useState('');
3536
const [unifiedUsers, setUnifiedUsers] = useState<UnifiedUser[]>([]);
37+
const [editingUser, setEditingUser] = useState<UnifiedUser | null>(null);
3638
const [addForm] = Form.useForm<AddNpubFormData>();
39+
const [editForm] = Form.useForm<AddNpubFormData>();
3740

3841
const readNpubs = useAllowedUsersNpubs('read');
3942
const writeNpubs = useAllowedUsersNpubs('write');
@@ -132,6 +135,67 @@ export const NPubManagement: React.FC<NPubManagementProps> = ({
132135
}
133136
};
134137

138+
const handleEditUser = (user: UnifiedUser) => {
139+
setEditingUser(user);
140+
setIsEditModalVisible(true);
141+
// Set form values after modal is visible
142+
setTimeout(() => {
143+
editForm.setFieldsValue({
144+
npub: user.npub,
145+
tier: user.tier,
146+
readAccess: user.readAccess,
147+
writeAccess: user.writeAccess
148+
});
149+
}, 0);
150+
};
151+
152+
const handleSaveEdit = async () => {
153+
try {
154+
const values = await editForm.validateFields();
155+
const originalUser = editingUser!;
156+
157+
// Check what actually changed
158+
const readChanged = originalUser.readAccess !== values.readAccess;
159+
const writeChanged = originalUser.writeAccess !== values.writeAccess;
160+
const tierChanged = originalUser.tier !== values.tier;
161+
162+
// Handle read access changes
163+
if (readChanged || (tierChanged && values.readAccess)) {
164+
if (values.readAccess) {
165+
// Remove old entry if exists and re-add with new tier
166+
if (originalUser.readAccess) {
167+
await readNpubs.removeNpub(values.npub);
168+
}
169+
await readNpubs.addNpub(values.npub, values.tier);
170+
} else {
171+
// Remove read access
172+
await readNpubs.removeNpub(values.npub);
173+
}
174+
}
175+
176+
// Handle write access changes
177+
if (writeChanged || (tierChanged && values.writeAccess)) {
178+
if (values.writeAccess) {
179+
// Remove old entry if exists and re-add with new tier
180+
if (originalUser.writeAccess) {
181+
await writeNpubs.removeNpub(values.npub);
182+
}
183+
await writeNpubs.addNpub(values.npub, values.tier);
184+
} else {
185+
// Remove write access
186+
await writeNpubs.removeNpub(values.npub);
187+
}
188+
}
189+
190+
setIsEditModalVisible(false);
191+
setEditingUser(null);
192+
editForm.resetFields();
193+
} catch (error) {
194+
console.error('Edit user error:', error);
195+
message.error('Failed to update user');
196+
}
197+
};
198+
135199
const handleRemoveUser = async (npub: string) => {
136200
try {
137201
// Remove from both lists
@@ -262,17 +326,27 @@ export const NPubManagement: React.FC<NPubManagementProps> = ({
262326
title: 'Actions',
263327
key: 'actions',
264328
render: (_: any, record: UnifiedUser) => (
265-
<Popconfirm
266-
title="Are you sure you want to remove this user completely?"
267-
onConfirm={() => handleRemoveUser(record.npub)}
268-
>
329+
<Space size="small">
269330
<Button
270331
type="text"
271-
danger
272-
icon={<DeleteOutlined />}
332+
icon={<EditOutlined />}
273333
size="small"
334+
onClick={() => handleEditUser(record)}
335+
title="Edit user"
274336
/>
275-
</Popconfirm>
337+
<Popconfirm
338+
title="Are you sure you want to remove this user completely?"
339+
onConfirm={() => handleRemoveUser(record.npub)}
340+
>
341+
<Button
342+
type="text"
343+
danger
344+
icon={<DeleteOutlined />}
345+
size="small"
346+
title="Remove user"
347+
/>
348+
</Popconfirm>
349+
</Space>
276350
)
277351
}
278352
];
@@ -372,6 +446,65 @@ export const NPubManagement: React.FC<NPubManagementProps> = ({
372446
</Form>
373447
</Modal>
374448

449+
{/* Edit User Modal */}
450+
<Modal
451+
title="Edit User"
452+
open={isEditModalVisible}
453+
onOk={handleSaveEdit}
454+
onCancel={() => {
455+
setIsEditModalVisible(false);
456+
setEditingUser(null);
457+
editForm.resetFields();
458+
}}
459+
destroyOnClose
460+
>
461+
<Form
462+
form={editForm}
463+
layout="vertical"
464+
initialValues={{
465+
npub: editingUser?.npub || '',
466+
tier: editingUser?.tier || '',
467+
readAccess: editingUser?.readAccess || false,
468+
writeAccess: editingUser?.writeAccess || false
469+
}}
470+
>
471+
<Form.Item
472+
name="npub"
473+
label="NPUB"
474+
>
475+
<Input disabled />
476+
</Form.Item>
477+
478+
<Form.Item
479+
name="tier"
480+
label="Tier"
481+
rules={[{ required: true, message: 'Please select a tier' }]}
482+
>
483+
<Select placeholder="Select tier" options={tierOptions} />
484+
</Form.Item>
485+
486+
<Form.Item
487+
label="Permissions"
488+
style={{ marginBottom: 0 }}
489+
>
490+
<Space direction="vertical">
491+
<div style={{ display: 'flex', alignItems: 'center', gap: '8px', color: 'var(--text-main-color)' }}>
492+
<Form.Item name="readAccess" valuePropName="checked" style={{ marginBottom: 0 }}>
493+
<S.StyledSwitch size="small" />
494+
</Form.Item>
495+
<span>Read Access</span>
496+
</div>
497+
<div style={{ display: 'flex', alignItems: 'center', gap: '8px', color: 'var(--text-main-color)' }}>
498+
<Form.Item name="writeAccess" valuePropName="checked" style={{ marginBottom: 0 }}>
499+
<S.StyledSwitch size="small" />
500+
</Form.Item>
501+
<span>Write Access</span>
502+
</div>
503+
</Space>
504+
</Form.Item>
505+
</Form>
506+
</Modal>
507+
375508
{/* Bulk Import Modal */}
376509
<Modal
377510
title="Bulk Import Users"

0 commit comments

Comments
 (0)