diff --git a/frontend/src/app.svelte b/frontend/src/app.svelte index 77a54d5..b68c4d1 100644 --- a/frontend/src/app.svelte +++ b/frontend/src/app.svelte @@ -1,21 +1,20 @@ - + -
+
- {#if environment} + {#if $environment && $applicationSettings}
openConnection(e.detail)} bind:modalOpen={addressBarModalOpen} /> @@ -63,6 +65,7 @@ {#key $contextMenu} {/key} + {/if}
diff --git a/frontend/src/organisms/connection/collection/find.svelte b/frontend/src/organisms/connection/collection/find.svelte index f3c45f7..de3e84e 100644 --- a/frontend/src/organisms/connection/collection/find.svelte +++ b/frontend/src/organisms/connection/collection/find.svelte @@ -8,15 +8,16 @@ import FindViewConfigModal from './find-viewconfig.svelte'; import { onMount } from 'svelte'; import Grid from '../../../components/grid.svelte'; + import { applicationSettings } from '../../../stores'; export let collection; const defaults = { query: '{}', - sort: '{ "_id": 1 }', + sort: $applicationSettings.defaultSort || '{ "_id": 1 }', fields: '{}', skip: 0, - limit: 15, + limit: $applicationSettings.defaultLimit || 15, }; let form = { ...defaults }; @@ -72,7 +73,9 @@ async function refresh() { await getViewConfig(); - await submitQuery(); + if ($applicationSettings.autosubmitQuery) { + await submitQuery(); + } } function prev() { diff --git a/frontend/src/organisms/connection/index.svelte b/frontend/src/organisms/connection/index.svelte index 7f730ce..80b8140 100644 --- a/frontend/src/organisms/connection/index.svelte +++ b/frontend/src/organisms/connection/index.svelte @@ -1,7 +1,6 @@ diff --git a/frontend/src/organisms/settings/index.svelte b/frontend/src/organisms/settings/index.svelte new file mode 100644 index 0000000..7275f5a --- /dev/null +++ b/frontend/src/organisms/settings/index.svelte @@ -0,0 +1,37 @@ + + + +
+ + + + + + + + + + + +
+
+ + diff --git a/frontend/src/stores.js b/frontend/src/stores.js index e7810c9..d2e5c5f 100644 --- a/frontend/src/stores.js +++ b/frontend/src/stores.js @@ -1,4 +1,6 @@ import { writable } from 'svelte/store'; +import { Environment } from '../wailsjs/runtime/runtime'; +import { Settings, UpdateSettings } from '../wailsjs/go/app/App'; export const busy = (() => { const { update, subscribe } = writable(0); @@ -21,6 +23,7 @@ export const busy = (() => { export const contextMenu = (() => { const { set, subscribe } = writable(); + return { show: (evt, menu) => set(menu ? { position: [ evt.clientX, evt.clientY ], @@ -32,3 +35,31 @@ export const contextMenu = (() => { })(); export const connections = writable({}); + +export const applicationSettings = (() => { + const { set, subscribe } = writable({}); + const reload = async() => { + const newSettings = await Settings(); + set(newSettings); + return newSettings; + }; + + reload(); + subscribe(newSettings => { + UpdateSettings(JSON.stringify(newSettings || {})); + }); + + return { reload, set, subscribe }; +})(); + +export const environment = (() => { + const { set, subscribe } = writable({}); + const reload = async() => { + const newEnv = await Environment(); + set(newEnv); + return newEnv; + }; + + reload(); + return { reload, subscribe }; +})(); diff --git a/frontend/src/utils.js b/frontend/src/utils.js index 3b1a9af..c36d6fc 100644 --- a/frontend/src/utils.js +++ b/frontend/src/utils.js @@ -1,3 +1,6 @@ +import { get } from 'svelte/store'; +import { environment } from './stores'; + export function resolveKeypath(object, path) { // Get a value from an object with a JSON path, from Webdesq core @@ -19,3 +22,14 @@ export function resolveKeypath(object, path) { return result; } + +export function controlKeyDown(event) { + const env = get(environment); + // @ts-ignore + if (env?.platform === 'darwin') { + return event?.metaKey; + } + else { + return event?.ctrlKey; + } +} diff --git a/frontend/wailsjs/go/app/App.d.ts b/frontend/wailsjs/go/app/App.d.ts index 4375111..224351c 100755 --- a/frontend/wailsjs/go/app/App.d.ts +++ b/frontend/wailsjs/go/app/App.d.ts @@ -32,6 +32,10 @@ export function RemoveItemById(arg1:string,arg2:string,arg3:string,arg4:string): export function RemoveItems(arg1:string,arg2:string,arg3:string,arg4:string,arg5:boolean):Promise; +export function Settings():Promise; + export function UpdateHost(arg1:string,arg2:string):Promise; export function UpdateItems(arg1:string,arg2:string,arg3:string,arg4:string):Promise; + +export function UpdateSettings(arg1:string):Promise; diff --git a/frontend/wailsjs/go/app/App.js b/frontend/wailsjs/go/app/App.js index 805c93a..4f5ae33 100755 --- a/frontend/wailsjs/go/app/App.js +++ b/frontend/wailsjs/go/app/App.js @@ -58,6 +58,10 @@ export function RemoveItems(arg1, arg2, arg3, arg4, arg5) { return window['go']['app']['App']['RemoveItems'](arg1, arg2, arg3, arg4, arg5); } +export function Settings() { + return window['go']['app']['App']['Settings'](); +} + export function UpdateHost(arg1, arg2) { return window['go']['app']['App']['UpdateHost'](arg1, arg2); } @@ -65,3 +69,7 @@ export function UpdateHost(arg1, arg2) { export function UpdateItems(arg1, arg2, arg3, arg4) { return window['go']['app']['App']['UpdateItems'](arg1, arg2, arg3, arg4); } + +export function UpdateSettings(arg1) { + return window['go']['app']['App']['UpdateSettings'](arg1); +} diff --git a/frontend/wailsjs/go/models.ts b/frontend/wailsjs/go/models.ts index a620a89..2b82c66 100755 --- a/frontend/wailsjs/go/models.ts +++ b/frontend/wailsjs/go/models.ts @@ -1,5 +1,21 @@ export namespace app { + export class Settings { + defaultLimit: number; + defaultSort: string; + autosubmitQuery: boolean; + + static createFrom(source: any = {}) { + return new Settings(source); + } + + constructor(source: any = {}) { + if ('string' === typeof source) source = JSON.parse(source); + this.defaultLimit = source["defaultLimit"]; + this.defaultSort = source["defaultSort"]; + this.autosubmitQuery = source["autosubmitQuery"]; + } + } export class findResult { total: number; results: any; diff --git a/internal/app/settings.go b/internal/app/settings.go index a4c8c56..5a4d760 100644 --- a/internal/app/settings.go +++ b/internal/app/settings.go @@ -1,18 +1,37 @@ package app import ( + "encoding/json" "errors" + "fmt" + "io/ioutil" "os" "path/filepath" - "runtime" + goRuntime "runtime" + + "github.com/wailsapp/wails/v2/pkg/runtime" ) +type Settings struct { + DefaultLimit int64 `json:"defaultLimit"` + DefaultSort string `json:"defaultSort"` + AutosubmitQuery bool `json:"autosubmitQuery"` +} + +func NewSettings() Settings { + return Settings{ + DefaultLimit: 20, + DefaultSort: `{ "_id": 1 }`, + AutosubmitQuery: true, + } +} + func appDataDirectory() (string, error) { var err error homeDir, err := os.UserHomeDir() prefDir := "" - switch runtime.GOOS { + switch goRuntime.GOOS { case "windows": prefDir = filepath.Join(homeDir, "/AppData/Local/Mongodup") case "darwin": @@ -35,3 +54,85 @@ func appDataFilePath(filename string) (string, error) { path := filepath.Join(dir, filename) return path, nil } + +func (a *App) Settings() Settings { + s := NewSettings() + filePath, err := appDataFilePath("settings.json") + if err != nil { + fmt.Println(err.Error()) + runtime.MessageDialog(a.ctx, runtime.MessageDialogOptions{ + Type: runtime.ErrorDialog, + Title: "Could not retrieve application settings, using defaults!", + Message: err.Error(), + }) + return s + } + + jsonData, err := ioutil.ReadFile(filePath) + if err != nil { + // It's ok if the file cannot be opened, for example if it is not accessible. + // Therefore no error is returned. + fmt.Println(err.Error()) + return s + } + + if len(jsonData) == 0 { + return s + } else { + err = json.Unmarshal(jsonData, &s) + + if err != nil { + fmt.Println(err.Error()) + runtime.MessageDialog(a.ctx, runtime.MessageDialogOptions{ + Type: runtime.ErrorDialog, + Title: "Could not retrieve application settings, using defaults!", + Message: err.Error(), + }) + } + return s + } +} + +func (a *App) UpdateSettings(jsonData string) Settings { + s := a.Settings() + err := json.Unmarshal([]byte(jsonData), &s) + if err != nil { + runtime.MessageDialog(a.ctx, runtime.MessageDialogOptions{ + Type: runtime.InfoDialog, + Title: "Malformed JSON", + Message: err.Error(), + }) + return s + } + + filePath, err := appDataFilePath("settings.json") + if err != nil { + runtime.MessageDialog(a.ctx, runtime.MessageDialogOptions{ + Type: runtime.InfoDialog, + Title: "Could not update settings.json", + Message: err.Error(), + }) + return s + } + + newJson, err := json.MarshalIndent(s, "", "\t") + if err != nil { + runtime.MessageDialog(a.ctx, runtime.MessageDialogOptions{ + Type: runtime.InfoDialog, + Title: "Could not marshal settings into JSON", + Message: err.Error(), + }) + return s + } + + err = ioutil.WriteFile(filePath, newJson, os.ModePerm) + if err != nil { + runtime.MessageDialog(a.ctx, runtime.MessageDialogOptions{ + Type: runtime.InfoDialog, + Title: "Could not update host list", + Message: err.Error(), + }) + } + + return s +}