@matdata/yasgui 5.5.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 +2 -0
- package/build/ts/src/ConfigExportImport.js.map +1 -1
- 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 +0 -1
- package/build/ts/src/Tab.js +54 -82
- package/build/ts/src/Tab.js.map +1 -1
- package/build/ts/src/TabSettingsModal.js +145 -22
- 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 +9 -6
- 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 +117 -117
- package/build/yasgui.min.js.map +3 -3
- package/package.json +1 -1
- package/src/ConfigExportImport.ts +2 -0
- package/src/PersistentConfig.ts +10 -0
- package/src/Tab.ts +107 -110
- package/src/TabSettingsModal.ts +175 -26
- package/src/defaults.ts +1 -1
- package/src/endpointSelect.scss +12 -0
- package/src/index.ts +27 -10
- package/src/version.ts +1 -1
package/src/TabSettingsModal.ts
CHANGED
|
@@ -34,6 +34,9 @@ const AcceptHeaderGraphMap: { key: string; value: string }[] = [
|
|
|
34
34
|
{ key: "TSV", value: "text/tab-separated-values,*/*;q=0.9" },
|
|
35
35
|
];
|
|
36
36
|
|
|
37
|
+
// Default API Key header name
|
|
38
|
+
const DEFAULT_API_KEY_HEADER = "X-API-Key";
|
|
39
|
+
|
|
37
40
|
export default class TabSettingsModal {
|
|
38
41
|
private tab: Tab;
|
|
39
42
|
private modalOverlay!: HTMLElement;
|
|
@@ -423,7 +426,10 @@ export default class TabSettingsModal {
|
|
|
423
426
|
const snippetsBarCheckbox = document.createElement("input");
|
|
424
427
|
snippetsBarCheckbox.type = "checkbox";
|
|
425
428
|
snippetsBarCheckbox.id = "showSnippetsBar";
|
|
426
|
-
|
|
429
|
+
// Read from global config
|
|
430
|
+
const persistedValue = this.tab.yasgui.persistentConfig.getShowSnippetsBar();
|
|
431
|
+
snippetsBarCheckbox.checked =
|
|
432
|
+
persistedValue !== undefined ? persistedValue : this.tab.yasgui.config.showSnippetsBar !== false;
|
|
427
433
|
|
|
428
434
|
const snippetsBarLabel = document.createElement("label");
|
|
429
435
|
snippetsBarLabel.htmlFor = "showSnippetsBar";
|
|
@@ -689,22 +695,42 @@ export default class TabSettingsModal {
|
|
|
689
695
|
const body = document.createElement("div");
|
|
690
696
|
addClass(body, "authModalBody");
|
|
691
697
|
|
|
692
|
-
// Auth type
|
|
698
|
+
// Auth type
|
|
693
699
|
const typeSection = document.createElement("div");
|
|
694
700
|
addClass(typeSection, "authModalSection");
|
|
695
701
|
const typeLabel = document.createElement("label");
|
|
696
702
|
typeLabel.textContent = "Authentication Type";
|
|
697
703
|
const typeSelect = document.createElement("select");
|
|
704
|
+
|
|
698
705
|
const basicOption = document.createElement("option");
|
|
699
706
|
basicOption.value = "basic";
|
|
700
707
|
basicOption.textContent = "HTTP Basic Authentication";
|
|
701
708
|
typeSelect.appendChild(basicOption);
|
|
702
|
-
|
|
709
|
+
|
|
710
|
+
const bearerOption = document.createElement("option");
|
|
711
|
+
bearerOption.value = "bearer";
|
|
712
|
+
bearerOption.textContent = "Bearer Token";
|
|
713
|
+
typeSelect.appendChild(bearerOption);
|
|
714
|
+
|
|
715
|
+
const apiKeyOption = document.createElement("option");
|
|
716
|
+
apiKeyOption.value = "apiKey";
|
|
717
|
+
apiKeyOption.textContent = "API Key (Custom Header)";
|
|
718
|
+
typeSelect.appendChild(apiKeyOption);
|
|
719
|
+
|
|
720
|
+
// Set the current auth type
|
|
721
|
+
if (existingAuth) {
|
|
722
|
+
typeSelect.value = existingAuth.type;
|
|
723
|
+
}
|
|
724
|
+
|
|
703
725
|
typeSection.appendChild(typeLabel);
|
|
704
726
|
typeSection.appendChild(typeSelect);
|
|
705
727
|
body.appendChild(typeSection);
|
|
706
728
|
|
|
707
|
-
//
|
|
729
|
+
// Basic Auth Fields
|
|
730
|
+
const basicAuthFields = document.createElement("div");
|
|
731
|
+
basicAuthFields.id = "basicAuthFields";
|
|
732
|
+
addClass(basicAuthFields, "authFieldsContainer");
|
|
733
|
+
|
|
708
734
|
const usernameSection = document.createElement("div");
|
|
709
735
|
addClass(usernameSection, "authModalSection");
|
|
710
736
|
const usernameLabel = document.createElement("label");
|
|
@@ -712,13 +738,12 @@ export default class TabSettingsModal {
|
|
|
712
738
|
const usernameInput = document.createElement("input");
|
|
713
739
|
usernameInput.type = "text";
|
|
714
740
|
usernameInput.placeholder = "Enter username";
|
|
715
|
-
usernameInput.value = existingAuth?.username
|
|
741
|
+
usernameInput.value = existingAuth?.type === "basic" ? existingAuth.username : "";
|
|
716
742
|
usernameInput.autocomplete = "username";
|
|
717
743
|
usernameSection.appendChild(usernameLabel);
|
|
718
744
|
usernameSection.appendChild(usernameInput);
|
|
719
|
-
|
|
745
|
+
basicAuthFields.appendChild(usernameSection);
|
|
720
746
|
|
|
721
|
-
// Password
|
|
722
747
|
const passwordSection = document.createElement("div");
|
|
723
748
|
addClass(passwordSection, "authModalSection");
|
|
724
749
|
const passwordLabel = document.createElement("label");
|
|
@@ -726,11 +751,81 @@ export default class TabSettingsModal {
|
|
|
726
751
|
const passwordInput = document.createElement("input");
|
|
727
752
|
passwordInput.type = "password";
|
|
728
753
|
passwordInput.placeholder = "Enter password";
|
|
729
|
-
passwordInput.value = existingAuth?.password
|
|
754
|
+
passwordInput.value = existingAuth?.type === "basic" ? existingAuth.password : "";
|
|
730
755
|
passwordInput.autocomplete = "current-password";
|
|
731
756
|
passwordSection.appendChild(passwordLabel);
|
|
732
757
|
passwordSection.appendChild(passwordInput);
|
|
733
|
-
|
|
758
|
+
basicAuthFields.appendChild(passwordSection);
|
|
759
|
+
|
|
760
|
+
body.appendChild(basicAuthFields);
|
|
761
|
+
|
|
762
|
+
// Bearer Token Fields
|
|
763
|
+
const bearerAuthFields = document.createElement("div");
|
|
764
|
+
bearerAuthFields.id = "bearerAuthFields";
|
|
765
|
+
addClass(bearerAuthFields, "authFieldsContainer");
|
|
766
|
+
bearerAuthFields.style.display = "none";
|
|
767
|
+
|
|
768
|
+
const tokenSection = document.createElement("div");
|
|
769
|
+
addClass(tokenSection, "authModalSection");
|
|
770
|
+
const tokenLabel = document.createElement("label");
|
|
771
|
+
tokenLabel.textContent = "Bearer Token";
|
|
772
|
+
const tokenInput = document.createElement("input");
|
|
773
|
+
tokenInput.type = "password";
|
|
774
|
+
tokenInput.placeholder = "Enter bearer token";
|
|
775
|
+
tokenInput.autocomplete = "off";
|
|
776
|
+
tokenInput.value = existingAuth?.type === "bearer" ? existingAuth.token : "";
|
|
777
|
+
tokenSection.appendChild(tokenLabel);
|
|
778
|
+
tokenSection.appendChild(tokenInput);
|
|
779
|
+
bearerAuthFields.appendChild(tokenSection);
|
|
780
|
+
|
|
781
|
+
body.appendChild(bearerAuthFields);
|
|
782
|
+
|
|
783
|
+
// API Key Fields
|
|
784
|
+
const apiKeyAuthFields = document.createElement("div");
|
|
785
|
+
apiKeyAuthFields.id = "apiKeyAuthFields";
|
|
786
|
+
addClass(apiKeyAuthFields, "authFieldsContainer");
|
|
787
|
+
apiKeyAuthFields.style.display = "none";
|
|
788
|
+
|
|
789
|
+
const headerNameSection = document.createElement("div");
|
|
790
|
+
addClass(headerNameSection, "authModalSection");
|
|
791
|
+
const headerNameLabel = document.createElement("label");
|
|
792
|
+
headerNameLabel.textContent = "Header Name";
|
|
793
|
+
const headerNameInput = document.createElement("input");
|
|
794
|
+
headerNameInput.type = "text";
|
|
795
|
+
headerNameInput.placeholder = `e.g., ${DEFAULT_API_KEY_HEADER}`;
|
|
796
|
+
headerNameInput.value = existingAuth?.type === "apiKey" ? existingAuth.headerName : DEFAULT_API_KEY_HEADER;
|
|
797
|
+
headerNameSection.appendChild(headerNameLabel);
|
|
798
|
+
headerNameSection.appendChild(headerNameInput);
|
|
799
|
+
apiKeyAuthFields.appendChild(headerNameSection);
|
|
800
|
+
|
|
801
|
+
const apiKeySection = document.createElement("div");
|
|
802
|
+
addClass(apiKeySection, "authModalSection");
|
|
803
|
+
const apiKeyLabel = document.createElement("label");
|
|
804
|
+
apiKeyLabel.textContent = "API Key";
|
|
805
|
+
const apiKeyInput = document.createElement("input");
|
|
806
|
+
apiKeyInput.type = "password";
|
|
807
|
+
apiKeyInput.placeholder = "Enter API key";
|
|
808
|
+
apiKeyInput.autocomplete = "off";
|
|
809
|
+
apiKeyInput.value = existingAuth?.type === "apiKey" ? existingAuth.apiKey : "";
|
|
810
|
+
apiKeySection.appendChild(apiKeyLabel);
|
|
811
|
+
apiKeySection.appendChild(apiKeyInput);
|
|
812
|
+
apiKeyAuthFields.appendChild(apiKeySection);
|
|
813
|
+
|
|
814
|
+
body.appendChild(apiKeyAuthFields);
|
|
815
|
+
|
|
816
|
+
// Function to toggle fields based on auth type
|
|
817
|
+
const toggleAuthFields = () => {
|
|
818
|
+
const authType = typeSelect.value;
|
|
819
|
+
basicAuthFields.style.display = authType === "basic" ? "block" : "none";
|
|
820
|
+
bearerAuthFields.style.display = authType === "bearer" ? "block" : "none";
|
|
821
|
+
apiKeyAuthFields.style.display = authType === "apiKey" ? "block" : "none";
|
|
822
|
+
};
|
|
823
|
+
|
|
824
|
+
// Set initial visibility
|
|
825
|
+
toggleAuthFields();
|
|
826
|
+
|
|
827
|
+
// Update visibility when auth type changes
|
|
828
|
+
typeSelect.onchange = toggleAuthFields;
|
|
734
829
|
|
|
735
830
|
// Security notice
|
|
736
831
|
const securityNotice = document.createElement("div");
|
|
@@ -778,22 +873,60 @@ export default class TabSettingsModal {
|
|
|
778
873
|
saveButton.type = "button";
|
|
779
874
|
addClass(saveButton, "authSaveButton");
|
|
780
875
|
saveButton.onclick = () => {
|
|
781
|
-
const
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
876
|
+
const authType = typeSelect.value;
|
|
877
|
+
|
|
878
|
+
if (authType === "basic") {
|
|
879
|
+
const username = usernameInput.value.trim();
|
|
880
|
+
const password = passwordInput.value;
|
|
881
|
+
|
|
882
|
+
if (username && password) {
|
|
883
|
+
this.tab.yasgui.persistentConfig.addOrUpdateEndpoint(endpoint, {
|
|
884
|
+
authentication: {
|
|
885
|
+
type: "basic",
|
|
886
|
+
username,
|
|
887
|
+
password,
|
|
888
|
+
},
|
|
889
|
+
});
|
|
890
|
+
authModalOverlay.remove();
|
|
891
|
+
const endpointsList = this.modalContent.querySelector(".endpointsTable");
|
|
892
|
+
if (endpointsList) this.renderEndpointsList(endpointsList as HTMLElement);
|
|
893
|
+
} else {
|
|
894
|
+
alert("Please enter both username and password.");
|
|
895
|
+
}
|
|
896
|
+
} else if (authType === "bearer") {
|
|
897
|
+
const token = tokenInput.value.trim();
|
|
898
|
+
|
|
899
|
+
if (token) {
|
|
900
|
+
this.tab.yasgui.persistentConfig.addOrUpdateEndpoint(endpoint, {
|
|
901
|
+
authentication: {
|
|
902
|
+
type: "bearer",
|
|
903
|
+
token,
|
|
904
|
+
},
|
|
905
|
+
});
|
|
906
|
+
authModalOverlay.remove();
|
|
907
|
+
const endpointsList = this.modalContent.querySelector(".endpointsTable");
|
|
908
|
+
if (endpointsList) this.renderEndpointsList(endpointsList as HTMLElement);
|
|
909
|
+
} else {
|
|
910
|
+
alert("Please enter a bearer token.");
|
|
911
|
+
}
|
|
912
|
+
} else if (authType === "apiKey") {
|
|
913
|
+
const headerName = headerNameInput.value.trim();
|
|
914
|
+
const apiKey = apiKeyInput.value.trim();
|
|
915
|
+
|
|
916
|
+
if (headerName && apiKey) {
|
|
917
|
+
this.tab.yasgui.persistentConfig.addOrUpdateEndpoint(endpoint, {
|
|
918
|
+
authentication: {
|
|
919
|
+
type: "apiKey",
|
|
920
|
+
headerName,
|
|
921
|
+
apiKey,
|
|
922
|
+
},
|
|
923
|
+
});
|
|
924
|
+
authModalOverlay.remove();
|
|
925
|
+
const endpointsList = this.modalContent.querySelector(".endpointsTable");
|
|
926
|
+
if (endpointsList) this.renderEndpointsList(endpointsList as HTMLElement);
|
|
927
|
+
} else {
|
|
928
|
+
alert("Please enter both header name and API key.");
|
|
929
|
+
}
|
|
797
930
|
}
|
|
798
931
|
};
|
|
799
932
|
|
|
@@ -927,7 +1060,23 @@ export default class TabSettingsModal {
|
|
|
927
1060
|
}
|
|
928
1061
|
const snippetsBarCheckbox = document.getElementById("showSnippetsBar") as HTMLInputElement;
|
|
929
1062
|
if (snippetsBarCheckbox) {
|
|
930
|
-
|
|
1063
|
+
// Save globally to config and persistent storage
|
|
1064
|
+
this.tab.yasgui.config.showSnippetsBar = snippetsBarCheckbox.checked;
|
|
1065
|
+
this.tab.yasgui.persistentConfig.setShowSnippetsBar(snippetsBarCheckbox.checked);
|
|
1066
|
+
|
|
1067
|
+
// Apply to all tabs by updating each Yasqe instance's config and refreshing
|
|
1068
|
+
this.tab.yasgui.persistentConfig.getTabs().forEach((tabId: string) => {
|
|
1069
|
+
const tab = this.tab.yasgui.getTab(tabId);
|
|
1070
|
+
if (tab) {
|
|
1071
|
+
const tabYasqe = tab.getYasqe();
|
|
1072
|
+
if (tabYasqe) {
|
|
1073
|
+
// Update the individual Yasqe instance's config
|
|
1074
|
+
tabYasqe.config.showSnippetsBar = snippetsBarCheckbox.checked;
|
|
1075
|
+
// Refresh the snippets bar to reflect the change
|
|
1076
|
+
tabYasqe.refreshSnippetsBar();
|
|
1077
|
+
}
|
|
1078
|
+
}
|
|
1079
|
+
});
|
|
931
1080
|
}
|
|
932
1081
|
yasqe.saveQuery();
|
|
933
1082
|
}
|
package/src/defaults.ts
CHANGED
|
@@ -22,7 +22,6 @@ export default function initialize(): Config<CatalogueItem> {
|
|
|
22
22
|
return "yagui_" + id;
|
|
23
23
|
},
|
|
24
24
|
tabName: "Query",
|
|
25
|
-
corsProxy: undefined,
|
|
26
25
|
persistencyExpire: 60 * 60 * 24 * 30,
|
|
27
26
|
persistenceLabelResponse: "response",
|
|
28
27
|
persistenceLabelConfig: "config",
|
|
@@ -31,6 +30,7 @@ export default function initialize(): Config<CatalogueItem> {
|
|
|
31
30
|
theme: undefined,
|
|
32
31
|
showThemeToggle: true,
|
|
33
32
|
orientation: "vertical",
|
|
33
|
+
showSnippetsBar: true,
|
|
34
34
|
endpointButtons: undefined,
|
|
35
35
|
endpointCatalogueOptions: {
|
|
36
36
|
getData: () => {
|
package/src/endpointSelect.scss
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
margin: 4px 0px;
|
|
5
5
|
border: 2px solid #ccc;
|
|
6
6
|
width: 100%;
|
|
7
|
+
min-width: 200px;
|
|
7
8
|
&:hover {
|
|
8
9
|
border-color: #bbb;
|
|
9
10
|
}
|
|
@@ -125,6 +126,11 @@
|
|
|
125
126
|
align-items: center;
|
|
126
127
|
gap: 4px;
|
|
127
128
|
margin-left: 4px;
|
|
129
|
+
|
|
130
|
+
// Hide on small screens (mobile)
|
|
131
|
+
@media (max-width: 768px) {
|
|
132
|
+
display: none;
|
|
133
|
+
}
|
|
128
134
|
}
|
|
129
135
|
|
|
130
136
|
.endpointButton {
|
|
@@ -152,5 +158,11 @@
|
|
|
152
158
|
outline: 2px solid var(--yasgui-endpoint-button-focus, #5cb3fd);
|
|
153
159
|
outline-offset: 2px;
|
|
154
160
|
}
|
|
161
|
+
|
|
162
|
+
// Reduce padding on medium screens
|
|
163
|
+
@media (max-width: 1024px) {
|
|
164
|
+
padding: 4px 8px;
|
|
165
|
+
font-size: 12px;
|
|
166
|
+
}
|
|
155
167
|
}
|
|
156
168
|
}
|
package/src/index.ts
CHANGED
|
@@ -38,13 +38,23 @@ export interface EndpointButton {
|
|
|
38
38
|
|
|
39
39
|
export interface EndpointConfig {
|
|
40
40
|
endpoint: string;
|
|
41
|
-
label?: string;
|
|
42
|
-
showAsButton?: boolean;
|
|
43
|
-
authentication?:
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
41
|
+
label?: string; // Optional label for the endpoint
|
|
42
|
+
showAsButton?: boolean; // Whether to show as a quick-switch button (requires label)
|
|
43
|
+
authentication?:
|
|
44
|
+
| {
|
|
45
|
+
type: "basic";
|
|
46
|
+
username: string;
|
|
47
|
+
password: string;
|
|
48
|
+
}
|
|
49
|
+
| {
|
|
50
|
+
type: "bearer";
|
|
51
|
+
token: string;
|
|
52
|
+
}
|
|
53
|
+
| {
|
|
54
|
+
type: "apiKey";
|
|
55
|
+
headerName: string;
|
|
56
|
+
apiKey: string;
|
|
57
|
+
};
|
|
48
58
|
}
|
|
49
59
|
export interface Config<EndpointObject extends CatalogueItem = CatalogueItem> {
|
|
50
60
|
/**
|
|
@@ -54,7 +64,6 @@ export interface Config<EndpointObject extends CatalogueItem = CatalogueItem> {
|
|
|
54
64
|
endpointInfo: ((tab?: Tab) => Element) | undefined;
|
|
55
65
|
copyEndpointOnNewTab: boolean;
|
|
56
66
|
tabName: string;
|
|
57
|
-
corsProxy: string | undefined;
|
|
58
67
|
endpointCatalogueOptions: EndpointSelectConfig<EndpointObject>;
|
|
59
68
|
endpointButtons?: EndpointButton[];
|
|
60
69
|
//The function allows us to modify the config before we pass it on to a tab
|
|
@@ -68,7 +77,6 @@ export interface Config<EndpointObject extends CatalogueItem = CatalogueItem> {
|
|
|
68
77
|
yasr: YasrConfig;
|
|
69
78
|
requestConfig: YasguiRequestConfig;
|
|
70
79
|
contextMenuContainer: HTMLElement | undefined;
|
|
71
|
-
nonSslDomain?: string;
|
|
72
80
|
theme?: Theme;
|
|
73
81
|
showThemeToggle?: boolean;
|
|
74
82
|
/**
|
|
@@ -77,6 +85,10 @@ export interface Config<EndpointObject extends CatalogueItem = CatalogueItem> {
|
|
|
77
85
|
* 'horizontal': YASQE on left, YASR on right
|
|
78
86
|
*/
|
|
79
87
|
orientation?: "vertical" | "horizontal";
|
|
88
|
+
/**
|
|
89
|
+
* Show code snippets bar in all tabs (global setting)
|
|
90
|
+
*/
|
|
91
|
+
showSnippetsBar?: boolean;
|
|
80
92
|
}
|
|
81
93
|
export type PartialConfig = {
|
|
82
94
|
[P in keyof Config]?: Config[P] extends object ? Partial<Config[P]> : Config[P];
|
|
@@ -141,6 +153,12 @@ export class Yasgui extends EventEmitter {
|
|
|
141
153
|
this.themeManager.listenToSystemTheme();
|
|
142
154
|
this.persistentConfig = new PersistentConfig(this);
|
|
143
155
|
|
|
156
|
+
// Load persisted showSnippetsBar if available
|
|
157
|
+
const persistedShowSnippetsBar = this.persistentConfig.getShowSnippetsBar();
|
|
158
|
+
if (persistedShowSnippetsBar !== undefined) {
|
|
159
|
+
this.config.showSnippetsBar = persistedShowSnippetsBar;
|
|
160
|
+
}
|
|
161
|
+
|
|
144
162
|
this.tabElements = new TabElements(this);
|
|
145
163
|
this.tabPanelsEl = document.createElement("div");
|
|
146
164
|
|
|
@@ -416,7 +434,6 @@ export class Yasgui extends EventEmitter {
|
|
|
416
434
|
public static Yasr = Yasr;
|
|
417
435
|
public static Yasqe = Yasqe;
|
|
418
436
|
public static defaults = initializeDefaults();
|
|
419
|
-
public static corsEnabled: { [endpoint: string]: boolean } = {};
|
|
420
437
|
}
|
|
421
438
|
|
|
422
439
|
export function getRandomId() {
|
package/src/version.ts
CHANGED