import React, { useState, useEffect } from 'react'; import { Table, Button, Space, Typography, Modal, Form, Input, Select, message, Popconfirm, Tag, Card, Row, Col, } from 'antd'; import { PlusOutlined, EditOutlined, DeleteOutlined, EyeOutlined, CopyOutlined, } from '@ant-design/icons'; import { apiService, Application, CreateApplicationRequest } from '../services/apiService'; import dayjs from 'dayjs'; const { Title, Text } = Typography; const { Option } = Select; const Applications: React.FC = () => { const [applications, setApplications] = useState([]); const [loading, setLoading] = useState(false); const [modalVisible, setModalVisible] = useState(false); const [editingApp, setEditingApp] = useState(null); const [detailModalVisible, setDetailModalVisible] = useState(false); const [selectedApp, setSelectedApp] = useState(null); const [form] = Form.useForm(); useEffect(() => { loadApplications(); }, []); const loadApplications = async () => { try { setLoading(true); const response = await apiService.getApplications(); setApplications(response.data); } catch (error) { console.error('Failed to load applications:', error); message.error('Failed to load applications'); } finally { setLoading(false); } }; const handleCreate = () => { setEditingApp(null); form.resetFields(); setModalVisible(true); }; const handleEdit = (app: Application) => { setEditingApp(app); form.setFieldsValue({ app_id: app.app_id, app_link: app.app_link, type: app.type, callback_url: app.callback_url, token_prefix: app.token_prefix, token_renewal_duration: formatDuration(app.token_renewal_duration), max_token_duration: formatDuration(app.max_token_duration), owner_type: app.owner.type, owner_name: app.owner.name, owner_owner: app.owner.owner, }); setModalVisible(true); }; const handleDelete = async (appId: string) => { try { await apiService.deleteApplication(appId); message.success('Application deleted successfully'); loadApplications(); } catch (error) { console.error('Failed to delete application:', error); message.error('Failed to delete application'); } }; const handleSubmit = async (values: any) => { try { const requestData: CreateApplicationRequest = { app_id: values.app_id, app_link: values.app_link, type: values.type, callback_url: values.callback_url, token_prefix: values.token_prefix, token_renewal_duration: values.token_renewal_duration, max_token_duration: values.max_token_duration, owner: { type: values.owner_type, name: values.owner_name, owner: values.owner_owner, }, }; if (editingApp) { await apiService.updateApplication(editingApp.app_id, requestData); message.success('Application updated successfully'); } else { await apiService.createApplication(requestData); message.success('Application created successfully'); } setModalVisible(false); loadApplications(); } catch (error) { console.error('Failed to save application:', error); message.error('Failed to save application'); } }; const showDetails = (app: Application) => { setSelectedApp(app); setDetailModalVisible(true); }; const copyToClipboard = (text: string) => { navigator.clipboard.writeText(text); message.success('Copied to clipboard'); }; const formatDuration = (nanoseconds: number): string => { const hours = Math.floor(nanoseconds / (1000000000 * 60 * 60)); return `${hours}h`; }; const columns = [ { title: 'App ID', dataIndex: 'app_id', key: 'app_id', render: (text: string) => {text}, }, { title: 'App Link', dataIndex: 'app_link', key: 'app_link', render: (text: string) => ( {text} ), }, { title: 'Type', dataIndex: 'type', key: 'type', render: (types: string[]) => ( <> {types.map((type) => ( {type.toUpperCase()} ))} ), }, { title: 'Token Prefix', dataIndex: 'token_prefix', key: 'token_prefix', render: (prefix: string) => prefix ? {prefix} : Default, }, { title: 'Owner', dataIndex: 'owner', key: 'owner', render: (owner: Application['owner']) => (
{owner.name}
{owner.type} • {owner.owner}
), }, { title: 'Created', dataIndex: 'created_at', key: 'created_at', render: (date: string) => dayjs(date).format('MMM DD, YYYY'), }, { title: 'Actions', key: 'actions', render: (_: any, record: Application) => ( `${range[0]}-${range[1]} of ${total} applications`, }} /> {/* Create/Edit Modal */} setModalVisible(false)} onOk={() => form.submit()} width={600} >
{ const value = e.target.value.toUpperCase(); form.setFieldValue('token_prefix', value); }} />
{/* Details Modal */} setDetailModalVisible(false)} footer={[ , ]} width={700} > {selectedApp && ( App ID:
{selectedApp.app_id}
App Link:
{selectedApp.app_link}
Type:
{selectedApp.type.map((type) => ( {type.toUpperCase()} ))}
Callback URL:
{selectedApp.callback_url}
HMAC Key:
••••••••••••••••
Token Prefix:
{selectedApp.token_prefix ? ( <> {selectedApp.token_prefix} (Static: {selectedApp.token_prefix}T-, User: {selectedApp.token_prefix}UT-) ) : ( Default (kms_) )}
Token Renewal Duration:
{formatDuration(selectedApp.token_renewal_duration)}
Max Token Duration:
{formatDuration(selectedApp.max_token_duration)}
Type:
{selectedApp.owner.type.toUpperCase()}
Name:
{selectedApp.owner.name}
Contact:
{selectedApp.owner.owner}
Created:
{dayjs(selectedApp.created_at).format('MMMM DD, YYYY HH:mm:ss')}
Updated:
{dayjs(selectedApp.updated_at).format('MMMM DD, YYYY HH:mm:ss')}
)} ); }; export default Applications;