refactor(i18n): Extracted multiple fields in the Service component for translation.
- Extracted multiple fields in the Service component for translation. - Optimized the structure of the translation file, categorizing it by functional modules.
This commit is contained in:
@@ -37,7 +37,7 @@ export function ServiceConfigFields({ form }: ServiceConfigFieldsProps) {
|
||||
name="interval"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Check Interval</FormLabel>
|
||||
<FormLabel>{t("checkInterval")}</FormLabel>
|
||||
{!isCustomInterval ? (
|
||||
<FormControl>
|
||||
<Select onValueChange={handleIntervalChange} value={isCustomInterval ? "custom" : field.value}>
|
||||
@@ -45,13 +45,13 @@ export function ServiceConfigFields({ form }: ServiceConfigFieldsProps) {
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="30">30 seconds</SelectItem>
|
||||
<SelectItem value="60">1 minute</SelectItem>
|
||||
<SelectItem value="300">5 minutes</SelectItem>
|
||||
<SelectItem value="900">15 minutes</SelectItem>
|
||||
<SelectItem value="1800">30 minutes</SelectItem>
|
||||
<SelectItem value="3600">1 hour</SelectItem>
|
||||
<SelectItem value="custom">Custom</SelectItem>
|
||||
<SelectItem value="30">30 {t("seconds")}</SelectItem>
|
||||
<SelectItem value="60">1 {t("minute")}</SelectItem>
|
||||
<SelectItem value="300">5 {t("minutes")}</SelectItem>
|
||||
<SelectItem value="900">15 {t("minutes")}</SelectItem>
|
||||
<SelectItem value="1800">30 {t("minutes")}</SelectItem>
|
||||
<SelectItem value="3600">1 {t("hour")}</SelectItem>
|
||||
<SelectItem value="custom">{t("custom")}</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</FormControl>
|
||||
@@ -60,7 +60,7 @@ export function ServiceConfigFields({ form }: ServiceConfigFieldsProps) {
|
||||
<FormControl>
|
||||
<Input
|
||||
type="number"
|
||||
placeholder="Enter interval in seconds"
|
||||
placeholder={t("checkIntervalPlaceholder")}
|
||||
value={field.value}
|
||||
onChange={field.onChange}
|
||||
min="10"
|
||||
@@ -74,14 +74,14 @@ export function ServiceConfigFields({ form }: ServiceConfigFieldsProps) {
|
||||
}}
|
||||
className="text-sm text-blue-600 hover:text-blue-800"
|
||||
>
|
||||
Back to presets
|
||||
{t("backToPresets")}
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
<FormDescription className="text-xs">
|
||||
{isCustomInterval
|
||||
? "Enter custom interval in seconds (minimum 10 seconds)"
|
||||
: "How often to check the service status"
|
||||
? t("checkIntervalDescCustom")
|
||||
: t("checkIntervalDesc")
|
||||
}
|
||||
</FormDescription>
|
||||
<FormMessage />
|
||||
@@ -94,22 +94,22 @@ export function ServiceConfigFields({ form }: ServiceConfigFieldsProps) {
|
||||
name="retries"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Retry Attempts</FormLabel>
|
||||
<FormLabel>{t("retryAttempts")}</FormLabel>
|
||||
<FormControl>
|
||||
<Select onValueChange={field.onChange} defaultValue={field.value}>
|
||||
<SelectTrigger>
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="1">1 attempt</SelectItem>
|
||||
<SelectItem value="2">2 attempts</SelectItem>
|
||||
<SelectItem value="3">3 attempts</SelectItem>
|
||||
<SelectItem value="5">5 attempts</SelectItem>
|
||||
<SelectItem value="1">1 {t("attempt")}</SelectItem>
|
||||
<SelectItem value="2">2 {t("attempts")}</SelectItem>
|
||||
<SelectItem value="3">3 {t("attempts")}</SelectItem>
|
||||
<SelectItem value="5">5 {t("attempts")}</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</FormControl>
|
||||
<FormDescription className="text-xs">
|
||||
Number of retry attempts before marking as down
|
||||
{t("retryAttemptsDesc")}
|
||||
</FormDescription>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
|
||||
@@ -150,7 +150,7 @@ export function ServiceForm({
|
||||
<ServiceFormActions
|
||||
isSubmitting={isSubmitting}
|
||||
onCancel={onCancel}
|
||||
submitLabel={isEdit ? "Update Service" : "Create Service"}
|
||||
submitLabel={isEdit ? t("updateService") : t("createService")}
|
||||
/>
|
||||
</form>
|
||||
</Form>
|
||||
|
||||
@@ -9,12 +9,14 @@ import { useQuery } from "@tanstack/react-query";
|
||||
import { alertConfigService, AlertConfiguration } from "@/services/alertConfigService";
|
||||
import { serviceNotificationTemplateService, ServiceNotificationTemplate } from "@/services/serviceNotificationTemplateService";
|
||||
import { useState, useEffect } from "react";
|
||||
import { useLanguage } from "@/contexts/LanguageContext.tsx";
|
||||
|
||||
interface ServiceNotificationFieldsProps {
|
||||
form: UseFormReturn<ServiceFormData>;
|
||||
}
|
||||
|
||||
export function ServiceNotificationFields({ form }: ServiceNotificationFieldsProps) {
|
||||
const { t } = useLanguage();
|
||||
const [alertConfigs, setAlertConfigs] = useState<AlertConfiguration[]>([]);
|
||||
|
||||
// Get the current form values for debugging
|
||||
@@ -88,10 +90,10 @@ export function ServiceNotificationFields({ form }: ServiceNotificationFieldsPro
|
||||
<FormItem className="flex flex-row items-center justify-between rounded-lg border p-4">
|
||||
<div className="space-y-0.5">
|
||||
<FormLabel className="text-base">
|
||||
Enable Notifications
|
||||
{t("enableNotifications")}
|
||||
</FormLabel>
|
||||
<FormDescription>
|
||||
Enable or disable notifications for this service
|
||||
{t("enableNotificationsDesc")}
|
||||
</FormDescription>
|
||||
</div>
|
||||
<FormControl>
|
||||
@@ -115,11 +117,11 @@ export function ServiceNotificationFields({ form }: ServiceNotificationFieldsPro
|
||||
name="notificationChannels"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Notification Channels</FormLabel>
|
||||
<FormLabel>{t("notificationChannels")}</FormLabel>
|
||||
<FormDescription>
|
||||
{notificationStatus === "enabled"
|
||||
? "Select notification channels for this service"
|
||||
: "Enable notifications first to select channels"}
|
||||
? t("notificationChannelsEnabledDesc")
|
||||
: t("notificationChannelsDesc")}
|
||||
</FormDescription>
|
||||
|
||||
{/* Display selected channels as badges */}
|
||||
@@ -144,7 +146,7 @@ export function ServiceNotificationFields({ form }: ServiceNotificationFieldsPro
|
||||
value="" // Always reset to empty after selection
|
||||
>
|
||||
<SelectTrigger className={notificationStatus !== "enabled" ? 'opacity-50' : ''}>
|
||||
<SelectValue placeholder="Add a notification channel" />
|
||||
<SelectValue placeholder={t("notificationChannelsPlaceholder")} />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{alertConfigs
|
||||
@@ -169,7 +171,7 @@ export function ServiceNotificationFields({ form }: ServiceNotificationFieldsPro
|
||||
|
||||
return (
|
||||
<FormItem>
|
||||
<FormLabel>Alert Template</FormLabel>
|
||||
<FormLabel>{t("alertTemplate")}</FormLabel>
|
||||
<FormControl>
|
||||
<Select
|
||||
onValueChange={(value) => {
|
||||
@@ -179,7 +181,7 @@ export function ServiceNotificationFields({ form }: ServiceNotificationFieldsPro
|
||||
disabled={notificationStatus !== "enabled" || isLoadingTemplates}
|
||||
>
|
||||
<SelectTrigger className={notificationStatus !== "enabled" ? 'opacity-50' : ''}>
|
||||
<SelectValue placeholder={isLoadingTemplates ? "Loading templates..." : "Select an alert template"} />
|
||||
<SelectValue placeholder={isLoadingTemplates ? t("alertTemplateLoading") : t("alertTemplatePlaceholder")} />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{serviceTemplates?.map((template) => (
|
||||
@@ -192,8 +194,8 @@ export function ServiceNotificationFields({ form }: ServiceNotificationFieldsPro
|
||||
</FormControl>
|
||||
<FormDescription>
|
||||
{notificationStatus === "enabled"
|
||||
? "Choose a template for alert messages"
|
||||
: "Enable notifications first to select template"}
|
||||
? t("alertTemplateEnabledDesc")
|
||||
: t("alertTemplateDesc")}
|
||||
</FormDescription>
|
||||
</FormItem>
|
||||
);
|
||||
|
||||
@@ -9,12 +9,14 @@ import { regionalService } from "@/services/regionalService";
|
||||
import { MapPin, Loader2, X, Plus } from "lucide-react";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { useLanguage } from "@/contexts/LanguageContext.tsx";
|
||||
|
||||
interface ServiceRegionalFieldsProps {
|
||||
form: UseFormReturn<ServiceFormData>;
|
||||
}
|
||||
|
||||
export function ServiceRegionalFields({ form }: ServiceRegionalFieldsProps) {
|
||||
const { t } = useLanguage();
|
||||
const regionalMonitoringEnabled = form.watch("regionalMonitoringEnabled");
|
||||
const currentRegionalAgents = form.watch("regionalAgents") || [];
|
||||
|
||||
@@ -79,10 +81,10 @@ export function ServiceRegionalFields({ form }: ServiceRegionalFieldsProps) {
|
||||
<div className="space-y-0.5">
|
||||
<FormLabel className="text-base font-medium flex items-center gap-2">
|
||||
<MapPin className="h-4 w-4" />
|
||||
Regional Monitoring
|
||||
{t("regionalMonitoring")}
|
||||
</FormLabel>
|
||||
<div className="text-sm text-muted-foreground">
|
||||
Assign this service to regional monitoring agents for distributed monitoring
|
||||
{t("regionalMonitoringDesc")}
|
||||
</div>
|
||||
</div>
|
||||
<FormControl>
|
||||
@@ -107,7 +109,7 @@ export function ServiceRegionalFields({ form }: ServiceRegionalFieldsProps) {
|
||||
name="regionalAgents"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Regional Agents</FormLabel>
|
||||
<FormLabel>{t("regionalAgents")}</FormLabel>
|
||||
|
||||
{/* Display selected agents */}
|
||||
{currentRegionalAgents.length > 0 && (
|
||||
@@ -140,12 +142,12 @@ export function ServiceRegionalFields({ form }: ServiceRegionalFieldsProps) {
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder={
|
||||
isLoading
|
||||
? "Loading agents..."
|
||||
? t("regionalAgentsLoading")
|
||||
: availableAgents.length > 0
|
||||
? "Select additional regional agents..."
|
||||
? t("regionalAgentsAvailablePlaceholder")
|
||||
: currentRegionalAgents.length > 0
|
||||
? "All available agents selected"
|
||||
: "No regional agents available"
|
||||
? t("regionalAgentsAllSelected")
|
||||
: t("regionalAgentsNoAvailable")
|
||||
} />
|
||||
</SelectTrigger>
|
||||
</FormControl>
|
||||
@@ -154,14 +156,14 @@ export function ServiceRegionalFields({ form }: ServiceRegionalFieldsProps) {
|
||||
<SelectItem value="loading" disabled>
|
||||
<div className="flex items-center gap-2">
|
||||
<Loader2 className="h-4 w-4 animate-spin" />
|
||||
Loading agents...
|
||||
t("regionalAgentsLoading")
|
||||
</div>
|
||||
</SelectItem>
|
||||
) : availableAgents.length === 0 ? (
|
||||
<SelectItem value="no-agents" disabled>
|
||||
{currentRegionalAgents.length > 0
|
||||
? "All available agents selected"
|
||||
: "No online regional agents available"
|
||||
? t("regionalAgentsAllSelected")
|
||||
: t("regionalAgentsNoOnlineAvailable")
|
||||
}
|
||||
</SelectItem>
|
||||
) : (
|
||||
@@ -190,13 +192,13 @@ export function ServiceRegionalFields({ form }: ServiceRegionalFieldsProps) {
|
||||
|
||||
{regionalMonitoringEnabled && onlineAgents.length === 0 && !isLoading && (
|
||||
<p className="text-sm text-amber-600">
|
||||
No online regional agents found. Services will use default monitoring.
|
||||
{t("regionalAgentsNotFoundMessage")}
|
||||
</p>
|
||||
)}
|
||||
|
||||
{currentRegionalAgents.length === 0 && regionalMonitoringEnabled && (
|
||||
<p className="text-sm text-orange-600">
|
||||
No regional agents selected. Service will use default monitoring.
|
||||
{t("regionalAgentsNotSelectedMessage")}
|
||||
</p>
|
||||
)}
|
||||
|
||||
|
||||
@@ -4,12 +4,14 @@ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@
|
||||
import { Globe, Wifi, Server, Globe2 } from "lucide-react";
|
||||
import { UseFormReturn } from "react-hook-form";
|
||||
import { ServiceFormData } from "./types";
|
||||
import { useLanguage } from "@/contexts/LanguageContext.tsx";
|
||||
|
||||
interface ServiceTypeFieldProps {
|
||||
form: UseFormReturn<ServiceFormData>;
|
||||
}
|
||||
|
||||
export function ServiceTypeField({ form }: ServiceTypeFieldProps) {
|
||||
const { t } = useLanguage();
|
||||
const getServiceIcon = (type: string) => {
|
||||
switch (type) {
|
||||
case "http":
|
||||
@@ -31,7 +33,7 @@ export function ServiceTypeField({ form }: ServiceTypeFieldProps) {
|
||||
name="type"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Service Type</FormLabel>
|
||||
<FormLabel>{t("serviceType")}</FormLabel>
|
||||
<FormControl>
|
||||
<Select
|
||||
onValueChange={field.onChange}
|
||||
@@ -56,7 +58,7 @@ export function ServiceTypeField({ form }: ServiceTypeFieldProps) {
|
||||
<span>HTTP/S</span>
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground mt-1">
|
||||
Monitor websites and REST APIs with HTTP/HTTPS Protocol
|
||||
{t("serviceTypeHTTPDesc")}
|
||||
</p>
|
||||
</div>
|
||||
</SelectItem>
|
||||
@@ -67,7 +69,7 @@ export function ServiceTypeField({ form }: ServiceTypeFieldProps) {
|
||||
<span>PING</span>
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground mt-1">
|
||||
Monitor host availability with PING Protocol
|
||||
{t("serviceTypePINGDesc")}
|
||||
</p>
|
||||
</div>
|
||||
</SelectItem>
|
||||
@@ -78,7 +80,7 @@ export function ServiceTypeField({ form }: ServiceTypeFieldProps) {
|
||||
<span>TCP</span>
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground mt-1">
|
||||
Monitor TCP port connectivity with TCP Protocol
|
||||
{t("serviceTypeTCPDesc")}
|
||||
</p>
|
||||
</div>
|
||||
</SelectItem>
|
||||
@@ -89,7 +91,7 @@ export function ServiceTypeField({ form }: ServiceTypeFieldProps) {
|
||||
<span>DNS</span>
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground mt-1">
|
||||
Monitor DNS resolution
|
||||
{t("serviceTypeDNSDesc")}
|
||||
</p>
|
||||
</div>
|
||||
</SelectItem>
|
||||
|
||||
@@ -3,12 +3,14 @@ import { FormControl, FormField, FormItem, FormLabel, FormMessage, FormDescripti
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { UseFormReturn } from "react-hook-form";
|
||||
import { ServiceFormData } from "./types";
|
||||
import { useLanguage } from "@/contexts/LanguageContext.tsx";
|
||||
|
||||
interface ServiceUrlFieldProps {
|
||||
form: UseFormReturn<ServiceFormData>;
|
||||
}
|
||||
|
||||
export function ServiceUrlField({ form }: ServiceUrlFieldProps) {
|
||||
const { t } = useLanguage();
|
||||
const serviceType = form.watch("type");
|
||||
|
||||
const getPlaceholder = () => {
|
||||
@@ -22,35 +24,35 @@ export function ServiceUrlField({ form }: ServiceUrlFieldProps) {
|
||||
case "dns":
|
||||
return "example.com";
|
||||
default:
|
||||
return "Enter URL or hostname";
|
||||
return t("targetDefaultPlaceholder");
|
||||
}
|
||||
};
|
||||
|
||||
const getDescription = () => {
|
||||
switch (serviceType) {
|
||||
case "http":
|
||||
return "Enter the full URL including protocol (http:// or https://)";
|
||||
return t("targetHTTPDesc");
|
||||
case "ping":
|
||||
return "Enter hostname or IP address to ping";
|
||||
return t("targetPINGDesc");
|
||||
case "tcp":
|
||||
return "Enter hostname or IP address for TCP connection test";
|
||||
return t("targetTCPDesc");
|
||||
case "dns":
|
||||
return "Enter domain name for DNS record monitoring (A, AAAA, MX, etc.)";
|
||||
return t("targetDNSDesc");
|
||||
default:
|
||||
return "Enter the target URL or hostname for monitoring";
|
||||
return t("targetDefaultDesc");
|
||||
}
|
||||
};
|
||||
|
||||
const getFieldLabel = () => {
|
||||
switch (serviceType) {
|
||||
case "dns":
|
||||
return "Domain Name";
|
||||
return t("targetDNS");
|
||||
case "ping":
|
||||
return "Hostname/IP";
|
||||
case "tcp":
|
||||
return "Hostname/IP";
|
||||
default:
|
||||
return "Target URL/Host";
|
||||
return t("targetDefault");
|
||||
}
|
||||
};
|
||||
|
||||
@@ -99,7 +101,7 @@ export function ServiceUrlField({ form }: ServiceUrlFieldProps) {
|
||||
/>
|
||||
</FormControl>
|
||||
<FormDescription className="text-xs">
|
||||
Enter the port number for TCP connection test
|
||||
{t("targetTCPPortDesc")}
|
||||
</FormDescription>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
|
||||
@@ -170,7 +170,7 @@ const DataRetentionSettings = () => {
|
||||
<Alert className="border-blue-200 bg-blue-50 dark:bg-blue-950 dark:border-blue-800">
|
||||
<AlertTriangle className="h-5 w-5 text-blue-600 dark:text-blue-400" />
|
||||
<AlertDescription className="text-blue-700 dark:text-blue-300">
|
||||
<span className="font-medium">Permission Notice:</span> As an admin user, you do not have access to data retention settings. These settings can only be accessed and modified by Super Admins.
|
||||
<span className="font-medium">{t("permissionNotice")}</span> As an admin user, you do not have access to data retention settings. These settings can only be accessed and modified by Super Admins.
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
</CardContent>
|
||||
|
||||
@@ -143,7 +143,7 @@ const GeneralSettingsPanel: React.FC<GeneralSettingsPanelProps> = () => {
|
||||
<Alert className="border-blue-200 bg-blue-50 dark:bg-blue-950 dark:border-blue-800">
|
||||
<ShieldAlert className="h-5 w-5 text-blue-600 dark:text-blue-400" />
|
||||
<AlertDescription className="text-blue-700 dark:text-blue-300">
|
||||
<span className="font-medium">Permission Notice:</span> As an admin user, you do not have access to view or modify system and mail settings. These settings can only be accessed and modified by Super Admins. Contact your Super Admin if you need to make changes to system configuration or mail settings.
|
||||
<span className="font-medium">{t("permissionNotice")}</span> {t("permissionNoticeAddUser")}
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
</CardContent>
|
||||
@@ -153,11 +153,11 @@ const GeneralSettingsPanel: React.FC<GeneralSettingsPanelProps> = () => {
|
||||
}
|
||||
|
||||
if (isLoading) {
|
||||
return <div className="p-4">Loading settings...</div>;
|
||||
return <div className="p-4">{t("loadingSettings")}</div>;
|
||||
}
|
||||
|
||||
if (error) {
|
||||
return <div className="p-4 text-red-500">Error loading settings</div>;
|
||||
return <div className="p-4 text-red-500">{t("loadingSettingsError")}</div>;
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -10,7 +10,10 @@ import { UserCog, Loader2, AlertCircle, Info, Users, ShieldAlert } from "lucide-
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Alert, AlertDescription } from "@/components/ui/alert";
|
||||
import { authService } from "@/services/authService";
|
||||
import { useLanguage } from "@/contexts/LanguageContext.tsx";
|
||||
|
||||
const UserManagement = () => {
|
||||
const { t } = useLanguage();
|
||||
const {
|
||||
users,
|
||||
loading,
|
||||
@@ -44,21 +47,21 @@ const UserManagement = () => {
|
||||
<AccordionTrigger className="py-4 px-5 bg-card hover:bg-card/90 hover:no-underline rounded-lg text-lg font-medium flex items-center w-full">
|
||||
<div className="flex items-center">
|
||||
<UserCog className="h-5 w-5 mr-2 text-green-500" />
|
||||
<span>User Management</span>
|
||||
<span>{t("userManagement")}</span>
|
||||
</div>
|
||||
</AccordionTrigger>
|
||||
<AccordionContent className="p-4 pt-6 bg-background rounded-b-lg">
|
||||
<div className="flex justify-between items-center mb-6">
|
||||
<h2 className="text-2xl font-bold">User Management</h2>
|
||||
<h2 className="text-2xl font-bold">{t("userManagement")}</h2>
|
||||
{isSuperAdmin && <button onClick={() => setIsAddUserDialogOpen(true)} className="bg-green-500 hover:bg-green-600 text-white py-2 px-4 rounded-md flex items-center">
|
||||
<span className="mr-1">+</span> Add User
|
||||
<span className="mr-1">+</span> {t("addUser")}
|
||||
</button>}
|
||||
</div>
|
||||
|
||||
{!isSuperAdmin && <Alert className="mb-6 border-blue-200 bg-blue-50 dark:bg-blue-950 dark:border-blue-800">
|
||||
<ShieldAlert className="h-5 w-5 text-blue-600 dark:text-blue-400" />
|
||||
<AlertDescription className="text-blue-700 dark:text-blue-300">
|
||||
<span className="font-medium">Permission Notice:</span> As an admin user, you have access to view and modify existing user details. However, only Super Admins have permission to create new user accounts. Contact your Super Admin if you need to add a new user.
|
||||
<span className="font-medium">{t("permissionNotice")}</span> As an admin user, you have access to view and modify existing user details. However, only Super Admins have permission to create new user accounts. Contact your Super Admin if you need to add a new user.
|
||||
</AlertDescription>
|
||||
</Alert>}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user