Skip to content

Commit b4eae5b

Browse files
committed
feat(yasgui): redesign the settings and make request settings global
The settings follow the settings window of textfold: pages grouped in the navigation with icons, each setting a row with one line about it and its control on the right, a fixed header and footer, and changes that apply at once (the footer says "Saved"; Done closes). A new General page holds the theme (Light, Dark or System), the editor themes, the request settings and what happens before a query runs. Request method, Accept headers and custom HTTP headers now apply to every tab, including tabs opened later. The formatter, auto-format and the CONSTRUCT check apply to every tab too and are kept across reloads. Settings > AI keeps the services as cards and gets a form with a provider list that fills in the base URL (still editable, with a reset), a link to get an API key, and Fetch models with a searchable model list. When a browser can't read a model list (CORS), the provider's known models are offered and the form explains what to do.
1 parent f278fe8 commit b4eae5b

18 files changed

Lines changed: 2841 additions & 1192 deletions

‎.changeset/settings-redesign.md‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
"@matdata/yasgui": minor
3+
---
4+
5+
Redesign the settings, after the settings window of textfold. The pages are grouped in the navigation (Querying, Your data, Assistant, Help) with an icon each, and each setting is a row with one line about it and its control on the right (switches, segmented choices, selects). The header and footer stay in place while the page scrolls. Changes apply at once: the Save and Cancel buttons are gone, the footer says "Saved" after a change, and Done closes the settings.
6+
7+
The new **General** page holds the theme (Light, Dark or System), the editor themes, the request settings and what happens before a query runs. The request method, Accept headers and custom HTTP headers now apply to every tab, including tabs opened later (stored as `requestSettings` in the persisted config); the formatter, auto-format and the CONSTRUCT check now apply to every tab too, and are kept across reloads. `tab.openSettings("request")` still works and opens General.
8+
9+
Settings → AI: services stay cards, with the default one selected. Adding or editing a service now starts with a **Provider** list (searchable, grouped); the provider fills in the base URL, which can still be changed (marked "Changed", with a reset) and links to the page where users get an API key. **Fetch models** replaces Test connection and fills a searchable **Model** list, with the provider's recommended models first and any model id accepted. When a browser can't read a service's model list (CORS), MatGUI says so, offers the models it knows for that provider, and explains what to do (a proxy, OpenRouter, or the CORS setting of Ollama or LM Studio). Services remember their provider (`providerId`).

‎docs/developer-guide.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -712,7 +712,7 @@ interface Config {
712712
showSnippetsBar?: boolean; // default: false
713713

714714
// Tooltip with the label, description and type of an IRI hovered in the editor,
715-
// fetched from the tab's endpoint. Users can also switch it off in Settings → Editor
715+
// fetched from the tab's endpoint. Users can also switch it off in Settings → General
716716
iriHover?: boolean; // default: true
717717

718718
// Look up IRIs the endpoint doesn't describe in LOV (lov.linkeddata.es)
@@ -2574,7 +2574,7 @@ const id = tab.getId();
25742574
25752575
##### `openSettings(section?: string): void`
25762576
2577-
Open the settings modal of this tab, optionally on a section (for example `"endpoints"`).
2577+
Open the settings modal of this tab, optionally on a page: `"general"`, `"endpoints"`, `"prefix"`, `"editor"`, `"workspaces"`, `"importexport"`, `"ai"`, `"shortcuts"` or `"about"`. `"request"`, the name of an earlier page, opens `"general"`.
25782578
25792579
```javascript
25802580
tab.openSettings("endpoints");

‎docs/user-guide.md‎

Lines changed: 37 additions & 47 deletions
Large diffs are not rendered by default.

‎packages/yasgui/src/PersistentConfig.ts‎

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,21 @@ export interface PersistedJson {
2323
codeMirrorThemeLight?: string; // User-selected CodeMirror theme for light mode
2424
codeMirrorThemeDark?: string; // User-selected CodeMirror theme for dark mode
2525
sidePanel?: SidePanelState; // Left side panel (Queries / Endpoint / AI)
26+
requestSettings?: RequestSettings; // Request settings of Settings → General, shared by all tabs
27+
editorSettings?: EditorSettings; // Formatter and checks of Settings → General and Editor, shared by all tabs
28+
}
29+
/** Settings of the query editor that apply to every tab */
30+
export interface EditorSettings {
31+
formatterType?: "sparql-formatter" | "legacy";
32+
autoformatOnQuery?: boolean;
33+
checkConstructVariables?: boolean;
34+
}
35+
/** The request settings users change in Settings → General; they apply to every tab */
36+
export interface RequestSettings {
37+
method?: "GET" | "POST";
38+
acceptHeaderSelect?: string;
39+
acceptHeaderGraph?: string;
40+
headers?: { [name: string]: string };
2641
}
2742
export interface SidePanelState {
2843
open: boolean;
@@ -193,6 +208,25 @@ export default class PersistentConfig {
193208
this.toStorage();
194209
}
195210

211+
/** The request settings shared by all tabs, or undefined when the user never changed them */
212+
public getRequestSettings(): RequestSettings | undefined {
213+
return this.persistedJson.requestSettings;
214+
}
215+
216+
public setRequestSettings(settings: RequestSettings) {
217+
this.persistedJson.requestSettings = { ...this.persistedJson.requestSettings, ...settings };
218+
this.toStorage();
219+
}
220+
221+
public getEditorSettings(): EditorSettings {
222+
return this.persistedJson.editorSettings || {};
223+
}
224+
225+
public setEditorSettings(settings: EditorSettings) {
226+
this.persistedJson.editorSettings = { ...this.persistedJson.editorSettings, ...settings };
227+
this.toStorage();
228+
}
229+
196230
public getIriHoverEnabled(): boolean {
197231
return this.persistedJson.iriHoverEnabled !== false;
198232
}

‎packages/yasgui/src/Tab.ts‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -881,6 +881,21 @@ export class Tab extends EventEmitter {
881881
return undefined;
882882
}
883883

884+
/** Apply the editor settings shared by all tabs (Settings → General and Editor) to the query editor */
885+
public applyEditorSettings() {
886+
if (!this.yasqe) return;
887+
const settings = this.yasgui.persistentConfig.getEditorSettings();
888+
if (this.yasqe.persistentConfig) {
889+
if (settings.formatterType) this.yasqe.persistentConfig.formatterType = settings.formatterType;
890+
if (settings.autoformatOnQuery !== undefined) {
891+
this.yasqe.persistentConfig.autoformatOnQuery = settings.autoformatOnQuery;
892+
}
893+
}
894+
if (settings.checkConstructVariables !== undefined) {
895+
this.yasqe.setCheckConstructVariables(settings.checkConstructVariables);
896+
}
897+
}
898+
884899
/** Open the settings modal of this tab, optionally on a section (e.g. "endpoints") */
885900
public openSettings(section?: string) {
886901
this.settingsModal?.open(section);
@@ -1488,6 +1503,7 @@ export class Tab extends EventEmitter {
14881503
throw new Error("Expected a wrapper element before instantiating yasqe");
14891504
}
14901505
this.yasqe = new Yasqe(this.yasqeWrapperEl, yasqeConf);
1506+
this.applyEditorSettings();
14911507

14921508
// Hook up the save button to managed query save
14931509
this.yasqe.on("saveManagedQuery", () => {

0 commit comments

Comments
 (0)