mirror of
https://github.com/garraflavatra/rolens.git
synced 2025-01-18 13:07:58 +00:00
Save queries
This commit is contained in:
parent
3291bc845f
commit
5f358885a3
@ -96,9 +96,12 @@
|
|||||||
contextMenu.show(evt, item.menu);
|
contextMenu.show(evt, item.menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeItem(index) {
|
function removeItem(index, itemKey) {
|
||||||
items.splice(index, 1);
|
if (Array.isArray(items)) {
|
||||||
items = items;
|
items.splice(index, 1);
|
||||||
|
items = items;
|
||||||
|
}
|
||||||
|
dispatch('removeItem', itemKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatValue(value) {
|
function formatValue(value) {
|
||||||
@ -167,7 +170,7 @@
|
|||||||
|
|
||||||
{#if canRemoveItems}
|
{#if canRemoveItems}
|
||||||
<td class="has-button">
|
<td class="has-button">
|
||||||
<button class="btn-sm" type="button" on:click={() => removeItem(index)}>
|
<button class="btn-sm" type="button" on:click|stopPropagation={() => removeItem(index, item[key])} on:dblclick|stopPropagation>
|
||||||
<Icon name="x" />
|
<Icon name="x" />
|
||||||
</button>
|
</button>
|
||||||
</td>
|
</td>
|
||||||
|
@ -62,6 +62,7 @@
|
|||||||
bind:inputsValid
|
bind:inputsValid
|
||||||
on:select
|
on:select
|
||||||
on:trigger
|
on:trigger
|
||||||
|
on:removeItem
|
||||||
/>
|
/>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
@ -87,6 +88,7 @@
|
|||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
|
table-layout: fixed;
|
||||||
}
|
}
|
||||||
|
|
||||||
table thead {
|
table thead {
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
<style>
|
<style>
|
||||||
.hint {
|
.hint {
|
||||||
padding: 1rem;
|
padding: 0.5rem;
|
||||||
margin-bottom: 0.5rem;
|
margin-bottom: 0.5rem;
|
||||||
display: grid;
|
display: grid;
|
||||||
gap: 1rem;
|
gap: 1rem;
|
||||||
@ -17,9 +17,14 @@
|
|||||||
background-color: rgba(255, 214, 64, 0.5);
|
background-color: rgba(255, 214, 64, 0.5);
|
||||||
border: 1px solid #c5a42e;
|
border: 1px solid #c5a42e;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
align-self: center;
|
align-self: center;
|
||||||
|
line-height: 1.3;
|
||||||
|
}
|
||||||
|
.content :global(strong) {
|
||||||
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
6
frontend/src/components/icon.svelte
vendored
6
frontend/src/components/icon.svelte
vendored
@ -81,5 +81,11 @@
|
|||||||
<circle cx="12" cy="12" r="10"/>
|
<circle cx="12" cy="12" r="10"/>
|
||||||
{:else if name === 'info'}
|
{:else if name === 'info'}
|
||||||
<circle cx="12" cy="12" r="10"/><path d="M12 16v-4M12 8h.01"/>
|
<circle cx="12" cy="12" r="10"/><path d="M12 16v-4M12 8h.01"/>
|
||||||
|
{:else if name === 'play'}
|
||||||
|
<path d="m5 3 14 9-14 9V3z"/>
|
||||||
|
{:else if name === 'upload'}
|
||||||
|
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4M17 8l-5-5-5 5M12 3v12"/>
|
||||||
|
{:else if name === 'save'}
|
||||||
|
<path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z"/><path d="M17 21v-8H7v8M7 3v5h8"/>
|
||||||
{/if}
|
{/if}
|
||||||
</svg>
|
</svg>
|
||||||
|
45
frontend/src/lib/stores/queries.js
Normal file
45
frontend/src/lib/stores/queries.js
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
import { get, writable } from 'svelte/store';
|
||||||
|
import { RemoveQuery, SavedQueries, SaveQuery, UpdateQueries } from '../../../wailsjs/go/app/App';
|
||||||
|
|
||||||
|
const { set, subscribe } = writable({});
|
||||||
|
let skipUpdate = true;
|
||||||
|
|
||||||
|
async function reload() {
|
||||||
|
const newViewStore = await SavedQueries();
|
||||||
|
set(newViewStore);
|
||||||
|
return newViewStore;
|
||||||
|
}
|
||||||
|
|
||||||
|
function forCollection(hostKey, dbKey, collKey) {
|
||||||
|
const allViews = get({ subscribe });
|
||||||
|
const entries = Object.entries(allViews).filter(v => (
|
||||||
|
v[1].hostKey === hostKey &&
|
||||||
|
v[1].dbKey === dbKey &&
|
||||||
|
v[1].collKey === collKey
|
||||||
|
));
|
||||||
|
|
||||||
|
return Object.fromEntries(entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function create(query) {
|
||||||
|
const newId = await SaveQuery(JSON.stringify(query));
|
||||||
|
await reload();
|
||||||
|
return newId;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function remove(id) {
|
||||||
|
await RemoveQuery(id);
|
||||||
|
await reload();
|
||||||
|
}
|
||||||
|
|
||||||
|
reload();
|
||||||
|
subscribe(newViewStore => {
|
||||||
|
if (skipUpdate) {
|
||||||
|
skipUpdate = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
UpdateQueries(JSON.stringify(newViewStore));
|
||||||
|
});
|
||||||
|
|
||||||
|
const queries = { reload, create, remove, set, subscribe, forCollection };
|
||||||
|
export default queries;
|
@ -0,0 +1,134 @@
|
|||||||
|
<script>
|
||||||
|
import Icon from '../../../../components/icon.svelte';
|
||||||
|
import { createEventDispatcher } from 'svelte';
|
||||||
|
import Modal from '../../../../components/modal.svelte';
|
||||||
|
import { input } from '../../../../lib/actions';
|
||||||
|
import queries from '../../../../lib/stores/queries';
|
||||||
|
import Grid from '../../../../components/grid.svelte';
|
||||||
|
import Hint from '../../../../components/hint.svelte';
|
||||||
|
|
||||||
|
export let queryToSave = undefined;
|
||||||
|
export let collection = {};
|
||||||
|
export let show = false;
|
||||||
|
|
||||||
|
const dispatch = createEventDispatcher();
|
||||||
|
let gridSelectedPath = [];
|
||||||
|
let selectedKey = '';
|
||||||
|
|
||||||
|
function submit() {
|
||||||
|
if (queryToSave) {
|
||||||
|
queryToSave.hostKey = collection.hostKey;
|
||||||
|
queryToSave.dbKey = collection.dbKey;
|
||||||
|
queryToSave.collKey = collection.key;
|
||||||
|
|
||||||
|
const newId = queries.create(queryToSave);
|
||||||
|
|
||||||
|
if (newId) {
|
||||||
|
dispatch('created', newId);
|
||||||
|
queryToSave = undefined;
|
||||||
|
selectedKey = newId;
|
||||||
|
select();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
select();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function select() {
|
||||||
|
dispatch('select', selectedKey);
|
||||||
|
show = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridSelect(event) {
|
||||||
|
if (event?.detail?.level === 0) {
|
||||||
|
selectedKey = event.detail.itemKey;
|
||||||
|
|
||||||
|
if (queryToSave) {
|
||||||
|
queryToSave.name = event.detail.itemKey;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridTrigger(event) {
|
||||||
|
gridSelect(event);
|
||||||
|
select();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function gridRemove(event) {
|
||||||
|
await queries.remove(event.detail);
|
||||||
|
}
|
||||||
|
|
||||||
|
$: if (queryToSave && !queryToSave.name) {
|
||||||
|
queryToSave.name = 'New query';
|
||||||
|
}
|
||||||
|
$: if (queryToSave?.name) {
|
||||||
|
gridSelectedPath = [ queryToSave.name ];
|
||||||
|
}
|
||||||
|
$: if (selectedKey) {
|
||||||
|
gridSelectedPath = [ selectedKey ];
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<Modal bind:show title={queryToSave ? 'Save query' : 'Load query'} width="500px">
|
||||||
|
<form on:submit|preventDefault={submit}>
|
||||||
|
{#if queryToSave}
|
||||||
|
<label class="field queryname">
|
||||||
|
<span class="label">Query name</span>
|
||||||
|
<input type="text" bind:value={queryToSave.name} use:input={{ autofocus: true }} />
|
||||||
|
</label>
|
||||||
|
<label class="field">
|
||||||
|
<textarea bind:value={queryToSave.remarks} placeholder="Remarks…" use:input></textarea>
|
||||||
|
</label>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<div class="querylist">
|
||||||
|
<Grid
|
||||||
|
columns={[ { key: 'name', title: 'Query name' } ]}
|
||||||
|
items={$queries}
|
||||||
|
showHeaders={true}
|
||||||
|
canRemoveItems={true}
|
||||||
|
bind:activePath={gridSelectedPath}
|
||||||
|
on:select={gridSelect}
|
||||||
|
on:trigger={gridTrigger}
|
||||||
|
on:removeItem={gridRemove}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{#if queryToSave}
|
||||||
|
<button class="btn" type="submit">
|
||||||
|
<Icon name="save" /> Save query
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{#if Object.keys($queries).includes(queryToSave.name)}
|
||||||
|
<Hint>
|
||||||
|
You are about to <strong>overwrite</strong> a saved query. Rename it
|
||||||
|
if you do not want to overwrite.
|
||||||
|
</Hint>
|
||||||
|
{/if}
|
||||||
|
{:else}
|
||||||
|
<button class="btn" type="submit" disabled={!selectedKey}>
|
||||||
|
<Icon name="upload" /> Load query
|
||||||
|
</button>
|
||||||
|
{/if}
|
||||||
|
</form>
|
||||||
|
</Modal>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.field, .querylist {
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
textarea {
|
||||||
|
min-height: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.querylist {
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
min-height: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn + :global(.hint) {
|
||||||
|
margin-top: 0.5rem;
|
||||||
|
}
|
||||||
|
</style>
|
@ -9,6 +9,8 @@
|
|||||||
import Icon from '../../../components/icon.svelte';
|
import Icon from '../../../components/icon.svelte';
|
||||||
import ObjectGrid from '../../../components/objectgrid.svelte';
|
import ObjectGrid from '../../../components/objectgrid.svelte';
|
||||||
import views from '../../../lib/stores/views';
|
import views from '../../../lib/stores/views';
|
||||||
|
import QueryChooser from './components/querychooser.svelte';
|
||||||
|
import queries from '../../../lib/stores/queries';
|
||||||
// import ObjectViewer from '../../../components/objectviewer.svelte';
|
// import ObjectViewer from '../../../components/objectviewer.svelte';
|
||||||
|
|
||||||
export let collection;
|
export let collection;
|
||||||
@ -28,6 +30,9 @@
|
|||||||
let queryField;
|
let queryField;
|
||||||
let activePath = [];
|
let activePath = [];
|
||||||
let objectViewerData;
|
let objectViewerData;
|
||||||
|
let queryToSave;
|
||||||
|
let showQueryChooser = false;
|
||||||
|
|
||||||
$: viewsForCollection = views.forCollection(collection.hostKey, collection.dbKey, collection.key);
|
$: viewsForCollection = views.forCollection(collection.hostKey, collection.dbKey, collection.key);
|
||||||
$: code = `db.${collection.key}.find(${form.query || '{}'}${form.fields && form.fields !== '{}' ? `, ${form.fields}` : ''}).sort(${form.sort})${form.skip ? `.skip(${form.skip})` : ''}${form.limit ? `.limit(${form.limit})` : ''};`;
|
$: code = `db.${collection.key}.find(${form.query || '{}'}${form.fields && form.fields !== '{}' ? `, ${form.fields}` : ''}).sort(${form.sort})${form.skip ? `.skip(${form.skip})` : ''}${form.limit ? `.limit(${form.limit})` : ''};`;
|
||||||
$: lastPage = (submittedForm.limit && result?.results?.length) ? Math.max(0, Math.ceil((result.total - submittedForm.limit) / submittedForm.limit)) : 0;
|
$: lastPage = (submittedForm.limit && result?.results?.length) ? Math.max(0, Math.ceil((result.total - submittedForm.limit) / submittedForm.limit)) : 0;
|
||||||
@ -50,6 +55,23 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function loadQuery() {
|
||||||
|
queryToSave = undefined;
|
||||||
|
showQueryChooser = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveQuery() {
|
||||||
|
queryToSave = form;
|
||||||
|
showQueryChooser = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function queryChosen(event) {
|
||||||
|
if ($queries[event?.detail]) {
|
||||||
|
form = { ...$queries[event?.detail] };
|
||||||
|
submitQuery();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function prev() {
|
function prev() {
|
||||||
form.skip -= form.limit;
|
form.skip -= form.limit;
|
||||||
if (form.skip < 0) {
|
if (form.skip < 0) {
|
||||||
@ -131,13 +153,22 @@
|
|||||||
<span class="label">Limit</span>
|
<span class="label">Limit</span>
|
||||||
<input type="number" min="0" bind:value={form.limit} use:input placeholder={defaults.limit} list="limits" />
|
<input type="number" min="0" bind:value={form.limit} use:input placeholder={defaults.limit} list="limits" />
|
||||||
</label>
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
<button type="submit" class="btn">Run</button>
|
<div class="form-row three">
|
||||||
|
<CodeExample {code} />
|
||||||
|
<button class="btn" type="button" on:click={loadQuery} title="Load query…">
|
||||||
|
<Icon name="upload" />
|
||||||
|
</button>
|
||||||
|
<button class="btn" type="button" on:click={saveQuery} title="Save query as…">
|
||||||
|
<Icon name="save" />
|
||||||
|
</button>
|
||||||
|
<button type="submit" class="btn" title="Run query">
|
||||||
|
<Icon name="play" /> Run
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<CodeExample {code} />
|
|
||||||
|
|
||||||
<div class="result">
|
<div class="result">
|
||||||
<div class="grid">
|
<div class="grid">
|
||||||
{#key result}
|
{#key result}
|
||||||
@ -198,6 +229,12 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<QueryChooser
|
||||||
|
bind:queryToSave
|
||||||
|
bind:show={showQueryChooser}
|
||||||
|
on:select={queryChosen}
|
||||||
|
/>
|
||||||
|
|
||||||
<!-- <ObjectViewer bind:data={objectViewerData} /> -->
|
<!-- <ObjectViewer bind:data={objectViewerData} /> -->
|
||||||
|
|
||||||
<datalist id="limits">
|
<datalist id="limits">
|
||||||
@ -218,19 +255,23 @@
|
|||||||
.find {
|
.find {
|
||||||
display: grid;
|
display: grid;
|
||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
grid-template: auto auto 1fr / 1fr;
|
grid-template: auto 1fr / 1fr;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-row {
|
.form-row {
|
||||||
display: grid;
|
display: grid;
|
||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
}
|
}
|
||||||
.form-row.one {
|
.form-row.one {
|
||||||
grid-template: 1fr / 3fr 2fr;
|
grid-template: 1fr / 3fr 2fr;
|
||||||
margin-bottom: 0.5rem;
|
|
||||||
}
|
}
|
||||||
.form-row.two {
|
.form-row.two {
|
||||||
grid-template: 1fr / 5fr 1fr 1fr 1fr;
|
grid-template: 1fr / 5fr 1fr 1fr;
|
||||||
|
}
|
||||||
|
.form-row.three {
|
||||||
|
margin-bottom: 0rem;
|
||||||
|
grid-template: 1fr / 1fr repeat(3, auto);
|
||||||
}
|
}
|
||||||
|
|
||||||
.result {
|
.result {
|
||||||
|
10
frontend/wailsjs/go/app/App.d.ts
vendored
10
frontend/wailsjs/go/app/App.d.ts
vendored
@ -17,7 +17,7 @@ export function DropIndex(arg1:string,arg2:string,arg3:string,arg4:string):Promi
|
|||||||
|
|
||||||
export function Environment():Promise<app.EnvironmentInfo>;
|
export function Environment():Promise<app.EnvironmentInfo>;
|
||||||
|
|
||||||
export function FindItems(arg1:string,arg2:string,arg3:string,arg4:string):Promise<app.findResult>;
|
export function FindItems(arg1:string,arg2:string,arg3:string,arg4:string):Promise<app.QueryResult>;
|
||||||
|
|
||||||
export function GetIndexes(arg1:string,arg2:string,arg3:string):Promise<Array<primitive.M>>;
|
export function GetIndexes(arg1:string,arg2:string,arg3:string):Promise<Array<primitive.M>>;
|
||||||
|
|
||||||
@ -43,10 +43,16 @@ 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<number>;
|
export function RemoveItems(arg1:string,arg2:string,arg3:string,arg4:string,arg5:boolean):Promise<number>;
|
||||||
|
|
||||||
|
export function RemoveQuery(arg1:string):Promise<void>;
|
||||||
|
|
||||||
export function RemoveView(arg1:string):Promise<void>;
|
export function RemoveView(arg1:string):Promise<void>;
|
||||||
|
|
||||||
export function RenameCollection(arg1:string,arg2:string,arg3:string,arg4:string):Promise<boolean>;
|
export function RenameCollection(arg1:string,arg2:string,arg3:string,arg4:string):Promise<boolean>;
|
||||||
|
|
||||||
|
export function SaveQuery(arg1:string):Promise<string>;
|
||||||
|
|
||||||
|
export function SavedQueries():Promise<map[string]app.SavedQuery>;
|
||||||
|
|
||||||
export function Settings():Promise<app.Settings>;
|
export function Settings():Promise<app.Settings>;
|
||||||
|
|
||||||
export function TruncateCollection(arg1:string,arg2:string,arg3:string):Promise<boolean>;
|
export function TruncateCollection(arg1:string,arg2:string,arg3:string):Promise<boolean>;
|
||||||
@ -55,6 +61,8 @@ export function UpdateHost(arg1:string,arg2:string):Promise<void>;
|
|||||||
|
|
||||||
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>;
|
||||||
|
|
||||||
|
export function UpdateQueries(arg1:string):Promise<boolean>;
|
||||||
|
|
||||||
export function UpdateSettings(arg1:string):Promise<app.Settings>;
|
export function UpdateSettings(arg1:string):Promise<app.Settings>;
|
||||||
|
|
||||||
export function UpdateViewStore(arg1:string):Promise<void>;
|
export function UpdateViewStore(arg1:string):Promise<void>;
|
||||||
|
@ -78,6 +78,10 @@ export function RemoveItems(arg1, arg2, arg3, arg4, arg5) {
|
|||||||
return window['go']['app']['App']['RemoveItems'](arg1, arg2, arg3, arg4, arg5);
|
return window['go']['app']['App']['RemoveItems'](arg1, arg2, arg3, arg4, arg5);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function RemoveQuery(arg1) {
|
||||||
|
return window['go']['app']['App']['RemoveQuery'](arg1);
|
||||||
|
}
|
||||||
|
|
||||||
export function RemoveView(arg1) {
|
export function RemoveView(arg1) {
|
||||||
return window['go']['app']['App']['RemoveView'](arg1);
|
return window['go']['app']['App']['RemoveView'](arg1);
|
||||||
}
|
}
|
||||||
@ -86,6 +90,14 @@ export function RenameCollection(arg1, arg2, arg3, arg4) {
|
|||||||
return window['go']['app']['App']['RenameCollection'](arg1, arg2, arg3, arg4);
|
return window['go']['app']['App']['RenameCollection'](arg1, arg2, arg3, arg4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function SaveQuery(arg1) {
|
||||||
|
return window['go']['app']['App']['SaveQuery'](arg1);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function SavedQueries() {
|
||||||
|
return window['go']['app']['App']['SavedQueries']();
|
||||||
|
}
|
||||||
|
|
||||||
export function Settings() {
|
export function Settings() {
|
||||||
return window['go']['app']['App']['Settings']();
|
return window['go']['app']['App']['Settings']();
|
||||||
}
|
}
|
||||||
@ -102,6 +114,10 @@ export function UpdateItems(arg1, arg2, arg3, arg4) {
|
|||||||
return window['go']['app']['App']['UpdateItems'](arg1, arg2, arg3, arg4);
|
return window['go']['app']['App']['UpdateItems'](arg1, arg2, arg3, arg4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function UpdateQueries(arg1) {
|
||||||
|
return window['go']['app']['App']['UpdateQueries'](arg1);
|
||||||
|
}
|
||||||
|
|
||||||
export function UpdateSettings(arg1) {
|
export function UpdateSettings(arg1) {
|
||||||
return window['go']['app']['App']['UpdateSettings'](arg1);
|
return window['go']['app']['App']['UpdateSettings'](arg1);
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,20 @@ export namespace app {
|
|||||||
this.logDirectory = source["logDirectory"];
|
this.logDirectory = source["logDirectory"];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
export class QueryResult {
|
||||||
|
total: number;
|
||||||
|
results: string[];
|
||||||
|
|
||||||
|
static createFrom(source: any = {}) {
|
||||||
|
return new QueryResult(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(source: any = {}) {
|
||||||
|
if ('string' === typeof source) source = JSON.parse(source);
|
||||||
|
this.total = source["total"];
|
||||||
|
this.results = source["results"];
|
||||||
|
}
|
||||||
|
}
|
||||||
export class Settings {
|
export class Settings {
|
||||||
defaultLimit: number;
|
defaultLimit: number;
|
||||||
defaultSort: string;
|
defaultSort: string;
|
||||||
@ -44,20 +58,6 @@ export namespace app {
|
|||||||
this.defaultExportDirectory = source["defaultExportDirectory"];
|
this.defaultExportDirectory = source["defaultExportDirectory"];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export class findResult {
|
|
||||||
total: number;
|
|
||||||
results: string[];
|
|
||||||
|
|
||||||
static createFrom(source: any = {}) {
|
|
||||||
return new findResult(source);
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(source: any = {}) {
|
|
||||||
if ('string' === typeof source) source = JSON.parse(source);
|
|
||||||
this.total = source["total"];
|
|
||||||
this.results = source["results"];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,25 +4,26 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
"github.com/wailsapp/wails/v2/pkg/runtime"
|
"github.com/wailsapp/wails/v2/pkg/runtime"
|
||||||
|
|
||||||
"go.mongodb.org/mongo-driver/bson"
|
"go.mongodb.org/mongo-driver/bson"
|
||||||
mongoOptions "go.mongodb.org/mongo-driver/mongo/options"
|
mongoOptions "go.mongodb.org/mongo-driver/mongo/options"
|
||||||
)
|
)
|
||||||
|
|
||||||
type findResult struct {
|
type Query struct {
|
||||||
|
Fields string `json:"fields"`
|
||||||
|
Limit int64 `json:"limit"`
|
||||||
|
Query string `json:"query"`
|
||||||
|
Skip int64 `json:"skip"`
|
||||||
|
Sort string `json:"sort"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type QueryResult struct {
|
||||||
Total int64 `json:"total"`
|
Total int64 `json:"total"`
|
||||||
Results []string `json:"results"`
|
Results []string `json:"results"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) FindItems(hostKey, dbKey, collKey string, formJson string) findResult {
|
func (a *App) FindItems(hostKey, dbKey, collKey string, formJson string) QueryResult {
|
||||||
var out findResult
|
var out QueryResult
|
||||||
var form struct {
|
var form Query
|
||||||
Fields string `json:"fields"`
|
|
||||||
Limit int64 `json:"limit"`
|
|
||||||
Query string `json:"query"`
|
|
||||||
Skip int64 `json:"skip"`
|
|
||||||
Sort string `json:"sort"`
|
|
||||||
}
|
|
||||||
|
|
||||||
err := json.Unmarshal([]byte(formJson), &form)
|
err := json.Unmarshal([]byte(formJson), &form)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
121
internal/app/collection_find_queries.go
Normal file
121
internal/app/collection_find_queries.go
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
package app
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
|
|
||||||
|
"github.com/wailsapp/wails/v2/pkg/runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SavedQuery struct {
|
||||||
|
Query
|
||||||
|
Name string `json:"name"`
|
||||||
|
Remarks string `json:"remarks"`
|
||||||
|
HostKey string `json:"hostKey"`
|
||||||
|
DbKey string `json:"dbKey"`
|
||||||
|
CollKey string `json:"collKey"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateQueryFile(a *App, newData map[string]SavedQuery) error {
|
||||||
|
filePath := path.Join(a.Env.DataDirectory, "queries.json")
|
||||||
|
jsonData, err := json.MarshalIndent(newData, "", "\t")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = ioutil.WriteFile(filePath, jsonData, os.ModePerm)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *App) SavedQueries() map[string]SavedQuery {
|
||||||
|
filePath := path.Join(a.Env.DataDirectory, "queries.json")
|
||||||
|
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.
|
||||||
|
runtime.LogInfo(a.ctx, "Could not open queries.json")
|
||||||
|
runtime.LogInfo(a.ctx, err.Error())
|
||||||
|
return make(map[string]SavedQuery, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(jsonData) == 0 {
|
||||||
|
return make(map[string]SavedQuery, 0)
|
||||||
|
} else {
|
||||||
|
var queries map[string]SavedQuery
|
||||||
|
err = json.Unmarshal(jsonData, &queries)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
runtime.LogInfo(a.ctx, "queries.json file contains malformatted JSON data")
|
||||||
|
runtime.LogInfo(a.ctx, err.Error())
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return queries
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *App) SaveQuery(jsonData string) string {
|
||||||
|
var query SavedQuery
|
||||||
|
err := json.Unmarshal([]byte(jsonData), &query)
|
||||||
|
if err != nil {
|
||||||
|
runtime.LogError(a.ctx, "Add query: malformed form")
|
||||||
|
runtime.LogError(a.ctx, err.Error())
|
||||||
|
runtime.MessageDialog(a.ctx, runtime.MessageDialogOptions{
|
||||||
|
Type: runtime.InfoDialog,
|
||||||
|
Title: "Malformed JSON",
|
||||||
|
})
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
queries := a.SavedQueries()
|
||||||
|
queries[query.Name] = query
|
||||||
|
err = updateQueryFile(a, queries)
|
||||||
|
if err != nil {
|
||||||
|
runtime.MessageDialog(a.ctx, runtime.MessageDialogOptions{
|
||||||
|
Type: runtime.InfoDialog,
|
||||||
|
Title: "Could not update query list",
|
||||||
|
})
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return query.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *App) RemoveQuery(queryName string) {
|
||||||
|
queries := a.SavedQueries()
|
||||||
|
delete(queries, queryName)
|
||||||
|
if err := updateQueryFile(a, queries); err != nil {
|
||||||
|
runtime.MessageDialog(a.ctx, runtime.MessageDialogOptions{
|
||||||
|
Type: runtime.InfoDialog,
|
||||||
|
Title: "Could not update query list",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *App) UpdateQueries(jsonData string) bool {
|
||||||
|
var queries map[string]SavedQuery
|
||||||
|
err := json.Unmarshal([]byte(jsonData), &queries)
|
||||||
|
if err != nil {
|
||||||
|
runtime.LogError(a.ctx, "Update queries: malformed form")
|
||||||
|
runtime.LogError(a.ctx, err.Error())
|
||||||
|
runtime.MessageDialog(a.ctx, runtime.MessageDialogOptions{
|
||||||
|
Type: runtime.InfoDialog,
|
||||||
|
Title: "Malformed JSON",
|
||||||
|
})
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
err = updateQueryFile(a, queries)
|
||||||
|
if err != nil {
|
||||||
|
runtime.MessageDialog(a.ctx, runtime.MessageDialogOptions{
|
||||||
|
Type: runtime.InfoDialog,
|
||||||
|
Title: "Could not save queries",
|
||||||
|
})
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user