Spaces:
Runtime error
Runtime error
| import React, { useState } from 'react' | |
| import { | |
| Card, | |
| CardContent, | |
| TextField, | |
| Button, | |
| Box, | |
| Alert as MuiAlert, | |
| FormControl, | |
| InputLabel, | |
| Select, | |
| MenuItem, | |
| Chip, | |
| OutlinedInput, | |
| Typography, | |
| } from '@mui/material' | |
| import { alertsApi } from '../api' | |
| export const CreateAlert: React.FC = () => { | |
| const [formData, setFormData] = useState({ | |
| source: '', | |
| source_id: '', | |
| title: '', | |
| description: '', | |
| severity: 'HIGH' as const, | |
| category: '', | |
| affected_service: [] as string[], | |
| tags: [] as string[], | |
| }) | |
| const [loading, setLoading] = useState(false) | |
| const [success, setSuccess] = useState(false) | |
| const [error, setError] = useState<string | null>(null) | |
| const [serviceInput, setServiceInput] = useState('') | |
| const [tagInput, setTagInput] = useState('') | |
| const handleChange = (e: React.ChangeEvent<HTMLInputElement | { name?: string; value: unknown }>) => { | |
| const name = e.target.name as string | |
| const value = e.target.value | |
| setFormData((prev) => ({ | |
| ...prev, | |
| [name]: value, | |
| })) | |
| } | |
| const handleAddService = () => { | |
| if (serviceInput.trim() && !formData.affected_service.includes(serviceInput)) { | |
| setFormData((prev) => ({ | |
| ...prev, | |
| affected_service: [...prev.affected_service, serviceInput], | |
| })) | |
| setServiceInput('') | |
| } | |
| } | |
| const handleAddTag = () => { | |
| if (tagInput.trim() && !formData.tags.includes(tagInput)) { | |
| setFormData((prev) => ({ | |
| ...prev, | |
| tags: [...prev.tags, tagInput], | |
| })) | |
| setTagInput('') | |
| } | |
| } | |
| const handleRemoveService = (service: string) => { | |
| setFormData((prev) => ({ | |
| ...prev, | |
| affected_service: prev.affected_service.filter((s) => s !== service), | |
| })) | |
| } | |
| const handleRemoveTag = (tag: string) => { | |
| setFormData((prev) => ({ | |
| ...prev, | |
| tags: prev.tags.filter((t) => t !== tag), | |
| })) | |
| } | |
| const handleSubmit = async (e: React.FormEvent) => { | |
| e.preventDefault() | |
| if (!formData.source || !formData.source_id || !formData.title) { | |
| setError('Please fill in all required fields (Source, Source ID, Title)') | |
| return | |
| } | |
| try { | |
| setLoading(true) | |
| setError(null) | |
| await alertsApi.createAlert(formData) | |
| setSuccess(true) | |
| setFormData({ | |
| source: '', | |
| source_id: '', | |
| title: '', | |
| description: '', | |
| severity: 'HIGH', | |
| category: '', | |
| affected_service: [], | |
| tags: [], | |
| }) | |
| setTimeout(() => setSuccess(false), 3000) | |
| } catch (err: any) { | |
| setError(err.message || 'Failed to create alert') | |
| } finally { | |
| setLoading(false) | |
| } | |
| } | |
| return ( | |
| <Card> | |
| <CardContent> | |
| <Typography variant="h6" gutterBottom> | |
| Create New Alert | |
| </Typography> | |
| {success && ( | |
| <MuiAlert severity="success" sx={{ mb: 2 }}> | |
| Alert created successfully! | |
| </MuiAlert> | |
| )} | |
| {error && ( | |
| <MuiAlert severity="error" sx={{ mb: 2 }}> | |
| {error} | |
| </MuiAlert> | |
| )} | |
| <Box component="form" onSubmit={handleSubmit} sx={{ display: 'flex', flexDirection: 'column', gap: 2 }}> | |
| {/* Source */} | |
| <TextField | |
| label="Source (Required)" | |
| name="source" | |
| value={formData.source} | |
| onChange={handleChange} | |
| placeholder="e.g., prometheus, datadog, newrelic" | |
| fullWidth | |
| required | |
| /> | |
| {/* Source ID */} | |
| <TextField | |
| label="Source ID (Required)" | |
| name="source_id" | |
| value={formData.source_id} | |
| onChange={handleChange} | |
| placeholder="e.g., prom_001, dd_alert_123" | |
| fullWidth | |
| required | |
| /> | |
| {/* Title */} | |
| <TextField | |
| label="Title (Required)" | |
| name="title" | |
| value={formData.title} | |
| onChange={handleChange} | |
| placeholder="e.g., High CPU Usage" | |
| fullWidth | |
| required | |
| /> | |
| {/* Description */} | |
| <TextField | |
| label="Description" | |
| name="description" | |
| value={formData.description} | |
| onChange={handleChange} | |
| placeholder="Alert details" | |
| fullWidth | |
| multiline | |
| rows={3} | |
| /> | |
| {/* Severity */} | |
| <FormControl fullWidth> | |
| <InputLabel>Severity</InputLabel> | |
| <Select | |
| name="severity" | |
| value={formData.severity} | |
| onChange={handleChange} | |
| label="Severity" | |
| > | |
| <MenuItem value="CRITICAL">🔴 CRITICAL</MenuItem> | |
| <MenuItem value="HIGH">🟠 HIGH</MenuItem> | |
| <MenuItem value="MEDIUM">🟡 MEDIUM</MenuItem> | |
| <MenuItem value="LOW">🔵 LOW</MenuItem> | |
| <MenuItem value="INFO">⚪ INFO</MenuItem> | |
| </Select> | |
| </FormControl> | |
| {/* Category */} | |
| <TextField | |
| label="Category" | |
| name="category" | |
| value={formData.category} | |
| onChange={handleChange} | |
| placeholder="e.g., Performance, Security, Infrastructure" | |
| fullWidth | |
| /> | |
| {/* Affected Services */} | |
| <Box> | |
| <Box sx={{ display: 'flex', gap: 1, mb: 1 }}> | |
| <TextField | |
| label="Add Service" | |
| value={serviceInput} | |
| onChange={(e) => setServiceInput(e.target.value)} | |
| placeholder="api-server" | |
| size="small" | |
| sx={{ flex: 1 }} | |
| onKeyPress={(e) => e.key === 'Enter' && (e.preventDefault(), handleAddService())} | |
| /> | |
| <Button onClick={handleAddService} variant="outlined" size="small"> | |
| Add | |
| </Button> | |
| </Box> | |
| <Box sx={{ display: 'flex', gap: 1, flexWrap: 'wrap' }}> | |
| {formData.affected_service.map((service) => ( | |
| <Chip | |
| key={service} | |
| label={service} | |
| onDelete={() => handleRemoveService(service)} | |
| color="primary" | |
| variant="outlined" | |
| /> | |
| ))} | |
| </Box> | |
| </Box> | |
| {/* Tags */} | |
| <Box> | |
| <Box sx={{ display: 'flex', gap: 1, mb: 1 }}> | |
| <TextField | |
| label="Add Tag" | |
| value={tagInput} | |
| onChange={(e) => setTagInput(e.target.value)} | |
| placeholder="production" | |
| size="small" | |
| sx={{ flex: 1 }} | |
| onKeyPress={(e) => e.key === 'Enter' && (e.preventDefault(), handleAddTag())} | |
| /> | |
| <Button onClick={handleAddTag} variant="outlined" size="small"> | |
| Add | |
| </Button> | |
| </Box> | |
| <Box sx={{ display: 'flex', gap: 1, flexWrap: 'wrap' }}> | |
| {formData.tags.map((tag) => ( | |
| <Chip | |
| key={tag} | |
| label={tag} | |
| onDelete={() => handleRemoveTag(tag)} | |
| color="secondary" | |
| variant="outlined" | |
| /> | |
| ))} | |
| </Box> | |
| </Box> | |
| {/* Submit Button */} | |
| <Button | |
| type="submit" | |
| variant="contained" | |
| size="large" | |
| disabled={loading} | |
| sx={{ mt: 2 }} | |
| > | |
| {loading ? 'Creating...' : 'Create Alert'} | |
| </Button> | |
| </Box> | |
| </CardContent> | |
| </Card> | |
| ) | |
| } | |