Fix jwt-token
This commit is contained in:
@@ -41,6 +41,16 @@ export const EditAlertModal = ({ rule, onClose, onSuccess }) => {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (rule) {
|
if (rule) {
|
||||||
|
// Normalize alert_channels - ensure it's always an array
|
||||||
|
let alertChannels = rule.alert_channels || ['sms'];
|
||||||
|
if (typeof alertChannels === 'object' && !Array.isArray(alertChannels)) {
|
||||||
|
// Convert object like {sms: true, webhook: false, email: true} to array
|
||||||
|
alertChannels = Object.keys(alertChannels).filter(key => alertChannels[key]);
|
||||||
|
}
|
||||||
|
if (!Array.isArray(alertChannels)) {
|
||||||
|
alertChannels = ['sms']; // fallback to default
|
||||||
|
}
|
||||||
|
|
||||||
setFormData({
|
setFormData({
|
||||||
name: rule.name || '',
|
name: rule.name || '',
|
||||||
description: rule.description || '',
|
description: rule.description || '',
|
||||||
@@ -48,7 +58,7 @@ export const EditAlertModal = ({ rule, onClose, onSuccess }) => {
|
|||||||
min_detections: rule.min_detections || 1,
|
min_detections: rule.min_detections || 1,
|
||||||
time_window: rule.time_window || 300,
|
time_window: rule.time_window || 300,
|
||||||
cooldown_period: rule.cooldown_period || 600,
|
cooldown_period: rule.cooldown_period || 600,
|
||||||
alert_channels: rule.alert_channels || ['sms'],
|
alert_channels: alertChannels,
|
||||||
min_threat_level: rule.min_threat_level || '',
|
min_threat_level: rule.min_threat_level || '',
|
||||||
drone_types: rule.drone_types || [],
|
drone_types: rule.drone_types || [],
|
||||||
device_ids: rule.device_ids || [],
|
device_ids: rule.device_ids || [],
|
||||||
@@ -67,12 +77,17 @@ export const EditAlertModal = ({ rule, onClose, onSuccess }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleChannelChange = (channel, checked) => {
|
const handleChannelChange = (channel, checked) => {
|
||||||
setFormData(prev => ({
|
setFormData(prev => {
|
||||||
...prev,
|
// Ensure alert_channels is always an array
|
||||||
alert_channels: checked
|
const currentChannels = Array.isArray(prev.alert_channels) ? prev.alert_channels : [];
|
||||||
? [...prev.alert_channels, channel]
|
|
||||||
: prev.alert_channels.filter(c => c !== channel)
|
return {
|
||||||
}));
|
...prev,
|
||||||
|
alert_channels: checked
|
||||||
|
? [...currentChannels, channel]
|
||||||
|
: currentChannels.filter(c => c !== channel)
|
||||||
|
};
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleDroneTypeChange = (droneType, checked) => {
|
const handleDroneTypeChange = (droneType, checked) => {
|
||||||
@@ -269,7 +284,7 @@ export const EditAlertModal = ({ rule, onClose, onSuccess }) => {
|
|||||||
<label key={channel} className="flex items-center">
|
<label key={channel} className="flex items-center">
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
checked={formData.alert_channels.includes(channel)}
|
checked={Array.isArray(formData.alert_channels) && formData.alert_channels.includes(channel)}
|
||||||
onChange={(e) => handleChannelChange(channel, e.target.checked)}
|
onChange={(e) => handleChannelChange(channel, e.target.checked)}
|
||||||
className="h-4 w-4 text-primary-600 focus:ring-primary-500 border-gray-300 rounded"
|
className="h-4 w-4 text-primary-600 focus:ring-primary-500 border-gray-300 rounded"
|
||||||
/>
|
/>
|
||||||
@@ -281,7 +296,7 @@ export const EditAlertModal = ({ rule, onClose, onSuccess }) => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{formData.alert_channels.includes('sms') && (
|
{Array.isArray(formData.alert_channels) && formData.alert_channels.includes('sms') && (
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||||
SMS Phone Number
|
SMS Phone Number
|
||||||
@@ -297,7 +312,7 @@ export const EditAlertModal = ({ rule, onClose, onSuccess }) => {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{formData.alert_channels.includes('webhook') && (
|
{Array.isArray(formData.alert_channels) && formData.alert_channels.includes('webhook') && (
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||||
Webhook URL
|
Webhook URL
|
||||||
|
|||||||
@@ -366,14 +366,25 @@ const Alerts = () => {
|
|||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div className="flex space-x-1">
|
<div className="flex space-x-1">
|
||||||
{(rule.alert_channels || []).map((channel, index) => (
|
{(() => {
|
||||||
<span
|
// Normalize alert_channels - ensure it's always an array
|
||||||
key={index}
|
let alertChannels = rule.alert_channels || [];
|
||||||
className="px-2 py-1 bg-blue-100 text-blue-800 rounded text-xs"
|
if (typeof alertChannels === 'object' && !Array.isArray(alertChannels)) {
|
||||||
>
|
// Convert object like {sms: true, webhook: false, email: true} to array
|
||||||
{channel}
|
alertChannels = Object.keys(alertChannels).filter(key => alertChannels[key]);
|
||||||
</span>
|
}
|
||||||
))}
|
if (!Array.isArray(alertChannels)) {
|
||||||
|
alertChannels = []; // fallback to empty array
|
||||||
|
}
|
||||||
|
return alertChannels.map((channel, index) => (
|
||||||
|
<span
|
||||||
|
key={index}
|
||||||
|
className="px-2 py-1 bg-blue-100 text-blue-800 rounded text-xs"
|
||||||
|
>
|
||||||
|
{channel}
|
||||||
|
</span>
|
||||||
|
));
|
||||||
|
})()}
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
@@ -860,12 +871,17 @@ const CreateAlertRuleModal = ({ onClose, onSave }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleChannelChange = (channel, checked) => {
|
const handleChannelChange = (channel, checked) => {
|
||||||
setFormData(prev => ({
|
setFormData(prev => {
|
||||||
...prev,
|
// Ensure alert_channels is always an array
|
||||||
alert_channels: checked
|
const currentChannels = Array.isArray(prev.alert_channels) ? prev.alert_channels : [];
|
||||||
? [...prev.alert_channels, channel]
|
|
||||||
: prev.alert_channels.filter(c => c !== channel)
|
return {
|
||||||
}));
|
...prev,
|
||||||
|
alert_channels: checked
|
||||||
|
? [...currentChannels, channel]
|
||||||
|
: currentChannels.filter(c => c !== channel)
|
||||||
|
};
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleDroneTypeChange = (droneType, checked) => {
|
const handleDroneTypeChange = (droneType, checked) => {
|
||||||
@@ -1000,7 +1016,7 @@ const CreateAlertRuleModal = ({ onClose, onSave }) => {
|
|||||||
<label key={channel} className="flex items-center">
|
<label key={channel} className="flex items-center">
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
checked={formData.alert_channels.includes(channel)}
|
checked={Array.isArray(formData.alert_channels) && formData.alert_channels.includes(channel)}
|
||||||
onChange={(e) => handleChannelChange(channel, e.target.checked)}
|
onChange={(e) => handleChannelChange(channel, e.target.checked)}
|
||||||
className="h-4 w-4 text-primary-600 focus:ring-primary-500 border-gray-300 rounded"
|
className="h-4 w-4 text-primary-600 focus:ring-primary-500 border-gray-300 rounded"
|
||||||
/>
|
/>
|
||||||
@@ -1074,7 +1090,7 @@ const CreateAlertRuleModal = ({ onClose, onSave }) => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Conditional channel-specific fields */}
|
{/* Conditional channel-specific fields */}
|
||||||
{formData.alert_channels.includes('sms') && (
|
{Array.isArray(formData.alert_channels) && formData.alert_channels.includes('sms') && (
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||||
SMS Phone Number
|
SMS Phone Number
|
||||||
@@ -1093,7 +1109,7 @@ const CreateAlertRuleModal = ({ onClose, onSave }) => {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{formData.alert_channels.includes('webhook') && (
|
{Array.isArray(formData.alert_channels) && formData.alert_channels.includes('webhook') && (
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||||
Webhook URL *
|
Webhook URL *
|
||||||
@@ -1102,7 +1118,7 @@ const CreateAlertRuleModal = ({ onClose, onSave }) => {
|
|||||||
type="url"
|
type="url"
|
||||||
name="webhook_url"
|
name="webhook_url"
|
||||||
placeholder="https://your-webhook-endpoint.com/alerts"
|
placeholder="https://your-webhook-endpoint.com/alerts"
|
||||||
required={formData.alert_channels.includes('webhook')}
|
required={Array.isArray(formData.alert_channels) && formData.alert_channels.includes('webhook')}
|
||||||
className="w-full border border-gray-300 rounded-md px-3 py-2 focus:ring-primary-500 focus:border-primary-500"
|
className="w-full border border-gray-300 rounded-md px-3 py-2 focus:ring-primary-500 focus:border-primary-500"
|
||||||
value={formData.webhook_url || ''}
|
value={formData.webhook_url || ''}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
|
|||||||
Reference in New Issue
Block a user