@matdata/yasgui 5.4.0 → 5.5.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.
@@ -111,56 +111,63 @@ export default class TabSettingsModal {
111
111
 
112
112
  this.modalContent.appendChild(header);
113
113
 
114
- // Body with tabs
114
+ // Body with sidebar navigation
115
115
  const body = document.createElement("div");
116
116
  addClass(body, "modalBody");
117
117
 
118
- const tabsContainer = document.createElement("div");
119
- addClass(tabsContainer, "modalTabs");
118
+ // Sidebar navigation
119
+ const sidebar = document.createElement("div");
120
+ addClass(sidebar, "modalSidebar");
120
121
 
121
122
  const requestTab = document.createElement("button");
122
123
  requestTab.textContent = "Request";
123
- addClass(requestTab, "modalTabButton", "active");
124
+ addClass(requestTab, "modalNavButton", "active");
124
125
  requestTab.onclick = () => this.switchTab("request");
125
126
 
127
+ const endpointsTab = document.createElement("button");
128
+ endpointsTab.textContent = "SPARQL Endpoints";
129
+ addClass(endpointsTab, "modalNavButton");
130
+ endpointsTab.onclick = () => this.switchTab("endpoints");
131
+
126
132
  const prefixTab = document.createElement("button");
127
133
  prefixTab.textContent = "Prefixes";
128
- addClass(prefixTab, "modalTabButton");
134
+ addClass(prefixTab, "modalNavButton");
129
135
  prefixTab.onclick = () => this.switchTab("prefix");
130
136
 
131
137
  const editorTab = document.createElement("button");
132
138
  editorTab.textContent = "Editor";
133
- addClass(editorTab, "modalTabButton");
139
+ addClass(editorTab, "modalNavButton");
134
140
  editorTab.onclick = () => this.switchTab("editor");
135
141
 
136
- const endpointsTab = document.createElement("button");
137
- endpointsTab.textContent = "Endpoint Buttons";
138
- addClass(endpointsTab, "modalTabButton");
139
- endpointsTab.onclick = () => this.switchTab("endpoints");
140
-
141
142
  const importExportTab = document.createElement("button");
142
143
  importExportTab.textContent = "Import/Export";
143
- addClass(importExportTab, "modalTabButton");
144
+ addClass(importExportTab, "modalNavButton");
144
145
  importExportTab.onclick = () => this.switchTab("importexport");
145
146
 
146
147
  const shortcutsTab = document.createElement("button");
147
148
  shortcutsTab.textContent = "Keyboard Shortcuts";
148
- addClass(shortcutsTab, "modalTabButton");
149
+ addClass(shortcutsTab, "modalNavButton");
149
150
  shortcutsTab.onclick = () => this.switchTab("shortcuts");
150
151
 
151
152
  const aboutTab = document.createElement("button");
152
153
  aboutTab.textContent = "About";
153
- addClass(aboutTab, "modalTabButton");
154
+ addClass(aboutTab, "modalNavButton");
154
155
  aboutTab.onclick = () => this.switchTab("about");
155
156
 
156
- tabsContainer.appendChild(requestTab);
157
- tabsContainer.appendChild(prefixTab);
158
- tabsContainer.appendChild(editorTab);
159
- tabsContainer.appendChild(endpointsTab);
160
- tabsContainer.appendChild(importExportTab);
161
- tabsContainer.appendChild(shortcutsTab);
162
- tabsContainer.appendChild(aboutTab);
163
- body.appendChild(tabsContainer);
157
+ sidebar.appendChild(requestTab);
158
+ sidebar.appendChild(endpointsTab);
159
+ sidebar.appendChild(prefixTab);
160
+ sidebar.appendChild(editorTab);
161
+ sidebar.appendChild(importExportTab);
162
+ sidebar.appendChild(shortcutsTab);
163
+ sidebar.appendChild(aboutTab);
164
+
165
+ // Content area container
166
+ const contentArea = document.createElement("div");
167
+ addClass(contentArea, "modalContentArea");
168
+
169
+ body.appendChild(sidebar);
170
+ body.appendChild(contentArea);
164
171
 
165
172
  // Tab content containers
166
173
  const requestContent = document.createElement("div");
@@ -168,6 +175,11 @@ export default class TabSettingsModal {
168
175
  requestContent.id = "request-content";
169
176
  this.drawRequestSettings(requestContent);
170
177
 
178
+ const endpointsContent = document.createElement("div");
179
+ addClass(endpointsContent, "modalTabContent");
180
+ endpointsContent.id = "endpoints-content";
181
+ this.drawEndpointsSettings(endpointsContent);
182
+
171
183
  const prefixContent = document.createElement("div");
172
184
  addClass(prefixContent, "modalTabContent");
173
185
  prefixContent.id = "prefix-content";
@@ -178,11 +190,6 @@ export default class TabSettingsModal {
178
190
  editorContent.id = "editor-content";
179
191
  this.drawEditorSettings(editorContent);
180
192
 
181
- const endpointsContent = document.createElement("div");
182
- addClass(endpointsContent, "modalTabContent");
183
- endpointsContent.id = "endpoints-content";
184
- this.drawEndpointButtonsSettings(endpointsContent);
185
-
186
193
  const importExportContent = document.createElement("div");
187
194
  addClass(importExportContent, "modalTabContent");
188
195
  importExportContent.id = "importexport-content";
@@ -198,13 +205,13 @@ export default class TabSettingsModal {
198
205
  aboutContent.id = "about-content";
199
206
  this.drawAboutSettings(aboutContent);
200
207
 
201
- body.appendChild(requestContent);
202
- body.appendChild(prefixContent);
203
- body.appendChild(editorContent);
204
- body.appendChild(endpointsContent);
205
- body.appendChild(importExportContent);
206
- body.appendChild(shortcutsContent);
207
- body.appendChild(aboutContent);
208
+ contentArea.appendChild(requestContent);
209
+ contentArea.appendChild(endpointsContent);
210
+ contentArea.appendChild(prefixContent);
211
+ contentArea.appendChild(editorContent);
212
+ contentArea.appendChild(importExportContent);
213
+ contentArea.appendChild(shortcutsContent);
214
+ contentArea.appendChild(aboutContent);
208
215
 
209
216
  this.modalContent.appendChild(body);
210
217
 
@@ -232,15 +239,15 @@ export default class TabSettingsModal {
232
239
  }
233
240
 
234
241
  private switchTab(tabName: string) {
235
- const buttons = this.modalContent.querySelectorAll(".modalTabButton");
242
+ const buttons = this.modalContent.querySelectorAll(".modalNavButton");
236
243
  const contents = this.modalContent.querySelectorAll(".modalTabContent");
237
244
 
238
245
  buttons.forEach((btn, index) => {
239
246
  if (
240
247
  (tabName === "request" && index === 0) ||
241
- (tabName === "prefix" && index === 1) ||
242
- (tabName === "editor" && index === 2) ||
243
- (tabName === "endpoints" && index === 3) ||
248
+ (tabName === "endpoints" && index === 1) ||
249
+ (tabName === "prefix" && index === 2) ||
250
+ (tabName === "editor" && index === 3) ||
244
251
  (tabName === "importexport" && index === 4) ||
245
252
  (tabName === "shortcuts" && index === 5) ||
246
253
  (tabName === "about" && index === 6)
@@ -436,6 +443,369 @@ export default class TabSettingsModal {
436
443
  container.appendChild(snippetsBarSection);
437
444
  }
438
445
 
446
+ private drawEndpointsSettings(container: HTMLElement) {
447
+ const section = document.createElement("div");
448
+ addClass(section, "settingsSection");
449
+
450
+ const label = document.createElement("label");
451
+ label.textContent = "SPARQL Endpoints";
452
+ addClass(label, "settingsLabel");
453
+
454
+ const help = document.createElement("div");
455
+ help.textContent =
456
+ "Manage your SPARQL endpoints. Each endpoint can have its own authentication and be displayed as a quick-switch button.";
457
+ addClass(help, "settingsHelp");
458
+
459
+ section.appendChild(label);
460
+ section.appendChild(help);
461
+
462
+ // List of endpoints
463
+ const endpointsList = document.createElement("div");
464
+ addClass(endpointsList, "endpointsTable");
465
+ this.renderEndpointsList(endpointsList);
466
+ section.appendChild(endpointsList);
467
+
468
+ container.appendChild(section);
469
+ }
470
+
471
+ private renderEndpointsList(container: HTMLElement) {
472
+ container.innerHTML = "";
473
+ const configs = this.tab.yasgui.persistentConfig.getEndpointConfigs();
474
+
475
+ // Create table (even if empty, we'll show add form)
476
+ const table = document.createElement("table");
477
+ addClass(table, "endpointsTableElement");
478
+
479
+ // Header
480
+ const thead = document.createElement("thead");
481
+ const headerRow = document.createElement("tr");
482
+ const headers = ["Endpoint", "Label", "Button", "Authentication", "Actions"];
483
+ headers.forEach((h) => {
484
+ const th = document.createElement("th");
485
+ th.textContent = h;
486
+ headerRow.appendChild(th);
487
+ });
488
+ thead.appendChild(headerRow);
489
+ table.appendChild(thead);
490
+
491
+ // Body
492
+ const tbody = document.createElement("tbody");
493
+
494
+ if (configs.length === 0) {
495
+ // Show empty message in table
496
+ const emptyRow = document.createElement("tr");
497
+ const emptyCell = document.createElement("td");
498
+ emptyCell.colSpan = 5;
499
+ emptyCell.textContent = "No endpoints yet. Add one below or access an endpoint to have it automatically tracked.";
500
+ addClass(emptyCell, "emptyMessage");
501
+ emptyCell.style.textAlign = "center";
502
+ emptyCell.style.padding = "20px";
503
+ emptyRow.appendChild(emptyCell);
504
+ tbody.appendChild(emptyRow);
505
+ }
506
+
507
+ configs.forEach((config, index) => {
508
+ const row = document.createElement("tr");
509
+
510
+ // Endpoint column
511
+ const endpointCell = document.createElement("td");
512
+ endpointCell.textContent = config.endpoint;
513
+ endpointCell.title = config.endpoint;
514
+ addClass(endpointCell, "endpointCell");
515
+ row.appendChild(endpointCell);
516
+
517
+ // Label column (editable)
518
+ const labelCell = document.createElement("td");
519
+ const labelInput = document.createElement("input");
520
+ labelInput.type = "text";
521
+ labelInput.value = config.label || "";
522
+ labelInput.placeholder = "Optional label";
523
+ addClass(labelInput, "endpointLabelInput");
524
+ labelInput.onchange = () => {
525
+ this.tab.yasgui.persistentConfig.addOrUpdateEndpoint(config.endpoint, {
526
+ label: labelInput.value.trim() || undefined,
527
+ });
528
+ this.renderEndpointsList(container);
529
+ this.tab.refreshEndpointButtons();
530
+ };
531
+ labelCell.appendChild(labelInput);
532
+ row.appendChild(labelCell);
533
+
534
+ // Show as Button checkbox (requires label)
535
+ const buttonCell = document.createElement("td");
536
+ const buttonCheckbox = document.createElement("input");
537
+ buttonCheckbox.type = "checkbox";
538
+ buttonCheckbox.checked = !!config.showAsButton;
539
+ buttonCheckbox.disabled = !config.label;
540
+ buttonCheckbox.setAttribute(
541
+ "aria-label",
542
+ config.label ? "Show this endpoint as a quick-switch button" : "Add a label first to enable button",
543
+ );
544
+ buttonCheckbox.title = config.label
545
+ ? "Show this endpoint as a quick-switch button"
546
+ : "Add a label first to enable button";
547
+ buttonCheckbox.onchange = () => {
548
+ this.tab.yasgui.persistentConfig.addOrUpdateEndpoint(config.endpoint, {
549
+ showAsButton: buttonCheckbox.checked,
550
+ });
551
+ this.tab.refreshEndpointButtons();
552
+ };
553
+ buttonCell.appendChild(buttonCheckbox);
554
+ addClass(buttonCell, "centerCell");
555
+ row.appendChild(buttonCell);
556
+
557
+ // Authentication column
558
+ const authCell = document.createElement("td");
559
+ const authButton = document.createElement("button");
560
+ authButton.type = "button";
561
+ addClass(authButton, "configureAuthButton");
562
+ if (config.authentication) {
563
+ authButton.textContent = "✓ Configured";
564
+ addClass(authButton, "authenticated");
565
+ } else {
566
+ authButton.textContent = "Configure";
567
+ }
568
+ authButton.onclick = () => this.showAuthenticationModal(config.endpoint);
569
+ authCell.appendChild(authButton);
570
+ addClass(authCell, "centerCell");
571
+ row.appendChild(authCell);
572
+
573
+ // Actions column
574
+ const actionsCell = document.createElement("td");
575
+ const deleteButton = document.createElement("button");
576
+ deleteButton.type = "button";
577
+ deleteButton.textContent = "Delete";
578
+ addClass(deleteButton, "deleteEndpointButton");
579
+ deleteButton.onclick = () => {
580
+ if (confirm(`Delete endpoint "${config.endpoint}"?`)) {
581
+ this.tab.yasgui.persistentConfig.deleteEndpointConfig(config.endpoint);
582
+ this.renderEndpointsList(container);
583
+ this.tab.refreshEndpointButtons();
584
+ }
585
+ };
586
+ actionsCell.appendChild(deleteButton);
587
+ addClass(actionsCell, "centerCell");
588
+ row.appendChild(actionsCell);
589
+
590
+ tbody.appendChild(row);
591
+ });
592
+ table.appendChild(tbody);
593
+ container.appendChild(table);
594
+
595
+ // Add endpoint form
596
+ const addForm = document.createElement("div");
597
+ addClass(addForm, "addEndpointForm");
598
+
599
+ const addFormTitle = document.createElement("div");
600
+ addFormTitle.textContent = "Add New Endpoint";
601
+ addClass(addFormTitle, "addFormTitle");
602
+ addForm.appendChild(addFormTitle);
603
+
604
+ const formInputs = document.createElement("div");
605
+ addClass(formInputs, "addFormInputs");
606
+
607
+ const endpointInput = document.createElement("input");
608
+ endpointInput.type = "url";
609
+ endpointInput.placeholder = "Endpoint URL (e.g., https://dbpedia.org/sparql)";
610
+ addClass(endpointInput, "addEndpointInput");
611
+ formInputs.appendChild(endpointInput);
612
+
613
+ const addButton = document.createElement("button");
614
+ addButton.type = "button";
615
+ addButton.textContent = "+ Add Endpoint";
616
+ addClass(addButton, "addEndpointButton");
617
+ addButton.onclick = () => {
618
+ const endpoint = endpointInput.value.trim();
619
+
620
+ if (!endpoint) {
621
+ alert("Please enter an endpoint URL.");
622
+ return;
623
+ }
624
+
625
+ // Validate URL format
626
+ // Check for supported protocol first
627
+ if (!/^https?:\/\//i.test(endpoint)) {
628
+ alert("Endpoint URL must start with http:// or https://");
629
+ return;
630
+ }
631
+ try {
632
+ new URL(endpoint);
633
+ } catch (e) {
634
+ // Show the error message if available, otherwise a generic one
635
+ alert(e instanceof Error && e.message ? "Malformed URL: " + e.message : "Please enter a valid URL.");
636
+ return;
637
+ }
638
+
639
+ // Check if endpoint already exists
640
+ const existing = this.tab.yasgui.persistentConfig.getEndpointConfig(endpoint);
641
+ if (existing) {
642
+ alert("This endpoint is already in the list.");
643
+ return;
644
+ }
645
+
646
+ // Add the endpoint
647
+ this.tab.yasgui.persistentConfig.addOrUpdateEndpoint(endpoint, {});
648
+
649
+ // Clear input
650
+ endpointInput.value = "";
651
+
652
+ // Refresh list
653
+ this.renderEndpointsList(container);
654
+ this.tab.refreshEndpointButtons();
655
+ };
656
+ formInputs.appendChild(addButton);
657
+
658
+ addForm.appendChild(formInputs);
659
+ container.appendChild(addForm);
660
+ }
661
+
662
+ private showAuthenticationModal(endpoint: string) {
663
+ const config = this.tab.yasgui.persistentConfig.getEndpointConfig(endpoint);
664
+ const existingAuth = config?.authentication;
665
+
666
+ // Create modal overlay
667
+ const authModalOverlay = document.createElement("div");
668
+ addClass(authModalOverlay, "authModalOverlay");
669
+ authModalOverlay.onclick = () => authModalOverlay.remove();
670
+
671
+ // Create modal content
672
+ const authModal = document.createElement("div");
673
+ addClass(authModal, "authModal");
674
+ authModal.onclick = (e) => e.stopPropagation();
675
+
676
+ // Header
677
+ const header = document.createElement("div");
678
+ addClass(header, "authModalHeader");
679
+ const title = document.createElement("h3");
680
+ title.textContent = "Configure Authentication";
681
+ const subtitle = document.createElement("div");
682
+ subtitle.textContent = endpoint;
683
+ addClass(subtitle, "authModalSubtitle");
684
+ header.appendChild(title);
685
+ header.appendChild(subtitle);
686
+ authModal.appendChild(header);
687
+
688
+ // Body
689
+ const body = document.createElement("div");
690
+ addClass(body, "authModalBody");
691
+
692
+ // Auth type (for now only basic, but designed for future)
693
+ const typeSection = document.createElement("div");
694
+ addClass(typeSection, "authModalSection");
695
+ const typeLabel = document.createElement("label");
696
+ typeLabel.textContent = "Authentication Type";
697
+ const typeSelect = document.createElement("select");
698
+ const basicOption = document.createElement("option");
699
+ basicOption.value = "basic";
700
+ basicOption.textContent = "HTTP Basic Authentication";
701
+ typeSelect.appendChild(basicOption);
702
+ // Future: Add OAuth, Bearer Token, etc.
703
+ typeSection.appendChild(typeLabel);
704
+ typeSection.appendChild(typeSelect);
705
+ body.appendChild(typeSection);
706
+
707
+ // Username
708
+ const usernameSection = document.createElement("div");
709
+ addClass(usernameSection, "authModalSection");
710
+ const usernameLabel = document.createElement("label");
711
+ usernameLabel.textContent = "Username";
712
+ const usernameInput = document.createElement("input");
713
+ usernameInput.type = "text";
714
+ usernameInput.placeholder = "Enter username";
715
+ usernameInput.value = existingAuth?.username || "";
716
+ usernameInput.autocomplete = "username";
717
+ usernameSection.appendChild(usernameLabel);
718
+ usernameSection.appendChild(usernameInput);
719
+ body.appendChild(usernameSection);
720
+
721
+ // Password
722
+ const passwordSection = document.createElement("div");
723
+ addClass(passwordSection, "authModalSection");
724
+ const passwordLabel = document.createElement("label");
725
+ passwordLabel.textContent = "Password";
726
+ const passwordInput = document.createElement("input");
727
+ passwordInput.type = "password";
728
+ passwordInput.placeholder = "Enter password";
729
+ passwordInput.value = existingAuth?.password || "";
730
+ passwordInput.autocomplete = "current-password";
731
+ passwordSection.appendChild(passwordLabel);
732
+ passwordSection.appendChild(passwordInput);
733
+ body.appendChild(passwordSection);
734
+
735
+ // Security notice
736
+ const securityNotice = document.createElement("div");
737
+ addClass(securityNotice, "authSecurityNotice");
738
+ securityNotice.innerHTML = `
739
+ <strong>⚠️ Security Notice:</strong>
740
+ <ul>
741
+ <li>Credentials are stored in browser localStorage</li>
742
+ <li>Only use with HTTPS endpoints</li>
743
+ <li>Be cautious when using on shared computers</li>
744
+ </ul>
745
+ `;
746
+ body.appendChild(securityNotice);
747
+
748
+ authModal.appendChild(body);
749
+
750
+ // Footer
751
+ const footer = document.createElement("div");
752
+ addClass(footer, "authModalFooter");
753
+
754
+ const removeButton = document.createElement("button");
755
+ removeButton.textContent = "Remove Authentication";
756
+ removeButton.type = "button";
757
+ addClass(removeButton, "authRemoveButton");
758
+ removeButton.onclick = () => {
759
+ this.tab.yasgui.persistentConfig.addOrUpdateEndpoint(endpoint, {
760
+ authentication: undefined,
761
+ });
762
+ authModalOverlay.remove();
763
+ const endpointsList = this.modalContent.querySelector(".endpointsTable");
764
+ if (endpointsList) this.renderEndpointsList(endpointsList as HTMLElement);
765
+ };
766
+ if (!existingAuth) {
767
+ removeButton.disabled = true;
768
+ }
769
+
770
+ const cancelButton = document.createElement("button");
771
+ cancelButton.textContent = "Cancel";
772
+ cancelButton.type = "button";
773
+ addClass(cancelButton, "authCancelButton");
774
+ cancelButton.onclick = () => authModalOverlay.remove();
775
+
776
+ const saveButton = document.createElement("button");
777
+ saveButton.textContent = "Save";
778
+ saveButton.type = "button";
779
+ addClass(saveButton, "authSaveButton");
780
+ saveButton.onclick = () => {
781
+ const username = usernameInput.value.trim();
782
+ const password = passwordInput.value;
783
+
784
+ if (username && password) {
785
+ this.tab.yasgui.persistentConfig.addOrUpdateEndpoint(endpoint, {
786
+ authentication: {
787
+ type: "basic",
788
+ username,
789
+ password,
790
+ },
791
+ });
792
+ authModalOverlay.remove();
793
+ const endpointsList = this.modalContent.querySelector(".endpointsTable");
794
+ if (endpointsList) this.renderEndpointsList(endpointsList as HTMLElement);
795
+ } else {
796
+ alert("Please enter both username and password.");
797
+ }
798
+ };
799
+
800
+ footer.appendChild(removeButton);
801
+ footer.appendChild(cancelButton);
802
+ footer.appendChild(saveButton);
803
+ authModal.appendChild(footer);
804
+
805
+ authModalOverlay.appendChild(authModal);
806
+ document.body.appendChild(authModalOverlay);
807
+ }
808
+
439
809
  private drawRequestSettings(container: HTMLElement) {
440
810
  // This is a simplified version - you can expand based on TabPanel.ts
441
811
  const reqConfig = this.tab.getRequestConfig();
@@ -576,6 +946,9 @@ export default class TabSettingsModal {
576
946
  this.tab.setRequestConfig(updates);
577
947
  }
578
948
 
949
+ // Note: Authentication is now handled per-endpoint in the Endpoints tab,
950
+ // not per-tab anymore. No need to save it here.
951
+
579
952
  // Refresh endpoint buttons to show any changes
580
953
  this.tab.refreshEndpointButtons();
581
954
 
@@ -674,116 +1047,8 @@ export default class TabSettingsModal {
674
1047
  this.tab.yasgui.persistentConfig.setPrefixes(deduplicated);
675
1048
  }
676
1049
 
677
- private drawEndpointButtonsSettings(container: HTMLElement) {
678
- const section = document.createElement("div");
679
- addClass(section, "settingsSection");
680
-
681
- const label = document.createElement("label");
682
- label.textContent = "Custom Endpoint Buttons";
683
- addClass(label, "settingsLabel");
684
-
685
- const help = document.createElement("div");
686
- help.textContent = "Add custom endpoint buttons that will appear next to the endpoint textbox.";
687
- addClass(help, "settingsHelp");
688
-
689
- section.appendChild(label);
690
- section.appendChild(help);
691
-
692
- // List of existing buttons
693
- const buttonsList = document.createElement("div");
694
- addClass(buttonsList, "endpointButtonsList");
695
- this.renderEndpointButtonsList(buttonsList);
696
- section.appendChild(buttonsList);
697
-
698
- // Form to add new button
699
- const addForm = document.createElement("div");
700
- addClass(addForm, "addEndpointButtonForm");
701
-
702
- const labelInput = document.createElement("input");
703
- labelInput.type = "text";
704
- labelInput.placeholder = "Button label (e.g., DBpedia)";
705
- addClass(labelInput, "endpointButtonLabelInput");
706
-
707
- const endpointInput = document.createElement("input");
708
- endpointInput.type = "url";
709
- endpointInput.placeholder = "Endpoint URL (e.g., https://dbpedia.org/sparql)";
710
- addClass(endpointInput, "endpointButtonEndpointInput");
711
-
712
- const addButton = document.createElement("button");
713
- addButton.textContent = "+ Add Button";
714
- addClass(addButton, "addEndpointButton");
715
- addButton.type = "button";
716
- addButton.onclick = () => {
717
- const labelValue = labelInput.value.trim();
718
- const endpointValue = endpointInput.value.trim();
719
-
720
- if (!labelValue || !endpointValue) {
721
- alert("Please enter both a label and an endpoint URL.");
722
- return;
723
- }
724
-
725
- // Add to persistent config
726
- const currentButtons = this.tab.yasgui.persistentConfig.getCustomEndpointButtons();
727
- currentButtons.push({ label: labelValue, endpoint: endpointValue });
728
- this.tab.yasgui.persistentConfig.setCustomEndpointButtons(currentButtons);
729
-
730
- // Clear inputs
731
- labelInput.value = "";
732
- endpointInput.value = "";
733
-
734
- // Refresh list
735
- this.renderEndpointButtonsList(buttonsList);
736
- };
737
-
738
- addForm.appendChild(labelInput);
739
- addForm.appendChild(endpointInput);
740
- addForm.appendChild(addButton);
741
- section.appendChild(addForm);
742
-
743
- container.appendChild(section);
744
- }
745
-
746
- private renderEndpointButtonsList(container: HTMLElement) {
747
- container.innerHTML = "";
748
- const customButtons = this.tab.yasgui.persistentConfig.getCustomEndpointButtons();
749
-
750
- if (customButtons.length === 0) {
751
- const emptyMsg = document.createElement("div");
752
- emptyMsg.textContent = "No custom buttons yet. Add one below.";
753
- addClass(emptyMsg, "emptyMessage");
754
- container.appendChild(emptyMsg);
755
- return;
756
- }
757
-
758
- customButtons.forEach((btn, index) => {
759
- const item = document.createElement("div");
760
- addClass(item, "endpointButtonItem");
761
-
762
- const labelSpan = document.createElement("span");
763
- labelSpan.textContent = `${btn.label}`;
764
- addClass(labelSpan, "buttonLabel");
765
-
766
- const endpointSpan = document.createElement("span");
767
- endpointSpan.textContent = btn.endpoint;
768
- addClass(endpointSpan, "buttonEndpoint");
769
-
770
- const removeBtn = document.createElement("button");
771
- removeBtn.textContent = "×";
772
- addClass(removeBtn, "removeButton");
773
- removeBtn.type = "button";
774
- removeBtn.onclick = () => {
775
- const currentButtons = this.tab.yasgui.persistentConfig.getCustomEndpointButtons();
776
- currentButtons.splice(index, 1);
777
- this.tab.yasgui.persistentConfig.setCustomEndpointButtons(currentButtons);
778
- this.renderEndpointButtonsList(container);
779
- };
780
-
781
- item.appendChild(labelSpan);
782
- item.appendChild(endpointSpan);
783
- item.appendChild(removeBtn);
784
- container.appendChild(item);
785
- });
786
- }
1050
+ // Old endpoint buttons functionality has been merged into drawEndpointsSettings
1051
+ // Keeping this for reference if needed for backwards compatibility
787
1052
 
788
1053
  private getThemeToggleIcon(): string {
789
1054
  const currentTheme = this.tab.yasgui.getTheme();
package/src/index.ts CHANGED
@@ -35,6 +35,17 @@ export interface EndpointButton {
35
35
  endpoint: string;
36
36
  label: string;
37
37
  }
38
+
39
+ export interface EndpointConfig {
40
+ endpoint: string;
41
+ label?: string; // Optional label for the endpoint
42
+ showAsButton?: boolean; // Whether to show as a quick-switch button (requires label)
43
+ authentication?: {
44
+ type: 'basic'; // For now only basic, but designed for future auth types
45
+ username: string;
46
+ password: string;
47
+ };
48
+ }
38
49
  export interface Config<EndpointObject extends CatalogueItem = CatalogueItem> {
39
50
  /**
40
51
  * Autofocus yasqe on load or tab switch