@matdata/yasgui 5.5.0 → 5.7.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/OAuth2Utils.d.ts +18 -0
- package/build/ts/src/OAuth2Utils.js +214 -0
- package/build/ts/src/OAuth2Utils.js.map +1 -0
- package/build/ts/src/PersistentConfig.d.ts +3 -0
- package/build/ts/src/PersistentConfig.js +7 -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 +116 -85
- package/build/ts/src/Tab.js.map +1 -1
- package/build/ts/src/TabSettingsModal.d.ts +1 -0
- package/build/ts/src/TabSettingsModal.js +330 -27
- 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 +21 -6
- package/build/ts/src/index.js +7 -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 +185 -157
- package/build/yasgui.min.js.map +4 -4
- package/package.json +3 -2
- package/src/ConfigExportImport.ts +3 -0
- package/src/OAuth2Utils.ts +315 -0
- package/src/PersistentConfig.ts +10 -0
- package/src/Tab.ts +191 -111
- package/src/TabSettingsModal.scss +70 -3
- package/src/TabSettingsModal.ts +400 -30
- package/src/defaults.ts +1 -1
- package/src/endpointSelect.scss +12 -0
- package/src/index.ts +42 -10
- package/src/tab.scss +1 -0
- package/src/themes.scss +1 -0
- package/src/version.ts +1 -1
|
@@ -11,6 +11,8 @@ import { addClass, removeClass } from "@matdata/yasgui-utils";
|
|
|
11
11
|
import "./TabSettingsModal.scss";
|
|
12
12
|
import * as ConfigExportImport from "./ConfigExportImport";
|
|
13
13
|
import { VERSION } from "./version";
|
|
14
|
+
import * as OAuth2Utils from "./OAuth2Utils";
|
|
15
|
+
import PersistentConfig from "./PersistentConfig";
|
|
14
16
|
const MOON_ICON = `<svg viewBox="0 0 24 24" fill="currentColor">
|
|
15
17
|
<path d="M12 3c-4.97 0-9 4.03-9 9s4.03 9 9 9 9-4.03 9-9c0-.46-.04-.92-.1-1.36-.98 1.37-2.58 2.26-4.4 2.26-2.98 0-5.4-2.42-5.4-5.4 0-1.81.89-3.42 2.26-4.4-.44-.06-.9-.1-1.36-.1z"/>
|
|
16
18
|
</svg>`;
|
|
@@ -36,6 +38,7 @@ const AcceptHeaderGraphMap = [
|
|
|
36
38
|
{ key: "CSV", value: "text/csv,*/*;q=0.9" },
|
|
37
39
|
{ key: "TSV", value: "text/tab-separated-values,*/*;q=0.9" },
|
|
38
40
|
];
|
|
41
|
+
const DEFAULT_API_KEY_HEADER = "X-API-Key";
|
|
39
42
|
export default class TabSettingsModal {
|
|
40
43
|
constructor(tab, controlBarEl) {
|
|
41
44
|
this.tab = tab;
|
|
@@ -73,7 +76,6 @@ export default class TabSettingsModal {
|
|
|
73
76
|
createModal() {
|
|
74
77
|
this.modalOverlay = document.createElement("div");
|
|
75
78
|
addClass(this.modalOverlay, "tabSettingsModalOverlay");
|
|
76
|
-
this.modalOverlay.onclick = () => this.close();
|
|
77
79
|
this.modalContent = document.createElement("div");
|
|
78
80
|
addClass(this.modalContent, "tabSettingsModal");
|
|
79
81
|
this.modalContent.onclick = (e) => e.stopPropagation();
|
|
@@ -326,7 +328,9 @@ export default class TabSettingsModal {
|
|
|
326
328
|
const snippetsBarCheckbox = document.createElement("input");
|
|
327
329
|
snippetsBarCheckbox.type = "checkbox";
|
|
328
330
|
snippetsBarCheckbox.id = "showSnippetsBar";
|
|
329
|
-
|
|
331
|
+
const persistedValue = this.tab.yasgui.persistentConfig.getShowSnippetsBar();
|
|
332
|
+
snippetsBarCheckbox.checked =
|
|
333
|
+
persistedValue !== undefined ? persistedValue : this.tab.yasgui.config.showSnippetsBar !== false;
|
|
330
334
|
const snippetsBarLabel = document.createElement("label");
|
|
331
335
|
snippetsBarLabel.htmlFor = "showSnippetsBar";
|
|
332
336
|
snippetsBarLabel.textContent = "Show code snippets bar";
|
|
@@ -538,9 +542,27 @@ export default class TabSettingsModal {
|
|
|
538
542
|
basicOption.value = "basic";
|
|
539
543
|
basicOption.textContent = "HTTP Basic Authentication";
|
|
540
544
|
typeSelect.appendChild(basicOption);
|
|
545
|
+
const bearerOption = document.createElement("option");
|
|
546
|
+
bearerOption.value = "bearer";
|
|
547
|
+
bearerOption.textContent = "Bearer Token";
|
|
548
|
+
typeSelect.appendChild(bearerOption);
|
|
549
|
+
const apiKeyOption = document.createElement("option");
|
|
550
|
+
apiKeyOption.value = "apiKey";
|
|
551
|
+
apiKeyOption.textContent = "API Key (Custom Header)";
|
|
552
|
+
typeSelect.appendChild(apiKeyOption);
|
|
553
|
+
const oauth2Option = document.createElement("option");
|
|
554
|
+
oauth2Option.value = "oauth2";
|
|
555
|
+
oauth2Option.textContent = "OAuth 2.0";
|
|
556
|
+
typeSelect.appendChild(oauth2Option);
|
|
557
|
+
if (existingAuth) {
|
|
558
|
+
typeSelect.value = existingAuth.type;
|
|
559
|
+
}
|
|
541
560
|
typeSection.appendChild(typeLabel);
|
|
542
561
|
typeSection.appendChild(typeSelect);
|
|
543
562
|
body.appendChild(typeSection);
|
|
563
|
+
const basicAuthFields = document.createElement("div");
|
|
564
|
+
basicAuthFields.id = "basicAuthFields";
|
|
565
|
+
addClass(basicAuthFields, "authFieldsContainer");
|
|
544
566
|
const usernameSection = document.createElement("div");
|
|
545
567
|
addClass(usernameSection, "authModalSection");
|
|
546
568
|
const usernameLabel = document.createElement("label");
|
|
@@ -548,11 +570,11 @@ export default class TabSettingsModal {
|
|
|
548
570
|
const usernameInput = document.createElement("input");
|
|
549
571
|
usernameInput.type = "text";
|
|
550
572
|
usernameInput.placeholder = "Enter username";
|
|
551
|
-
usernameInput.value = (existingAuth === null || existingAuth === void 0 ? void 0 : existingAuth.
|
|
573
|
+
usernameInput.value = (existingAuth === null || existingAuth === void 0 ? void 0 : existingAuth.type) === "basic" ? existingAuth.username : "";
|
|
552
574
|
usernameInput.autocomplete = "username";
|
|
553
575
|
usernameSection.appendChild(usernameLabel);
|
|
554
576
|
usernameSection.appendChild(usernameInput);
|
|
555
|
-
|
|
577
|
+
basicAuthFields.appendChild(usernameSection);
|
|
556
578
|
const passwordSection = document.createElement("div");
|
|
557
579
|
addClass(passwordSection, "authModalSection");
|
|
558
580
|
const passwordLabel = document.createElement("label");
|
|
@@ -560,11 +582,153 @@ export default class TabSettingsModal {
|
|
|
560
582
|
const passwordInput = document.createElement("input");
|
|
561
583
|
passwordInput.type = "password";
|
|
562
584
|
passwordInput.placeholder = "Enter password";
|
|
563
|
-
passwordInput.value = (existingAuth === null || existingAuth === void 0 ? void 0 : existingAuth.
|
|
585
|
+
passwordInput.value = (existingAuth === null || existingAuth === void 0 ? void 0 : existingAuth.type) === "basic" ? existingAuth.password : "";
|
|
564
586
|
passwordInput.autocomplete = "current-password";
|
|
565
587
|
passwordSection.appendChild(passwordLabel);
|
|
566
588
|
passwordSection.appendChild(passwordInput);
|
|
567
|
-
|
|
589
|
+
basicAuthFields.appendChild(passwordSection);
|
|
590
|
+
body.appendChild(basicAuthFields);
|
|
591
|
+
const bearerAuthFields = document.createElement("div");
|
|
592
|
+
bearerAuthFields.id = "bearerAuthFields";
|
|
593
|
+
addClass(bearerAuthFields, "authFieldsContainer");
|
|
594
|
+
bearerAuthFields.style.display = "none";
|
|
595
|
+
const tokenSection = document.createElement("div");
|
|
596
|
+
addClass(tokenSection, "authModalSection");
|
|
597
|
+
const tokenLabel = document.createElement("label");
|
|
598
|
+
tokenLabel.textContent = "Bearer Token";
|
|
599
|
+
const tokenInput = document.createElement("input");
|
|
600
|
+
tokenInput.type = "password";
|
|
601
|
+
tokenInput.placeholder = "Enter bearer token";
|
|
602
|
+
tokenInput.autocomplete = "off";
|
|
603
|
+
tokenInput.value = (existingAuth === null || existingAuth === void 0 ? void 0 : existingAuth.type) === "bearer" ? existingAuth.token : "";
|
|
604
|
+
tokenSection.appendChild(tokenLabel);
|
|
605
|
+
tokenSection.appendChild(tokenInput);
|
|
606
|
+
bearerAuthFields.appendChild(tokenSection);
|
|
607
|
+
body.appendChild(bearerAuthFields);
|
|
608
|
+
const apiKeyAuthFields = document.createElement("div");
|
|
609
|
+
apiKeyAuthFields.id = "apiKeyAuthFields";
|
|
610
|
+
addClass(apiKeyAuthFields, "authFieldsContainer");
|
|
611
|
+
apiKeyAuthFields.style.display = "none";
|
|
612
|
+
const headerNameSection = document.createElement("div");
|
|
613
|
+
addClass(headerNameSection, "authModalSection");
|
|
614
|
+
const headerNameLabel = document.createElement("label");
|
|
615
|
+
headerNameLabel.textContent = "Header Name";
|
|
616
|
+
const headerNameInput = document.createElement("input");
|
|
617
|
+
headerNameInput.type = "text";
|
|
618
|
+
headerNameInput.placeholder = `e.g., ${DEFAULT_API_KEY_HEADER}`;
|
|
619
|
+
headerNameInput.value = (existingAuth === null || existingAuth === void 0 ? void 0 : existingAuth.type) === "apiKey" ? existingAuth.headerName : DEFAULT_API_KEY_HEADER;
|
|
620
|
+
headerNameSection.appendChild(headerNameLabel);
|
|
621
|
+
headerNameSection.appendChild(headerNameInput);
|
|
622
|
+
apiKeyAuthFields.appendChild(headerNameSection);
|
|
623
|
+
const apiKeySection = document.createElement("div");
|
|
624
|
+
addClass(apiKeySection, "authModalSection");
|
|
625
|
+
const apiKeyLabel = document.createElement("label");
|
|
626
|
+
apiKeyLabel.textContent = "API Key";
|
|
627
|
+
const apiKeyInput = document.createElement("input");
|
|
628
|
+
apiKeyInput.type = "password";
|
|
629
|
+
apiKeyInput.placeholder = "Enter API key";
|
|
630
|
+
apiKeyInput.autocomplete = "off";
|
|
631
|
+
apiKeyInput.value = (existingAuth === null || existingAuth === void 0 ? void 0 : existingAuth.type) === "apiKey" ? existingAuth.apiKey : "";
|
|
632
|
+
apiKeySection.appendChild(apiKeyLabel);
|
|
633
|
+
apiKeySection.appendChild(apiKeyInput);
|
|
634
|
+
apiKeyAuthFields.appendChild(apiKeySection);
|
|
635
|
+
body.appendChild(apiKeyAuthFields);
|
|
636
|
+
const oauth2AuthFields = document.createElement("div");
|
|
637
|
+
oauth2AuthFields.id = "oauth2AuthFields";
|
|
638
|
+
addClass(oauth2AuthFields, "authFieldsContainer");
|
|
639
|
+
oauth2AuthFields.style.display = "none";
|
|
640
|
+
const clientIdSection = document.createElement("div");
|
|
641
|
+
addClass(clientIdSection, "authModalSection");
|
|
642
|
+
const clientIdLabel = document.createElement("label");
|
|
643
|
+
clientIdLabel.textContent = "Client ID";
|
|
644
|
+
const clientIdInput = document.createElement("input");
|
|
645
|
+
clientIdInput.type = "text";
|
|
646
|
+
clientIdInput.placeholder = "Enter OAuth 2.0 client ID";
|
|
647
|
+
clientIdInput.value = (existingAuth === null || existingAuth === void 0 ? void 0 : existingAuth.type) === "oauth2" ? existingAuth.clientId : "";
|
|
648
|
+
clientIdSection.appendChild(clientIdLabel);
|
|
649
|
+
clientIdSection.appendChild(clientIdInput);
|
|
650
|
+
oauth2AuthFields.appendChild(clientIdSection);
|
|
651
|
+
const authEndpointSection = document.createElement("div");
|
|
652
|
+
addClass(authEndpointSection, "authModalSection");
|
|
653
|
+
const authEndpointLabel = document.createElement("label");
|
|
654
|
+
authEndpointLabel.textContent = "Authorization Endpoint";
|
|
655
|
+
const authEndpointInput = document.createElement("input");
|
|
656
|
+
authEndpointInput.type = "url";
|
|
657
|
+
authEndpointInput.placeholder = "https://provider.com/oauth/authorize";
|
|
658
|
+
authEndpointInput.value = (existingAuth === null || existingAuth === void 0 ? void 0 : existingAuth.type) === "oauth2" ? existingAuth.authorizationEndpoint : "";
|
|
659
|
+
authEndpointSection.appendChild(authEndpointLabel);
|
|
660
|
+
authEndpointSection.appendChild(authEndpointInput);
|
|
661
|
+
oauth2AuthFields.appendChild(authEndpointSection);
|
|
662
|
+
const tokenEndpointSection = document.createElement("div");
|
|
663
|
+
addClass(tokenEndpointSection, "authModalSection");
|
|
664
|
+
const tokenEndpointLabel = document.createElement("label");
|
|
665
|
+
tokenEndpointLabel.textContent = "Token Endpoint";
|
|
666
|
+
const tokenEndpointInput = document.createElement("input");
|
|
667
|
+
tokenEndpointInput.type = "url";
|
|
668
|
+
tokenEndpointInput.placeholder = "https://provider.com/oauth/token";
|
|
669
|
+
tokenEndpointInput.value = (existingAuth === null || existingAuth === void 0 ? void 0 : existingAuth.type) === "oauth2" ? existingAuth.tokenEndpoint : "";
|
|
670
|
+
tokenEndpointSection.appendChild(tokenEndpointLabel);
|
|
671
|
+
tokenEndpointSection.appendChild(tokenEndpointInput);
|
|
672
|
+
oauth2AuthFields.appendChild(tokenEndpointSection);
|
|
673
|
+
const redirectUriSection = document.createElement("div");
|
|
674
|
+
addClass(redirectUriSection, "authModalSection");
|
|
675
|
+
const redirectUriLabel = document.createElement("label");
|
|
676
|
+
redirectUriLabel.textContent = "Redirect URI (Optional)";
|
|
677
|
+
const redirectUriInput = document.createElement("input");
|
|
678
|
+
redirectUriInput.type = "url";
|
|
679
|
+
redirectUriInput.placeholder = window.location.origin + window.location.pathname;
|
|
680
|
+
redirectUriInput.value = (existingAuth === null || existingAuth === void 0 ? void 0 : existingAuth.type) === "oauth2" ? existingAuth.redirectUri || "" : "";
|
|
681
|
+
const redirectUriHelp = document.createElement("div");
|
|
682
|
+
redirectUriHelp.textContent = "Leave empty to use current page URL. Must be registered with OAuth provider.";
|
|
683
|
+
addClass(redirectUriHelp, "authInputHelp");
|
|
684
|
+
redirectUriSection.appendChild(redirectUriLabel);
|
|
685
|
+
redirectUriSection.appendChild(redirectUriInput);
|
|
686
|
+
redirectUriSection.appendChild(redirectUriHelp);
|
|
687
|
+
oauth2AuthFields.appendChild(redirectUriSection);
|
|
688
|
+
const scopeSection = document.createElement("div");
|
|
689
|
+
addClass(scopeSection, "authModalSection");
|
|
690
|
+
const scopeLabel = document.createElement("label");
|
|
691
|
+
scopeLabel.textContent = "Scope (Optional)";
|
|
692
|
+
const scopeInput = document.createElement("input");
|
|
693
|
+
scopeInput.type = "text";
|
|
694
|
+
scopeInput.placeholder = "e.g., read write";
|
|
695
|
+
scopeInput.value = (existingAuth === null || existingAuth === void 0 ? void 0 : existingAuth.type) === "oauth2" ? existingAuth.scope || "" : "";
|
|
696
|
+
const scopeHelp = document.createElement("div");
|
|
697
|
+
scopeHelp.textContent = "Space-separated list of OAuth 2.0 scopes";
|
|
698
|
+
addClass(scopeHelp, "authInputHelp");
|
|
699
|
+
scopeSection.appendChild(scopeLabel);
|
|
700
|
+
scopeSection.appendChild(scopeInput);
|
|
701
|
+
scopeSection.appendChild(scopeHelp);
|
|
702
|
+
oauth2AuthFields.appendChild(scopeSection);
|
|
703
|
+
if ((existingAuth === null || existingAuth === void 0 ? void 0 : existingAuth.type) === "oauth2" && existingAuth.accessToken) {
|
|
704
|
+
const tokenStatusSection = document.createElement("div");
|
|
705
|
+
addClass(tokenStatusSection, "authModalSection");
|
|
706
|
+
const tokenStatusLabel = document.createElement("label");
|
|
707
|
+
tokenStatusLabel.textContent = "Authentication Status";
|
|
708
|
+
const tokenStatus = document.createElement("div");
|
|
709
|
+
addClass(tokenStatus, "oauth2TokenStatus");
|
|
710
|
+
tokenStatus.innerHTML = "✓ Authenticated";
|
|
711
|
+
addClass(tokenStatus, "authenticated");
|
|
712
|
+
tokenStatusSection.appendChild(tokenStatusLabel);
|
|
713
|
+
tokenStatusSection.appendChild(tokenStatus);
|
|
714
|
+
oauth2AuthFields.appendChild(tokenStatusSection);
|
|
715
|
+
}
|
|
716
|
+
body.appendChild(oauth2AuthFields);
|
|
717
|
+
const toggleAuthFields = () => {
|
|
718
|
+
const authType = typeSelect.value;
|
|
719
|
+
basicAuthFields.style.display = authType === "basic" ? "block" : "none";
|
|
720
|
+
bearerAuthFields.style.display = authType === "bearer" ? "block" : "none";
|
|
721
|
+
apiKeyAuthFields.style.display = authType === "apiKey" ? "block" : "none";
|
|
722
|
+
oauth2AuthFields.style.display = authType === "oauth2" ? "block" : "none";
|
|
723
|
+
};
|
|
724
|
+
toggleAuthFields();
|
|
725
|
+
typeSelect.onchange = toggleAuthFields;
|
|
726
|
+
const helpLink = document.createElement("div");
|
|
727
|
+
addClass(helpLink, "authHelpLink");
|
|
728
|
+
helpLink.innerHTML = `
|
|
729
|
+
📚 <a href="https://triply.cc/docs/yasgui#authentication" target="_blank" rel="noopener noreferrer">View authentication documentation</a>
|
|
730
|
+
`;
|
|
731
|
+
body.appendChild(helpLink);
|
|
568
732
|
const securityNotice = document.createElement("div");
|
|
569
733
|
addClass(securityNotice, "authSecurityNotice");
|
|
570
734
|
securityNotice.innerHTML = `
|
|
@@ -583,15 +747,18 @@ export default class TabSettingsModal {
|
|
|
583
747
|
removeButton.textContent = "Remove Authentication";
|
|
584
748
|
removeButton.type = "button";
|
|
585
749
|
addClass(removeButton, "authRemoveButton");
|
|
586
|
-
|
|
587
|
-
this.tab.yasgui.persistentConfig.addOrUpdateEndpoint(endpoint, {
|
|
588
|
-
authentication: undefined,
|
|
589
|
-
});
|
|
750
|
+
const closeModalAndRefresh = () => {
|
|
590
751
|
authModalOverlay.remove();
|
|
591
752
|
const endpointsList = this.modalContent.querySelector(".endpointsTable");
|
|
592
753
|
if (endpointsList)
|
|
593
754
|
this.renderEndpointsList(endpointsList);
|
|
594
755
|
};
|
|
756
|
+
removeButton.onclick = () => {
|
|
757
|
+
this.tab.yasgui.persistentConfig.addOrUpdateEndpoint(endpoint, {
|
|
758
|
+
authentication: undefined,
|
|
759
|
+
});
|
|
760
|
+
closeModalAndRefresh();
|
|
761
|
+
};
|
|
595
762
|
if (!existingAuth) {
|
|
596
763
|
removeButton.disabled = true;
|
|
597
764
|
}
|
|
@@ -605,23 +772,118 @@ export default class TabSettingsModal {
|
|
|
605
772
|
saveButton.type = "button";
|
|
606
773
|
addClass(saveButton, "authSaveButton");
|
|
607
774
|
saveButton.onclick = () => {
|
|
608
|
-
const
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
775
|
+
const authType = typeSelect.value;
|
|
776
|
+
if (authType === "basic") {
|
|
777
|
+
const username = usernameInput.value.trim();
|
|
778
|
+
const password = passwordInput.value;
|
|
779
|
+
if (username && password) {
|
|
780
|
+
this.tab.yasgui.persistentConfig.addOrUpdateEndpoint(endpoint, {
|
|
781
|
+
authentication: {
|
|
782
|
+
type: "basic",
|
|
783
|
+
username,
|
|
784
|
+
password,
|
|
785
|
+
},
|
|
786
|
+
});
|
|
787
|
+
closeModalAndRefresh();
|
|
788
|
+
}
|
|
789
|
+
else {
|
|
790
|
+
alert("Please enter both username and password.");
|
|
791
|
+
}
|
|
622
792
|
}
|
|
623
|
-
else {
|
|
624
|
-
|
|
793
|
+
else if (authType === "bearer") {
|
|
794
|
+
const token = tokenInput.value.trim();
|
|
795
|
+
if (token) {
|
|
796
|
+
this.tab.yasgui.persistentConfig.addOrUpdateEndpoint(endpoint, {
|
|
797
|
+
authentication: {
|
|
798
|
+
type: "bearer",
|
|
799
|
+
token,
|
|
800
|
+
},
|
|
801
|
+
});
|
|
802
|
+
closeModalAndRefresh();
|
|
803
|
+
}
|
|
804
|
+
else {
|
|
805
|
+
alert("Please enter a bearer token.");
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
else if (authType === "apiKey") {
|
|
809
|
+
const headerName = headerNameInput.value.trim();
|
|
810
|
+
const apiKey = apiKeyInput.value.trim();
|
|
811
|
+
if (headerName && apiKey) {
|
|
812
|
+
this.tab.yasgui.persistentConfig.addOrUpdateEndpoint(endpoint, {
|
|
813
|
+
authentication: {
|
|
814
|
+
type: "apiKey",
|
|
815
|
+
headerName,
|
|
816
|
+
apiKey,
|
|
817
|
+
},
|
|
818
|
+
});
|
|
819
|
+
closeModalAndRefresh();
|
|
820
|
+
}
|
|
821
|
+
else {
|
|
822
|
+
alert("Please enter both header name and API key.");
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
else if (authType === "oauth2") {
|
|
826
|
+
const clientId = clientIdInput.value.trim();
|
|
827
|
+
const authorizationEndpoint = authEndpointInput.value.trim();
|
|
828
|
+
const tokenEndpoint = tokenEndpointInput.value.trim();
|
|
829
|
+
const redirectUri = redirectUriInput.value.trim() || window.location.origin + window.location.pathname;
|
|
830
|
+
const scope = scopeInput.value.trim();
|
|
831
|
+
if (!clientId || !authorizationEndpoint || !tokenEndpoint) {
|
|
832
|
+
alert("Please enter Client ID, Authorization Endpoint, and Token Endpoint.");
|
|
833
|
+
return;
|
|
834
|
+
}
|
|
835
|
+
if ((existingAuth === null || existingAuth === void 0 ? void 0 : existingAuth.type) === "oauth2" && existingAuth.accessToken) {
|
|
836
|
+
this.tab.yasgui.persistentConfig.addOrUpdateEndpoint(endpoint, {
|
|
837
|
+
authentication: {
|
|
838
|
+
type: "oauth2",
|
|
839
|
+
clientId,
|
|
840
|
+
authorizationEndpoint,
|
|
841
|
+
tokenEndpoint,
|
|
842
|
+
redirectUri,
|
|
843
|
+
scope,
|
|
844
|
+
accessToken: existingAuth.accessToken,
|
|
845
|
+
idToken: existingAuth.idToken,
|
|
846
|
+
refreshToken: existingAuth.refreshToken,
|
|
847
|
+
tokenExpiry: existingAuth.tokenExpiry,
|
|
848
|
+
},
|
|
849
|
+
});
|
|
850
|
+
closeModalAndRefresh();
|
|
851
|
+
return;
|
|
852
|
+
}
|
|
853
|
+
saveButton.disabled = true;
|
|
854
|
+
saveButton.textContent = "Authenticating...";
|
|
855
|
+
OAuth2Utils.startOAuth2Flow({
|
|
856
|
+
clientId,
|
|
857
|
+
authorizationEndpoint,
|
|
858
|
+
tokenEndpoint,
|
|
859
|
+
redirectUri,
|
|
860
|
+
scope,
|
|
861
|
+
})
|
|
862
|
+
.then((tokenResponse) => {
|
|
863
|
+
const tokenExpiry = OAuth2Utils.calculateTokenExpiry(tokenResponse.expires_in);
|
|
864
|
+
this.tab.yasgui.persistentConfig.addOrUpdateEndpoint(endpoint, {
|
|
865
|
+
authentication: {
|
|
866
|
+
type: "oauth2",
|
|
867
|
+
clientId,
|
|
868
|
+
authorizationEndpoint,
|
|
869
|
+
tokenEndpoint,
|
|
870
|
+
redirectUri,
|
|
871
|
+
scope,
|
|
872
|
+
accessToken: tokenResponse.access_token,
|
|
873
|
+
idToken: tokenResponse.id_token,
|
|
874
|
+
refreshToken: tokenResponse.refresh_token,
|
|
875
|
+
tokenExpiry,
|
|
876
|
+
},
|
|
877
|
+
});
|
|
878
|
+
closeModalAndRefresh();
|
|
879
|
+
alert("OAuth 2.0 authentication successful!");
|
|
880
|
+
})
|
|
881
|
+
.catch((error) => {
|
|
882
|
+
console.error("OAuth 2.0 authentication failed:", error);
|
|
883
|
+
alert("OAuth 2.0 authentication failed: " + error.message);
|
|
884
|
+
saveButton.disabled = false;
|
|
885
|
+
saveButton.textContent = "Save & Authenticate";
|
|
886
|
+
});
|
|
625
887
|
}
|
|
626
888
|
};
|
|
627
889
|
footer.appendChild(removeButton);
|
|
@@ -727,7 +989,18 @@ export default class TabSettingsModal {
|
|
|
727
989
|
}
|
|
728
990
|
const snippetsBarCheckbox = document.getElementById("showSnippetsBar");
|
|
729
991
|
if (snippetsBarCheckbox) {
|
|
730
|
-
|
|
992
|
+
this.tab.yasgui.config.showSnippetsBar = snippetsBarCheckbox.checked;
|
|
993
|
+
this.tab.yasgui.persistentConfig.setShowSnippetsBar(snippetsBarCheckbox.checked);
|
|
994
|
+
this.tab.yasgui.persistentConfig.getTabs().forEach((tabId) => {
|
|
995
|
+
const tab = this.tab.yasgui.getTab(tabId);
|
|
996
|
+
if (tab) {
|
|
997
|
+
const tabYasqe = tab.getYasqe();
|
|
998
|
+
if (tabYasqe) {
|
|
999
|
+
tabYasqe.config.showSnippetsBar = snippetsBarCheckbox.checked;
|
|
1000
|
+
tabYasqe.refreshSnippetsBar();
|
|
1001
|
+
}
|
|
1002
|
+
}
|
|
1003
|
+
});
|
|
731
1004
|
}
|
|
732
1005
|
yasqe.saveQuery();
|
|
733
1006
|
}
|
|
@@ -1125,6 +1398,22 @@ export default class TabSettingsModal {
|
|
|
1125
1398
|
footerInfo.appendChild(paragraph2);
|
|
1126
1399
|
aboutSection.appendChild(footerInfo);
|
|
1127
1400
|
container.appendChild(aboutSection);
|
|
1401
|
+
const storageSection = document.createElement("div");
|
|
1402
|
+
addClass(storageSection, "settingsSection");
|
|
1403
|
+
const storageTitle = document.createElement("h3");
|
|
1404
|
+
storageTitle.textContent = "Storage Management";
|
|
1405
|
+
storageSection.appendChild(storageTitle);
|
|
1406
|
+
const storageDescription = document.createElement("p");
|
|
1407
|
+
storageDescription.textContent =
|
|
1408
|
+
"Clear all locally stored data including tabs, queries, endpoint configurations, and preferences. This action cannot be undone.";
|
|
1409
|
+
addClass(storageDescription, "settingsHelp");
|
|
1410
|
+
storageSection.appendChild(storageDescription);
|
|
1411
|
+
const clearStorageButton = document.createElement("button");
|
|
1412
|
+
clearStorageButton.textContent = "Clear Persistent Storage";
|
|
1413
|
+
addClass(clearStorageButton, "dangerButton");
|
|
1414
|
+
clearStorageButton.onclick = () => this.clearPersistentStorage();
|
|
1415
|
+
storageSection.appendChild(clearStorageButton);
|
|
1416
|
+
container.appendChild(storageSection);
|
|
1128
1417
|
}
|
|
1129
1418
|
createAboutLink(label, url, description) {
|
|
1130
1419
|
const linkContainer = document.createElement("div");
|
|
@@ -1142,6 +1431,20 @@ export default class TabSettingsModal {
|
|
|
1142
1431
|
linkContainer.appendChild(desc);
|
|
1143
1432
|
return linkContainer;
|
|
1144
1433
|
}
|
|
1434
|
+
clearPersistentStorage() {
|
|
1435
|
+
const confirmed = confirm("Are you sure you want to clear all persistent storage?\n\n" +
|
|
1436
|
+
"This will delete:\n" +
|
|
1437
|
+
"- All saved tabs and queries\n" +
|
|
1438
|
+
"- Endpoint configurations and history\n" +
|
|
1439
|
+
"- Authentication settings\n" +
|
|
1440
|
+
"- Editor preferences\n" +
|
|
1441
|
+
"- Prefixes\n\n" +
|
|
1442
|
+
"This action cannot be undone and the page will reload.");
|
|
1443
|
+
if (confirmed) {
|
|
1444
|
+
PersistentConfig.clear();
|
|
1445
|
+
window.location.reload();
|
|
1446
|
+
}
|
|
1447
|
+
}
|
|
1145
1448
|
destroy() {
|
|
1146
1449
|
if (this.modalOverlay && this.modalOverlay.parentNode) {
|
|
1147
1450
|
this.modalOverlay.parentNode.removeChild(this.modalOverlay);
|