@@ -150,17 +150,14 @@ export class RESTDebugPanel {
150
150
api . config . pathPrefix
151
151
} `;
152
152
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
-
156
153
// Set the webview's content
157
154
this . _panel . webview . html = `
158
155
<!DOCTYPE html>
159
156
<html lang="en-us">
160
157
<head>
161
158
<meta charset="UTF-8">
162
159
<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 ( vscode . Uri . joinPath ( webviewFolderUri , "elements-1.6.3.js" ) ) } "></script>
164
161
<title>${ RESTDebugPanel . _viewTitle } </title>
165
162
<style>
166
163
.path-grid {
@@ -171,10 +168,10 @@ export class RESTDebugPanel {
171
168
.component-container > * {
172
169
margin: 0.5rem 0;
173
170
}
174
- vscode-text-area , vscode-text-field {
171
+ vscode-textarea , vscode-textfield {
175
172
width: 100%;
176
173
}
177
- vscode-panels {
174
+ vscode-tabs {
178
175
display: contents;
179
176
}
180
177
.path-grid-container {
@@ -187,90 +184,88 @@ export class RESTDebugPanel {
187
184
max-width: 45vw;
188
185
}
189
186
#button {
190
- margin-top: 1rem;
187
+ margin-top: 0.5rem;
188
+ }
189
+ vscode-tab-panel {
190
+ overflow: visible;
191
191
}
192
192
</style>
193
193
</head>
194
194
<body>
195
195
<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">
196
+ <form id="form">
197
+ <p>Use the tabs below to specify the REST request method, path, headers, query parameters and body.</p>
198
+ <p>Click the <vscode-badge>Start Debugging</vscode-badge> button to send the REST request and start the debugging session.</p>
199
+ <vscode-divider></vscode-divider>
200
+ <vscode-tabs id="panels" selected-index="0" aria-label="Method & Path, Headers, Query Parameters and Body">
201
+ <vscode-tab-header id="methodPathTab">METHOD & PATH</vscode-tab-header>
202
+ <vscode-tab-header id="headersTab">HEADERS</vscode-tab-header>
203
+ <vscode-tab-header id="paramsTab">QUERY PARAMETERS</vscode-tab-header>
204
+ <vscode-tab-header id="bodyTab">BODY</vscode-tab-header>
205
+ <vscode-tab-panel id="methodPathView">
207
206
<section class="component-container">
208
207
<p>
209
208
Select a method for this request, then select the web application
210
209
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
210
+ next to the dropdown.
211
+ </p>
212
+ <p>
213
+ The connection information of the server definition
212
214
is shown for clarity but it cannot be edited.
213
215
</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>
216
+ <vscode-radio-group id="method" name="method ">
217
+ <vscode-radio value="GET" name="method" checked >GET</vscode-radio>
218
+ <vscode-radio value="POST" name="method" >POST</vscode-radio>
219
+ <vscode-radio value="PUT" name="method" >PUT</vscode-radio>
220
+ <vscode-radio value="PATCH" name="method" >PATCH</vscode-radio>
221
+ <vscode-radio value="DELETE" name="method" >DELETE</vscode-radio>
222
+ <vscode-radio value="HEAD" name="method" >HEAD</vscode-radio>
223
+ <vscode-radio value="OPTIONS" name="method" >OPTIONS</vscode-radio>
222
224
</vscode-radio-group>
223
- <vscode-text-field readonly id="serverInfo"></vscode-text-field >
225
+ <vscode-textfield readonly id="serverInfo"></vscode-textfield >
224
226
<section class="path-grid">
225
227
<section class="path-grid-container">
226
- <vscode-dropdown id="webApp" position="below"></vscode-dropdown >
228
+ <vscode-single-select id="webApp" name="webApp" position="below"></vscode-single-select >
227
229
</section>
228
230
<section class="path-grid-container">
229
- <vscode-text-field id="path" placeholder="/path"></vscode-text-field >
231
+ <vscode-textfield id="path" name="path" placeholder="/path" pattern="^/.*$" required ></vscode-textfield >
230
232
</section>
231
233
</section>
232
234
</section>
233
- </vscode-panel-view >
234
- <vscode-panel-view id="headersView">
235
+ </vscode-tab-panel >
236
+ <vscode-tab-panel id="headersView">
235
237
<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>
238
+ <p>Enter your HTTP headers below, one per line, using the format 'HEADER: value'.</p>
239
+ <p>If no 'Authorization' header is present, the username and password of the server connection will be used.</p>
240
+ <p>If you provide a body, the 'Content-Type' header will be set automatically.</p>
241
+ <p>To disable a header, add a hash (<vscode-badge>#</vscode-badge>) to the start of that line.</p>
242
+ <vscode-textarea id="headersText" name="headersText" resize="vertical" placeholder="HEADER: value\n# INACTIVE_HEADER: value" rows="5"></vscode-textarea>
243
243
</section>
244
- </vscode-panel-view >
245
- <vscode-panel-view id="paramsView">
244
+ </vscode-tab-panel >
245
+ <vscode-tab-panel id="paramsView">
246
246
<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>
247
+ <p>Enter your query parameters below, one per line, using the format 'param=value'.</p>
248
+ <p>To disable a query parameter, add a hash (<vscode-badge>#</vscode-badge>) to the start of that line.</p>
249
+ <vscode-textarea id="paramsText" name="paramsText" resize="vertical" placeholder="param=1\n# inactive-param=1" rows="5"></vscode-textarea>
252
250
</section>
253
- </vscode-panel-view >
254
- <vscode-panel-view id="bodyView">
251
+ </vscode-tab-panel >
252
+ <vscode-tab-panel id="bodyView">
255
253
<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>
254
+ <p>To provide a request body, select the type of the body content and enter the content in the text box that appears.</p>
255
+ <vscode-radio-group id="bodyType" name="bodyType">
256
+ <vscode-radio checked value="No Body" name="bodyType">No Body</vscode-radio>
257
+ <vscode-radio value="JSON" name="bodyType">JSON</vscode-radio>
258
+ <vscode-radio value="Text" name="bodyType">Text</vscode-radio>
259
+ <vscode-radio value="XML" name="bodyType">XML</vscode-radio>
260
+ <vscode-radio value="HTML" name="bodyType">HTML</vscode-radio>
266
261
</vscode-radio-group>
267
- <vscode-text-area id="bodyContent" resize="vertical" rows="10" hidden></vscode-text-area >
262
+ <vscode-textarea id="bodyContent" name="bodyContent" resize="vertical" rows="10" hidden></vscode-textarea >
268
263
</section>
269
- </vscode-panel-view >
270
- </vscode-panels >
264
+ </vscode-tab-panel >
265
+ </vscode-tabs >
271
266
</form>
272
267
<vscode-divider></vscode-divider>
273
- <vscode-button id="button" appearance="primary" type="button" >Start Debugging</vscode-button>
268
+ <vscode-button id="button">Start Debugging</vscode-button>
274
269
<script>
275
270
const vscode = acquireVsCodeApi();
276
271
const form = document.getElementById("form");
@@ -284,76 +279,75 @@ export class RESTDebugPanel {
284
279
const button = document.getElementById("button");
285
280
const webApp = document.getElementById("webApp");
286
281
const formFields = [method, serverInfo, path, headersText, paramsText, bodyType, bodyContent, webApp];
282
+ const sendData = (submitted) => {
283
+ const data = Object.fromEntries(new FormData(form));
284
+ if (
285
+ Object.keys(data).length == (formFields.length - 1) &&
286
+ data.webApp != "" && data.method != "" && data.bodyType != "" &&
287
+ (!submitted || (submitted && path.checkValidity()))
288
+ ) {
289
+ vscode.postMessage({
290
+ submitted,
291
+ ...data
292
+ });
293
+ }
294
+ };
287
295
288
- const setFormData = (data) => {
296
+ window.onmessage = (event) => {
297
+ const data = event.data, currentVals = new FormData(form);
289
298
formFields.forEach((field) => {
290
- if (data[field.id] && field.value != data[field.id]) {
291
- field.value = data[field.id];
292
- }
293
299
if (field.id == "webApp" && webApp.children.length == 0) {
294
300
// Create options and set the initial value
301
+ const initIdx = data.webApps.findIndex((e) => e == data.webApp) ?? 0;
295
302
data.webApps.forEach((webAppStr, idx) => {
296
303
const option = document.createElement("vscode-option");
297
304
option.innerText = webAppStr;
298
305
option.setAttribute("value",webAppStr);
299
- if (idx == 0 ) {
300
- option.setAttribute(" selected", true) ;
306
+ if (idx == initIdx ) {
307
+ option.selected = true;
301
308
}
302
309
webApp.appendChild(option);
303
- if (idx == 0) {
304
- webApp.value = webAppStr;
305
- }
306
310
});
307
- if (data.webApp != undefined && data.webApp != "" && data.webApps.includes(data.webApp)) {
308
- webApp.value = data.webApp;
309
- }
310
311
// Update width of dropdown
311
312
const longest = data.webApps.reduce((a,b) => a.length > b.length ? a : b);
312
313
const context = document.createElement("canvas").getContext("2d");
313
314
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;
315
+ webApp.style.width = Math.ceil(context.measureText(longest).width*(4/3)) + "px";
316
+ } else if (data[field.id] != undefined && currentVals.get(field.id) != data[field.id]) {
317
+ if (["method","bodyType"].includes(field.id)) {
318
+ // Check the correct radio
319
+ for (const c of field.children) {
320
+ c.checked = (c.value == data[field.id]);
321
+ }
322
+ if (field.id == "bodyType") {
323
+ // Make sure bodyContent is shown or hidden correctly
324
+ bodyContent.hidden = (data[field.id] == "No Body");
325
+ }
326
+ } else {
327
+ field.value = data[field.id];
328
+ if (field.id == "path") {
329
+ // Make sure valid path is marked as valid
330
+ }
331
+ }
324
332
}
325
333
});
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
- }
334
+ };
335
+ form.onchange = () => sendData(false);
336
+ button.onclick = () => sendData(true);
350
337
bodyType.onchange = () => {
351
- if (bodyType.value == "No Body") {
352
- bodyContent.setAttribute("hidden","hidden");
353
- } else {
354
- bodyContent.removeAttribute("hidden");
338
+ let bt;
339
+ for (const c of bodyType.children) {
340
+ if (c.checked) {
341
+ bt = c.value;
342
+ break;
343
+ }
355
344
}
345
+ bodyContent.hidden = (bt == "No Body");
356
346
}
347
+ // Bubble change events up to the form
348
+ bodyContent.onchange = headersText.onchange =
349
+ paramsText.onchange = path.onchange =
350
+ webApp.onchange = () => form.dispatchEvent(new Event("change"));
357
351
</script>
358
352
</body>
359
353
</html>` ;
0 commit comments