@matdata/yasgui 5.3.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.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@matdata/yasgui",
3
3
  "description": "Yet Another SPARQL GUI",
4
- "version": "5.3.0",
4
+ "version": "5.5.0",
5
5
  "main": "build/yasgui.min.js",
6
6
  "types": "build/ts/src/index.d.ts",
7
7
  "license": "MIT",
@@ -304,6 +304,7 @@ export function parseFromTurtle(turtle: string): Partial<PersistedJson> {
304
304
  headers: {},
305
305
  withCredentials: false,
306
306
  adjustQueryBeforeRequest: false,
307
+ basicAuth: undefined,
307
308
  },
308
309
  yasr: {
309
310
  settings: {},
@@ -1,5 +1,5 @@
1
1
  import { Storage as YStorage } from "@matdata/yasgui-utils";
2
- import Yasgui, { EndpointButton } from "./";
2
+ import Yasgui, { EndpointButton, EndpointConfig } from "./";
3
3
  import * as Tab from "./Tab";
4
4
  export var storageNamespace = "triply";
5
5
  export interface PersistedJson {
@@ -10,7 +10,8 @@ export interface PersistedJson {
10
10
  lastClosedTab: { index: number; tab: Tab.PersistedJson } | undefined;
11
11
  prefixes?: string;
12
12
  autoCaptureEnabled?: boolean;
13
- customEndpointButtons?: EndpointButton[];
13
+ customEndpointButtons?: EndpointButton[]; // Legacy, kept for backwards compatibility
14
+ endpointConfigs?: EndpointConfig[]; // New endpoint-based storage with auth
14
15
  theme?: "light" | "dark";
15
16
  orientation?: "vertical" | "horizontal";
16
17
  }
@@ -24,6 +25,7 @@ function getDefaults(): PersistedJson {
24
25
  prefixes: "",
25
26
  autoCaptureEnabled: true,
26
27
  customEndpointButtons: [],
28
+ endpointConfigs: [],
27
29
  };
28
30
  }
29
31
 
@@ -163,6 +165,46 @@ export default class PersistentConfig {
163
165
  this.persistedJson.customEndpointButtons = buttons;
164
166
  this.toStorage();
165
167
  }
168
+
169
+ // New endpoint configuration methods
170
+ public getEndpointConfigs(): EndpointConfig[] {
171
+ return this.persistedJson.endpointConfigs || [];
172
+ }
173
+
174
+ public setEndpointConfigs(configs: EndpointConfig[]) {
175
+ this.persistedJson.endpointConfigs = configs;
176
+ this.toStorage();
177
+ }
178
+
179
+ public addOrUpdateEndpoint(endpoint: string, updates: Partial<Omit<EndpointConfig, "endpoint">>) {
180
+ const configs = this.getEndpointConfigs();
181
+ const existingIndex = configs.findIndex((c) => c.endpoint === endpoint);
182
+
183
+ if (existingIndex >= 0) {
184
+ // Update existing endpoint
185
+ const merged = { ...configs[existingIndex], ...updates };
186
+ if ("authentication" in updates && updates.authentication === undefined) {
187
+ delete merged.authentication;
188
+ }
189
+ configs[existingIndex] = merged;
190
+ } else {
191
+ // Add new endpoint
192
+ configs.push({ endpoint, ...updates });
193
+ }
194
+
195
+ this.setEndpointConfigs(configs);
196
+ }
197
+
198
+ public getEndpointConfig(endpoint: string): EndpointConfig | undefined {
199
+ const configs = this.getEndpointConfigs();
200
+ return configs.find((c) => c.endpoint === endpoint);
201
+ }
202
+
203
+ public deleteEndpointConfig(endpoint: string) {
204
+ const configs = this.getEndpointConfigs();
205
+ const filtered = configs.filter((c) => c.endpoint !== endpoint);
206
+ this.setEndpointConfigs(filtered);
207
+ }
166
208
  public static clear() {
167
209
  const storage = new YStorage(storageNamespace);
168
210
  storage.removeNamespace();
package/src/Tab.ts CHANGED
@@ -241,8 +241,8 @@ export class Tab extends EventEmitter {
241
241
  return this.persistentJson.requestConfig;
242
242
  }
243
243
  private initControlbar() {
244
- this.initEndpointSelectField();
245
244
  this.initOrientationToggle();
245
+ this.initEndpointSelectField();
246
246
  this.initEndpointButtons();
247
247
  if (this.yasgui.config.endpointInfo && this.controlBarEl) {
248
248
  this.controlBarEl.appendChild(this.yasgui.config.endpointInfo());
@@ -266,7 +266,7 @@ export class Tab extends EventEmitter {
266
266
  this.controlBarEl.appendChild(this.orientationToggleButton);
267
267
  }
268
268
 
269
- private updateOrientationToggleIcon() {
269
+ public updateOrientationToggleIcon() {
270
270
  if (!this.orientationToggleButton) return;
271
271
 
272
272
  // Show the icon for the layout we'll switch TO (not the current layout)
@@ -279,24 +279,38 @@ export class Tab extends EventEmitter {
279
279
  public toggleOrientation() {
280
280
  if (!this.rootEl) return;
281
281
 
282
- // Remove old orientation class
283
- removeClass(this.rootEl, `orientation-${this.currentOrientation}`);
284
-
285
282
  // Toggle orientation
286
- this.currentOrientation = this.currentOrientation === "vertical" ? "horizontal" : "vertical";
283
+ const newOrientation = this.currentOrientation === "vertical" ? "horizontal" : "vertical";
287
284
 
288
- // Add new orientation class
289
- addClass(this.rootEl, `orientation-${this.currentOrientation}`);
285
+ // Update global config
286
+ this.yasgui.config.orientation = newOrientation;
290
287
 
291
- // Update button icon
292
- this.updateOrientationToggleIcon();
288
+ // Apply to all tabs
289
+ for (const tabId in this.yasgui._tabs) {
290
+ const tab = this.yasgui._tabs[tabId];
291
+ if (tab && tab.rootEl) {
292
+ // Remove old orientation class
293
+ removeClass(tab.rootEl, `orientation-${tab.currentOrientation}`);
293
294
 
294
- // Refresh components to adjust to new layout
295
- if (this.yasqe) {
296
- this.yasqe.refresh();
297
- }
298
- if (this.yasr) {
299
- this.yasr.refresh();
295
+ // Update tab's orientation
296
+ tab.currentOrientation = newOrientation;
297
+
298
+ // Add new orientation class
299
+ addClass(tab.rootEl, `orientation-${newOrientation}`);
300
+
301
+ // Update button icon if it exists
302
+ if (tab.orientationToggleButton) {
303
+ tab.updateOrientationToggleIcon();
304
+ }
305
+
306
+ // Refresh components to adjust to new layout
307
+ if (tab.yasqe) {
308
+ tab.yasqe.refresh();
309
+ }
310
+ if (tab.yasr) {
311
+ tab.yasr.refresh();
312
+ }
313
+ }
300
314
  }
301
315
  }
302
316
  public getYasqe() {
@@ -345,10 +359,19 @@ export class Tab extends EventEmitter {
345
359
  // Clear existing buttons
346
360
  this.endpointButtonsContainer.innerHTML = "";
347
361
 
348
- // Merge config buttons with custom user buttons
362
+ // Get config buttons (for backwards compatibility)
349
363
  const configButtons = this.yasgui.config.endpointButtons || [];
364
+
365
+ // Get endpoint configs where showAsButton is true
366
+ const endpointConfigs = this.yasgui.persistentConfig.getEndpointConfigs();
367
+ const endpointButtons = endpointConfigs
368
+ .filter((config) => config.showAsButton && config.label)
369
+ .map((config) => ({ endpoint: config.endpoint, label: config.label! }));
370
+
371
+ // Also include legacy custom buttons for backwards compatibility
350
372
  const customButtons = this.yasgui.persistentConfig.getCustomEndpointButtons();
351
- const allButtons = [...configButtons, ...customButtons];
373
+
374
+ const allButtons = [...configButtons, ...endpointButtons, ...customButtons];
352
375
 
353
376
  if (allButtons.length === 0) {
354
377
  // Hide container if no buttons
@@ -399,6 +422,11 @@ export class Tab extends EventEmitter {
399
422
  this.persistentJson.requestConfig.endpoint = endpoint;
400
423
  this.emit("change", this, this.persistentJson);
401
424
  this.emit("endpointChange", this, endpoint);
425
+
426
+ // Auto-track this endpoint in endpoint configs (if not already present)
427
+ if (endpoint && !this.yasgui.persistentConfig.getEndpointConfig(endpoint)) {
428
+ this.yasgui.persistentConfig.addOrUpdateEndpoint(endpoint, {});
429
+ }
402
430
  }
403
431
  if (this.endpointSelect instanceof EndpointSelect) {
404
432
  this.endpointSelect.setEndpoint(endpoint, endpointHistory);
@@ -450,6 +478,28 @@ export class Tab extends EventEmitter {
450
478
  this.emit("change", this, this.persistentJson);
451
479
  }
452
480
 
481
+ /**
482
+ * Get authentication configuration for the current endpoint
483
+ * This retrieves auth from the endpoint-based storage
484
+ */
485
+ private getAuthForCurrentEndpoint() {
486
+ const endpoint = this.getEndpoint();
487
+ if (!endpoint) return undefined;
488
+
489
+ const endpointConfig = this.yasgui.persistentConfig.getEndpointConfig(endpoint);
490
+ if (!endpointConfig || !endpointConfig.authentication) return undefined;
491
+
492
+ // Convert endpoint auth to requestConfig format
493
+ if (endpointConfig.authentication.type === "basic") {
494
+ return {
495
+ username: endpointConfig.authentication.username,
496
+ password: endpointConfig.authentication.password,
497
+ };
498
+ }
499
+
500
+ return undefined;
501
+ }
502
+
453
503
  /**
454
504
  * The Yasgui configuration object may contain a custom request config
455
505
  * This request config object can contain getter functions, or plain json
@@ -510,6 +560,14 @@ export class Tab extends EventEmitter {
510
560
  //The adjustQueryBeforeRequest is meant to be a function though, so let's copy that as is
511
561
  adjustQueryBeforeRequest: this.yasgui.config.requestConfig.adjustQueryBeforeRequest,
512
562
  };
563
+
564
+ // Inject authentication from endpoint-based storage
565
+ // Only inject endpoint-based auth if basicAuth is not already set
566
+ const endpointAuth = this.getAuthForCurrentEndpoint();
567
+ if (endpointAuth && typeof processedReqConfig.basicAuth === "undefined") {
568
+ processedReqConfig.basicAuth = endpointAuth;
569
+ }
570
+
513
571
  if (this.yasgui.config.corsProxy && !Yasgui.corsEnabled[this.getEndpoint()]) {
514
572
  return {
515
573
  ...processedReqConfig,