mirror of
https://github.com/SECTL/SecScore.git
synced 2026-07-19 19:04:23 +08:00
eef6b703f7
- Added support for trigger trees in AutoScoreRule interface. - Implemented functions to convert query trees to JSON and vice versa. - Updated IntervalValue to use days, hours, and minutes instead of a single amount and unit. - Refactored IntervalValueWidget to allow separate input for days, hours, and minutes. - Added validation to ensure at least one interval trigger is present. - Enhanced user interface with informative alerts and tooltips for better user experience. - Updated localization files to include new strings for interval triggers and UI elements.
90 lines
3.0 KiB
TypeScript
90 lines
3.0 KiB
TypeScript
import React from "react"
|
|
import { InputNumber } from "antd"
|
|
import type { WidgetProps } from "@react-awesome-query-builder/antd"
|
|
import { useTranslation } from "react-i18next"
|
|
import {
|
|
getDefaultIntervalValue,
|
|
parseIntervalTriggerValue,
|
|
stringifyIntervalTriggerValue,
|
|
type IntervalValue,
|
|
} from "./IntervalValueCodec"
|
|
|
|
export { parseIntervalTriggerValue, stringifyIntervalTriggerValue } from "./IntervalValueCodec"
|
|
export type { IntervalValue, IntervalUnit } from "./IntervalValueCodec"
|
|
|
|
const buildNextIntervalValue = (
|
|
currentValue: IntervalValue | null,
|
|
patch: Partial<IntervalValue>
|
|
): IntervalValue => {
|
|
const base = currentValue ?? getDefaultIntervalValue()
|
|
return {
|
|
days: patch.days ?? base.days,
|
|
hours: patch.hours ?? base.hours,
|
|
minutes: patch.minutes ?? base.minutes,
|
|
}
|
|
}
|
|
|
|
const getDisplayValue = (value: number | undefined, fallback = 0) =>
|
|
typeof value === "number" && Number.isFinite(value) ? value : fallback
|
|
|
|
export const IntervalValueWidget: React.FC<WidgetProps> = ({
|
|
value,
|
|
setValue,
|
|
readonly,
|
|
}) => {
|
|
const { t } = useTranslation()
|
|
const parsedValue = parseIntervalTriggerValue(value)
|
|
|
|
const updateValue = (patch: Partial<IntervalValue>) => {
|
|
const nextValue = buildNextIntervalValue(parsedValue, patch)
|
|
const serialized = stringifyIntervalTriggerValue(nextValue)
|
|
setValue(serialized)
|
|
}
|
|
|
|
return (
|
|
<div style={{ display: "flex", gap: 12, minWidth: 360 }}>
|
|
<div style={{ display: "flex", flexDirection: "column", gap: 6, minWidth: 96 }}>
|
|
<span style={{ fontSize: 12, color: "var(--ss-text-secondary)" }}>
|
|
{t("autoScore.intervalPartDay")}
|
|
</span>
|
|
<InputNumber
|
|
min={0}
|
|
precision={0}
|
|
disabled={readonly}
|
|
value={getDisplayValue(parsedValue?.days)}
|
|
onChange={(next) => updateValue({ days: Math.max(0, Number(next ?? 0)) })}
|
|
style={{ width: "100%" }}
|
|
/>
|
|
</div>
|
|
<div style={{ display: "flex", flexDirection: "column", gap: 6, minWidth: 96 }}>
|
|
<span style={{ fontSize: 12, color: "var(--ss-text-secondary)" }}>
|
|
{t("autoScore.intervalPartHour")}
|
|
</span>
|
|
<InputNumber
|
|
min={0}
|
|
precision={0}
|
|
disabled={readonly}
|
|
value={getDisplayValue(parsedValue?.hours)}
|
|
onChange={(next) => updateValue({ hours: Math.max(0, Number(next ?? 0)) })}
|
|
style={{ width: "100%" }}
|
|
/>
|
|
</div>
|
|
<div style={{ display: "flex", flexDirection: "column", gap: 6, minWidth: 96 }}>
|
|
<span style={{ fontSize: 12, color: "var(--ss-text-secondary)" }}>
|
|
{t("autoScore.intervalPartMinute")}
|
|
</span>
|
|
<InputNumber
|
|
min={0}
|
|
precision={0}
|
|
disabled={readonly}
|
|
value={getDisplayValue(parsedValue?.minutes)}
|
|
onChange={(next) => updateValue({ minutes: Math.max(0, Number(next ?? 0)) })}
|
|
style={{ width: "100%" }}
|
|
/>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export default IntervalValueWidget
|