mirror of
https://github.com/garraflavatra/rolens.git
synced 2025-01-18 13:07:58 +00:00
Multiple improvements to the frontend
* Consistent usage of modal footer * Remove hosts * Moved hosts to dedicated store
This commit is contained in:
parent
27dc1f9117
commit
415efe9ac4
@ -1,6 +1,4 @@
|
|||||||
---
|
# Installing Rolens
|
||||||
title: Installation
|
|
||||||
---
|
|
||||||
|
|
||||||
## System requirements
|
## System requirements
|
||||||
|
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
<script>
|
<script>
|
||||||
import BlankState from '$components/blankstate.svelte';
|
import BlankState from '$components/blankstate.svelte';
|
||||||
import ContextMenu from '$components/contextmenu.svelte';
|
import ContextMenu from '$components/contextmenu.svelte';
|
||||||
import { connections } from '$lib/stores/connections';
|
import connections from '$lib/stores/connections';
|
||||||
import contextMenu from '$lib/stores/contextmenu';
|
import contextMenu from '$lib/stores/contextmenu';
|
||||||
import environment from '$lib/stores/environment';
|
import environment from '$lib/stores/environment';
|
||||||
|
import hosts from '$lib/stores/hosts';
|
||||||
import applicationInited from '$lib/stores/inited';
|
import applicationInited from '$lib/stores/inited';
|
||||||
import About from '$organisms/about.svelte';
|
import About from '$organisms/about.svelte';
|
||||||
import Connection from '$organisms/connection/index.svelte';
|
import Connection from '$organisms/connection/index.svelte';
|
||||||
@ -11,18 +12,22 @@
|
|||||||
import { EventsEmit, EventsOn } from '$wails/runtime';
|
import { EventsEmit, EventsOn } from '$wails/runtime';
|
||||||
import { tick } from 'svelte';
|
import { tick } from 'svelte';
|
||||||
|
|
||||||
const hosts = {};
|
|
||||||
const activeHostKey = '';
|
const activeHostKey = '';
|
||||||
let activeDbKey = '';
|
let activeDbKey = '';
|
||||||
let activeCollKey = '';
|
let activeCollKey = '';
|
||||||
let settingsModalOpen = false;
|
let settingsModalOpen = false;
|
||||||
let aboutModalOpen = false;
|
let aboutModalOpen = false;
|
||||||
let connectionManager;
|
let connectionManager;
|
||||||
let showWelcomeScreen = false;
|
let showWelcomeScreen = undefined;
|
||||||
|
|
||||||
$: host = hosts[activeHostKey];
|
$: host = hosts[activeHostKey];
|
||||||
$: connection = $connections[activeHostKey];
|
$: connection = $connections[activeHostKey];
|
||||||
$: showWelcomeScreen = !Object.keys(hosts).length;
|
|
||||||
|
hosts.subscribe(h => {
|
||||||
|
if (h && (showWelcomeScreen === undefined)) {
|
||||||
|
showWelcomeScreen = !Object.keys($hosts || {}).length;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
async function createFirstHost() {
|
async function createFirstHost() {
|
||||||
showWelcomeScreen = false;
|
showWelcomeScreen = false;
|
||||||
@ -39,14 +44,14 @@
|
|||||||
<div id="root" class="platform-{$environment?.platform}">
|
<div id="root" class="platform-{$environment?.platform}">
|
||||||
<div class="titlebar"></div>
|
<div class="titlebar"></div>
|
||||||
|
|
||||||
{#if $applicationInited}
|
{#if $applicationInited && $hosts && (showWelcomeScreen !== undefined)}
|
||||||
<main class:empty={showWelcomeScreen}>
|
<main class:empty={showWelcomeScreen}>
|
||||||
{#if showWelcomeScreen}
|
{#if showWelcomeScreen}
|
||||||
<BlankState label="Welcome to Rolens!" image="/logo.png" pale={false} big={true}>
|
<BlankState label="Welcome to Rolens!" image="/logo.png" pale={false} big={true}>
|
||||||
<button class="btn" on:click={createFirstHost}>Add your first host</button>
|
<button class="btn" on:click={createFirstHost}>Add your first host</button>
|
||||||
</BlankState>
|
</BlankState>
|
||||||
{:else}
|
{:else}
|
||||||
<Connection {hosts} {activeHostKey} bind:activeCollKey bind:activeDbKey bind:this={connectionManager} />
|
<Connection {activeHostKey} bind:activeCollKey bind:activeDbKey bind:this={connectionManager} />
|
||||||
{/if}
|
{/if}
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
import { writable } from 'svelte/store';
|
import { writable } from 'svelte/store';
|
||||||
|
|
||||||
export const connections = writable({});
|
const connections = writable({});
|
||||||
|
|
||||||
|
export default connections;
|
||||||
|
11
frontend/src/lib/stores/hosts.js
Normal file
11
frontend/src/lib/stores/hosts.js
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import { Hosts } from "$wails/go/app/App";
|
||||||
|
import { writable } from "svelte/store";
|
||||||
|
import applicationInited from "./inited";
|
||||||
|
|
||||||
|
const { set, subscribe } = writable();
|
||||||
|
|
||||||
|
const update = async () => set(await Hosts());
|
||||||
|
applicationInited.defer(update);
|
||||||
|
|
||||||
|
const hosts = { update, subscribe };
|
||||||
|
export default hosts;
|
@ -2,13 +2,35 @@ import { derived } from 'svelte/store';
|
|||||||
import environment from './environment';
|
import environment from './environment';
|
||||||
import applicationSettings from './settings';
|
import applicationSettings from './settings';
|
||||||
|
|
||||||
const applicationInited = derived([ environment, applicationSettings ], ([ env, settings ], set) => {
|
let alreadyInited = false;
|
||||||
|
|
||||||
|
const listeners = [];
|
||||||
|
const defer = listener => {
|
||||||
|
if (alreadyInited) {
|
||||||
|
listener();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
listeners.push(listener)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const { subscribe } = derived([ environment, applicationSettings ], ([ env, settings ], set) => {
|
||||||
|
if (alreadyInited) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (env && settings) {
|
if (env && settings) {
|
||||||
set(true);
|
set(true);
|
||||||
|
alreadyInited = true;
|
||||||
|
|
||||||
// Remove loading spinner.
|
// Remove loading spinner.
|
||||||
document.getElementById('app-loading')?.remove();
|
document.getElementById('app-loading')?.remove();
|
||||||
|
|
||||||
|
// Call hooks
|
||||||
|
listeners.forEach(l => l());
|
||||||
}
|
}
|
||||||
}, false);
|
}, false);
|
||||||
|
|
||||||
|
const applicationInited = { defer, subscribe };
|
||||||
|
|
||||||
export default applicationInited;
|
export default applicationInited;
|
||||||
|
@ -56,12 +56,13 @@
|
|||||||
<Icon name="cog" />
|
<Icon name="cog" />
|
||||||
</button>
|
</button>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<button class="btn" type="submit">
|
|
||||||
<Icon name="play" />
|
|
||||||
Start export
|
|
||||||
</button>
|
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
<svelte:fragment slot="footer">
|
||||||
|
<button class="btn" on:click={performExport}>
|
||||||
|
<Icon name="play" /> Start export
|
||||||
|
</button>
|
||||||
|
</svelte:fragment>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
@ -86,16 +86,16 @@
|
|||||||
No rules
|
No rules
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="buttons">
|
|
||||||
<button class="btn" type="button" on:click={addRule} disabled={index.model.some(r => r.sort === 'hashed')}>
|
|
||||||
<Icon name="+" /> Add rule
|
|
||||||
</button>
|
|
||||||
<button class="btn" type="submit" disabled={!index.model.length || index.model.some(r => !r.key)}>
|
|
||||||
<Icon name="+" /> Create index
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
<div class="buttons" slot="footer">
|
||||||
|
<button class="btn" on:click={addRule} disabled={index.model.some(r => r.sort === 'hashed')}>
|
||||||
|
<Icon name="+" /> Add rule
|
||||||
|
</button>
|
||||||
|
<button class="btn" on:click={create} disabled={!index.model.length || index.model.some(r => !r.key)}>
|
||||||
|
<Icon name="+" /> Create index
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
@ -128,7 +128,7 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
}
|
}
|
||||||
.buttons button[type="submit"] {
|
.buttons:nth-child(2) {
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -4,13 +4,13 @@
|
|||||||
import Icon from '$components/icon.svelte';
|
import Icon from '$components/icon.svelte';
|
||||||
import Modal from '$components/modal.svelte';
|
import Modal from '$components/modal.svelte';
|
||||||
import input from '$lib/actions/input';
|
import input from '$lib/actions/input';
|
||||||
|
import hosts from '$lib/stores/hosts';
|
||||||
import queries from '$lib/stores/queries';
|
import queries from '$lib/stores/queries';
|
||||||
import { createEventDispatcher } from 'svelte';
|
import { createEventDispatcher } from 'svelte';
|
||||||
|
|
||||||
export let queryToSave = undefined;
|
export let queryToSave = undefined;
|
||||||
export let collection = {};
|
export let collection = {};
|
||||||
export let show = false;
|
export let show = false;
|
||||||
export let hosts = {};
|
|
||||||
|
|
||||||
const dispatch = createEventDispatcher();
|
const dispatch = createEventDispatcher();
|
||||||
let gridSelectedPath = [];
|
let gridSelectedPath = [];
|
||||||
@ -88,7 +88,7 @@
|
|||||||
columns={[ { key: 'n', title: 'Query name' }, { key: 'h', title: 'Host' }, { key: 'ns', title: 'Namespace' } ]}
|
columns={[ { key: 'n', title: 'Query name' }, { key: 'h', title: 'Host' }, { key: 'ns', title: 'Namespace' } ]}
|
||||||
key="n"
|
key="n"
|
||||||
items={Object.entries($queries).reduce((object, [ name, query ]) => {
|
items={Object.entries($queries).reduce((object, [ name, query ]) => {
|
||||||
object[query.name] = { n: name, h: hosts[query.hostKey]?.name || '?', ns: `${query.dbKey}.${query.collKey}` };
|
object[query.name] = { n: name, h: $hosts[query.hostKey]?.name || '?', ns: `${query.dbKey}.${query.collKey}` };
|
||||||
return object;
|
return object;
|
||||||
}, {})}
|
}, {})}
|
||||||
showHeaders={true}
|
showHeaders={true}
|
||||||
@ -100,23 +100,25 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{#if queryToSave && Object.keys($queries).includes(queryToSave.name)}
|
||||||
|
<Hint>
|
||||||
|
You are about to <strong>overwrite</strong> a saved query. Give it
|
||||||
|
another name if you do not want to overwrite.
|
||||||
|
</Hint>
|
||||||
|
{/if}
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<svelte:fragment slot="footer">
|
||||||
{#if queryToSave}
|
{#if queryToSave}
|
||||||
<button class="btn" type="submit">
|
<button class="btn" on:click={submit}>
|
||||||
<Icon name="save" /> Save query
|
<Icon name="save" /> Save query
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
{#if Object.keys($queries).includes(queryToSave.name)}
|
|
||||||
<Hint>
|
|
||||||
You are about to <strong>overwrite</strong> a saved query. Give it
|
|
||||||
another name if you do not want to overwrite.
|
|
||||||
</Hint>
|
|
||||||
{/if}
|
|
||||||
{:else}
|
{:else}
|
||||||
<button class="btn" type="submit" disabled={!selectedKey}>
|
<button class="btn" on:click={submit} disabled={!selectedKey}>
|
||||||
<Icon name="upload" /> Load query
|
<Icon name="upload" /> Load query
|
||||||
</button>
|
</button>
|
||||||
{/if}
|
{/if}
|
||||||
</form>
|
</svelte:fragment>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
import QueryChooser from './components/querychooser.svelte';
|
import QueryChooser from './components/querychooser.svelte';
|
||||||
|
|
||||||
export let collection;
|
export let collection;
|
||||||
export let hosts = {};
|
|
||||||
|
|
||||||
const dispatch = createEventDispatcher();
|
const dispatch = createEventDispatcher();
|
||||||
const defaults = {
|
const defaults = {
|
||||||
@ -252,7 +251,6 @@
|
|||||||
bind:queryToSave
|
bind:queryToSave
|
||||||
bind:show={showQueryChooser}
|
bind:show={showQueryChooser}
|
||||||
on:select={queryChosen}
|
on:select={queryChosen}
|
||||||
{hosts}
|
|
||||||
{collection}
|
{collection}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
export let hostKey;
|
export let hostKey;
|
||||||
export let dbKey;
|
export let dbKey;
|
||||||
export let collectionKey;
|
export let collectionKey;
|
||||||
export let hosts = {};
|
|
||||||
|
|
||||||
let tab = 'find';
|
let tab = 'find';
|
||||||
let find;
|
let find;
|
||||||
@ -62,7 +61,7 @@
|
|||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
{#if tab === 'stats'} <Stats {collection} />
|
{#if tab === 'stats'} <Stats {collection} />
|
||||||
{:else if tab === 'find'} <Find {collection} {hosts} bind:this={find} on:openViewConfig={openViewConfig} />
|
{:else if tab === 'find'} <Find {collection} bind:this={find} on:openViewConfig={openViewConfig} />
|
||||||
{:else if tab === 'insert'} <Insert {collection} on:performFind={catchQuery} on:openViewConfig={openViewConfig} />
|
{:else if tab === 'insert'} <Insert {collection} on:performFind={catchQuery} on:openViewConfig={openViewConfig} />
|
||||||
{:else if tab === 'update'} <Update {collection} on:performFind={catchQuery} />
|
{:else if tab === 'update'} <Update {collection} on:performFind={catchQuery} />
|
||||||
{:else if tab === 'remove'} <Remove {collection} />
|
{:else if tab === 'remove'} <Remove {collection} />
|
||||||
|
@ -3,12 +3,12 @@
|
|||||||
import Grid from '$components/grid.svelte';
|
import Grid from '$components/grid.svelte';
|
||||||
import Modal from '$components/modal.svelte';
|
import Modal from '$components/modal.svelte';
|
||||||
import { startProgress } from '$lib/progress';
|
import { startProgress } from '$lib/progress';
|
||||||
import { connections } from '$lib/stores/connections';
|
import connections from '$lib/stores/connections';
|
||||||
|
import hosts from '$lib/stores/hosts';
|
||||||
import applicationSettings from '$lib/stores/settings';
|
import applicationSettings from '$lib/stores/settings';
|
||||||
import { OpenConnection, OpenDatabase, PerformDump } from '$wails/go/app/App';
|
import { OpenConnection, OpenDatabase, PerformDump } from '$wails/go/app/App';
|
||||||
|
|
||||||
export let info;
|
export let info;
|
||||||
export let hosts = {};
|
|
||||||
|
|
||||||
$: if (info) {
|
$: if (info) {
|
||||||
info.outdir = info.outdir || $applicationSettings.defaultExportDirectory;
|
info.outdir = info.outdir || $applicationSettings.defaultExportDirectory;
|
||||||
@ -83,7 +83,7 @@
|
|||||||
hideChildrenToggles
|
hideChildrenToggles
|
||||||
items={[
|
items={[
|
||||||
{ id: undefined, name: '(localhost)' },
|
{ id: undefined, name: '(localhost)' },
|
||||||
...Object.keys(hosts).map(id => ({ id, name: hosts[id]?.name })),
|
...Object.keys($hosts).map(id => ({ id, name: $hosts[id]?.name })),
|
||||||
]}
|
]}
|
||||||
on:select={e => selectHost(e.detail?.itemKey)}
|
on:select={e => selectHost(e.detail?.itemKey)}
|
||||||
/>
|
/>
|
||||||
@ -123,11 +123,11 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
|
||||||
<button type="submit" class="btn">Perform dump</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
<svelte:fragment slot="footer">
|
||||||
|
<button class="btn" on:click={performDump}>Perform dump</button>
|
||||||
|
</svelte:fragment>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
@ -1,18 +1,18 @@
|
|||||||
<script>
|
<script>
|
||||||
import Modal from '$components/modal.svelte';
|
import Modal from '$components/modal.svelte';
|
||||||
import input from '$lib/actions/input';
|
import input from '$lib/actions/input';
|
||||||
|
import hosts from '$lib/stores/hosts';
|
||||||
import { AddHost, UpdateHost } from '$wails/go/app/App';
|
import { AddHost, UpdateHost } from '$wails/go/app/App';
|
||||||
import { createEventDispatcher } from 'svelte';
|
import { createEventDispatcher } from 'svelte';
|
||||||
|
|
||||||
export let show = false;
|
export let show = false;
|
||||||
export let hostKey = '';
|
export let hostKey = '';
|
||||||
export let hosts = {};
|
|
||||||
|
|
||||||
const dispatch = createEventDispatcher();
|
const dispatch = createEventDispatcher();
|
||||||
let form = {};
|
let form = {};
|
||||||
let error = '';
|
let error = '';
|
||||||
$: valid = validate(form);
|
$: valid = validate(form);
|
||||||
$: host = hosts[hostKey];
|
$: host = $hosts[hostKey];
|
||||||
|
|
||||||
$: if (show || !show) {
|
$: if (show || !show) {
|
||||||
init();
|
init();
|
||||||
@ -36,7 +36,10 @@
|
|||||||
await UpdateHost(hostKey, JSON.stringify(form));
|
await UpdateHost(hostKey, JSON.stringify(form));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
await AddHost(JSON.stringify(form));
|
const newHostKey = await AddHost(JSON.stringify(form));
|
||||||
|
if (newHostKey) {
|
||||||
|
hostKey = newHostKey;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
show = false;
|
show = false;
|
||||||
dispatch('reload');
|
dispatch('reload');
|
||||||
@ -58,18 +61,18 @@
|
|||||||
<span class="label">Connection string</span>
|
<span class="label">Connection string</span>
|
||||||
<input type="text" placeholder="mongodb://..." bind:value={form.uri} spellcheck="false" use:input />
|
<input type="text" placeholder="mongodb://..." bind:value={form.uri} spellcheck="false" use:input />
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<div class="result">
|
|
||||||
<div>
|
|
||||||
{#if error}
|
|
||||||
<div class="error">{error}</div>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
<button class="btn" disabled={!valid} type="submit">
|
|
||||||
{host ? 'Save' : 'Create'}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
<div class="result" slot="footer">
|
||||||
|
<div>
|
||||||
|
{#if error}
|
||||||
|
<div class="error">{error}</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
<button class="btn" disabled={!valid} on:click={submit}>
|
||||||
|
{host ? 'Save' : 'Create'}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
<script>
|
<script>
|
||||||
import Grid from '$components/grid.svelte';
|
import Grid from '$components/grid.svelte';
|
||||||
import { startProgress } from '$lib/progress';
|
import { startProgress } from '$lib/progress';
|
||||||
import { connections } from '$lib/stores/connections';
|
import connections from '$lib/stores/connections';
|
||||||
import { WindowSetTitle } from '$wails/runtime/runtime';
|
import { WindowSetTitle } from '$wails/runtime/runtime';
|
||||||
import { createEventDispatcher } from 'svelte';
|
import { createEventDispatcher } from 'svelte';
|
||||||
import { DropCollection, DropDatabase, OpenCollection, OpenConnection, OpenDatabase, TruncateCollection } from '../../../wailsjs/go/app/App';
|
import { DropCollection, DropDatabase, OpenCollection, OpenConnection, OpenDatabase, RemoveHost, TruncateCollection } from '../../../wailsjs/go/app/App';
|
||||||
|
import hosts from '$lib/stores/hosts';
|
||||||
|
import { tick } from 'svelte';
|
||||||
|
|
||||||
export let hosts = {};
|
|
||||||
export let activeHostKey = '';
|
export let activeHostKey = '';
|
||||||
export let activeDbKey = '';
|
export let activeDbKey = '';
|
||||||
export let activeCollKey = '';
|
export let activeCollKey = '';
|
||||||
@ -16,7 +17,7 @@
|
|||||||
$: activeHostKey = activeGridPath[0] || activeHostKey;
|
$: activeHostKey = activeGridPath[0] || activeHostKey;
|
||||||
$: activeDbKey = activeGridPath[1];
|
$: activeDbKey = activeGridPath[1];
|
||||||
$: activeCollKey = activeGridPath[2];
|
$: activeCollKey = activeGridPath[2];
|
||||||
$: host = hosts[activeHostKey];
|
$: host = $hosts[activeHostKey];
|
||||||
$: connection = $connections[activeHostKey];
|
$: connection = $connections[activeHostKey];
|
||||||
$: database = connection?.databases[activeDbKey];
|
$: database = connection?.databases[activeDbKey];
|
||||||
$: collection = database?.collections?.[activeCollKey];
|
$: collection = database?.collections?.[activeCollKey];
|
||||||
@ -38,12 +39,21 @@
|
|||||||
});
|
});
|
||||||
activeHostKey = hostKey;
|
activeHostKey = hostKey;
|
||||||
dispatch('connected', hostKey);
|
dispatch('connected', hostKey);
|
||||||
WindowSetTitle(`${hosts[activeHostKey].name} - Rolens`);
|
WindowSetTitle(`${$hosts[activeHostKey].name} - Rolens`);
|
||||||
}
|
}
|
||||||
|
|
||||||
progress.end();
|
progress.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function removeHost(hostKey) {
|
||||||
|
activeCollKey = '';
|
||||||
|
activeDbKey = '';
|
||||||
|
activeHostKey = '';
|
||||||
|
await tick();
|
||||||
|
await RemoveHost(hostKey);
|
||||||
|
hosts.update();
|
||||||
|
}
|
||||||
|
|
||||||
async function openDatabase(dbKey) {
|
async function openDatabase(dbKey) {
|
||||||
const progress = startProgress(`Opening database "${dbKey}"…`);
|
const progress = startProgress(`Opening database "${dbKey}"…`);
|
||||||
const collections = await OpenDatabase(activeHostKey, dbKey);
|
const collections = await OpenDatabase(activeHostKey, dbKey);
|
||||||
@ -88,9 +98,9 @@
|
|||||||
<Grid
|
<Grid
|
||||||
striped={false}
|
striped={false}
|
||||||
columns={[ { key: 'name' }, { key: 'count', right: true } ]}
|
columns={[ { key: 'name' }, { key: 'count', right: true } ]}
|
||||||
items={Object.keys(hosts).map(hostKey => ({
|
items={Object.keys($hosts).map(hostKey => ({
|
||||||
id: hostKey,
|
id: hostKey,
|
||||||
name: hosts[hostKey].name,
|
name: $hosts[hostKey].name,
|
||||||
icon: 'server',
|
icon: 'server',
|
||||||
children: Object.keys(connection?.databases || {}).sort().map(dbKey => ({
|
children: Object.keys(connection?.databases || {}).sort().map(dbKey => ({
|
||||||
id: dbKey,
|
id: dbKey,
|
||||||
@ -122,7 +132,8 @@
|
|||||||
menu: [
|
menu: [
|
||||||
{ label: 'New database…', fn: () => dispatch('newDatabase') },
|
{ label: 'New database…', fn: () => dispatch('newDatabase') },
|
||||||
{ separator: true },
|
{ separator: true },
|
||||||
{ label: `Edit host ${hosts[hostKey].name}…`, fn: () => dispatch('editHost', hostKey) },
|
{ label: `Edit host ${$hosts[hostKey].name}…`, fn: () => dispatch('editHost', hostKey) },
|
||||||
|
{ label: `Remove host…`, fn: () => removeHost(hostKey) },
|
||||||
],
|
],
|
||||||
}))}
|
}))}
|
||||||
bind:activePath={activeGridPath}
|
bind:activePath={activeGridPath}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<script>
|
<script>
|
||||||
import { startProgress } from '$lib/progress';
|
import { startProgress } from '$lib/progress';
|
||||||
import { connections } from '$lib/stores/connections';
|
import connections from '$lib/stores/connections';
|
||||||
import { Hosts, RenameCollection } from '$wails/go/app/App';
|
import { Hosts, RenameCollection } from '$wails/go/app/App';
|
||||||
import { EnterText } from '$wails/go/ui/UI';
|
import { EnterText } from '$wails/go/ui/UI';
|
||||||
import { EventsOn } from '$wails/runtime/runtime';
|
import { EventsOn } from '$wails/runtime/runtime';
|
||||||
@ -10,8 +10,9 @@
|
|||||||
import HostDetail from './hostdetail.svelte';
|
import HostDetail from './hostdetail.svelte';
|
||||||
import HostTree from './hosttree.svelte';
|
import HostTree from './hosttree.svelte';
|
||||||
import sharedState from '$lib/stores/sharedstate';
|
import sharedState from '$lib/stores/sharedstate';
|
||||||
|
import Icon from '$components/icon.svelte';
|
||||||
|
import hosts from '$lib/stores/hosts';
|
||||||
|
|
||||||
export let hosts = {};
|
|
||||||
export let activeHostKey = '';
|
export let activeHostKey = '';
|
||||||
export let activeDbKey = '';
|
export let activeDbKey = '';
|
||||||
export let activeCollKey = '';
|
export let activeCollKey = '';
|
||||||
@ -25,10 +26,6 @@
|
|||||||
$: sharedState.currentDb.set(activeDbKey);
|
$: sharedState.currentDb.set(activeDbKey);
|
||||||
$: sharedState.currentColl.set(activeCollKey);
|
$: sharedState.currentColl.set(activeCollKey);
|
||||||
|
|
||||||
async function getHosts() {
|
|
||||||
hosts = await Hosts();
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createHost() {
|
export function createHost() {
|
||||||
hostDetailKey = '';
|
hostDetailKey = '';
|
||||||
showHostDetail = true;
|
showHostDetail = true;
|
||||||
@ -89,12 +86,16 @@
|
|||||||
EventsOn('CreateHost', createHost);
|
EventsOn('CreateHost', createHost);
|
||||||
EventsOn('CreateDatabase', createDatabase);
|
EventsOn('CreateDatabase', createDatabase);
|
||||||
EventsOn('CreateCollection', createCollection);
|
EventsOn('CreateCollection', createCollection);
|
||||||
onMount(getHosts);
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="tree">
|
<div class="tree">
|
||||||
|
<div class="tree-buttons">
|
||||||
|
<button class="button-small" on:click={createHost}>
|
||||||
|
<Icon name="+" /> New host
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
<HostTree
|
<HostTree
|
||||||
{hosts}
|
|
||||||
bind:activeHostKey
|
bind:activeHostKey
|
||||||
bind:activeCollKey
|
bind:activeCollKey
|
||||||
bind:activeDbKey
|
bind:activeDbKey
|
||||||
@ -114,21 +115,22 @@
|
|||||||
hostKey={activeHostKey}
|
hostKey={activeHostKey}
|
||||||
dbKey={activeDbKey}
|
dbKey={activeDbKey}
|
||||||
collectionKey={activeCollKey}
|
collectionKey={activeCollKey}
|
||||||
{hosts}
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<HostDetail
|
<HostDetail
|
||||||
bind:show={showHostDetail}
|
bind:show={showHostDetail}
|
||||||
on:reload={getHosts}
|
on:reload={hosts.update}
|
||||||
hostKey={activeHostKey}
|
hostKey={activeHostKey}
|
||||||
{hosts}
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<DumpInfo bind:info={exportInfo} {hosts} />
|
<DumpInfo bind:info={exportInfo} />
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.tree {
|
.tree {
|
||||||
padding: 0.5rem;
|
padding: 0.5rem;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
}
|
}
|
||||||
|
.tree-buttons {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
6
frontend/wailsjs/go/app/App.d.ts
generated
vendored
6
frontend/wailsjs/go/app/App.d.ts
generated
vendored
@ -7,7 +7,7 @@ import {menu} from '../models';
|
|||||||
import {context} from '../models';
|
import {context} from '../models';
|
||||||
import {ui} from '../models';
|
import {ui} from '../models';
|
||||||
|
|
||||||
export function AddHost(arg1:string):Promise<void>;
|
export function AddHost(arg1:string):Promise<string>;
|
||||||
|
|
||||||
export function Aggregate(arg1:string,arg2:string,arg3:string,arg4:string,arg5:string):Promise<void>;
|
export function Aggregate(arg1:string,arg2:string,arg3:string,arg4:string,arg5:string):Promise<void>;
|
||||||
|
|
||||||
@ -43,7 +43,7 @@ export function PerformFindExport(arg1:string,arg2:string,arg3:string,arg4:strin
|
|||||||
|
|
||||||
export function PurgeLogDirectory():Promise<void>;
|
export function PurgeLogDirectory():Promise<void>;
|
||||||
|
|
||||||
export function RemoveHost(arg1:string):Promise<void>;
|
export function RemoveHost(arg1:string):Promise<boolean>;
|
||||||
|
|
||||||
export function RemoveItemById(arg1:string,arg2:string,arg3:string,arg4:string):Promise<boolean>;
|
export function RemoveItemById(arg1:string,arg2:string,arg3:string,arg4:string):Promise<boolean>;
|
||||||
|
|
||||||
@ -67,7 +67,7 @@ export function Startup(arg1:context.Context,arg2:ui.UI):Promise<void>;
|
|||||||
|
|
||||||
export function TruncateCollection(arg1:string,arg2:string,arg3:string):Promise<boolean>;
|
export function TruncateCollection(arg1:string,arg2:string,arg3:string):Promise<boolean>;
|
||||||
|
|
||||||
export function UpdateHost(arg1:string,arg2:string):Promise<void>;
|
export function UpdateHost(arg1:string,arg2:string):Promise<boolean>;
|
||||||
|
|
||||||
export function UpdateItems(arg1:string,arg2:string,arg3:string,arg4:string):Promise<number>;
|
export function UpdateItems(arg1:string,arg2:string,arg3:string,arg4:string):Promise<number>;
|
||||||
|
|
||||||
|
@ -45,6 +45,7 @@ func (a *App) Menu() *menu.Menu {
|
|||||||
fileMenu.AddText("Update", keys.Combo("u", keys.CmdOrCtrlKey, keys.OptionOrAltKey), menuCallbackEmit(a, "OpenCollectionTab", "update"))
|
fileMenu.AddText("Update", keys.Combo("u", keys.CmdOrCtrlKey, keys.OptionOrAltKey), menuCallbackEmit(a, "OpenCollectionTab", "update"))
|
||||||
fileMenu.AddText("Remove", keys.Combo("r", keys.CmdOrCtrlKey, keys.OptionOrAltKey), menuCallbackEmit(a, "OpenCollectionTab", "remove"))
|
fileMenu.AddText("Remove", keys.Combo("r", keys.CmdOrCtrlKey, keys.OptionOrAltKey), menuCallbackEmit(a, "OpenCollectionTab", "remove"))
|
||||||
fileMenu.AddText("Indexes", keys.Combo("x", keys.CmdOrCtrlKey, keys.OptionOrAltKey), menuCallbackEmit(a, "OpenCollectionTab", "indexes"))
|
fileMenu.AddText("Indexes", keys.Combo("x", keys.CmdOrCtrlKey, keys.OptionOrAltKey), menuCallbackEmit(a, "OpenCollectionTab", "indexes"))
|
||||||
|
fileMenu.AddText("Aggregate", keys.Combo("a", keys.CmdOrCtrlKey, keys.OptionOrAltKey), menuCallbackEmit(a, "OpenCollectionTab", "aggregate"))
|
||||||
|
|
||||||
if runtime.GOOS == "darwin" {
|
if runtime.GOOS == "darwin" {
|
||||||
appMenu.Append(menu.EditMenu())
|
appMenu.Append(menu.EditMenu())
|
||||||
|
@ -34,8 +34,7 @@ func (a *App) Hosts() (map[string]Host, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
// It's ok if the file cannot be opened, for example if it is not accessible.
|
// It's ok if the file cannot be opened, for example if it is not accessible.
|
||||||
// Therefore no error is returned.
|
// Therefore no error is returned.
|
||||||
runtime.LogInfo(a.ctx, "Could not open hosts.json")
|
runtime.LogInfof(a.ctx, "Could not open hosts.json (%s), trying to create it.", err.Error())
|
||||||
runtime.LogInfo(a.ctx, err.Error())
|
|
||||||
return make(map[string]Host, 0), nil
|
return make(map[string]Host, 0), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,84 +45,80 @@ func (a *App) Hosts() (map[string]Host, error) {
|
|||||||
err = json.Unmarshal(jsonData, &hosts)
|
err = json.Unmarshal(jsonData, &hosts)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
runtime.LogInfo(a.ctx, "host.json file contains malformatted JSON data")
|
runtime.LogInfof(a.ctx, "host.json file contains malformatted JSON data: %s", err.Error())
|
||||||
runtime.LogInfo(a.ctx, err.Error())
|
|
||||||
return nil, errors.New("host.json file contains malformatted JSON data")
|
return nil, errors.New("host.json file contains malformatted JSON data")
|
||||||
}
|
}
|
||||||
return hosts, nil
|
return hosts, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) AddHost(jsonData string) error {
|
func (a *App) AddHost(jsonData string) string {
|
||||||
hosts, err := a.Hosts()
|
hosts, err := a.Hosts()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
zenity.Error(err.Error(), zenity.Title("Error while retrieving hosts"), zenity.ErrorIcon)
|
zenity.Error(err.Error(), zenity.Title("Error while retrieving hosts"), zenity.ErrorIcon)
|
||||||
return errors.New("could not retrieve existing host list")
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
var newHost Host
|
var newHost Host
|
||||||
err = json.Unmarshal([]byte(jsonData), &newHost)
|
err = json.Unmarshal([]byte(jsonData), &newHost)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
runtime.LogError(a.ctx, "Add host: malformed form")
|
runtime.LogErrorf(a.ctx, "Add host: malformed form: %s", err.Error())
|
||||||
runtime.LogError(a.ctx, err.Error())
|
|
||||||
zenity.Error(err.Error(), zenity.Title("Could not parse JSON"), zenity.ErrorIcon)
|
zenity.Error(err.Error(), zenity.Title("Could not parse JSON"), zenity.ErrorIcon)
|
||||||
return errors.New("invalid JSON")
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
id, err := uuid.NewRandom()
|
id, err := uuid.NewRandom()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
runtime.LogError(a.ctx, "Add host: failed to generate a UUID")
|
runtime.LogErrorf(a.ctx, "Add host: failed to generate a UUID: %s", err.Error())
|
||||||
runtime.LogError(a.ctx, err.Error())
|
|
||||||
zenity.Error(err.Error(), zenity.Title("Error while generating UUID"), zenity.ErrorIcon)
|
zenity.Error(err.Error(), zenity.Title("Error while generating UUID"), zenity.ErrorIcon)
|
||||||
return errors.New("could not generate a UUID")
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
hosts[id.String()] = newHost
|
hosts[id.String()] = newHost
|
||||||
err = updateHostsFile(a, hosts)
|
err = updateHostsFile(a, hosts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
zenity.Error(err.Error(), zenity.Title("Error while updating host list"), zenity.ErrorIcon)
|
zenity.Error(err.Error(), zenity.Title("Error while updating host list"), zenity.ErrorIcon)
|
||||||
return errors.New("could not update host list")
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return id.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) UpdateHost(hostKey string, jsonData string) error {
|
func (a *App) UpdateHost(hostKey string, jsonData string) bool {
|
||||||
hosts, err := a.Hosts()
|
hosts, err := a.Hosts()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
zenity.Error(err.Error(), zenity.Title("Error while getting hosts"), zenity.ErrorIcon)
|
zenity.Error(err.Error(), zenity.Title("Error while getting hosts"), zenity.ErrorIcon)
|
||||||
return errors.New("could not retrieve existing host list")
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
var host Host
|
var host Host
|
||||||
err = json.Unmarshal([]byte(jsonData), &host)
|
err = json.Unmarshal([]byte(jsonData), &host)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
runtime.LogError(a.ctx, "Could not parse update host JSON")
|
runtime.LogErrorf(a.ctx, "Could not parse update host JSON: %s", err.Error())
|
||||||
runtime.LogError(a.ctx, err.Error())
|
|
||||||
zenity.Error(err.Error(), zenity.Title("Could not parse JSON"), zenity.ErrorIcon)
|
zenity.Error(err.Error(), zenity.Title("Could not parse JSON"), zenity.ErrorIcon)
|
||||||
return errors.New("invalid JSON")
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
hosts[hostKey] = host
|
hosts[hostKey] = host
|
||||||
err = updateHostsFile(a, hosts)
|
err = updateHostsFile(a, hosts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
zenity.Error(err.Error(), zenity.Title("Error while updating hosts"), zenity.ErrorIcon)
|
zenity.Error(err.Error(), zenity.Title("Error while updating hosts"), zenity.ErrorIcon)
|
||||||
return errors.New("could not update host list")
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) RemoveHost(key string) error {
|
func (a *App) RemoveHost(key string) bool {
|
||||||
hosts, err := a.Hosts()
|
hosts, err := a.Hosts()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
zenity.Error(err.Error(), zenity.Title("Error while retrieving hosts"), zenity.ErrorIcon)
|
zenity.Error(err.Error(), zenity.Title("Error while retrieving hosts"), zenity.ErrorIcon)
|
||||||
return errors.New("could not retrieve existing host list")
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
err = zenity.Question("Are you sure you want to remove "+hosts[key].Name+"?", zenity.Title("Confirm"), zenity.WarningIcon)
|
err = zenity.Question("Are you sure you want to remove "+hosts[key].Name+"?", zenity.Title("Confirm"), zenity.WarningIcon)
|
||||||
if err == zenity.ErrCanceled {
|
if err == zenity.ErrCanceled {
|
||||||
return errors.New("operation aborted")
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
delete(hosts, key)
|
delete(hosts, key)
|
||||||
@ -131,7 +126,8 @@ func (a *App) RemoveHost(key string) error {
|
|||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
zenity.Error(err.Error(), zenity.Title("Error while updating hosts"), zenity.ErrorIcon)
|
zenity.Error(err.Error(), zenity.Title("Error while updating hosts"), zenity.ErrorIcon)
|
||||||
return errors.New("could not update host list")
|
return false
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user