From 30281327345a339c4c729e932074c22e7b29615b Mon Sep 17 00:00:00 2001 From: Charis Kyriakou Date: Wed, 20 Mar 2024 12:21:49 +0000 Subject: [PATCH] Add React components for showing model alert results --- .../model-editor/model-alerts/model-alerts.ts | 7 ++ .../ModelAlertsResults.stories.tsx | 22 +++++ .../view/model-alerts/ModelAlertsResults.tsx | 91 +++++++++++++++++++ .../src/view/model-alerts/ModelDetails.tsx | 52 +++++++++++ 4 files changed, 172 insertions(+) create mode 100644 extensions/ql-vscode/src/model-editor/model-alerts/model-alerts.ts create mode 100644 extensions/ql-vscode/src/stories/model-alerts/ModelAlertsResults.stories.tsx create mode 100644 extensions/ql-vscode/src/view/model-alerts/ModelAlertsResults.tsx create mode 100644 extensions/ql-vscode/src/view/model-alerts/ModelDetails.tsx diff --git a/extensions/ql-vscode/src/model-editor/model-alerts/model-alerts.ts b/extensions/ql-vscode/src/model-editor/model-alerts/model-alerts.ts new file mode 100644 index 00000000000..5938f3191d2 --- /dev/null +++ b/extensions/ql-vscode/src/model-editor/model-alerts/model-alerts.ts @@ -0,0 +1,7 @@ +import type { AnalysisAlert } from "../../variant-analysis/shared/analysis-result"; +import type { ModeledMethod } from "../modeled-method"; + +export interface ModelAlerts { + model: ModeledMethod; + alerts: AnalysisAlert[]; +} diff --git a/extensions/ql-vscode/src/stories/model-alerts/ModelAlertsResults.stories.tsx b/extensions/ql-vscode/src/stories/model-alerts/ModelAlertsResults.stories.tsx new file mode 100644 index 00000000000..8207ca6f312 --- /dev/null +++ b/extensions/ql-vscode/src/stories/model-alerts/ModelAlertsResults.stories.tsx @@ -0,0 +1,22 @@ +import type { Meta, StoryFn } from "@storybook/react"; + +import { ModelAlertsResults as ModelAlertsResultsComponent } from "../../view/model-alerts/ModelAlertsResults"; +import { createSinkModeledMethod } from "../../../test/factories/model-editor/modeled-method-factories"; +import { createMockAnalysisAlert } from "../../../test/factories/variant-analysis/shared/analysis-alert"; + +export default { + title: "Model Alerts/Model Alerts Results", + component: ModelAlertsResultsComponent, +} as Meta; + +const Template: StoryFn = (args) => ( + +); + +export const ModelAlertsResults = Template.bind({}); +ModelAlertsResults.args = { + modelAlerts: { + model: createSinkModeledMethod(), + alerts: [createMockAnalysisAlert()], + }, +}; diff --git a/extensions/ql-vscode/src/view/model-alerts/ModelAlertsResults.tsx b/extensions/ql-vscode/src/view/model-alerts/ModelAlertsResults.tsx new file mode 100644 index 00000000000..d612afce2c0 --- /dev/null +++ b/extensions/ql-vscode/src/view/model-alerts/ModelAlertsResults.tsx @@ -0,0 +1,91 @@ +import { styled } from "styled-components"; +import type { ModelAlerts } from "../../model-editor/model-alerts/model-alerts"; +import { Codicon } from "../common"; +import { useState } from "react"; +import { VSCodeBadge } from "@vscode/webview-ui-toolkit/react"; +import { formatDecimal } from "../../common/number"; +import AnalysisAlertResult from "../variant-analysis/AnalysisAlertResult"; +import { MethodName } from "../model-editor/MethodName"; +import { ModelDetails } from "./ModelDetails"; + +// This will ensure that these icons have a className which we can use in the TitleContainer +const ExpandCollapseCodicon = styled(Codicon)``; + +const TitleContainer = styled.button` + display: flex; + gap: 0.5em; + align-items: center; + width: 100%; + + color: var(--vscode-editor-foreground); + background-color: transparent; + border: none; + cursor: pointer; + + &:disabled { + cursor: default; + + ${ExpandCollapseCodicon} { + color: var(--vscode-disabledForeground); + } + } +`; + +const ModelTypeText = styled.span` + font-size: 0.85em; + color: var(--vscode-descriptionForeground); +`; + +const ModelDetailsContainer = styled.div` + padding-top: 10px; +`; + +const AlertsContainer = styled.ul` + list-style-type: none; + margin: 1em 0 0; + padding: 0.5em 0 0 0; +`; + +const Alert = styled.li` + margin-bottom: 1em; + background-color: var(--vscode-notifications-background); +`; + +interface Props { + modelAlerts: ModelAlerts; +} + +export const ModelAlertsResults = ({ + modelAlerts, +}: Props): React.JSX.Element => { + const [isExpanded, setExpanded] = useState(true); + return ( +
+ setExpanded(!isExpanded)}> + {isExpanded && ( + + )} + {!isExpanded && ( + + )} + {formatDecimal(modelAlerts.alerts.length)} + + {modelAlerts.model.type} + + {isExpanded && ( + <> + + + + + {modelAlerts.alerts.map((r, i) => ( + + + + ))} + + + )} +
+ ); +}; diff --git a/extensions/ql-vscode/src/view/model-alerts/ModelDetails.tsx b/extensions/ql-vscode/src/view/model-alerts/ModelDetails.tsx new file mode 100644 index 00000000000..fe508bc80e7 --- /dev/null +++ b/extensions/ql-vscode/src/view/model-alerts/ModelDetails.tsx @@ -0,0 +1,52 @@ +import { styled } from "styled-components"; +import { + modeledMethodSupportsInput, + modeledMethodSupportsKind, + modeledMethodSupportsOutput, +} from "../../model-editor/modeled-method"; +import type { ModeledMethod } from "../../model-editor/modeled-method"; + +const DetailsContainer = styled.div` + display: flex; +`; + +const Detail = styled.span` + display: flex; + margin-right: 30px; +`; + +const Label = styled.span` + color: var(--vscode-descriptionForeground); + margin-right: 10px; +`; + +const Value = styled.span``; + +export const ModelDetails = ({ model }: { model: ModeledMethod }) => { + return ( + + + + {model.type} + + {modeledMethodSupportsInput(model) && ( + + + {model.input} + + )} + {modeledMethodSupportsOutput(model) && ( + + + {model.output} + + )} + {modeledMethodSupportsKind(model) && ( + + + {model.kind} + + )} + + ); +};