feat: add ast function for user scoring condition#1520
Conversation
8802e86 to
5e9842a
Compare
|
ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (16)
🚧 Files skipped from review as they are similar to previous changes (12)
📜 Recent review details⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
🧰 Additional context used📓 Path-based instructions (6)**/*.{ts,tsx}📄 CodeRabbit inference engine (CLAUDE.md)
Files:
packages/app-builder/src/components/**/*.tsx📄 CodeRabbit inference engine (CLAUDE.md)
Files:
**/*.{ts,tsx,js,jsx,json,css}📄 CodeRabbit inference engine (CLAUDE.md)
Files:
packages/app-builder/src/**/*.{ts,tsx}📄 CodeRabbit inference engine (CLAUDE.md)
Files:
packages/app-builder/src/services/**/*.{ts,tsx}📄 CodeRabbit inference engine (CLAUDE.md)
Files:
packages/app-builder/src/routes/**/*.tsx📄 CodeRabbit inference engine (CLAUDE.md)
Files:
🔇 Additional comments (5)
📝 WalkthroughWalkthroughThis PR adds a Record Risk Level Check operand: AST node + type guard, edit modal and multi-select editor, operand display chips, menu registration with scoring-ruleset gating, server builderOptions enriched with scoring data, route loader consolidation to use getBuilderOptionsFn, and i18n entries. ChangesRecord Risk Level Check Operand
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 7
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@packages/app-builder/src/components/AstBuilder/edition/EditModal/modals/RecordRiskLevelCheck/RecordRiskLevelCheck.tsx`:
- Around line 3-9: The imports for RecordRiskLevelCheckAstNode and MaxRiskLevel
are used only as types and must be marked with the type modifier to satisfy
Biome's useImportType rule; update the import statements that bring in
RecordRiskLevelCheckAstNode and MaxRiskLevel so they use "import type" (i.e.,
import type { RecordRiskLevelCheckAstNode } and import type { MaxRiskLevel })
while leaving the runtime imports (SCORING_LEVELS_COLORS,
SCORING_LEVELS_LABEL_KEYS, scoringLevelEntries) as normal imports.
- Around line 62-77: Replace the hardcoded placeholder on the SelectV2 component
and the copied translation key used in the Callout with dedicated i18n keys:
change placeholder="Risk Level" to
placeholder={t('scenarios:record_risk_level.placeholder')} and replace
t('scenarios:edit_ip_has_flag.premium_callout') with
t('scenarios:record_risk_level.premium_callout'); then add the corresponding
keys (record_risk_level.placeholder and record_risk_level.premium_callout) to
the en/scenarios.json and the fr/ar locale files with appropriate translations.
- Around line 24-26: The code casts scoringSettings.maxRiskLevel to MaxRiskLevel
without validation; import isMaxRiskLevelInRange and use it to guard access to
SCORING_LEVELS_COLORS and calls to scoringLevelEntries so you only call
scoringLevelEntries(...) when scoringSettings exists AND
isMaxRiskLevelInRange(scoringSettings.maxRiskLevel) is true; otherwise set
levelColorsEntries to null (or a safe fallback). Update the import list to
include isMaxRiskLevelInRange and reference scoringSettings,
SCORING_LEVELS_COLORS, scoringLevelEntries, and MaxRiskLevel in the guarded
logic.
In `@packages/app-builder/src/components/AstBuilder/OperandInfos.tsx`:
- Around line 150-163: The code indexes levelColorsMap[level] and
levelLabelsMap[level] without guarding against invalid keys (the cast on
scoringSettings.maxRiskLevel can hide runtime mismatches), which can throw; in
the render path (around levelColorsMap, levelLabelsMap,
node.children[0].constant and the t(...) call) validate that the maps exist and
the specific level key exists before using them (e.g., compute safeLevelColors/
safeLevelLabels from SCORING_LEVELS_COLORS and SCORING_LEVELS_LABEL_KEYS with a
fallback map or filter node.children[0].constant to include only keys present in
the maps), and use a sensible default color/label or skip rendering that level
to avoid runtime crashes.
In `@packages/app-builder/src/models/astNode/builder-ast-node.ts`:
- Line 19: The import of RecordRiskLevelCheckAstNode should be a type-only
import to match others and satisfy Biome's useImportType rule: change the import
line that currently imports isRecordRiskLevelCheckAstNode and
RecordRiskLevelCheckAstNode from './risk' so that RecordRiskLevelCheckAstNode is
prefixed with the type modifier (i.e., import isRecordRiskLevelCheckAstNode,
type RecordRiskLevelCheckAstNode from './risk'), leaving
isRecordRiskLevelCheckAstNode as a value import.
In `@packages/app-builder/src/server-fns/scenarios.ts`:
- Line 51: The import for ScoringSettings is using a relative path and missing
the type modifier; update the import in scenarios.ts to use the project alias
and declare it as a type import (e.g., import type { ScoringSettings } from
'@app-builder/models/scoring') so the symbol ScoringSettings is imported via the
`@app-builder/models` path and treated as a type-only import.
In `@packages/app-builder/src/services/ast-node/getAstNodeDisplayName.ts`:
- Around line 108-110: The hardcoded English string in getAstNodeDisplayName
should be replaced with a translation key so the label localizes; change the
branch that checks isRecordRiskLevelCheckAstNode(astNode) to return a
translation key (e.g., 'astNode.matchRiskLevel') or call the project's i18n
helper (e.g., i18n.t('astNode.matchRiskLevel')) consistent with how other
branches in getAstNodeDisplayName produce localized labels.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: b27907f3-e638-404e-b083-ce6200dee4e7
📒 Files selected for processing (16)
packages/app-builder/src/components/AstBuilder/OperandInfos.tsxpackages/app-builder/src/components/AstBuilder/edition/EditModal/EditModal.tsxpackages/app-builder/src/components/AstBuilder/edition/EditModal/modals/RecordRiskLevelCheck/RecordRiskLevelCheck.tsxpackages/app-builder/src/components/AstBuilder/edition/OperandMenu/MenuOption.tsxpackages/app-builder/src/components/AstBuilder/edition/base-options.tspackages/app-builder/src/components/UserScoring/ScoringRuleEditPanel.tsxpackages/app-builder/src/locales/ar/scenarios.jsonpackages/app-builder/src/locales/en/scenarios.jsonpackages/app-builder/src/locales/fr/scenarios.jsonpackages/app-builder/src/models/astNode/builder-ast-node.tspackages/app-builder/src/models/astNode/risk.tspackages/app-builder/src/routes/_app/_builder/detection/scenarios/$scenarioId/i/$iterationId/_edit-view/trigger.tsxpackages/app-builder/src/routes/_app/_builder/detection/scenarios/$scenarioId/i/$iterationId/rules.$ruleId.tsxpackages/app-builder/src/routes/_app/_builder/detection/scenarios/$scenarioId/i/$iterationId/screenings.$screeningId.tsxpackages/app-builder/src/server-fns/scenarios.tspackages/app-builder/src/services/ast-node/getAstNodeDisplayName.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: check / main
- GitHub Check: e2e
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx}: Import internal app-builder models using the path alias@app-builder/models/*
Import UI components fromui-design-systemusing direct imports likeimport { Button, Modal, Select, cn } from 'ui-design-system'
Use TanStack Query hooks for server state management, importing from@app-builder/queries/*
Use TanStack Form for form handling
Use Zod for schema validation
Files:
packages/app-builder/src/components/UserScoring/ScoringRuleEditPanel.tsxpackages/app-builder/src/services/ast-node/getAstNodeDisplayName.tspackages/app-builder/src/components/AstBuilder/edition/EditModal/EditModal.tsxpackages/app-builder/src/components/AstBuilder/edition/base-options.tspackages/app-builder/src/models/astNode/builder-ast-node.tspackages/app-builder/src/components/AstBuilder/edition/EditModal/modals/RecordRiskLevelCheck/RecordRiskLevelCheck.tsxpackages/app-builder/src/server-fns/scenarios.tspackages/app-builder/src/routes/_app/_builder/detection/scenarios/$scenarioId/i/$iterationId/rules.$ruleId.tsxpackages/app-builder/src/models/astNode/risk.tspackages/app-builder/src/routes/_app/_builder/detection/scenarios/$scenarioId/i/$iterationId/screenings.$screeningId.tsxpackages/app-builder/src/components/AstBuilder/OperandInfos.tsxpackages/app-builder/src/routes/_app/_builder/detection/scenarios/$scenarioId/i/$iterationId/_edit-view/trigger.tsxpackages/app-builder/src/components/AstBuilder/edition/OperandMenu/MenuOption.tsx
packages/app-builder/src/components/**/*.tsx
📄 CodeRabbit inference engine (CLAUDE.md)
Organize app-builder source code into feature-specific component folders (Cases/, Decisions/, etc.) within the components directory
Files:
packages/app-builder/src/components/UserScoring/ScoringRuleEditPanel.tsxpackages/app-builder/src/components/AstBuilder/edition/EditModal/EditModal.tsxpackages/app-builder/src/components/AstBuilder/edition/EditModal/modals/RecordRiskLevelCheck/RecordRiskLevelCheck.tsxpackages/app-builder/src/components/AstBuilder/OperandInfos.tsxpackages/app-builder/src/components/AstBuilder/edition/OperandMenu/MenuOption.tsx
**/*.{ts,tsx,js,jsx,json,css}
📄 CodeRabbit inference engine (CLAUDE.md)
Run
bun run format:writeto format all files according to Biome standards
Files:
packages/app-builder/src/components/UserScoring/ScoringRuleEditPanel.tsxpackages/app-builder/src/services/ast-node/getAstNodeDisplayName.tspackages/app-builder/src/components/AstBuilder/edition/EditModal/EditModal.tsxpackages/app-builder/src/locales/ar/scenarios.jsonpackages/app-builder/src/locales/fr/scenarios.jsonpackages/app-builder/src/components/AstBuilder/edition/base-options.tspackages/app-builder/src/locales/en/scenarios.jsonpackages/app-builder/src/models/astNode/builder-ast-node.tspackages/app-builder/src/components/AstBuilder/edition/EditModal/modals/RecordRiskLevelCheck/RecordRiskLevelCheck.tsxpackages/app-builder/src/server-fns/scenarios.tspackages/app-builder/src/routes/_app/_builder/detection/scenarios/$scenarioId/i/$iterationId/rules.$ruleId.tsxpackages/app-builder/src/models/astNode/risk.tspackages/app-builder/src/routes/_app/_builder/detection/scenarios/$scenarioId/i/$iterationId/screenings.$screeningId.tsxpackages/app-builder/src/components/AstBuilder/OperandInfos.tsxpackages/app-builder/src/routes/_app/_builder/detection/scenarios/$scenarioId/i/$iterationId/_edit-view/trigger.tsxpackages/app-builder/src/components/AstBuilder/edition/OperandMenu/MenuOption.tsx
packages/app-builder/src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Run
bun run type-checkin app-builder and ui-design-system packages to verify TypeScript types
Files:
packages/app-builder/src/components/UserScoring/ScoringRuleEditPanel.tsxpackages/app-builder/src/services/ast-node/getAstNodeDisplayName.tspackages/app-builder/src/components/AstBuilder/edition/EditModal/EditModal.tsxpackages/app-builder/src/components/AstBuilder/edition/base-options.tspackages/app-builder/src/models/astNode/builder-ast-node.tspackages/app-builder/src/components/AstBuilder/edition/EditModal/modals/RecordRiskLevelCheck/RecordRiskLevelCheck.tsxpackages/app-builder/src/server-fns/scenarios.tspackages/app-builder/src/routes/_app/_builder/detection/scenarios/$scenarioId/i/$iterationId/rules.$ruleId.tsxpackages/app-builder/src/models/astNode/risk.tspackages/app-builder/src/routes/_app/_builder/detection/scenarios/$scenarioId/i/$iterationId/screenings.$screeningId.tsxpackages/app-builder/src/components/AstBuilder/OperandInfos.tsxpackages/app-builder/src/routes/_app/_builder/detection/scenarios/$scenarioId/i/$iterationId/_edit-view/trigger.tsxpackages/app-builder/src/components/AstBuilder/edition/OperandMenu/MenuOption.tsx
packages/app-builder/src/services/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Place business logic in services directory
Files:
packages/app-builder/src/services/ast-node/getAstNodeDisplayName.ts
packages/app-builder/src/models/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use type definitions with adapters in the models directory
Files:
packages/app-builder/src/models/astNode/builder-ast-node.tspackages/app-builder/src/models/astNode/risk.ts
packages/app-builder/src/routes/**/*.tsx
📄 CodeRabbit inference engine (CLAUDE.md)
packages/app-builder/src/routes/**/*.tsx: Use flat routes with+folders for organizing Remix routes (e.g.,_builder+/cases+/$caseId.tsx)
Usehandleproperty in routes for breadcrumbs
Use loaders for data fetching in Remix routes
Files:
packages/app-builder/src/routes/_app/_builder/detection/scenarios/$scenarioId/i/$iterationId/rules.$ruleId.tsxpackages/app-builder/src/routes/_app/_builder/detection/scenarios/$scenarioId/i/$iterationId/screenings.$screeningId.tsxpackages/app-builder/src/routes/_app/_builder/detection/scenarios/$scenarioId/i/$iterationId/_edit-view/trigger.tsx
🔇 Additional comments (6)
packages/app-builder/src/models/astNode/risk.ts (1)
24-52: LGTM — new node definition is clean and consistent.The shape, constructor, and type guard all follow the same patterns as
RecordHasPastAlertsAstNode.packages/app-builder/src/components/AstBuilder/edition/OperandMenu/MenuOption.tsx (1)
41-88: LGTM — gating logic is clean.
hasScoringRulesetis correctly wired through,isRestrictedClientRiskis properly narrowed tomonitoringListCheckAstNodeName, and the newdisabledScoringCheckpath is well-structured.packages/app-builder/src/routes/_app/_builder/detection/scenarios/$scenarioId/i/$iterationId/rules.$ruleId.tsx (1)
44-53: LGTM — clean consolidation throughgetBuilderOptionsFn.Calling a server function from within another server function runs inline on the server (no HTTP round-trip per TanStack Start's SSR semantics), so the
Promise.allpattern here is efficient.packages/app-builder/src/routes/_app/_builder/detection/scenarios/$scenarioId/i/$iterationId/_edit-view/trigger.tsx (1)
26-41: LGTM — elegant simplification.Removing the local
triggerLoaderand delegating directly togetBuilderOptionsFnreduces duplicated fetching logic across routes.packages/app-builder/src/routes/_app/_builder/detection/scenarios/$scenarioId/i/$iterationId/screenings.$screeningId.tsx (1)
58-75: LGTM — clean consolidation.
entitlementsis correctly retained (still needed for NER gating on Line 606) and thegetBuilderOptionsFncomposition mirrors the rule and trigger loaders well.packages/app-builder/src/server-fns/scenarios.ts (1)
327-330: ⚡ Quick winUnconditional scoring API calls may break the builder for tenants without scoring.
continuousScreening.listConfigurations()is guarded byisContinuousScreeningAvailable(entitlements), falling back toPromise.resolve([]). However,userScoring.listRulesets()anduserScoring.getSettings()have no such guard. If either method throws or rejects for tenants without a scoring configuration, the entirePromise.all()would reject, taking down the rule builder, trigger editor, and screening editor for those users.Verify that the
userScoringservice methods either:
- Guard against errors for tenants without scoring, or
- Are wrapped with error handling (e.g.,
.catch()fallback likecontinuousScreening)
| <SelectV2<number> | ||
| multiple | ||
| options={levelsOptions} | ||
| value={node.children[0].constant} | ||
| placeholder="Risk Level" | ||
| onChange={(value) => { | ||
| node.children[0].constant = value; | ||
| }} | ||
| /> | ||
| </div> | ||
| <EditionEvaluationErrors id={node.id} filterOut={['FUNCTION_ERROR']} /> | ||
| </div> | ||
| {!hasValidLicense ? ( | ||
| <Callout icon="lock" variant="outlined" color="red"> | ||
| {t('scenarios:edit_ip_has_flag.premium_callout')} | ||
| </Callout> |
There was a problem hiding this comment.
Two i18n issues: hardcoded placeholder and borrowed translation key.
- Line 66:
placeholder="Risk Level"is a raw English string. It should be passed throught()with a dedicated key, just as the modal title and description are. - Line 76:
t('scenarios:edit_ip_has_flag.premium_callout')re-uses the IP-flag premium callout key — this is a copy-paste artefact. If the IP-flag copy ever changes independently, this modal silently shows wrong text.
🛠️ Proposed fix
- placeholder="Risk Level"
+ placeholder={t('scenarios:edit_record_risk_level_check.placeholder')}- {t('scenarios:edit_ip_has_flag.premium_callout')}
+ {t('scenarios:edit_record_risk_level_check.premium_callout')}Add the two new keys to en/scenarios.json (and the fr/ar equivalents).
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| <SelectV2<number> | |
| multiple | |
| options={levelsOptions} | |
| value={node.children[0].constant} | |
| placeholder="Risk Level" | |
| onChange={(value) => { | |
| node.children[0].constant = value; | |
| }} | |
| /> | |
| </div> | |
| <EditionEvaluationErrors id={node.id} filterOut={['FUNCTION_ERROR']} /> | |
| </div> | |
| {!hasValidLicense ? ( | |
| <Callout icon="lock" variant="outlined" color="red"> | |
| {t('scenarios:edit_ip_has_flag.premium_callout')} | |
| </Callout> | |
| <SelectV2<number> | |
| multiple | |
| options={levelsOptions} | |
| value={node.children[0].constant} | |
| placeholder={t('scenarios:edit_record_risk_level_check.placeholder')} | |
| onChange={(value) => { | |
| node.children[0].constant = value; | |
| }} | |
| /> | |
| </div> | |
| <EditionEvaluationErrors id={node.id} filterOut={['FUNCTION_ERROR']} /> | |
| </div> | |
| {!hasValidLicense ? ( | |
| <Callout icon="lock" variant="outlined" color="red"> | |
| {t('scenarios:edit_record_risk_level_check.premium_callout')} | |
| </Callout> |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@packages/app-builder/src/components/AstBuilder/edition/EditModal/modals/RecordRiskLevelCheck/RecordRiskLevelCheck.tsx`
around lines 62 - 77, Replace the hardcoded placeholder on the SelectV2
component and the copied translation key used in the Callout with dedicated i18n
keys: change placeholder="Risk Level" to
placeholder={t('scenarios:record_risk_level.placeholder')} and replace
t('scenarios:edit_ip_has_flag.premium_callout') with
t('scenarios:record_risk_level.premium_callout'); then add the corresponding
keys (record_risk_level.placeholder and record_risk_level.premium_callout) to
the en/scenarios.json and the fr/ar locale files with appropriate translations.
| const levelColorsMap = SCORING_LEVELS_COLORS[scoringSettings.maxRiskLevel as MaxRiskLevel]; | ||
| const levelLabelsMap = SCORING_LEVELS_LABEL_KEYS[scoringSettings.maxRiskLevel as MaxRiskLevel]; | ||
|
|
||
| return ( | ||
| <> | ||
| <div className="flex gap-v2-xs items-center"> | ||
| {node.children[0].constant.map((level) => ( | ||
| <div | ||
| key={level} | ||
| className="flex gap-v2-xs items-center border rounded-full px-v2-sm py-v2-xs text-small" | ||
| style={{ borderColor: levelColorsMap[level] }} | ||
| > | ||
| <div className="size-4 rounded-full" style={{ backgroundColor: levelColorsMap[level] }} /> | ||
| <span>{t(levelLabelsMap[level])}</span> |
There was a problem hiding this comment.
Guard score-level maps before indexing to avoid runtime crashes.
Here, type casting may hide invalid runtime values; if map lookup fails, property access can throw.
Or, as the bard might whisper: “When maps be void, let not the render bleed.”
Suggested patch
- const levelColorsMap = SCORING_LEVELS_COLORS[scoringSettings.maxRiskLevel as MaxRiskLevel];
- const levelLabelsMap = SCORING_LEVELS_LABEL_KEYS[scoringSettings.maxRiskLevel as MaxRiskLevel];
+ const levelColorsMap = SCORING_LEVELS_COLORS[scoringSettings.maxRiskLevel as MaxRiskLevel];
+ const levelLabelsMap = SCORING_LEVELS_LABEL_KEYS[scoringSettings.maxRiskLevel as MaxRiskLevel];
+ if (!levelColorsMap || !levelLabelsMap) return null;
@@
- {node.children[0].constant.map((level) => (
- <div
- key={level}
- className="flex gap-v2-xs items-center border rounded-full px-v2-sm py-v2-xs text-small"
- style={{ borderColor: levelColorsMap[level] }}
- >
- <div className="size-4 rounded-full" style={{ backgroundColor: levelColorsMap[level] }} />
- <span>{t(levelLabelsMap[level])}</span>
- </div>
- ))}
+ {node.children[0].constant.map((level) => {
+ const color = levelColorsMap[level];
+ const labelKey = levelLabelsMap[level];
+ if (!color || !labelKey) return null;
+ return (
+ <div
+ key={level}
+ className="flex gap-v2-xs items-center border rounded-full px-v2-sm py-v2-xs text-small"
+ style={{ borderColor: color }}
+ >
+ <div className="size-4 rounded-full" style={{ backgroundColor: color }} />
+ <span>{t(labelKey)}</span>
+ </div>
+ );
+ })}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const levelColorsMap = SCORING_LEVELS_COLORS[scoringSettings.maxRiskLevel as MaxRiskLevel]; | |
| const levelLabelsMap = SCORING_LEVELS_LABEL_KEYS[scoringSettings.maxRiskLevel as MaxRiskLevel]; | |
| return ( | |
| <> | |
| <div className="flex gap-v2-xs items-center"> | |
| {node.children[0].constant.map((level) => ( | |
| <div | |
| key={level} | |
| className="flex gap-v2-xs items-center border rounded-full px-v2-sm py-v2-xs text-small" | |
| style={{ borderColor: levelColorsMap[level] }} | |
| > | |
| <div className="size-4 rounded-full" style={{ backgroundColor: levelColorsMap[level] }} /> | |
| <span>{t(levelLabelsMap[level])}</span> | |
| const levelColorsMap = SCORING_LEVELS_COLORS[scoringSettings.maxRiskLevel as MaxRiskLevel]; | |
| const levelLabelsMap = SCORING_LEVELS_LABEL_KEYS[scoringSettings.maxRiskLevel as MaxRiskLevel]; | |
| if (!levelColorsMap || !levelLabelsMap) return null; | |
| return ( | |
| <> | |
| <div className="flex gap-v2-xs items-center"> | |
| {node.children[0].constant.map((level) => { | |
| const color = levelColorsMap[level]; | |
| const labelKey = levelLabelsMap[level]; | |
| if (!color || !labelKey) return null; | |
| return ( | |
| <div | |
| key={level} | |
| className="flex gap-v2-xs items-center border rounded-full px-v2-sm py-v2-xs text-small" | |
| style={{ borderColor: color }} | |
| > | |
| <div className="size-4 rounded-full" style={{ backgroundColor: color }} /> | |
| <span>{t(labelKey)}</span> |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/app-builder/src/components/AstBuilder/OperandInfos.tsx` around lines
150 - 163, The code indexes levelColorsMap[level] and levelLabelsMap[level]
without guarding against invalid keys (the cast on scoringSettings.maxRiskLevel
can hide runtime mismatches), which can throw; in the render path (around
levelColorsMap, levelLabelsMap, node.children[0].constant and the t(...) call)
validate that the maps exist and the specific level key exists before using them
(e.g., compute safeLevelColors/ safeLevelLabels from SCORING_LEVELS_COLORS and
SCORING_LEVELS_LABEL_KEYS with a fallback map or filter
node.children[0].constant to include only keys present in the maps), and use a
sensible default color/label or skip rendering that level to avoid runtime
crashes.
5e9842a to
2a3bd7a
Compare
2a3bd7a to
14f1996
Compare
Summary by CodeRabbit
New Features
Localization
Refactor
Behavior