fix(alerts): отклонять запись устаревшего снимка правил

This commit is contained in:
Denozordec committed 2026-10-03 18:41:48 +07:00
1 parent c5c1c2812d
commit 382e318b97
23 files changed
+126 -43

No files matched your search

+8 -4
View File
@@ -1529,7 +1529,7 @@ function AddRuleSheet({
initialForm,
editRuleId,
onTestRuleTelegram,
testTelegramDisabled, saving,saveDisabled,saveError,review,testOutcome,testError,testReview,
testTelegramDisabled, saving,saveDisabled,saveError,review,onRefresh,testOutcome,testError,testReview,
}: {
open: boolean
onClose: () => void
@@ -1538,6 +1538,7 @@ function AddRuleSheet({
saving:boolean
saveDisabled:boolean
saveError:string|null
onRefresh:()=>void
review:React.ReactNode
testOutcome:string|null
testError:string|null
@@ -2199,6 +2200,7 @@ function AddRuleSheet({
Тест в Telegram
</Button>
) : null}
{saveError?<Button type="button" size="sm" variant="outline" className="h-auto whitespace-normal" disabled={saving} onClick={onRefresh}>Обновить снимок — сохранить черновик</Button>:null}
{testError?<p role="alert" className="w-full text-xs text-destructive break-words">{testError}</p>:null}
{testOutcome?<p role="status" className="w-full text-xs break-words">{testOutcome}</p>:null}
{testReview}
@@ -2242,6 +2244,7 @@ function AlertsContent() {
return {...baseMeta,bgpPeers:catalogs.bgp.data?.map(row=>row.serverName+": "+row.name),greTunnelDetail,greTunnelTargets:greTunnelDetail?.map(row=>row.targetLabel)}
},[baseMeta,catalogs.bgp.data,catalogs.servers.data,catalogs.gre.data])
const [configRevision,setConfigRevision]=useState<string|null>(null)
const [known,setKnown]=useState(!isLive)
const [receivedAt,setReceivedAt]=useState<string|null>(null)
const pageActive=useRef(true),reader=useRef<AbortController|null>(null),revision=useRef(0)
@@ -2262,7 +2265,7 @@ function AlertsContent() {
const [operationBusy,setOperationBusy]=useState(false)
const beginOperation=()=>{if(!pageActive.current||operationLock.current)return false;operationLock.current=true;reader.current?.abort();revision.current++;setLoadBusy(false);setOperationBusy(true);return true}
const endOperation=()=>{operationLock.current=false;setOperationBusy(false)}
const config=useAlertsConfigWrite(backendUrl,isLive,known&&backendStatus===true,beginOperation,endOperation)
const config=useAlertsConfigWrite(backendUrl,isLive,known&&backendStatus===true,configRevision,beginOperation,endOperation)
const preview=useAlertsTelegramPreview(backendUrl,isLive,known&&backendStatus===true&&tokenConfigured,beginOperation,endOperation)
const rulesSaveBusy=config.busy
const writesDisabled=!config.enabled||operationBusy||config.unknown
@@ -2317,7 +2320,7 @@ function AlertsContent() {
try {
const data = await getAlerts(backendUrl,{signal:controller.signal})
if(!pageActive.current||requestRevision!==revision.current)return
setKnown(true);setReceivedAt(new Date().toISOString())
setConfigRevision(data.revision);setKnown(true);setReceivedAt(new Date().toISOString())
setTokenConfigured(data.telegram.tokenConfigured)
setTg({
token: "",
@@ -2348,7 +2351,7 @@ function AlertsContent() {
const flushAlertsConfig=useCallback(async(nextRules:AlertRule[],nextGroups:AlertGroup[])=>{
const receipt=await config.save({rules:nextRules.map(toApiRuleBody),groups:nextGroups.map(toApiGroupBody)})
if(!receipt||!pageActive.current)return false
setRules(mapApiRules(receipt.rules));setGroups(mapApiGroups(receipt.groups));return true
setConfigRevision(receipt.revision);setRules(mapApiRules(receipt.rules));setGroups(mapApiGroups(receipt.groups));return true
},[config])
const testRuleTelegramFromForm=async(p:RuleTelegramTestPayload)=>preview.test({
@@ -2809,6 +2812,7 @@ function AlertsContent() {
open={sheetOpen}
onClose={closeRuleSheet}
onSave={handleRuleSheetSave}
onRefresh={()=>void load()}
saving={rulesSaveBusy} saveDisabled={writesDisabled} saveError={config.error??loadError}
review={config.unknown&&!config.busy?<div className="w-full space-y-2"><p role="status" className="text-xs">Результат записи неизвестен. Проверьте правила в БД перед повтором; черновик сохранён в этой форме.</p><Button type="button" size="sm" variant="outline" className="h-auto whitespace-normal" disabled={!config.enabled||operationBusy} onClick={config.review}>Я проверил правила — разрешить новый запрос</Button></div>:null}
typeTargets={typeTargets}