mirror of
https://github.com/garraflavatra/rolens.git
synced 2025-07-04 08:05:11 +00:00
Compare commits
9 Commits
Author | SHA1 | Date | |
---|---|---|---|
e5ef2d7007
|
|||
a0d029e7f6
|
|||
7eb7f97d21
|
|||
33d41064cc
|
|||
a23f14b494 | |||
8a0d305d7b
|
|||
6163288dfc
|
|||
c05ac2074b
|
|||
79d42fd44e
|
8
.github/ISSUE_TEMPLATE/feature.yml
vendored
8
.github/ISSUE_TEMPLATE/feature.yml
vendored
@ -17,14 +17,6 @@ body:
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
id: version
|
||||
attributes:
|
||||
label: Version
|
||||
description: What version of Rolens are you running?
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: importance
|
||||
attributes:
|
||||
|
1
.github/fosstodon-badge.svg
vendored
Normal file
1
.github/fosstodon-badge.svg
vendored
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="83" height="20" role="img" aria-label="Fosstodon"><title>Fosstodon</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="83" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="0" height="20" fill="#555"/><rect x="0" width="83" height="20" fill="#ddd"/><rect width="83" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><image x="5" y="3" width="14" height="14" xlink:href="data:image/svg+xml;base64,PHN2ZyBmaWxsPSIjNjM2NEZGIiByb2xlPSJpbWciIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48dGl0bGU+TWFzdG9kb248L3RpdGxlPjxwYXRoIGQ9Ik0yMy4yNjggNS4zMTNjLS4zNS0yLjU3OC0yLjYxNy00LjYxLTUuMzA0LTUuMDA0QzE3LjUxLjI0MiAxNS43OTIgMCAxMS44MTMgMGgtLjAzYy0zLjk4IDAtNC44MzUuMjQyLTUuMjg4LjMwOUMzLjg4Mi42OTIgMS40OTYgMi41MTguOTE3IDUuMTI3LjY0IDYuNDEyLjYxIDcuODM3LjY2MSA5LjE0M2MuMDc0IDEuODc0LjA4OCAzLjc0NS4yNiA1LjYxMS4xMTggMS4yNC4zMjUgMi40Ny42MiAzLjY4LjU1IDIuMjM3IDIuNzc3IDQuMDk4IDQuOTYgNC44NTcgMi4zMzYuNzkyIDQuODQ5LjkyMyA3LjI1Ni4zOC4yNjUtLjA2MS41MjctLjEzMi43ODYtLjIxMy41ODUtLjE4NCAxLjI3LS4zOSAxLjc3NC0uNzUzYS4wNTcuMDU3IDAgMCAwIC4wMjMtLjA0M3YtMS44MDlhLjA1Mi4wNTIgMCAwIDAtLjAyLS4wNDEuMDUzLjA1MyAwIDAgMC0uMDQ2LS4wMSAyMC4yODIgMjAuMjgyIDAgMCAxLTQuNzA5LjU0NWMtMi43MyAwLTMuNDYzLTEuMjg0LTMuNjc0LTEuODE4YTUuNTkzIDUuNTkzIDAgMCAxLS4zMTktMS40MzMuMDUzLjA1MyAwIDAgMSAuMDY2LS4wNTRjMS41MTcuMzYzIDMuMDcyLjU0NiA0LjYzMi41NDYuMzc2IDAgLjc1IDAgMS4xMjUtLjAxIDEuNTctLjA0NCAzLjIyNC0uMTI0IDQuNzY4LS40MjIuMDM4LS4wMDguMDc3LS4wMTUuMTEtLjAyNCAyLjQzNS0uNDY0IDQuNzUzLTEuOTIgNC45ODktNS42MDQuMDA4LS4xNDUuMDMtMS41Mi4wMy0xLjY3LjAwMi0uNTEyLjE2Ny0zLjYzLS4wMjQtNS41NDV6bS0zLjc0OCA5LjE5NWgtMi41NjFWOC4yOWMwLTEuMzA5LS41NS0xLjk3Ni0xLjY3LTEuOTc2LTEuMjMgMC0xLjg0Ni43OS0xLjg0NiAyLjM1djMuNDAzaC0yLjU0NlY4LjY2M2MwLTEuNTYtLjYxNy0yLjM1LTEuODQ4LTIuMzUtMS4xMTIgMC0xLjY2OC42NjgtMS42NyAxLjk3N3Y2LjIxOEg0LjgyMlY4LjEwMmMwLTEuMzEuMzM3LTIuMzUgMS4wMTEtMy4xMi42OTYtLjc3IDEuNjA4LTEuMTY0IDIuNzQtMS4xNjQgMS4zMTEgMCAyLjMwMi41IDIuOTYyIDEuNDk4bC42MzggMS4wNi42MzgtMS4wNmMuNjYtLjk5OSAxLjY1LTEuNDk4IDIuOTYtMS40OTggMS4xMyAwIDIuMDQzLjM5NSAyLjc0IDEuMTY0LjY3NS43NyAxLjAxMiAxLjgxIDEuMDEyIDMuMTJ6Ii8+PC9zdmc+"/><text aria-hidden="true" x="505" y="150" fill="#ccc" fill-opacity=".3" transform="scale(.1)" textLength="550">Fosstodon</text><text x="505" y="140" transform="scale(.1)" fill="#333" textLength="550">Fosstodon</text></g></svg>
|
After Width: | Height: | Size: 2.6 KiB |
61
.github/issue_template/bug.yml
vendored
61
.github/issue_template/bug.yml
vendored
@ -1,61 +0,0 @@
|
||||
name: Bug report
|
||||
description: Use this to report something that is not working properly.
|
||||
labels: [bug]
|
||||
assignees: [garraflavatra]
|
||||
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for taking the time to fill out this bug report!
|
||||
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Bug description
|
||||
description: Give a brief description of the bug. What feature is broken?
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: reproduction
|
||||
attributes:
|
||||
label: Reproduction
|
||||
description: Include a reproduction if applicable. What did you do before the bug appeared?
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
id: version
|
||||
attributes:
|
||||
label: Version
|
||||
description: What version of Rolens are you running?
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: logs
|
||||
attributes:
|
||||
label: Relevant log output
|
||||
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
|
||||
render: shell
|
||||
|
||||
- type: textarea
|
||||
id: environment
|
||||
attributes:
|
||||
label: Environment information
|
||||
description: Please open Rolens and select _Rolens > Open log directory_. Open the `environment.json` file and paste its contents here.
|
||||
render: shell
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: severity
|
||||
attributes:
|
||||
label: Severity of this bug
|
||||
options:
|
||||
- Annoying
|
||||
- Blocking a specific feature
|
||||
- Blocking all usage
|
||||
validations:
|
||||
required: true
|
6
.github/issue_template/config.yml
vendored
6
.github/issue_template/config.yml
vendored
@ -1,6 +0,0 @@
|
||||
blank_issues_enabled: false
|
||||
|
||||
contact_links:
|
||||
- name: Forums
|
||||
url: https://github.com/garraflavatra/rolens/discussions
|
||||
about: Do you have a question about Rolens? Please do not file an issue, but instead post your question here.
|
32
.github/issue_template/docs.yml
vendored
32
.github/issue_template/docs.yml
vendored
@ -1,32 +0,0 @@
|
||||
name: Documentation issue
|
||||
description: Report documentation issues here.
|
||||
labels: [documentation]
|
||||
assignees: [garraflavatra]
|
||||
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for taking the time to fill out this report!
|
||||
|
||||
- type: textarea
|
||||
id: source
|
||||
attributes:
|
||||
label: Source
|
||||
description: Which part of the documentation is erroneous? A link would be very nice!
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: problem
|
||||
attributes:
|
||||
label: Problem
|
||||
description: Why is it wrong?
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
id: solution
|
||||
attributes:
|
||||
label: Solution
|
||||
description: What should the documentation say instead?
|
37
.github/issue_template/feature.yml
vendored
37
.github/issue_template/feature.yml
vendored
@ -1,37 +0,0 @@
|
||||
name: Feature request
|
||||
description: Do you have an idea that could extend Rolens's possibilities? This is the place to propose it.
|
||||
labels: [enhancement]
|
||||
assignees: [garraflavatra]
|
||||
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for taking the time to propose a new feature!
|
||||
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Feature description
|
||||
description: Give a brief description of the feature you'd like to see. What issue does it solve, and what is it capable of?
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
id: version
|
||||
attributes:
|
||||
label: Version
|
||||
description: What version of Rolens are you running?
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: importance
|
||||
attributes:
|
||||
label: Importance
|
||||
options:
|
||||
- Nice to have
|
||||
- It would make Rolens more complete
|
||||
- I cannot use Rolens without it
|
||||
validations:
|
||||
required: true
|
9
CHANGELOG.md
Normal file
9
CHANGELOG.md
Normal file
@ -0,0 +1,9 @@
|
||||
## [v0.2.0](https://github.com/garraflavatra/rolens/releases/tag/v0.2.0)
|
||||
|
||||
* 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)
|
||||
|
||||
Initial release.
|
@ -2,7 +2,7 @@
|
||||
|
||||
Robust, blazing-fast, comprehensive, yet simple [MongoDB](https://www.mongodb.com/) administration tool for Windows, macOS and Linux.
|
||||
|
||||
[](https://github.com/garraflavatra/rolens/actions/workflows/ci.yml) [](https://garraflavatra.github.io/rolens)
|
||||
<a href="https://github.com/garraflavatra/rolens/actions/workflows/ci.yml" target="_blank"><img src="https://github.com/garraflavatra/rolens/actions/workflows/ci.yml/badge.svg" alt="CI" /></a> <a target="_blank" href="https://garraflavatra.github.io/rolens"><img src="./.github/docs-badge.svg" alt="Documentation" /></a> <a href="https://fosstodon.org/@rolens" target="_blank" rel="me"><img src="./.github/fosstodon-badge.svg" alt="Fosstodon" /></a>
|
||||
|
||||
## Why another MongoDB client?
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>{{.Name}}</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.wails.{{.Name}}</string>
|
||||
<string>nl.romeinvanburen.rolens</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>{{.Info.ProductVersion}}</string>
|
||||
<key>CFBundleGetInfoString</key>
|
||||
|
@ -8,7 +8,7 @@
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>{{.Name}}</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.wails.{{.Name}}</string>
|
||||
<string>nl.romeinvanburen.rolens</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>{{.Info.ProductVersion}}</string>
|
||||
<key>CFBundleGetInfoString</key>
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
|
||||
<assemblyIdentity type="win32" name="com.wails.{{.Name}}" version="{{.Info.ProductVersion}}.0" processorArchitecture="*"/>
|
||||
<assemblyIdentity type="win32" name="nl.romeinvanburen.rolens" version="{{.Info.ProductVersion}}.0" processorArchitecture="*"/>
|
||||
<dependency>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"/>
|
||||
|
6
docs/development.md
Normal file
6
docs/development.md
Normal file
@ -0,0 +1,6 @@
|
||||
---
|
||||
title: Development
|
||||
order: 50
|
||||
---
|
||||
|
||||
{{ collections.all | eleventyNavigation: "Development" | eleventyNavigationToMarkdown }}
|
7
docs/development/changelog.md
Normal file
7
docs/development/changelog.md
Normal file
@ -0,0 +1,7 @@
|
||||
---
|
||||
title: Changelog
|
||||
parent: Development
|
||||
order: 90
|
||||
---
|
||||
|
||||
{% filecontent "../CHANGELOG.md" %}
|
@ -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}
|
||||
@ -256,10 +275,10 @@
|
||||
|
||||
<ExportInfo on:openViewConfig bind:collection bind:info={exportInfo} />
|
||||
|
||||
{#key objectViewerData}
|
||||
{#if objectViewerData}
|
||||
<!-- @todo Implement save -->
|
||||
<ObjectViewer bind:data={objectViewerData} saveable />
|
||||
{/key}
|
||||
<ObjectViewer bind:data={objectViewerData} saveable on:save={saveDocument} bind:successMessage={objectViewerSuccessMessage} />
|
||||
{/if}
|
||||
|
||||
<datalist id="limits">
|
||||
{#each [ 1, 5, 10, 25, 50, 100, 200 ] as value}
|
||||
|
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);
|
||||
}
|
||||
|
@ -52,11 +52,15 @@ func (a *App) Menu() *menu.Menu {
|
||||
}
|
||||
|
||||
helpMenu := appMenu.AddSubmenu("Help")
|
||||
helpMenu.AddText("User guide", nil, menuCallbackURL(a, ""))
|
||||
helpMenu.AddText("User guide", nil, menuCallbackURL(a, "https://garraflavatra.github.io/rolens/user-guide/"))
|
||||
helpMenu.AddText("Website", nil, menuCallbackURL(a, "https://garraflavatra.github.io/rolens/"))
|
||||
helpMenu.AddText("Discussion board", nil, menuCallbackURL(a, "https://github.com/garraflavatra/rolens/discussions"))
|
||||
helpMenu.AddSeparator()
|
||||
helpMenu.AddText("Report a problem", nil, menuCallbackURL(a, "https://github.com/garraflavatra/rolens/issues/new"))
|
||||
helpMenu.AddText("Ask a question", nil, menuCallbackURL(a, "https://github.com/garraflavatra/rolens/discussions/new?category=questions"))
|
||||
helpMenu.AddSeparator()
|
||||
helpMenu.AddText("Star Rolens on GitHub", nil, menuCallbackURL(a, "https://github.com/garraflavatra/rolens"))
|
||||
helpMenu.AddText("Changelog", nil, menuCallbackURL(a, "https://garraflavatra.github.io/rolens/development/changelog/"))
|
||||
helpMenu.AddText("License", nil, menuCallbackURL(a, "https://github.com/garraflavatra/rolens/blob/main/LICENSE"))
|
||||
|
||||
return appMenu
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -9,5 +9,12 @@
|
||||
"author": {
|
||||
"name": "Romein van Buren",
|
||||
"email": "romein@vburen.nl"
|
||||
},
|
||||
"info": {
|
||||
"productName": "Rolens",
|
||||
"companyName": "Romein van Buren",
|
||||
"productVersion": "0.2.0",
|
||||
"comments": "The intuitive MongoDB administration tool",
|
||||
"copyright": "© Romein van Buren 2023 (GNU GPL 3.0)."
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
<a class="githubstars" href="https://github.com/garraflavatra/rolens" target="_blank">
|
||||
<span class="star">★</span>
|
||||
<a class="socialbadge" href="https://github.com/garraflavatra/rolens" target="_blank">
|
||||
<span class="star">
|
||||
<svg class="icon" viewBox="0 0 16 16"><path d="M3.612 15.443c-.386.198-.824-.149-.746-.592l.83-4.73L.173 6.765c-.329-.314-.158-.888.283-.95l4.898-.696L7.538.792c.197-.39.73-.39.927 0l2.184 4.327 4.898.696c.441.062.612.636.282.95l-3.522 3.356.83 4.73c.078.443-.36.79-.746.592L8 13.187l-4.389 2.256z"/></svg>
|
||||
</span>
|
||||
|
||||
{% if github.stars %}
|
||||
<span class="count">{{ github.stars }}</span>
|
||||
|
6
website/includes/mastodon.liquid
Normal file
6
website/includes/mastodon.liquid
Normal file
@ -0,0 +1,6 @@
|
||||
<a href="https://fosstodon.org/@rolens" class="socialbadge" rel="me">
|
||||
<span class="toot">
|
||||
<svg fill="#6364ff" class="icon" viewBox="0 0 16 16"><path d="M11.19 12.195c2.016-.24 3.77-1.475 3.99-2.603.348-1.778.32-4.339.32-4.339 0-3.47-2.286-4.488-2.286-4.488C12.062.238 10.083.017 8.027 0h-.05C5.92.017 3.942.238 2.79.765c0 0-2.285 1.017-2.285 4.488l-.002.662c-.004.64-.007 1.35.011 2.091.083 3.394.626 6.74 3.78 7.57 1.454.383 2.703.463 3.709.408 1.823-.1 2.847-.647 2.847-.647l-.06-1.317s-1.303.41-2.767.36c-1.45-.05-2.98-.156-3.215-1.928a3.614 3.614 0 0 1-.033-.496s1.424.346 3.228.428c1.103.05 2.137-.064 3.188-.189zm1.613-2.47H11.13v-4.08c0-.859-.364-1.295-1.091-1.295-.804 0-1.207.517-1.207 1.541v2.233H7.168V5.89c0-1.024-.403-1.541-1.207-1.541-.727 0-1.091.436-1.091 1.296v4.079H3.197V5.522c0-.859.22-1.541.66-2.046.456-.505 1.052-.764 1.793-.764.856 0 1.504.328 1.933.983L8 4.39l.417-.695c.429-.655 1.077-.983 1.934-.983.74 0 1.336.259 1.791.764.442.505.661 1.187.661 2.046v4.203z"/></svg>
|
||||
</span>
|
||||
Follow @rolens on Fosstodon
|
||||
</a>
|
@ -55,7 +55,10 @@ navigationOptions:
|
||||
<a href="{{ github.pageSourceUrl }}" target="_blank">edit the page</a>
|
||||
on GitHub.
|
||||
</p>
|
||||
<p>{% render "githubstars" %}</p>
|
||||
<p>
|
||||
{% render "githubstars" %}
|
||||
{% render "mastodon" %}
|
||||
</p>
|
||||
<p>
|
||||
© <a href="mailto:romein@vburen.nl">Romein van Buren</a> 2023.
|
||||
The <a href="{{ meta.repoUrl }}">source code</a> and compiled
|
||||
|
@ -268,16 +268,23 @@ article {
|
||||
|
||||
// MISC
|
||||
|
||||
.githubstars {
|
||||
.socialbadge {
|
||||
display: inline-block;
|
||||
text-decoration: none;
|
||||
color: #000;
|
||||
background-color: #ddd;
|
||||
padding: 0 4px;
|
||||
border-radius: 2px;
|
||||
margin: 0 0 4px 0;
|
||||
box-shadow: 0 1.25px #aaa;
|
||||
|
||||
&:hover { background-color: #ccc; }
|
||||
.star { color: #a69e2c; }
|
||||
.toot { color: #595aff; }
|
||||
.count { font-weight: 700; margin-right: 8px; }
|
||||
|
||||
svg {
|
||||
fill: currentColor;
|
||||
stroke: none;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user