mirror of
https://github.com/garraflavatra/rolens.git
synced 2024-11-22 10:25:48 +01:00
Find view: make changes to single documents from within the object editor
This commit is contained in:
parent
33d41064cc
commit
7eb7f97d21
@ -2,6 +2,7 @@
|
||||
|
||||
* Added some external links related to Rolens to the application menu.
|
||||
* Fix an infinite loop bug when a document in the find view has been double clicked.
|
||||
* Find view: added the ability to make changes to single documents from within the object editor.
|
||||
|
||||
## [v0.1.0](https://github.com/garraflavatra/rolens/releases/tag/v0.1.0)
|
||||
|
||||
|
@ -57,7 +57,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
function select(itemKey) {
|
||||
function select(itemKey, index) {
|
||||
if (!canSelect) {
|
||||
return false;
|
||||
}
|
||||
@ -72,7 +72,7 @@
|
||||
else {
|
||||
activePath = [ ...path, itemKey ];
|
||||
}
|
||||
dispatch('select', { level, itemKey });
|
||||
dispatch('select', { level, itemKey, index });
|
||||
}
|
||||
}
|
||||
|
||||
@ -88,9 +88,9 @@
|
||||
}
|
||||
}
|
||||
|
||||
function doubleClick(itemKey) {
|
||||
function doubleClick(itemKey, index) {
|
||||
// toggleChildren(itemKey, false);
|
||||
dispatch('trigger', { level, itemKey });
|
||||
dispatch('trigger', { level, itemKey, index });
|
||||
childrenOpen[itemKey] = true;
|
||||
}
|
||||
|
||||
@ -132,8 +132,8 @@
|
||||
|
||||
{#each _items as item, index}
|
||||
<tr
|
||||
on:click={() => select(item[key])}
|
||||
on:dblclick={() => doubleClick(item[key])}
|
||||
on:click={() => select(item[key], index)}
|
||||
on:dblclick={() => doubleClick(item[key], index)}
|
||||
on:contextmenu|preventDefault={evt => showContextMenu(evt, item)}
|
||||
class:selectable={canSelect}
|
||||
class:selected={canSelect && !activePath[level + 1] && activePath.every(k => path.includes(k) || k === item[key]) && (activePath[level] === item[key])}
|
||||
|
@ -25,6 +25,7 @@
|
||||
return;
|
||||
}
|
||||
text = e.state.doc.toString();
|
||||
dispatch('updated', { text });
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
@ -1,28 +1,20 @@
|
||||
<script>
|
||||
import { jsonLooseParse } from '$lib/strings';
|
||||
import { jsonLooseParse, looseJsonIsValid } from '$lib/strings';
|
||||
import { createEventDispatcher, onDestroy } from 'svelte';
|
||||
import Icon from './icon.svelte';
|
||||
import Modal from './modal.svelte';
|
||||
import ObjectEditor from './objecteditor.svelte';
|
||||
import { EJSON } from 'bson';
|
||||
|
||||
export let data;
|
||||
export let saveable = false;
|
||||
export let successMessage = '';
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
let copySucceeded = false;
|
||||
let timeout;
|
||||
let text = JSON.stringify(data, undefined, '\t');
|
||||
let newData;
|
||||
let invalid = false;
|
||||
|
||||
$: {
|
||||
try {
|
||||
newData = jsonLooseParse(text);
|
||||
}
|
||||
catch {
|
||||
invalid = true;
|
||||
}
|
||||
}
|
||||
let text = EJSON.stringify(data, undefined, '\t');
|
||||
$: invalid = !looseJsonIsValid(text);
|
||||
|
||||
async function copy() {
|
||||
await navigator.clipboard.writeText(text);
|
||||
@ -36,7 +28,7 @@
|
||||
}
|
||||
|
||||
function save() {
|
||||
dispatch('save', text);
|
||||
dispatch('save', { text, originalData: data });
|
||||
}
|
||||
|
||||
onDestroy(() => clearTimeout(timeout));
|
||||
@ -45,7 +37,7 @@
|
||||
{#if data}
|
||||
<Modal bind:show={data} contentPadding={false}>
|
||||
<div class="objectviewer">
|
||||
<ObjectEditor {text} />
|
||||
<ObjectEditor bind:text on:updated={() => successMessage = ''} />
|
||||
</div>
|
||||
|
||||
<svelte:fragment slot="footer">
|
||||
@ -62,6 +54,10 @@
|
||||
<button class="btn secondary" on:click={copy}>
|
||||
<Icon name={copySucceeded ? 'check' : 'clipboard'} /> Copy
|
||||
</button>
|
||||
|
||||
{#if successMessage}
|
||||
<span class="flash-green">{successMessage}</span>
|
||||
{/if}
|
||||
</svelte:fragment>
|
||||
</Modal>
|
||||
{/if}
|
||||
@ -74,4 +70,8 @@
|
||||
align-items: stretch;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.flash-green {
|
||||
margin-left: 0.5rem;
|
||||
}
|
||||
</style>
|
||||
|
@ -9,7 +9,7 @@
|
||||
import queries from '$lib/stores/queries';
|
||||
import applicationSettings from '$lib/stores/settings';
|
||||
import views from '$lib/stores/views';
|
||||
import { FindItems, RemoveItemById } from '$wails/go/app/App';
|
||||
import { FindItems, RemoveItemById, UpdateFoundDocument } from '$wails/go/app/App';
|
||||
import { EJSON } from 'bson';
|
||||
import { createEventDispatcher, onMount } from 'svelte';
|
||||
import ExportInfo from './components/export.svelte';
|
||||
@ -36,6 +36,7 @@
|
||||
let showQueryChooser = false;
|
||||
let exportInfo;
|
||||
let querying = false;
|
||||
let objectViewerSuccessMessage = '';
|
||||
|
||||
$: 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})` : ''};`;
|
||||
@ -124,8 +125,8 @@
|
||||
queryField?.select();
|
||||
}
|
||||
|
||||
function openJson(itemId) {
|
||||
const item = result?.results?.find(i => i._id == itemId);
|
||||
function openJson(index) {
|
||||
const item = result?.results?.[index];
|
||||
objectViewerData = item;
|
||||
}
|
||||
|
||||
@ -134,6 +135,24 @@
|
||||
submitQuery();
|
||||
}
|
||||
|
||||
async function saveDocument(event) {
|
||||
const progress = startProgress('Performing update…');
|
||||
const success = await UpdateFoundDocument(
|
||||
collection.hostKey,
|
||||
collection.dbKey,
|
||||
collection.key,
|
||||
EJSON.stringify({ _id: event.detail.originalData._id }),
|
||||
event.detail.text
|
||||
);
|
||||
|
||||
if (success) {
|
||||
objectViewerSuccessMessage = 'Document has been saved!';
|
||||
submitQuery();
|
||||
}
|
||||
|
||||
progress.end();
|
||||
}
|
||||
|
||||
$: collection && refresh();
|
||||
onMount(refresh);
|
||||
</script>
|
||||
@ -195,7 +214,7 @@
|
||||
data={result.results}
|
||||
hideObjectIndicators={$views[collection.viewKey]?.hideObjectIndicators}
|
||||
bind:activePath
|
||||
on:trigger={e => openJson(e.detail?.itemKey)}
|
||||
on:trigger={e => openJson(e.detail?.index)}
|
||||
/>
|
||||
{:else}
|
||||
<Grid
|
||||
@ -204,7 +223,7 @@
|
||||
showHeaders={true}
|
||||
items={result.results ? result.results.map(r => EJSON.deserialize(r)) : []}
|
||||
bind:activePath
|
||||
on:trigger={e => openJson(e.detail?.itemKey)}
|
||||
on:trigger={e => openJson(e.detail?.index)}
|
||||
/>
|
||||
{/if}
|
||||
{/key}
|
||||
@ -258,7 +277,7 @@
|
||||
|
||||
{#if objectViewerData}
|
||||
<!-- @todo Implement save -->
|
||||
<ObjectViewer bind:data={objectViewerData} saveable />
|
||||
<ObjectViewer bind:data={objectViewerData} saveable on:save={saveDocument} bind:successMessage={objectViewerSuccessMessage} />
|
||||
{/if}
|
||||
|
||||
<datalist id="limits">
|
||||
|
2
frontend/wailsjs/go/app/App.d.ts
generated
vendored
2
frontend/wailsjs/go/app/App.d.ts
generated
vendored
@ -67,6 +67,8 @@ export function Startup(arg1:context.Context,arg2:ui.UI):Promise<void>;
|
||||
|
||||
export function TruncateCollection(arg1:string,arg2:string,arg3:string):Promise<boolean>;
|
||||
|
||||
export function UpdateFoundDocument(arg1:string,arg2:string,arg3:string,arg4:string,arg5:string):Promise<boolean>;
|
||||
|
||||
export function UpdateHost(arg1:string,arg2:string):Promise<boolean>;
|
||||
|
||||
export function UpdateItems(arg1:string,arg2:string,arg3:string,arg4:string):Promise<number>;
|
||||
|
4
frontend/wailsjs/go/app/App.js
generated
4
frontend/wailsjs/go/app/App.js
generated
@ -122,6 +122,10 @@ export function TruncateCollection(arg1, arg2, arg3) {
|
||||
return window['go']['app']['App']['TruncateCollection'](arg1, arg2, arg3);
|
||||
}
|
||||
|
||||
export function UpdateFoundDocument(arg1, arg2, arg3, arg4, arg5) {
|
||||
return window['go']['app']['App']['UpdateFoundDocument'](arg1, arg2, arg3, arg4, arg5);
|
||||
}
|
||||
|
||||
export function UpdateHost(arg1, arg2) {
|
||||
return window['go']['app']['App']['UpdateHost'](arg1, arg2);
|
||||
}
|
||||
|
@ -46,24 +46,21 @@ func (a *App) FindItems(hostKey, dbKey, collKey, formJson string) QueryResult {
|
||||
|
||||
err = bson.UnmarshalExtJSON([]byte(form.Query), true, &query)
|
||||
if err != nil {
|
||||
runtime.LogInfo(a.ctx, "Invalid find query:")
|
||||
runtime.LogInfo(a.ctx, err.Error())
|
||||
runtime.LogInfof(a.ctx, "Invalid find query: %s", err.Error())
|
||||
zenity.Error(err.Error(), zenity.Title("Invalid query"), zenity.ErrorIcon)
|
||||
return out
|
||||
}
|
||||
|
||||
err = json.Unmarshal([]byte(form.Fields), &projection)
|
||||
if err != nil {
|
||||
runtime.LogInfo(a.ctx, "Invalid find projection:")
|
||||
runtime.LogInfo(a.ctx, err.Error())
|
||||
runtime.LogInfof(a.ctx, "Invalid find projection: %s", err.Error())
|
||||
zenity.Error(err.Error(), zenity.Title("Invalid projection"), zenity.ErrorIcon)
|
||||
return out
|
||||
}
|
||||
|
||||
err = json.Unmarshal([]byte(form.Sort), &sort)
|
||||
if err != nil {
|
||||
runtime.LogInfo(a.ctx, "Invalid find sort:")
|
||||
runtime.LogInfo(a.ctx, err.Error())
|
||||
runtime.LogInfof(a.ctx, "Invalid find sort: %s", err.Error())
|
||||
zenity.Error(err.Error(), zenity.Title("Invalid sort"), zenity.ErrorIcon)
|
||||
return out
|
||||
}
|
||||
@ -77,16 +74,14 @@ func (a *App) FindItems(hostKey, dbKey, collKey, formJson string) QueryResult {
|
||||
|
||||
total, err := client.Database(dbKey).Collection(collKey).CountDocuments(ctx, query, nil)
|
||||
if err != nil {
|
||||
runtime.LogWarning(a.ctx, "Encountered an error while counting documents:")
|
||||
runtime.LogWarning(a.ctx, err.Error())
|
||||
runtime.LogWarningf(a.ctx, "Encountered an error while counting documents: %s", err.Error())
|
||||
zenity.Error(err.Error(), zenity.Title("Error while counting docs"), zenity.ErrorIcon)
|
||||
return out
|
||||
}
|
||||
|
||||
cur, err := client.Database(dbKey).Collection(collKey).Find(ctx, query, &opt)
|
||||
if err != nil {
|
||||
runtime.LogWarning(a.ctx, "Encountered an error while performing query:")
|
||||
runtime.LogWarning(a.ctx, err.Error())
|
||||
runtime.LogWarningf(a.ctx, "Encountered an error while performing query: %s", err.Error())
|
||||
zenity.Error(err.Error(), zenity.Title("Error while querying"), zenity.ErrorIcon)
|
||||
return out
|
||||
}
|
||||
@ -96,14 +91,14 @@ func (a *App) FindItems(hostKey, dbKey, collKey, formJson string) QueryResult {
|
||||
err = cur.All(ctx, &results)
|
||||
|
||||
if err != nil {
|
||||
runtime.LogWarning(a.ctx, "Encountered an error while performing query:")
|
||||
runtime.LogWarning(a.ctx, err.Error())
|
||||
runtime.LogWarningf(a.ctx, "Encountered an error while performing query: %s", err.Error())
|
||||
zenity.Error(err.Error(), zenity.Title("Error while querying"), zenity.ErrorIcon)
|
||||
return out
|
||||
}
|
||||
|
||||
out.Results = make([]string, 0)
|
||||
out.Total = total
|
||||
out.Results = make([]string, 0)
|
||||
|
||||
for _, r := range results {
|
||||
marshalled, err := bson.MarshalExtJSON(r, true, true)
|
||||
if err != nil {
|
||||
@ -117,3 +112,33 @@ func (a *App) FindItems(hostKey, dbKey, collKey, formJson string) QueryResult {
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
func (a *App) UpdateFoundDocument(hostKey, dbKey, collKey, idJson, newDocJson string) bool {
|
||||
var id bson.M
|
||||
if err := bson.UnmarshalExtJSON([]byte(idJson), true, &id); err != nil {
|
||||
runtime.LogWarningf(a.ctx, "Could not parse find/update query: %s", err.Error())
|
||||
zenity.Error(err.Error(), zenity.Title("Couldn't parse update query"), zenity.ErrorIcon)
|
||||
return false
|
||||
}
|
||||
|
||||
var newDoc bson.M
|
||||
if err := bson.UnmarshalExtJSON([]byte(newDocJson), true, &newDoc); err != nil {
|
||||
runtime.LogWarningf(a.ctx, "Could not parse new find/update document: %s", err.Error())
|
||||
zenity.Error(err.Error(), zenity.Title("Couldn't parse document"), zenity.ErrorIcon)
|
||||
return false
|
||||
}
|
||||
|
||||
client, ctx, close, err := a.connectToHost(hostKey)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
defer close()
|
||||
|
||||
if _, err := client.Database(dbKey).Collection(collKey).UpdateOne(ctx, id, bson.M{"$set": newDoc}); err != nil {
|
||||
runtime.LogInfof(a.ctx, "Error while performing find/update: %s", err.Error())
|
||||
zenity.Error(err.Error(), zenity.Title("Unable to perform update"), zenity.ErrorIcon)
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user