microsoft/qdk

Public

mirrored from https://github.com/microsoft/qdkAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
32bcffe86a3647ddd45528ecb551f8feddd749ab

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

source/vscode/src/webview/webview.tsx

236lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4/// <reference types="@types/vscode-webview"/>
5
6const vscodeApi = acquireVsCodeApi();
7
8import { render } from "preact";
9import {
10 CircuitPanel,
11 CircuitProps,
12 EstimatesPanel,
13 Histogram,
14 setRenderer,
15 type ReData,
16} from "qsharp-lang/ux";
17import { HelpPage } from "./help";
18import { DocumentationView, IDocFile } from "./docview";
19import "./webview.css";
20
21// eslint-disable-next-line @typescript-eslint/ban-ts-comment
22// @ts-ignore - there are no types for this
23import mk from "@vscode/markdown-it-katex";
24import markdownIt from "markdown-it";
25import { setThemeStylesheet } from "./theme";
26const md = markdownIt("commonmark");
27md.use(mk, {
28 enableMathBlockInHtml: true,
29 enableMathInlineInHtml: true,
30});
31setRenderer((input: string) => md.render(input));
32
33window.addEventListener("message", onMessage);
34window.addEventListener("load", main);
35
36type HistogramState = {
37 viewType: "histogram";
38 panelId: string;
39 buckets: Array<[string, number]>;
40 shotCount: number;
41 suppressSettings?: boolean;
42};
43
44type EstimatesState = {
45 viewType: "estimates";
46 estimatesData: {
47 calculating: boolean;
48 estimates: ReData[];
49 };
50};
51
52type CircuitState = {
53 viewType: "circuit";
54 panelId: string;
55 props: CircuitProps;
56};
57
58type DocumentationState = {
59 viewType: "documentation";
60 fragmentsToRender: IDocFile[];
61 projectName: string;
62};
63
64type State =
65 | { viewType: "loading"; panelId: string }
66 | { viewType: "help" }
67 | HistogramState
68 | EstimatesState
69 | CircuitState
70 | DocumentationState;
71const loadingState: State = { viewType: "loading", panelId: "" };
72const helpState: State = { viewType: "help" };
73let state: State = loadingState;
74
75function main() {
76 state = (vscodeApi.getState() as any) || loadingState;
77 render(<App state={state} />, document.body);
78 setThemeStylesheet();
79 vscodeApi.postMessage({ command: "ready" });
80}
81
82function onMessage(event: any) {
83 const message = event.data;
84 if (!message?.command) {
85 console.error("Unknown message: ", message);
86 return;
87 }
88 switch (message.command) {
89 case "histogram": {
90 if (!message.buckets || typeof message.shotCount !== "number") {
91 console.error("No buckets in message: ", message);
92 return;
93 }
94 state = {
95 viewType: "histogram",
96 panelId: message.panelId,
97 buckets: message.buckets as Array<[string, number]>,
98 shotCount: message.shotCount,
99 suppressSettings: message.suppressSettings,
100 };
101 break;
102 }
103 case "estimates":
104 {
105 const newState: EstimatesState = {
106 viewType: "estimates",
107 estimatesData: {
108 calculating: !!message.calculating,
109 estimates: [],
110 },
111 };
112 // Copy over any existing estimates
113 if ((state as EstimatesState).estimatesData?.estimates) {
114 newState.estimatesData.estimates.push(
115 ...(state as EstimatesState).estimatesData.estimates,
116 );
117 }
118 // Append any new estimates
119 if (message.estimates) {
120 if (Array.isArray(message.estimates)) {
121 newState.estimatesData.estimates.push(...message.estimates);
122 } else {
123 newState.estimatesData.estimates.push(message.estimates);
124 }
125 }
126 state = newState;
127 }
128 break;
129 case "help":
130 state = helpState;
131 break;
132 case "circuit":
133 {
134 state = {
135 viewType: "circuit",
136 ...message,
137 };
138 }
139 break;
140 case "showDocumentationCommand":
141 {
142 state = {
143 viewType: "documentation",
144 fragmentsToRender: message.fragmentsToRender,
145 projectName: message.projectName,
146 };
147 }
148 break;
149 default:
150 console.error("Unknown command: ", message.command);
151 return;
152 }
153
154 vscodeApi.setState(state);
155 render(<App state={state} />, document.body);
156}
157
158function onRowDeleted(rowId: string) {
159 // Clone all the state to a new object
160 const newState: State = JSON.parse(JSON.stringify(state));
161
162 // Splice out the estimate that was deleted
163 const estimates = (newState as EstimatesState).estimatesData.estimates;
164 const index = estimates.findIndex(
165 (estimate) => estimate.jobParams.runName === rowId,
166 );
167 if (index >= 0) {
168 estimates.splice(index, 1);
169 }
170 state = newState;
171
172 vscodeApi.setState(state);
173 render(<App state={state} />, document.body);
174}
175
176function App({ state }: { state: State }) {
177 const onFilter = () => undefined;
178
179 switch (state.viewType) {
180 case "loading":
181 return <div>Loading...</div>;
182 case "histogram":
183 return (
184 <>
185 <Histogram
186 data={new Map(state.buckets)}
187 shotCount={state.shotCount}
188 filter=""
189 onFilter={onFilter}
190 shotsHeader={true}
191 ></Histogram>
192 {state.suppressSettings ? null : (
193 <p style="margin-top: 8px; font-size: 0.8em">
194 Note: If a{" "}
195 <a href="vscode://settings/Q%23.simulation.pauliNoise">
196 noise model
197 </a>{" "}
198 or any{" "}
199 <a href="vscode://settings/Q%23.simulation.qubitLoss">
200 qubit loss
201 </a>{" "}
202 has been configured, this may impact results
203 </p>
204 )}
205 </>
206 );
207 case "estimates":
208 return (
209 <EstimatesPanel
210 calculating={state.estimatesData.calculating}
211 estimatesData={state.estimatesData.estimates}
212 onRowDeleted={onRowDeleted}
213 colors={[]}
214 runNames={[]}
215 />
216 );
217 case "circuit":
218 return <CircuitPanel {...state.props}></CircuitPanel>;
219 case "help":
220 return <HelpPage />;
221 case "documentation":
222 // Ideally we'd have this on all web views, but it makes the font a little
223 // too large in the others right now. Something to unify later.
224 document.body.classList.add("markdown-body");
225 document.body.style.fontSize = "0.8em";
226 return (
227 <DocumentationView
228 fragmentsToRender={state.fragmentsToRender}
229 projectName={state.projectName}
230 />
231 );
232 default:
233 console.error("Unknown view type in state", state);
234 return <div>Loading error</div>;
235 }
236}
237