@@ -150,17 +150,16 @@ export class RESTDebugPanel {
150150 api . config . pathPrefix
151151 } `;
152152
153- // Get the path to the @vscode /webview-ui-toolkit minimized js
154- const toolkitUri = this . _panel . webview . asWebviewUri ( vscode . Uri . joinPath ( webviewFolderUri , "toolkit-1.2.1.min.js" ) ) ;
155-
156153 // Set the webview's content
157154 this . _panel . webview . html = `
158155 <!DOCTYPE html>
159156 <html lang="en-us">
160157 <head>
161158 <meta charset="UTF-8">
162159 <meta name="viewport" content="width=device-width, initial-scale=1.0">
163- <script type="module" src="${ toolkitUri } "></script>
160+ <script type="module" src="${ this . _panel . webview . asWebviewUri (
161+ vscode . Uri . joinPath ( webviewFolderUri , "elements-1.6.3.js" )
162+ ) } "></script>
164163 <title>${ RESTDebugPanel . _viewTitle } </title>
165164 <style>
166165 .path-grid {
@@ -171,10 +170,10 @@ export class RESTDebugPanel {
171170 .component-container > * {
172171 margin: 0.5rem 0;
173172 }
174- vscode-text-area , vscode-text-field {
173+ vscode-textarea , vscode-textfield {
175174 width: 100%;
176175 }
177- vscode-panels {
176+ vscode-tabs {
178177 display: contents;
179178 }
180179 .path-grid-container {
@@ -187,90 +186,88 @@ export class RESTDebugPanel {
187186 max-width: 45vw;
188187 }
189188 #button {
190- margin-top: 1rem;
189+ margin-top: 0.5rem;
190+ }
191+ vscode-tab-panel {
192+ overflow: visible;
191193 }
192194 </style>
193195 </head>
194196 <body>
195197 <h1>${ RESTDebugPanel . _viewTitle } </h1>
196- <form id="form">
197- <p>
198- Use the tabs below to specify the REST request method, path, headers, query parameters and body.
199- Click the 'Start Debugging' button to send the REST request and start the debugging session.
200- </p>
201- <vscode-panels id="panels" activeid="methodPathTab" aria-label="Method & Path, Headers, Query Parameters and Body">
202- <vscode-panel-tab id="methodPathTab">METHOD & PATH</vscode-panel-tab>
203- <vscode-panel-tab id="headersTab">HEADERS</vscode-panel-tab>
204- <vscode-panel-tab id="paramsTab">QUERY PARAMETERS</vscode-panel-tab>
205- <vscode-panel-tab id="bodyTab">BODY</vscode-panel-tab>
206- <vscode-panel-view id="methodPathView">
198+ <form id="form">
199+ <p>Use the tabs below to specify the REST request method, path, headers, query parameters and body.</p>
200+ <p>Click the <vscode-badge>Start Debugging</vscode-badge> button to send the REST request and start the debugging session.</p>
201+ <vscode-divider></vscode-divider>
202+ <vscode-tabs id="panels" selected-index="0" aria-label="Method & Path, Headers, Query Parameters and Body">
203+ <vscode-tab-header id="methodPathTab">METHOD & PATH</vscode-tab-header>
204+ <vscode-tab-header id="headersTab">HEADERS</vscode-tab-header>
205+ <vscode-tab-header id="paramsTab">QUERY PARAMETERS</vscode-tab-header>
206+ <vscode-tab-header id="bodyTab">BODY</vscode-tab-header>
207+ <vscode-tab-panel id="methodPathView">
207208 <section class="component-container">
208209 <p>
209210 Select a method for this request, then select the web application
210211 to use from the dropdown and enter the rest of the path in the input field
211- next to the dropdown. The connection information of the server definition
212+ next to the dropdown.
213+ </p>
214+ <p>
215+ The connection information of the server definition
212216 is shown for clarity but it cannot be edited.
213217 </p>
214- <vscode-radio-group id="method" orientation="horizontal ">
215- <vscode-radio checked value="GET">GET</vscode-radio>
216- <vscode-radio value="POST">POST</vscode-radio>
217- <vscode-radio value="PUT">PUT</vscode-radio>
218- <vscode-radio value="PATCH">PATCH</vscode-radio>
219- <vscode-radio value="DELETE">DELETE</vscode-radio>
220- <vscode-radio value="HEAD">HEAD</vscode-radio>
221- <vscode-radio value="OPTIONS">OPTIONS</vscode-radio>
218+ <vscode-radio-group id="method" name="method ">
219+ <vscode-radio value="GET" name="method" checked >GET</vscode-radio>
220+ <vscode-radio value="POST" name="method" >POST</vscode-radio>
221+ <vscode-radio value="PUT" name="method" >PUT</vscode-radio>
222+ <vscode-radio value="PATCH" name="method" >PATCH</vscode-radio>
223+ <vscode-radio value="DELETE" name="method" >DELETE</vscode-radio>
224+ <vscode-radio value="HEAD" name="method" >HEAD</vscode-radio>
225+ <vscode-radio value="OPTIONS" name="method" >OPTIONS</vscode-radio>
222226 </vscode-radio-group>
223- <vscode-text-field readonly id="serverInfo"></vscode-text-field >
227+ <vscode-textfield readonly id="serverInfo"></vscode-textfield >
224228 <section class="path-grid">
225229 <section class="path-grid-container">
226- <vscode-dropdown id="webApp" position="below"></vscode-dropdown >
230+ <vscode-single-select id="webApp" name="webApp" position="below"></vscode-single-select >
227231 </section>
228232 <section class="path-grid-container">
229- <vscode-text-field id="path" placeholder="/path"></vscode-text-field >
233+ <vscode-textfield id="path" name="path" placeholder="/path" pattern="^/.*$" required ></vscode-textfield >
230234 </section>
231235 </section>
232236 </section>
233- </vscode-panel-view >
234- <vscode-panel-view id="headersView">
237+ </vscode-tab-panel >
238+ <vscode-tab-panel id="headersView">
235239 <section class="component-container">
236- <p>
237- Enter your HTTP headers below, one per line, using the format 'HEADER: value'.
238- If no 'Authorization' header is present, the username and password of the server connection will be used.
239- If you provide a body, the 'Content-Type' header will be set automatically.
240- To disable a header, add a hash (#) to the start of that line.
241- </p>
242- <vscode-text-area id="headersText" resize="vertical" placeholder="HEADER: value\n# INACTIVE_HEADER: value" rows="5"></vscode-text-area>
240+ <p>Enter your HTTP headers below, one per line, using the format 'HEADER: value'.</p>
241+ <p>If no 'Authorization' header is present, the username and password of the server connection will be used.</p>
242+ <p>If you provide a body, the 'Content-Type' header will be set automatically.</p>
243+ <p>To disable a header, add a hash (<vscode-badge>#</vscode-badge>) to the start of that line.</p>
244+ <vscode-textarea id="headersText" name="headersText" resize="vertical" placeholder="HEADER: value\n# INACTIVE_HEADER: value" rows="5"></vscode-textarea>
243245 </section>
244- </vscode-panel-view >
245- <vscode-panel-view id="paramsView">
246+ </vscode-tab-panel >
247+ <vscode-tab-panel id="paramsView">
246248 <section class="component-container">
247- <p>
248- Enter your query parameters below, one per line, using the format 'param=1'.
249- To disable a query parameter, add a hash (#) to the start of that line.
250- </p>
251- <vscode-text-area id="paramsText" resize="vertical" placeholder="param=1\n# inactive-param=1" rows="5"></vscode-text-area>
249+ <p>Enter your query parameters below, one per line, using the format 'param=value'.</p>
250+ <p>To disable a query parameter, add a hash (<vscode-badge>#</vscode-badge>) to the start of that line.</p>
251+ <vscode-textarea id="paramsText" name="paramsText" resize="vertical" placeholder="param=1\n# inactive-param=1" rows="5"></vscode-textarea>
252252 </section>
253- </vscode-panel-view >
254- <vscode-panel-view id="bodyView">
253+ </vscode-tab-panel >
254+ <vscode-tab-panel id="bodyView">
255255 <section class="component-container">
256- <p>
257- To provide a request body, select the type of the body content
258- and enter the content in the text box that appears.
259- </p>
260- <vscode-radio-group id="bodyType" orientation="horizontal">
261- <vscode-radio checked value="No Body">No Body</vscode-radio>
262- <vscode-radio value="JSON">JSON</vscode-radio>
263- <vscode-radio value="Text">Text</vscode-radio>
264- <vscode-radio value="XML">XML</vscode-radio>
265- <vscode-radio value="HTML">HTML</vscode-radio>
256+ <p>To provide a request body, select the type of the body content and enter the content in the text box that appears.</p>
257+ <vscode-radio-group id="bodyType" name="bodyType">
258+ <vscode-radio checked value="No Body" name="bodyType">No Body</vscode-radio>
259+ <vscode-radio value="JSON" name="bodyType">JSON</vscode-radio>
260+ <vscode-radio value="Text" name="bodyType">Text</vscode-radio>
261+ <vscode-radio value="XML" name="bodyType">XML</vscode-radio>
262+ <vscode-radio value="HTML" name="bodyType">HTML</vscode-radio>
266263 </vscode-radio-group>
267- <vscode-text-area id="bodyContent" resize="vertical" rows="10" hidden></vscode-text-area >
264+ <vscode-textarea id="bodyContent" name="bodyContent" resize="vertical" rows="10" hidden></vscode-textarea >
268265 </section>
269- </vscode-panel-view >
270- </vscode-panels >
266+ </vscode-tab-panel >
267+ </vscode-tabs >
271268 </form>
272269 <vscode-divider></vscode-divider>
273- <vscode-button id="button" appearance="primary" type="button" >Start Debugging</vscode-button>
270+ <vscode-button id="button">Start Debugging</vscode-button>
274271 <script>
275272 const vscode = acquireVsCodeApi();
276273 const form = document.getElementById("form");
@@ -284,76 +281,75 @@ export class RESTDebugPanel {
284281 const button = document.getElementById("button");
285282 const webApp = document.getElementById("webApp");
286283 const formFields = [method, serverInfo, path, headersText, paramsText, bodyType, bodyContent, webApp];
284+ const sendData = (submitted) => {
285+ const data = Object.fromEntries(new FormData(form));
286+ if (
287+ Object.keys(data).length == (formFields.length - 1) &&
288+ data.webApp != "" && data.method != "" && data.bodyType != "" &&
289+ (!submitted || (submitted && path.checkValidity()))
290+ ) {
291+ vscode.postMessage({
292+ submitted,
293+ ...data
294+ });
295+ }
296+ };
287297
288- const setFormData = (data) => {
298+ window.onmessage = (event) => {
299+ const data = event.data, currentVals = new FormData(form);
289300 formFields.forEach((field) => {
290- if (data[field.id] && field.value != data[field.id]) {
291- field.value = data[field.id];
292- }
293301 if (field.id == "webApp" && webApp.children.length == 0) {
294302 // Create options and set the initial value
303+ const initIdx = data.webApps.findIndex((e) => e == data.webApp) ?? 0;
295304 data.webApps.forEach((webAppStr, idx) => {
296305 const option = document.createElement("vscode-option");
297306 option.innerText = webAppStr;
298307 option.setAttribute("value",webAppStr);
299- if (idx == 0 ) {
300- option.setAttribute(" selected", true) ;
308+ if (idx == initIdx ) {
309+ option.selected = true;
301310 }
302311 webApp.appendChild(option);
303- if (idx == 0) {
304- webApp.value = webAppStr;
305- }
306312 });
307- if (data.webApp != undefined && data.webApp != "" && data.webApps.includes(data.webApp)) {
308- webApp.value = data.webApp;
309- }
310313 // Update width of dropdown
311314 const longest = data.webApps.reduce((a,b) => a.length > b.length ? a : b);
312315 const context = document.createElement("canvas").getContext("2d");
313316 context.font = window.getComputedStyle(webApp,null).getPropertyValue("font");
314- webApp.style.width = Math.ceil(context.measureText(longest).width) + "px";
315- }
316- });
317- form.dispatchEvent(new Event("change"));
318- }
319- const getFormData = () => {
320- const data = {};
321- formFields.forEach((field) => {
322- if (field.id != "serverInfo" && field.value != undefined) {
323- data[field.id] = field.value;
317+ webApp.style.width = Math.ceil(context.measureText(longest).width*(4/3)) + "px";
318+ } else if (data[field.id] != undefined && currentVals.get(field.id) != data[field.id]) {
319+ if (["method","bodyType"].includes(field.id)) {
320+ // Check the correct radio
321+ for (const c of field.children) {
322+ c.checked = (c.value == data[field.id]);
323+ }
324+ if (field.id == "bodyType") {
325+ // Make sure bodyContent is shown or hidden correctly
326+ bodyContent.hidden = (data[field.id] == "No Body");
327+ }
328+ } else {
329+ field.value = data[field.id];
330+ if (field.id == "path") {
331+ // Make sure valid path is marked as valid
332+ }
333+ }
324334 }
325335 });
326- return data;
327- }
328-
329- window.onmessage = (event) => setFormData(event.data);
330- button.onclick = () => {
331- vscode.postMessage({
332- submitted: true,
333- ...getFormData()
334- });
335- }
336- form.onchange = (event) => {
337- if (event.target.id != "panels") {
338- const data = getFormData();
339- if (
340- Object.keys(data).length == formFields.length - 1 &&
341- data.webApp != "" && data.method != "" && data.bodyType != ""
342- ) {
343- vscode.postMessage({
344- submitted: false,
345- ...data
346- });
347- }
348- }
349- }
336+ };
337+ form.onchange = () => sendData(false);
338+ button.onclick = () => sendData(true);
350339 bodyType.onchange = () => {
351- if (bodyType.value == "No Body") {
352- bodyContent.setAttribute("hidden","hidden");
353- } else {
354- bodyContent.removeAttribute("hidden");
340+ let bt;
341+ for (const c of bodyType.children) {
342+ if (c.checked) {
343+ bt = c.value;
344+ break;
345+ }
355346 }
347+ bodyContent.hidden = (bt == "No Body");
356348 }
349+ // Bubble change events up to the form
350+ bodyContent.onchange = headersText.onchange =
351+ paramsText.onchange = path.onchange =
352+ webApp.onchange = () => form.dispatchEvent(new Event("change"));
357353 </script>
358354 </body>
359355 </html>` ;
0 commit comments