@matdata/yasgui 5.4.0 → 5.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/ts/src/ConfigExportImport.js +3 -0
- package/build/ts/src/ConfigExportImport.js.map +1 -1
- package/build/ts/src/PersistentConfig.d.ts +10 -1
- package/build/ts/src/PersistentConfig.js +39 -0
- package/build/ts/src/PersistentConfig.js.map +1 -1
- package/build/ts/src/Tab.d.ts +1 -1
- package/build/ts/src/Tab.js +76 -78
- package/build/ts/src/Tab.js.map +1 -1
- package/build/ts/src/TabSettingsModal.d.ts +3 -2
- package/build/ts/src/TabSettingsModal.js +453 -121
- package/build/ts/src/TabSettingsModal.js.map +1 -1
- package/build/ts/src/defaults.js +1 -1
- package/build/ts/src/defaults.js.map +1 -1
- package/build/ts/src/index.d.ts +18 -5
- package/build/ts/src/index.js +4 -1
- package/build/ts/src/index.js.map +1 -1
- package/build/ts/src/version.d.ts +1 -1
- package/build/ts/src/version.js +1 -1
- package/build/yasgui.min.css +1 -1
- package/build/yasgui.min.css.map +3 -3
- package/build/yasgui.min.js +128 -121
- package/build/yasgui.min.js.map +3 -3
- package/package.json +1 -1
- package/src/ConfigExportImport.ts +3 -0
- package/src/PersistentConfig.ts +54 -2
- package/src/Tab.ts +147 -106
- package/src/TabSettingsModal.scss +385 -16
- package/src/TabSettingsModal.ts +564 -150
- package/src/defaults.ts +1 -1
- package/src/endpointSelect.scss +12 -0
- package/src/index.ts +31 -3
- package/src/version.ts +1 -1
|
@@ -36,6 +36,7 @@ const AcceptHeaderGraphMap = [
|
|
|
36
36
|
{ key: "CSV", value: "text/csv,*/*;q=0.9" },
|
|
37
37
|
{ key: "TSV", value: "text/tab-separated-values,*/*;q=0.9" },
|
|
38
38
|
];
|
|
39
|
+
const DEFAULT_API_KEY_HEADER = "X-API-Key";
|
|
39
40
|
export default class TabSettingsModal {
|
|
40
41
|
constructor(tab, controlBarEl) {
|
|
41
42
|
this.tab = tab;
|
|
@@ -90,48 +91,55 @@ export default class TabSettingsModal {
|
|
|
90
91
|
this.modalContent.appendChild(header);
|
|
91
92
|
const body = document.createElement("div");
|
|
92
93
|
addClass(body, "modalBody");
|
|
93
|
-
const
|
|
94
|
-
addClass(
|
|
94
|
+
const sidebar = document.createElement("div");
|
|
95
|
+
addClass(sidebar, "modalSidebar");
|
|
95
96
|
const requestTab = document.createElement("button");
|
|
96
97
|
requestTab.textContent = "Request";
|
|
97
|
-
addClass(requestTab, "
|
|
98
|
+
addClass(requestTab, "modalNavButton", "active");
|
|
98
99
|
requestTab.onclick = () => this.switchTab("request");
|
|
100
|
+
const endpointsTab = document.createElement("button");
|
|
101
|
+
endpointsTab.textContent = "SPARQL Endpoints";
|
|
102
|
+
addClass(endpointsTab, "modalNavButton");
|
|
103
|
+
endpointsTab.onclick = () => this.switchTab("endpoints");
|
|
99
104
|
const prefixTab = document.createElement("button");
|
|
100
105
|
prefixTab.textContent = "Prefixes";
|
|
101
|
-
addClass(prefixTab, "
|
|
106
|
+
addClass(prefixTab, "modalNavButton");
|
|
102
107
|
prefixTab.onclick = () => this.switchTab("prefix");
|
|
103
108
|
const editorTab = document.createElement("button");
|
|
104
109
|
editorTab.textContent = "Editor";
|
|
105
|
-
addClass(editorTab, "
|
|
110
|
+
addClass(editorTab, "modalNavButton");
|
|
106
111
|
editorTab.onclick = () => this.switchTab("editor");
|
|
107
|
-
const endpointsTab = document.createElement("button");
|
|
108
|
-
endpointsTab.textContent = "Endpoint Buttons";
|
|
109
|
-
addClass(endpointsTab, "modalTabButton");
|
|
110
|
-
endpointsTab.onclick = () => this.switchTab("endpoints");
|
|
111
112
|
const importExportTab = document.createElement("button");
|
|
112
113
|
importExportTab.textContent = "Import/Export";
|
|
113
|
-
addClass(importExportTab, "
|
|
114
|
+
addClass(importExportTab, "modalNavButton");
|
|
114
115
|
importExportTab.onclick = () => this.switchTab("importexport");
|
|
115
116
|
const shortcutsTab = document.createElement("button");
|
|
116
117
|
shortcutsTab.textContent = "Keyboard Shortcuts";
|
|
117
|
-
addClass(shortcutsTab, "
|
|
118
|
+
addClass(shortcutsTab, "modalNavButton");
|
|
118
119
|
shortcutsTab.onclick = () => this.switchTab("shortcuts");
|
|
119
120
|
const aboutTab = document.createElement("button");
|
|
120
121
|
aboutTab.textContent = "About";
|
|
121
|
-
addClass(aboutTab, "
|
|
122
|
+
addClass(aboutTab, "modalNavButton");
|
|
122
123
|
aboutTab.onclick = () => this.switchTab("about");
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
124
|
+
sidebar.appendChild(requestTab);
|
|
125
|
+
sidebar.appendChild(endpointsTab);
|
|
126
|
+
sidebar.appendChild(prefixTab);
|
|
127
|
+
sidebar.appendChild(editorTab);
|
|
128
|
+
sidebar.appendChild(importExportTab);
|
|
129
|
+
sidebar.appendChild(shortcutsTab);
|
|
130
|
+
sidebar.appendChild(aboutTab);
|
|
131
|
+
const contentArea = document.createElement("div");
|
|
132
|
+
addClass(contentArea, "modalContentArea");
|
|
133
|
+
body.appendChild(sidebar);
|
|
134
|
+
body.appendChild(contentArea);
|
|
131
135
|
const requestContent = document.createElement("div");
|
|
132
136
|
addClass(requestContent, "modalTabContent", "active");
|
|
133
137
|
requestContent.id = "request-content";
|
|
134
138
|
this.drawRequestSettings(requestContent);
|
|
139
|
+
const endpointsContent = document.createElement("div");
|
|
140
|
+
addClass(endpointsContent, "modalTabContent");
|
|
141
|
+
endpointsContent.id = "endpoints-content";
|
|
142
|
+
this.drawEndpointsSettings(endpointsContent);
|
|
135
143
|
const prefixContent = document.createElement("div");
|
|
136
144
|
addClass(prefixContent, "modalTabContent");
|
|
137
145
|
prefixContent.id = "prefix-content";
|
|
@@ -140,10 +148,6 @@ export default class TabSettingsModal {
|
|
|
140
148
|
addClass(editorContent, "modalTabContent");
|
|
141
149
|
editorContent.id = "editor-content";
|
|
142
150
|
this.drawEditorSettings(editorContent);
|
|
143
|
-
const endpointsContent = document.createElement("div");
|
|
144
|
-
addClass(endpointsContent, "modalTabContent");
|
|
145
|
-
endpointsContent.id = "endpoints-content";
|
|
146
|
-
this.drawEndpointButtonsSettings(endpointsContent);
|
|
147
151
|
const importExportContent = document.createElement("div");
|
|
148
152
|
addClass(importExportContent, "modalTabContent");
|
|
149
153
|
importExportContent.id = "importexport-content";
|
|
@@ -156,13 +160,13 @@ export default class TabSettingsModal {
|
|
|
156
160
|
addClass(aboutContent, "modalTabContent");
|
|
157
161
|
aboutContent.id = "about-content";
|
|
158
162
|
this.drawAboutSettings(aboutContent);
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
163
|
+
contentArea.appendChild(requestContent);
|
|
164
|
+
contentArea.appendChild(endpointsContent);
|
|
165
|
+
contentArea.appendChild(prefixContent);
|
|
166
|
+
contentArea.appendChild(editorContent);
|
|
167
|
+
contentArea.appendChild(importExportContent);
|
|
168
|
+
contentArea.appendChild(shortcutsContent);
|
|
169
|
+
contentArea.appendChild(aboutContent);
|
|
166
170
|
this.modalContent.appendChild(body);
|
|
167
171
|
const footer = document.createElement("div");
|
|
168
172
|
addClass(footer, "modalFooter");
|
|
@@ -181,13 +185,13 @@ export default class TabSettingsModal {
|
|
|
181
185
|
document.body.appendChild(this.modalOverlay);
|
|
182
186
|
}
|
|
183
187
|
switchTab(tabName) {
|
|
184
|
-
const buttons = this.modalContent.querySelectorAll(".
|
|
188
|
+
const buttons = this.modalContent.querySelectorAll(".modalNavButton");
|
|
185
189
|
const contents = this.modalContent.querySelectorAll(".modalTabContent");
|
|
186
190
|
buttons.forEach((btn, index) => {
|
|
187
191
|
if ((tabName === "request" && index === 0) ||
|
|
188
|
-
(tabName === "
|
|
189
|
-
(tabName === "
|
|
190
|
-
(tabName === "
|
|
192
|
+
(tabName === "endpoints" && index === 1) ||
|
|
193
|
+
(tabName === "prefix" && index === 2) ||
|
|
194
|
+
(tabName === "editor" && index === 3) ||
|
|
191
195
|
(tabName === "importexport" && index === 4) ||
|
|
192
196
|
(tabName === "shortcuts" && index === 5) ||
|
|
193
197
|
(tabName === "about" && index === 6)) {
|
|
@@ -323,7 +327,9 @@ export default class TabSettingsModal {
|
|
|
323
327
|
const snippetsBarCheckbox = document.createElement("input");
|
|
324
328
|
snippetsBarCheckbox.type = "checkbox";
|
|
325
329
|
snippetsBarCheckbox.id = "showSnippetsBar";
|
|
326
|
-
|
|
330
|
+
const persistedValue = this.tab.yasgui.persistentConfig.getShowSnippetsBar();
|
|
331
|
+
snippetsBarCheckbox.checked =
|
|
332
|
+
persistedValue !== undefined ? persistedValue : this.tab.yasgui.config.showSnippetsBar !== false;
|
|
327
333
|
const snippetsBarLabel = document.createElement("label");
|
|
328
334
|
snippetsBarLabel.htmlFor = "showSnippetsBar";
|
|
329
335
|
snippetsBarLabel.textContent = "Show code snippets bar";
|
|
@@ -338,6 +344,405 @@ export default class TabSettingsModal {
|
|
|
338
344
|
snippetsBarSection.appendChild(snippetsBarHelp);
|
|
339
345
|
container.appendChild(snippetsBarSection);
|
|
340
346
|
}
|
|
347
|
+
drawEndpointsSettings(container) {
|
|
348
|
+
const section = document.createElement("div");
|
|
349
|
+
addClass(section, "settingsSection");
|
|
350
|
+
const label = document.createElement("label");
|
|
351
|
+
label.textContent = "SPARQL Endpoints";
|
|
352
|
+
addClass(label, "settingsLabel");
|
|
353
|
+
const help = document.createElement("div");
|
|
354
|
+
help.textContent =
|
|
355
|
+
"Manage your SPARQL endpoints. Each endpoint can have its own authentication and be displayed as a quick-switch button.";
|
|
356
|
+
addClass(help, "settingsHelp");
|
|
357
|
+
section.appendChild(label);
|
|
358
|
+
section.appendChild(help);
|
|
359
|
+
const endpointsList = document.createElement("div");
|
|
360
|
+
addClass(endpointsList, "endpointsTable");
|
|
361
|
+
this.renderEndpointsList(endpointsList);
|
|
362
|
+
section.appendChild(endpointsList);
|
|
363
|
+
container.appendChild(section);
|
|
364
|
+
}
|
|
365
|
+
renderEndpointsList(container) {
|
|
366
|
+
container.innerHTML = "";
|
|
367
|
+
const configs = this.tab.yasgui.persistentConfig.getEndpointConfigs();
|
|
368
|
+
const table = document.createElement("table");
|
|
369
|
+
addClass(table, "endpointsTableElement");
|
|
370
|
+
const thead = document.createElement("thead");
|
|
371
|
+
const headerRow = document.createElement("tr");
|
|
372
|
+
const headers = ["Endpoint", "Label", "Button", "Authentication", "Actions"];
|
|
373
|
+
headers.forEach((h) => {
|
|
374
|
+
const th = document.createElement("th");
|
|
375
|
+
th.textContent = h;
|
|
376
|
+
headerRow.appendChild(th);
|
|
377
|
+
});
|
|
378
|
+
thead.appendChild(headerRow);
|
|
379
|
+
table.appendChild(thead);
|
|
380
|
+
const tbody = document.createElement("tbody");
|
|
381
|
+
if (configs.length === 0) {
|
|
382
|
+
const emptyRow = document.createElement("tr");
|
|
383
|
+
const emptyCell = document.createElement("td");
|
|
384
|
+
emptyCell.colSpan = 5;
|
|
385
|
+
emptyCell.textContent = "No endpoints yet. Add one below or access an endpoint to have it automatically tracked.";
|
|
386
|
+
addClass(emptyCell, "emptyMessage");
|
|
387
|
+
emptyCell.style.textAlign = "center";
|
|
388
|
+
emptyCell.style.padding = "20px";
|
|
389
|
+
emptyRow.appendChild(emptyCell);
|
|
390
|
+
tbody.appendChild(emptyRow);
|
|
391
|
+
}
|
|
392
|
+
configs.forEach((config, index) => {
|
|
393
|
+
const row = document.createElement("tr");
|
|
394
|
+
const endpointCell = document.createElement("td");
|
|
395
|
+
endpointCell.textContent = config.endpoint;
|
|
396
|
+
endpointCell.title = config.endpoint;
|
|
397
|
+
addClass(endpointCell, "endpointCell");
|
|
398
|
+
row.appendChild(endpointCell);
|
|
399
|
+
const labelCell = document.createElement("td");
|
|
400
|
+
const labelInput = document.createElement("input");
|
|
401
|
+
labelInput.type = "text";
|
|
402
|
+
labelInput.value = config.label || "";
|
|
403
|
+
labelInput.placeholder = "Optional label";
|
|
404
|
+
addClass(labelInput, "endpointLabelInput");
|
|
405
|
+
labelInput.onchange = () => {
|
|
406
|
+
this.tab.yasgui.persistentConfig.addOrUpdateEndpoint(config.endpoint, {
|
|
407
|
+
label: labelInput.value.trim() || undefined,
|
|
408
|
+
});
|
|
409
|
+
this.renderEndpointsList(container);
|
|
410
|
+
this.tab.refreshEndpointButtons();
|
|
411
|
+
};
|
|
412
|
+
labelCell.appendChild(labelInput);
|
|
413
|
+
row.appendChild(labelCell);
|
|
414
|
+
const buttonCell = document.createElement("td");
|
|
415
|
+
const buttonCheckbox = document.createElement("input");
|
|
416
|
+
buttonCheckbox.type = "checkbox";
|
|
417
|
+
buttonCheckbox.checked = !!config.showAsButton;
|
|
418
|
+
buttonCheckbox.disabled = !config.label;
|
|
419
|
+
buttonCheckbox.setAttribute("aria-label", config.label ? "Show this endpoint as a quick-switch button" : "Add a label first to enable button");
|
|
420
|
+
buttonCheckbox.title = config.label
|
|
421
|
+
? "Show this endpoint as a quick-switch button"
|
|
422
|
+
: "Add a label first to enable button";
|
|
423
|
+
buttonCheckbox.onchange = () => {
|
|
424
|
+
this.tab.yasgui.persistentConfig.addOrUpdateEndpoint(config.endpoint, {
|
|
425
|
+
showAsButton: buttonCheckbox.checked,
|
|
426
|
+
});
|
|
427
|
+
this.tab.refreshEndpointButtons();
|
|
428
|
+
};
|
|
429
|
+
buttonCell.appendChild(buttonCheckbox);
|
|
430
|
+
addClass(buttonCell, "centerCell");
|
|
431
|
+
row.appendChild(buttonCell);
|
|
432
|
+
const authCell = document.createElement("td");
|
|
433
|
+
const authButton = document.createElement("button");
|
|
434
|
+
authButton.type = "button";
|
|
435
|
+
addClass(authButton, "configureAuthButton");
|
|
436
|
+
if (config.authentication) {
|
|
437
|
+
authButton.textContent = "✓ Configured";
|
|
438
|
+
addClass(authButton, "authenticated");
|
|
439
|
+
}
|
|
440
|
+
else {
|
|
441
|
+
authButton.textContent = "Configure";
|
|
442
|
+
}
|
|
443
|
+
authButton.onclick = () => this.showAuthenticationModal(config.endpoint);
|
|
444
|
+
authCell.appendChild(authButton);
|
|
445
|
+
addClass(authCell, "centerCell");
|
|
446
|
+
row.appendChild(authCell);
|
|
447
|
+
const actionsCell = document.createElement("td");
|
|
448
|
+
const deleteButton = document.createElement("button");
|
|
449
|
+
deleteButton.type = "button";
|
|
450
|
+
deleteButton.textContent = "Delete";
|
|
451
|
+
addClass(deleteButton, "deleteEndpointButton");
|
|
452
|
+
deleteButton.onclick = () => {
|
|
453
|
+
if (confirm(`Delete endpoint "${config.endpoint}"?`)) {
|
|
454
|
+
this.tab.yasgui.persistentConfig.deleteEndpointConfig(config.endpoint);
|
|
455
|
+
this.renderEndpointsList(container);
|
|
456
|
+
this.tab.refreshEndpointButtons();
|
|
457
|
+
}
|
|
458
|
+
};
|
|
459
|
+
actionsCell.appendChild(deleteButton);
|
|
460
|
+
addClass(actionsCell, "centerCell");
|
|
461
|
+
row.appendChild(actionsCell);
|
|
462
|
+
tbody.appendChild(row);
|
|
463
|
+
});
|
|
464
|
+
table.appendChild(tbody);
|
|
465
|
+
container.appendChild(table);
|
|
466
|
+
const addForm = document.createElement("div");
|
|
467
|
+
addClass(addForm, "addEndpointForm");
|
|
468
|
+
const addFormTitle = document.createElement("div");
|
|
469
|
+
addFormTitle.textContent = "Add New Endpoint";
|
|
470
|
+
addClass(addFormTitle, "addFormTitle");
|
|
471
|
+
addForm.appendChild(addFormTitle);
|
|
472
|
+
const formInputs = document.createElement("div");
|
|
473
|
+
addClass(formInputs, "addFormInputs");
|
|
474
|
+
const endpointInput = document.createElement("input");
|
|
475
|
+
endpointInput.type = "url";
|
|
476
|
+
endpointInput.placeholder = "Endpoint URL (e.g., https://dbpedia.org/sparql)";
|
|
477
|
+
addClass(endpointInput, "addEndpointInput");
|
|
478
|
+
formInputs.appendChild(endpointInput);
|
|
479
|
+
const addButton = document.createElement("button");
|
|
480
|
+
addButton.type = "button";
|
|
481
|
+
addButton.textContent = "+ Add Endpoint";
|
|
482
|
+
addClass(addButton, "addEndpointButton");
|
|
483
|
+
addButton.onclick = () => {
|
|
484
|
+
const endpoint = endpointInput.value.trim();
|
|
485
|
+
if (!endpoint) {
|
|
486
|
+
alert("Please enter an endpoint URL.");
|
|
487
|
+
return;
|
|
488
|
+
}
|
|
489
|
+
if (!/^https?:\/\//i.test(endpoint)) {
|
|
490
|
+
alert("Endpoint URL must start with http:// or https://");
|
|
491
|
+
return;
|
|
492
|
+
}
|
|
493
|
+
try {
|
|
494
|
+
new URL(endpoint);
|
|
495
|
+
}
|
|
496
|
+
catch (e) {
|
|
497
|
+
alert(e instanceof Error && e.message ? "Malformed URL: " + e.message : "Please enter a valid URL.");
|
|
498
|
+
return;
|
|
499
|
+
}
|
|
500
|
+
const existing = this.tab.yasgui.persistentConfig.getEndpointConfig(endpoint);
|
|
501
|
+
if (existing) {
|
|
502
|
+
alert("This endpoint is already in the list.");
|
|
503
|
+
return;
|
|
504
|
+
}
|
|
505
|
+
this.tab.yasgui.persistentConfig.addOrUpdateEndpoint(endpoint, {});
|
|
506
|
+
endpointInput.value = "";
|
|
507
|
+
this.renderEndpointsList(container);
|
|
508
|
+
this.tab.refreshEndpointButtons();
|
|
509
|
+
};
|
|
510
|
+
formInputs.appendChild(addButton);
|
|
511
|
+
addForm.appendChild(formInputs);
|
|
512
|
+
container.appendChild(addForm);
|
|
513
|
+
}
|
|
514
|
+
showAuthenticationModal(endpoint) {
|
|
515
|
+
const config = this.tab.yasgui.persistentConfig.getEndpointConfig(endpoint);
|
|
516
|
+
const existingAuth = config === null || config === void 0 ? void 0 : config.authentication;
|
|
517
|
+
const authModalOverlay = document.createElement("div");
|
|
518
|
+
addClass(authModalOverlay, "authModalOverlay");
|
|
519
|
+
authModalOverlay.onclick = () => authModalOverlay.remove();
|
|
520
|
+
const authModal = document.createElement("div");
|
|
521
|
+
addClass(authModal, "authModal");
|
|
522
|
+
authModal.onclick = (e) => e.stopPropagation();
|
|
523
|
+
const header = document.createElement("div");
|
|
524
|
+
addClass(header, "authModalHeader");
|
|
525
|
+
const title = document.createElement("h3");
|
|
526
|
+
title.textContent = "Configure Authentication";
|
|
527
|
+
const subtitle = document.createElement("div");
|
|
528
|
+
subtitle.textContent = endpoint;
|
|
529
|
+
addClass(subtitle, "authModalSubtitle");
|
|
530
|
+
header.appendChild(title);
|
|
531
|
+
header.appendChild(subtitle);
|
|
532
|
+
authModal.appendChild(header);
|
|
533
|
+
const body = document.createElement("div");
|
|
534
|
+
addClass(body, "authModalBody");
|
|
535
|
+
const typeSection = document.createElement("div");
|
|
536
|
+
addClass(typeSection, "authModalSection");
|
|
537
|
+
const typeLabel = document.createElement("label");
|
|
538
|
+
typeLabel.textContent = "Authentication Type";
|
|
539
|
+
const typeSelect = document.createElement("select");
|
|
540
|
+
const basicOption = document.createElement("option");
|
|
541
|
+
basicOption.value = "basic";
|
|
542
|
+
basicOption.textContent = "HTTP Basic Authentication";
|
|
543
|
+
typeSelect.appendChild(basicOption);
|
|
544
|
+
const bearerOption = document.createElement("option");
|
|
545
|
+
bearerOption.value = "bearer";
|
|
546
|
+
bearerOption.textContent = "Bearer Token";
|
|
547
|
+
typeSelect.appendChild(bearerOption);
|
|
548
|
+
const apiKeyOption = document.createElement("option");
|
|
549
|
+
apiKeyOption.value = "apiKey";
|
|
550
|
+
apiKeyOption.textContent = "API Key (Custom Header)";
|
|
551
|
+
typeSelect.appendChild(apiKeyOption);
|
|
552
|
+
if (existingAuth) {
|
|
553
|
+
typeSelect.value = existingAuth.type;
|
|
554
|
+
}
|
|
555
|
+
typeSection.appendChild(typeLabel);
|
|
556
|
+
typeSection.appendChild(typeSelect);
|
|
557
|
+
body.appendChild(typeSection);
|
|
558
|
+
const basicAuthFields = document.createElement("div");
|
|
559
|
+
basicAuthFields.id = "basicAuthFields";
|
|
560
|
+
addClass(basicAuthFields, "authFieldsContainer");
|
|
561
|
+
const usernameSection = document.createElement("div");
|
|
562
|
+
addClass(usernameSection, "authModalSection");
|
|
563
|
+
const usernameLabel = document.createElement("label");
|
|
564
|
+
usernameLabel.textContent = "Username";
|
|
565
|
+
const usernameInput = document.createElement("input");
|
|
566
|
+
usernameInput.type = "text";
|
|
567
|
+
usernameInput.placeholder = "Enter username";
|
|
568
|
+
usernameInput.value = (existingAuth === null || existingAuth === void 0 ? void 0 : existingAuth.type) === "basic" ? existingAuth.username : "";
|
|
569
|
+
usernameInput.autocomplete = "username";
|
|
570
|
+
usernameSection.appendChild(usernameLabel);
|
|
571
|
+
usernameSection.appendChild(usernameInput);
|
|
572
|
+
basicAuthFields.appendChild(usernameSection);
|
|
573
|
+
const passwordSection = document.createElement("div");
|
|
574
|
+
addClass(passwordSection, "authModalSection");
|
|
575
|
+
const passwordLabel = document.createElement("label");
|
|
576
|
+
passwordLabel.textContent = "Password";
|
|
577
|
+
const passwordInput = document.createElement("input");
|
|
578
|
+
passwordInput.type = "password";
|
|
579
|
+
passwordInput.placeholder = "Enter password";
|
|
580
|
+
passwordInput.value = (existingAuth === null || existingAuth === void 0 ? void 0 : existingAuth.type) === "basic" ? existingAuth.password : "";
|
|
581
|
+
passwordInput.autocomplete = "current-password";
|
|
582
|
+
passwordSection.appendChild(passwordLabel);
|
|
583
|
+
passwordSection.appendChild(passwordInput);
|
|
584
|
+
basicAuthFields.appendChild(passwordSection);
|
|
585
|
+
body.appendChild(basicAuthFields);
|
|
586
|
+
const bearerAuthFields = document.createElement("div");
|
|
587
|
+
bearerAuthFields.id = "bearerAuthFields";
|
|
588
|
+
addClass(bearerAuthFields, "authFieldsContainer");
|
|
589
|
+
bearerAuthFields.style.display = "none";
|
|
590
|
+
const tokenSection = document.createElement("div");
|
|
591
|
+
addClass(tokenSection, "authModalSection");
|
|
592
|
+
const tokenLabel = document.createElement("label");
|
|
593
|
+
tokenLabel.textContent = "Bearer Token";
|
|
594
|
+
const tokenInput = document.createElement("input");
|
|
595
|
+
tokenInput.type = "password";
|
|
596
|
+
tokenInput.placeholder = "Enter bearer token";
|
|
597
|
+
tokenInput.autocomplete = "off";
|
|
598
|
+
tokenInput.value = (existingAuth === null || existingAuth === void 0 ? void 0 : existingAuth.type) === "bearer" ? existingAuth.token : "";
|
|
599
|
+
tokenSection.appendChild(tokenLabel);
|
|
600
|
+
tokenSection.appendChild(tokenInput);
|
|
601
|
+
bearerAuthFields.appendChild(tokenSection);
|
|
602
|
+
body.appendChild(bearerAuthFields);
|
|
603
|
+
const apiKeyAuthFields = document.createElement("div");
|
|
604
|
+
apiKeyAuthFields.id = "apiKeyAuthFields";
|
|
605
|
+
addClass(apiKeyAuthFields, "authFieldsContainer");
|
|
606
|
+
apiKeyAuthFields.style.display = "none";
|
|
607
|
+
const headerNameSection = document.createElement("div");
|
|
608
|
+
addClass(headerNameSection, "authModalSection");
|
|
609
|
+
const headerNameLabel = document.createElement("label");
|
|
610
|
+
headerNameLabel.textContent = "Header Name";
|
|
611
|
+
const headerNameInput = document.createElement("input");
|
|
612
|
+
headerNameInput.type = "text";
|
|
613
|
+
headerNameInput.placeholder = `e.g., ${DEFAULT_API_KEY_HEADER}`;
|
|
614
|
+
headerNameInput.value = (existingAuth === null || existingAuth === void 0 ? void 0 : existingAuth.type) === "apiKey" ? existingAuth.headerName : DEFAULT_API_KEY_HEADER;
|
|
615
|
+
headerNameSection.appendChild(headerNameLabel);
|
|
616
|
+
headerNameSection.appendChild(headerNameInput);
|
|
617
|
+
apiKeyAuthFields.appendChild(headerNameSection);
|
|
618
|
+
const apiKeySection = document.createElement("div");
|
|
619
|
+
addClass(apiKeySection, "authModalSection");
|
|
620
|
+
const apiKeyLabel = document.createElement("label");
|
|
621
|
+
apiKeyLabel.textContent = "API Key";
|
|
622
|
+
const apiKeyInput = document.createElement("input");
|
|
623
|
+
apiKeyInput.type = "password";
|
|
624
|
+
apiKeyInput.placeholder = "Enter API key";
|
|
625
|
+
apiKeyInput.autocomplete = "off";
|
|
626
|
+
apiKeyInput.value = (existingAuth === null || existingAuth === void 0 ? void 0 : existingAuth.type) === "apiKey" ? existingAuth.apiKey : "";
|
|
627
|
+
apiKeySection.appendChild(apiKeyLabel);
|
|
628
|
+
apiKeySection.appendChild(apiKeyInput);
|
|
629
|
+
apiKeyAuthFields.appendChild(apiKeySection);
|
|
630
|
+
body.appendChild(apiKeyAuthFields);
|
|
631
|
+
const toggleAuthFields = () => {
|
|
632
|
+
const authType = typeSelect.value;
|
|
633
|
+
basicAuthFields.style.display = authType === "basic" ? "block" : "none";
|
|
634
|
+
bearerAuthFields.style.display = authType === "bearer" ? "block" : "none";
|
|
635
|
+
apiKeyAuthFields.style.display = authType === "apiKey" ? "block" : "none";
|
|
636
|
+
};
|
|
637
|
+
toggleAuthFields();
|
|
638
|
+
typeSelect.onchange = toggleAuthFields;
|
|
639
|
+
const securityNotice = document.createElement("div");
|
|
640
|
+
addClass(securityNotice, "authSecurityNotice");
|
|
641
|
+
securityNotice.innerHTML = `
|
|
642
|
+
<strong>⚠️ Security Notice:</strong>
|
|
643
|
+
<ul>
|
|
644
|
+
<li>Credentials are stored in browser localStorage</li>
|
|
645
|
+
<li>Only use with HTTPS endpoints</li>
|
|
646
|
+
<li>Be cautious when using on shared computers</li>
|
|
647
|
+
</ul>
|
|
648
|
+
`;
|
|
649
|
+
body.appendChild(securityNotice);
|
|
650
|
+
authModal.appendChild(body);
|
|
651
|
+
const footer = document.createElement("div");
|
|
652
|
+
addClass(footer, "authModalFooter");
|
|
653
|
+
const removeButton = document.createElement("button");
|
|
654
|
+
removeButton.textContent = "Remove Authentication";
|
|
655
|
+
removeButton.type = "button";
|
|
656
|
+
addClass(removeButton, "authRemoveButton");
|
|
657
|
+
removeButton.onclick = () => {
|
|
658
|
+
this.tab.yasgui.persistentConfig.addOrUpdateEndpoint(endpoint, {
|
|
659
|
+
authentication: undefined,
|
|
660
|
+
});
|
|
661
|
+
authModalOverlay.remove();
|
|
662
|
+
const endpointsList = this.modalContent.querySelector(".endpointsTable");
|
|
663
|
+
if (endpointsList)
|
|
664
|
+
this.renderEndpointsList(endpointsList);
|
|
665
|
+
};
|
|
666
|
+
if (!existingAuth) {
|
|
667
|
+
removeButton.disabled = true;
|
|
668
|
+
}
|
|
669
|
+
const cancelButton = document.createElement("button");
|
|
670
|
+
cancelButton.textContent = "Cancel";
|
|
671
|
+
cancelButton.type = "button";
|
|
672
|
+
addClass(cancelButton, "authCancelButton");
|
|
673
|
+
cancelButton.onclick = () => authModalOverlay.remove();
|
|
674
|
+
const saveButton = document.createElement("button");
|
|
675
|
+
saveButton.textContent = "Save";
|
|
676
|
+
saveButton.type = "button";
|
|
677
|
+
addClass(saveButton, "authSaveButton");
|
|
678
|
+
saveButton.onclick = () => {
|
|
679
|
+
const authType = typeSelect.value;
|
|
680
|
+
if (authType === "basic") {
|
|
681
|
+
const username = usernameInput.value.trim();
|
|
682
|
+
const password = passwordInput.value;
|
|
683
|
+
if (username && password) {
|
|
684
|
+
this.tab.yasgui.persistentConfig.addOrUpdateEndpoint(endpoint, {
|
|
685
|
+
authentication: {
|
|
686
|
+
type: "basic",
|
|
687
|
+
username,
|
|
688
|
+
password,
|
|
689
|
+
},
|
|
690
|
+
});
|
|
691
|
+
authModalOverlay.remove();
|
|
692
|
+
const endpointsList = this.modalContent.querySelector(".endpointsTable");
|
|
693
|
+
if (endpointsList)
|
|
694
|
+
this.renderEndpointsList(endpointsList);
|
|
695
|
+
}
|
|
696
|
+
else {
|
|
697
|
+
alert("Please enter both username and password.");
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
else if (authType === "bearer") {
|
|
701
|
+
const token = tokenInput.value.trim();
|
|
702
|
+
if (token) {
|
|
703
|
+
this.tab.yasgui.persistentConfig.addOrUpdateEndpoint(endpoint, {
|
|
704
|
+
authentication: {
|
|
705
|
+
type: "bearer",
|
|
706
|
+
token,
|
|
707
|
+
},
|
|
708
|
+
});
|
|
709
|
+
authModalOverlay.remove();
|
|
710
|
+
const endpointsList = this.modalContent.querySelector(".endpointsTable");
|
|
711
|
+
if (endpointsList)
|
|
712
|
+
this.renderEndpointsList(endpointsList);
|
|
713
|
+
}
|
|
714
|
+
else {
|
|
715
|
+
alert("Please enter a bearer token.");
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
else if (authType === "apiKey") {
|
|
719
|
+
const headerName = headerNameInput.value.trim();
|
|
720
|
+
const apiKey = apiKeyInput.value.trim();
|
|
721
|
+
if (headerName && apiKey) {
|
|
722
|
+
this.tab.yasgui.persistentConfig.addOrUpdateEndpoint(endpoint, {
|
|
723
|
+
authentication: {
|
|
724
|
+
type: "apiKey",
|
|
725
|
+
headerName,
|
|
726
|
+
apiKey,
|
|
727
|
+
},
|
|
728
|
+
});
|
|
729
|
+
authModalOverlay.remove();
|
|
730
|
+
const endpointsList = this.modalContent.querySelector(".endpointsTable");
|
|
731
|
+
if (endpointsList)
|
|
732
|
+
this.renderEndpointsList(endpointsList);
|
|
733
|
+
}
|
|
734
|
+
else {
|
|
735
|
+
alert("Please enter both header name and API key.");
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
};
|
|
739
|
+
footer.appendChild(removeButton);
|
|
740
|
+
footer.appendChild(cancelButton);
|
|
741
|
+
footer.appendChild(saveButton);
|
|
742
|
+
authModal.appendChild(footer);
|
|
743
|
+
authModalOverlay.appendChild(authModal);
|
|
744
|
+
document.body.appendChild(authModalOverlay);
|
|
745
|
+
}
|
|
341
746
|
drawRequestSettings(container) {
|
|
342
747
|
const reqConfig = this.tab.getRequestConfig();
|
|
343
748
|
const methodSection = this.createSection("Request Method");
|
|
@@ -434,7 +839,18 @@ export default class TabSettingsModal {
|
|
|
434
839
|
}
|
|
435
840
|
const snippetsBarCheckbox = document.getElementById("showSnippetsBar");
|
|
436
841
|
if (snippetsBarCheckbox) {
|
|
437
|
-
|
|
842
|
+
this.tab.yasgui.config.showSnippetsBar = snippetsBarCheckbox.checked;
|
|
843
|
+
this.tab.yasgui.persistentConfig.setShowSnippetsBar(snippetsBarCheckbox.checked);
|
|
844
|
+
this.tab.yasgui.persistentConfig.getTabs().forEach((tabId) => {
|
|
845
|
+
const tab = this.tab.yasgui.getTab(tabId);
|
|
846
|
+
if (tab) {
|
|
847
|
+
const tabYasqe = tab.getYasqe();
|
|
848
|
+
if (tabYasqe) {
|
|
849
|
+
tabYasqe.config.showSnippetsBar = snippetsBarCheckbox.checked;
|
|
850
|
+
tabYasqe.refreshSnippetsBar();
|
|
851
|
+
}
|
|
852
|
+
}
|
|
853
|
+
});
|
|
438
854
|
}
|
|
439
855
|
yasqe.saveQuery();
|
|
440
856
|
}
|
|
@@ -523,90 +939,6 @@ export default class TabSettingsModal {
|
|
|
523
939
|
const deduplicated = this.deduplicatePrefixes(combined);
|
|
524
940
|
this.tab.yasgui.persistentConfig.setPrefixes(deduplicated);
|
|
525
941
|
}
|
|
526
|
-
drawEndpointButtonsSettings(container) {
|
|
527
|
-
const section = document.createElement("div");
|
|
528
|
-
addClass(section, "settingsSection");
|
|
529
|
-
const label = document.createElement("label");
|
|
530
|
-
label.textContent = "Custom Endpoint Buttons";
|
|
531
|
-
addClass(label, "settingsLabel");
|
|
532
|
-
const help = document.createElement("div");
|
|
533
|
-
help.textContent = "Add custom endpoint buttons that will appear next to the endpoint textbox.";
|
|
534
|
-
addClass(help, "settingsHelp");
|
|
535
|
-
section.appendChild(label);
|
|
536
|
-
section.appendChild(help);
|
|
537
|
-
const buttonsList = document.createElement("div");
|
|
538
|
-
addClass(buttonsList, "endpointButtonsList");
|
|
539
|
-
this.renderEndpointButtonsList(buttonsList);
|
|
540
|
-
section.appendChild(buttonsList);
|
|
541
|
-
const addForm = document.createElement("div");
|
|
542
|
-
addClass(addForm, "addEndpointButtonForm");
|
|
543
|
-
const labelInput = document.createElement("input");
|
|
544
|
-
labelInput.type = "text";
|
|
545
|
-
labelInput.placeholder = "Button label (e.g., DBpedia)";
|
|
546
|
-
addClass(labelInput, "endpointButtonLabelInput");
|
|
547
|
-
const endpointInput = document.createElement("input");
|
|
548
|
-
endpointInput.type = "url";
|
|
549
|
-
endpointInput.placeholder = "Endpoint URL (e.g., https://dbpedia.org/sparql)";
|
|
550
|
-
addClass(endpointInput, "endpointButtonEndpointInput");
|
|
551
|
-
const addButton = document.createElement("button");
|
|
552
|
-
addButton.textContent = "+ Add Button";
|
|
553
|
-
addClass(addButton, "addEndpointButton");
|
|
554
|
-
addButton.type = "button";
|
|
555
|
-
addButton.onclick = () => {
|
|
556
|
-
const labelValue = labelInput.value.trim();
|
|
557
|
-
const endpointValue = endpointInput.value.trim();
|
|
558
|
-
if (!labelValue || !endpointValue) {
|
|
559
|
-
alert("Please enter both a label and an endpoint URL.");
|
|
560
|
-
return;
|
|
561
|
-
}
|
|
562
|
-
const currentButtons = this.tab.yasgui.persistentConfig.getCustomEndpointButtons();
|
|
563
|
-
currentButtons.push({ label: labelValue, endpoint: endpointValue });
|
|
564
|
-
this.tab.yasgui.persistentConfig.setCustomEndpointButtons(currentButtons);
|
|
565
|
-
labelInput.value = "";
|
|
566
|
-
endpointInput.value = "";
|
|
567
|
-
this.renderEndpointButtonsList(buttonsList);
|
|
568
|
-
};
|
|
569
|
-
addForm.appendChild(labelInput);
|
|
570
|
-
addForm.appendChild(endpointInput);
|
|
571
|
-
addForm.appendChild(addButton);
|
|
572
|
-
section.appendChild(addForm);
|
|
573
|
-
container.appendChild(section);
|
|
574
|
-
}
|
|
575
|
-
renderEndpointButtonsList(container) {
|
|
576
|
-
container.innerHTML = "";
|
|
577
|
-
const customButtons = this.tab.yasgui.persistentConfig.getCustomEndpointButtons();
|
|
578
|
-
if (customButtons.length === 0) {
|
|
579
|
-
const emptyMsg = document.createElement("div");
|
|
580
|
-
emptyMsg.textContent = "No custom buttons yet. Add one below.";
|
|
581
|
-
addClass(emptyMsg, "emptyMessage");
|
|
582
|
-
container.appendChild(emptyMsg);
|
|
583
|
-
return;
|
|
584
|
-
}
|
|
585
|
-
customButtons.forEach((btn, index) => {
|
|
586
|
-
const item = document.createElement("div");
|
|
587
|
-
addClass(item, "endpointButtonItem");
|
|
588
|
-
const labelSpan = document.createElement("span");
|
|
589
|
-
labelSpan.textContent = `${btn.label}`;
|
|
590
|
-
addClass(labelSpan, "buttonLabel");
|
|
591
|
-
const endpointSpan = document.createElement("span");
|
|
592
|
-
endpointSpan.textContent = btn.endpoint;
|
|
593
|
-
addClass(endpointSpan, "buttonEndpoint");
|
|
594
|
-
const removeBtn = document.createElement("button");
|
|
595
|
-
removeBtn.textContent = "×";
|
|
596
|
-
addClass(removeBtn, "removeButton");
|
|
597
|
-
removeBtn.type = "button";
|
|
598
|
-
removeBtn.onclick = () => {
|
|
599
|
-
const currentButtons = this.tab.yasgui.persistentConfig.getCustomEndpointButtons();
|
|
600
|
-
currentButtons.splice(index, 1);
|
|
601
|
-
this.tab.yasgui.persistentConfig.setCustomEndpointButtons(currentButtons);
|
|
602
|
-
this.renderEndpointButtonsList(container);
|
|
603
|
-
};
|
|
604
|
-
item.appendChild(labelSpan);
|
|
605
|
-
item.appendChild(endpointSpan);
|
|
606
|
-
item.appendChild(removeBtn);
|
|
607
|
-
container.appendChild(item);
|
|
608
|
-
});
|
|
609
|
-
}
|
|
610
942
|
getThemeToggleIcon() {
|
|
611
943
|
const currentTheme = this.tab.yasgui.getTheme();
|
|
612
944
|
return currentTheme === "dark" ? MOON_ICON : SUN_ICON;
|