fix: Duplicate template options (#51)

* fix: Duplicate template options

* fix: form option i18n text
This commit is contained in:
仓鼠
2024-12-14 10:16:33 +08:00
committed by GitHub
parent 8c8d3e3057
commit d67b9ff4d2
11 changed files with 46 additions and 128 deletions

View File

@@ -205,11 +205,13 @@ export const AlertRuleCard: React.FC<AlertRuleCardProps> = ({ data, mutate }) =>
</SelectTrigger> </SelectTrigger>
</FormControl> </FormControl>
<SelectContent> <SelectContent>
{Object.entries(triggerModes).map(([k, v]) => ( {Object.entries(triggerModes(t)).map(
<SelectItem key={k} value={k}> ([k, v]) => (
{v} <SelectItem key={k} value={k}>
</SelectItem> {v}
))} </SelectItem>
),
)}
</SelectContent> </SelectContent>
</Select> </Select>
<FormMessage /> <FormMessage />

View File

@@ -143,7 +143,7 @@ export const CronCard: React.FC<CronCardProps> = ({ data, mutate }) => {
</SelectTrigger> </SelectTrigger>
</FormControl> </FormControl>
<SelectContent> <SelectContent>
{Object.entries(cronTypes).map(([k, v]) => ( {Object.entries(cronTypes(t)).map(([k, v]) => (
<SelectItem key={k} value={k}> <SelectItem key={k} value={k}>
{v} {v}
</SelectItem> </SelectItem>
@@ -199,7 +199,7 @@ export const CronCard: React.FC<CronCardProps> = ({ data, mutate }) => {
</SelectTrigger> </SelectTrigger>
</FormControl> </FormControl>
<SelectContent> <SelectContent>
{Object.entries(cronCoverageTypes).map( {Object.entries(cronCoverageTypes(t)).map(
([k, v]) => ( ([k, v]) => (
<SelectItem key={k} value={k}> <SelectItem key={k} value={k}>
{v} {v}

View File

@@ -247,7 +247,7 @@ export const ServiceCard: React.FC<ServiceCardProps> = ({ data, mutate }) => {
</SelectTrigger> </SelectTrigger>
</FormControl> </FormControl>
<SelectContent> <SelectContent>
{Object.entries(serviceCoverageTypes).map( {Object.entries(serviceCoverageTypes(t)).map(
([k, v]) => ( ([k, v]) => (
<SelectItem key={k} value={k}> <SelectItem key={k} value={k}>
{v} {v}

View File

@@ -81,7 +81,7 @@ export default function AlertRulePage() {
{ {
header: t("TriggerMode"), header: t("TriggerMode"),
accessorKey: "trigger Mode", accessorKey: "trigger Mode",
accessorFn: (row) => triggerModes[row.trigger_mode] || "", accessorFn: (row) => triggerModes(t)[row.trigger_mode] || "",
}, },
{ {
header: t("Rules"), header: t("Rules"),

View File

@@ -74,7 +74,7 @@ export default function CronPage() {
{ {
header: t("Type"), header: t("Type"),
accessorKey: "taskType", accessorKey: "taskType",
accessorFn: (row) => cronTypes[row.task_type] || "", accessorFn: (row) => cronTypes(t)[row.task_type] || "",
}, },
{ {
header: t("CronExpression"), header: t("CronExpression"),

View File

@@ -248,92 +248,6 @@ export default function SettingsPage() {
</FormItem> </FormItem>
)} )}
/> />
<FormField
control={form.control}
name="user_template"
render={({ field }) => (
<FormItem>
<FormLabel>{t("Theme")}</FormLabel>
<FormControl>
<Select
value={field.value}
onValueChange={(value) => {
const template = config?.frontend_templates?.find(
(t) => t.path === value,
)
if (template) {
form.setValue(
"user_template",
template.path ?? "",
)
}
}}
>
<FormControl>
<SelectTrigger>
<SelectValue placeholder={t("SelectTheme")} />
</SelectTrigger>
</FormControl>
<SelectContent>
{(
config?.frontend_templates?.filter(
(t) => !t.is_admin,
) || []
).map((template) => (
<div key={template.path}>
<SelectItem value={template.path!}>
<div className="flex flex-col items-start gap-1">
<div className="font-medium">
{template.name}
</div>
<div className="flex items-center gap-2 text-sm text-muted-foreground">
<span>
{t("Author")}:{" "}
{template.author}
</span>
{!template.is_official ? (
<span className="px-1.5 py-0.5 rounded-md bg-red-100 text-red-800 text-xs">
{t("Community")}
</span>
) : (
<span className="px-1.5 py-0.5 rounded-md bg-blue-100 text-blue-800 text-xs">
{t("Official")}
</span>
)}
</div>
</div>
</SelectItem>
<div className="px-8 py-1">
<a
href={template.repository}
target="_blank"
rel="noopener noreferrer"
className="text-sm text-blue-600 hover:text-blue-800 hover:underline"
>
{template.repository}
</a>
</div>
</div>
))}
</SelectContent>
</Select>
</FormControl>
<FormMessage />
{!config?.frontend_templates?.find(
(t) => t.path === field.value,
)?.is_official && (
<div className="mt-2 text-sm text-yellow-700 dark:text-yellow-200 bg-yellow-100 dark:bg-yellow-900 border border-yellow-200 dark:border-yellow-700 rounded-md p-2">
<div className="font-medium text-lg mb-1">
{t("CommunityThemeWarning")}
</div>
<div className="text-yellow-700 dark:text-yellow-200">
{t("CommunityThemeDescription")}
</div>
</div>
)}
</FormItem>
)}
/>
<FormField <FormField
control={form.control} control={form.control}
name="custom_code" name="custom_code"
@@ -469,7 +383,7 @@ export default function SettingsPage() {
</FormControl> </FormControl>
<SelectContent> <SelectContent>
{Object.entries( {Object.entries(
settingCoverageTypes, settingCoverageTypes(t),
).map(([k, v]) => ( ).map(([k, v]) => (
<SelectItem key={k} value={k}> <SelectItem key={k} value={k}>
{v} {v}

View File

@@ -69,7 +69,9 @@ export default function WAFPage() {
header: t("LastBlockReason"), header: t("LastBlockReason"),
accessorKey: "lastBlockReason", accessorKey: "lastBlockReason",
accessorFn: (row) => row.last_block_reason, accessorFn: (row) => row.last_block_reason,
cell: ({ row }) => <span>{wafBlockReasons[row.original.last_block_reason] || ""}</span>, cell: ({ row }) => (
<span>{wafBlockReasons(t)[row.original.last_block_reason] || ""}</span>
),
}, },
{ {
header: t("LastBlockTime"), header: t("LastBlockTime"),

View File

@@ -1,6 +1,6 @@
import i18next from "i18next" import { TFunction } from "i18next"
export const triggerModes: Record<number, string> = { export const triggerModes = (t: TFunction<"translation", undefined>) => ({
0: i18next.t("Always"), 0: t("Always"),
1: i18next.t("Once"), 1: t("Once"),
} })

View File

@@ -1,12 +1,12 @@
import i18next from "i18next" import { TFunction } from "i18next"
export const cronTypes: Record<number, string> = { export const cronTypes = (t: TFunction<"translation", undefined>) => ({
0: i18next.t("Scheduled"), 0: t("Scheduled"),
1: i18next.t("Trigger"), 1: t("Trigger"),
} })
export const cronCoverageTypes: Record<number, string> = { export const cronCoverageTypes = (t: TFunction<"translation", undefined>) => ({
0: i18next.t("Coverages.Only"), 0: t("Coverages.Only"),
1: i18next.t("Coverages.Excludes"), 1: t("Coverages.Excludes"),
2: i18next.t("Coverages.Alarmed"), 2: t("Coverages.Alarmed"),
} })

View File

@@ -1,4 +1,4 @@
import i18next from "i18next" import { TFunction } from "i18next"
export const serviceTypes: Record<number, string> = { export const serviceTypes: Record<number, string> = {
1: "HTTP GET", 1: "HTTP GET",
@@ -6,7 +6,7 @@ export const serviceTypes: Record<number, string> = {
3: "TCPing", 3: "TCPing",
} }
export const serviceCoverageTypes: Record<number, string> = { export const serviceCoverageTypes = (t: TFunction<"translation", undefined>) => ({
0: i18next.t("Coverages.Excludes"), 0: t("Coverages.Excludes"),
1: i18next.t("Coverages.Only"), 1: t("Coverages.Only"),
} })

View File

@@ -1,9 +1,9 @@
import i18next from "i18next" import { TFunction } from "i18next"
export const settingCoverageTypes: Record<number, string> = { export const settingCoverageTypes = (t: TFunction<"translation", undefined>) => ({
1: i18next.t("Coverages.Excludes"), 1: t("Coverages.Excludes"),
2: i18next.t("Coverages.Only"), 2: t("Coverages.Only"),
} })
export const nezhaLang: Record<string, string> = { export const nezhaLang: Record<string, string> = {
"zh-CN": "简体中文(中国大陆)", "zh-CN": "简体中文(中国大陆)",
@@ -11,8 +11,8 @@ export const nezhaLang: Record<string, string> = {
"en-US": "English", "en-US": "English",
} }
export const wafBlockReasons: Record<number, string> = { export const wafBlockReasons = (t: TFunction<"translation", undefined>) => ({
1: i18next.t("LoginFailed"), 1: t("LoginFailed"),
2: i18next.t("BruteForceAttackingToken"), 2: t("BruteForceAttackingToken"),
3: i18next.t("BruteForceAttackingAgentSecret"), 3: t("BruteForceAttackingAgentSecret"),
} })