mirror of
https://github.com/garraflavatra/rolens.git
synced 2025-07-19 14:14:05 +00:00
A lot of improvements
This commit is contained in:
@ -1,6 +1,7 @@
|
||||
<script>
|
||||
import TabBar from '../../../components/tabbar.svelte';
|
||||
import Modal from '../../../components/modal.svelte';
|
||||
import Icon from '../../../components/icon.svelte';
|
||||
|
||||
export let show = false;
|
||||
export let activeView = 'list';
|
||||
@ -8,15 +9,55 @@
|
||||
hideObjectIndicators: false,
|
||||
columns: [],
|
||||
};
|
||||
export let firstItem = {};
|
||||
|
||||
let activeTab = activeView || 'list';
|
||||
|
||||
$: activeView && (activeTab = activeView);
|
||||
$: if (!config.columns || (config.columns.length === 0)) {
|
||||
config.columns = [ { key: '_id' } ];
|
||||
}
|
||||
|
||||
function addColumn(before) {
|
||||
if (typeof before === 'number') {
|
||||
config.columns = [
|
||||
...config.columns.slice(0, before),
|
||||
{},
|
||||
...config.columns.slice(before),
|
||||
];
|
||||
}
|
||||
else {
|
||||
config.columns = [ ...config.columns, {} ];
|
||||
}
|
||||
}
|
||||
|
||||
function addSuggestedColumns() {
|
||||
if ((typeof firstItem !== 'object') || (firstItem === null)) {
|
||||
return;
|
||||
}
|
||||
config.columns = Object.keys(firstItem).map(key => ({ key }));
|
||||
}
|
||||
|
||||
function moveColumn(oldIndex, delta) {
|
||||
const column = config.columns[oldIndex];
|
||||
const newIndex = oldIndex + delta;
|
||||
|
||||
config.columns.splice(oldIndex, 1);
|
||||
config.columns.splice(newIndex, 0, column);
|
||||
config.columns = config.columns;
|
||||
}
|
||||
|
||||
function removeColumn(index) {
|
||||
config.columns.splice(index, 1);
|
||||
config.columns = config.columns;
|
||||
}
|
||||
</script>
|
||||
|
||||
<Modal title="View configuration" bind:show contentPadding={false}>
|
||||
<TabBar
|
||||
tabs={[
|
||||
{ key: 'list', title: 'List view' },
|
||||
{ key: 'table', title: 'Table view' },
|
||||
{ key: 'table', title: 'Table view columns' },
|
||||
]}
|
||||
bind:selectedKey={activeTab}
|
||||
/>
|
||||
@ -30,11 +71,31 @@
|
||||
</label>
|
||||
</div>
|
||||
{:else if activeTab === 'table'}
|
||||
<input
|
||||
type="text"
|
||||
value={config.columns?.map(c => c.key).join(', ') || ''}
|
||||
on:input={e => config.columns = e.currentTarget.value?.split(',').map(k => ({ key: k.trim() })) || ''}
|
||||
/>
|
||||
{#each config.columns as column, columnIndex}
|
||||
<div class="column">
|
||||
<label class="field">
|
||||
<input type="text" bind:value={column.key} placeholder="Column keypath" />
|
||||
</label>
|
||||
<button class="btn" type="button" on:click={() => addColumn(columnIndex)} title="Add column before this one">
|
||||
<Icon name="+" />
|
||||
</button>
|
||||
<button class="btn" type="button" on:click={() => moveColumn(columnIndex, -1)} disabled={columnIndex === 0} title="Move column one position up">
|
||||
<Icon name="chev-u" />
|
||||
</button>
|
||||
<button class="btn" type="button" on:click={() => moveColumn(columnIndex, 1)} disabled={columnIndex === config.columns.length - 1} title="Move column one position down">
|
||||
<Icon name="chev-d" />
|
||||
</button>
|
||||
<button class="btn danger" type="button" on:click={() => removeColumn(columnIndex)} title="Remove this column">
|
||||
<Icon name="x" />
|
||||
</button>
|
||||
</div>
|
||||
{/each}
|
||||
<button class="btn" on:click={addColumn}>
|
||||
<Icon name="+" /> Add column
|
||||
</button>
|
||||
<button class="btn" on:click={addSuggestedColumns} disabled={!firstItem}>
|
||||
<Icon name="zap" /> Add suggested columns
|
||||
</button>
|
||||
{/if}
|
||||
</div>
|
||||
</Modal>
|
||||
@ -48,7 +109,11 @@
|
||||
display: flex;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
.flex + .flex {
|
||||
margin-top: 1rem;
|
||||
|
||||
.column {
|
||||
display: grid;
|
||||
grid-template: 1fr / 1fr repeat(4, auto);
|
||||
gap: 0.5rem;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
</style>
|
||||
|
@ -7,6 +7,7 @@
|
||||
import ObjectViewer from '../../../components/objectviewer.svelte';
|
||||
import FindViewConfigModal from './find-viewconfig.svelte';
|
||||
import { onMount } from 'svelte';
|
||||
import Grid from '../../../components/grid.svelte';
|
||||
|
||||
export let collection;
|
||||
|
||||
@ -28,6 +29,8 @@
|
||||
let viewConfigModalOpen = false;
|
||||
let viewConfig = {};
|
||||
$: 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;
|
||||
$: activePage = (submittedForm.limit && submittedForm.skip && result?.results?.length) ? submittedForm.skip / submittedForm.limit : 0;
|
||||
|
||||
$: collection && refresh();
|
||||
$: updateConfig(viewConfig);
|
||||
@ -43,6 +46,21 @@
|
||||
}
|
||||
}
|
||||
|
||||
async function updateConfig(viewConfig) {
|
||||
try {
|
||||
const hosts = await Hosts();
|
||||
hosts[collection.hostKey].databases = hosts[collection.hostKey].databases || {};
|
||||
hosts[collection.hostKey].databases[collection.dbKey] = hosts[collection.hostKey].databases[collection.dbKey] || {};
|
||||
hosts[collection.hostKey].databases[collection.dbKey].collections = hosts[collection.hostKey].databases[collection.dbKey].collections || {};
|
||||
hosts[collection.hostKey].databases[collection.dbKey].collections[collection.key] = hosts[collection.hostKey].databases[collection.dbKey].collections[collection.key] || {};
|
||||
hosts[collection.hostKey].databases[collection.dbKey].collections[collection.key].viewConfig = viewConfig;
|
||||
await UpdateHost(collection.hostKey, JSON.stringify(hosts[collection.hostKey]));
|
||||
}
|
||||
catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
async function submitQuery() {
|
||||
activePath = [];
|
||||
result = await FindItems(collection.hostKey, collection.dbKey, collection.key, JSON.stringify(form));
|
||||
@ -57,22 +75,6 @@
|
||||
await submitQuery();
|
||||
}
|
||||
|
||||
async function updateConfig(viewConfig) {
|
||||
try {
|
||||
const hosts = await Hosts();
|
||||
hosts[collection.hostKey].databases = hosts[collection.hostKey].databases || {};
|
||||
hosts[collection.hostKey].databases[collection.dbKey] = hosts[collection.hostKey].databases[collection.dbKey] || {};
|
||||
hosts[collection.hostKey].databases[collection.dbKey].collections = hosts[collection.hostKey].databases[collection.dbKey].collections || {};
|
||||
hosts[collection.hostKey].databases[collection.dbKey].collections[collection.key] = hosts[collection.hostKey].databases[collection.dbKey].collections[collection.key] || {};
|
||||
hosts[collection.hostKey].databases[collection.dbKey].collections[collection.key].viewConfig = viewConfig;
|
||||
await UpdateHost(collection.hostKey, JSON.stringify(hosts[collection.hostKey]));
|
||||
}
|
||||
catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
console.log(viewConfig);
|
||||
}
|
||||
|
||||
function prev() {
|
||||
form.skip -= form.limit;
|
||||
if (form.skip < 0) {
|
||||
@ -86,6 +88,16 @@
|
||||
submitQuery();
|
||||
}
|
||||
|
||||
function first() {
|
||||
form.skip = 0;
|
||||
submitQuery();
|
||||
}
|
||||
|
||||
function last() {
|
||||
form.skip = lastPage * submittedForm.limit;
|
||||
submitQuery();
|
||||
}
|
||||
|
||||
async function removeActive() {
|
||||
if (!activePath[0]) {
|
||||
return;
|
||||
@ -140,12 +152,12 @@
|
||||
|
||||
<label class="field">
|
||||
<span class="label">Skip</span>
|
||||
<input type="number" min="0" bind:value={form.skip} use:input placeholder={defaults.skip} />
|
||||
<input type="number" min="0" bind:value={form.skip} use:input placeholder={defaults.skip} list="skipstops" />
|
||||
</label>
|
||||
|
||||
<label class="field">
|
||||
<span class="label">Limit</span>
|
||||
<input type="number" min="0" bind:value={form.limit} use:input placeholder={defaults.limit} />
|
||||
<input type="number" min="0" bind:value={form.limit} use:input placeholder={defaults.limit} list="limits" />
|
||||
</label>
|
||||
|
||||
<button type="submit" class="btn">Run</button>
|
||||
@ -157,12 +169,23 @@
|
||||
<div class="result">
|
||||
<div class="grid">
|
||||
{#key result}
|
||||
<ObjectGrid
|
||||
data={result.results}
|
||||
hideObjectIndicators={viewConfig?.hideObjectIndicators}
|
||||
bind:activePath
|
||||
on:trigger={e => openJson(e.detail?.itemKey)}
|
||||
/>
|
||||
{#if view === 'table'}
|
||||
<Grid
|
||||
key="_id"
|
||||
columns={viewConfig.columns?.map(c => ({ key: c.key, title: c.key })) || []}
|
||||
showHeaders={true}
|
||||
items={result.results || []}
|
||||
bind:activePath
|
||||
on:trigger={e => openJson(e.detail?.itemKey)}
|
||||
/>
|
||||
{:else if view === 'list'}
|
||||
<ObjectGrid
|
||||
data={result.results}
|
||||
hideObjectIndicators={viewConfig?.hideObjectIndicators}
|
||||
bind:activePath
|
||||
on:trigger={e => openJson(e.detail?.itemKey)}
|
||||
/>
|
||||
{/if}
|
||||
{/key}
|
||||
</div>
|
||||
|
||||
@ -177,24 +200,44 @@
|
||||
<Icon name="cog" />
|
||||
</button>
|
||||
<button class="btn" on:click={toggleView} title="Toggle view">
|
||||
<Icon name={view} />
|
||||
<Icon name={view === 'table' ? 'list' : 'table'} />
|
||||
</button>
|
||||
<button class="btn danger" on:click={removeActive} disabled={!activePath?.length} title="Drop selected item">
|
||||
<Icon name="-" />
|
||||
</button>
|
||||
<button class="btn" on:click={prev} disabled={!submittedForm.limit || (submittedForm.skip <= 0) || !result?.results?.length} title="Previous {form.limit} items">
|
||||
<button class="btn" on:click={first} disabled={!submittedForm.limit || (submittedForm.skip <= 0) || !result?.results || (activePage === 0)} title="First page">
|
||||
<Icon name="chevs-l" />
|
||||
</button>
|
||||
<button class="btn" on:click={prev} disabled={!submittedForm.limit || (submittedForm.skip <= 0) || !result?.results || (activePage === 0)} title="Previous {submittedForm.limit} items">
|
||||
<Icon name="chev-l" />
|
||||
</button>
|
||||
<button class="btn" on:click={next} disabled={!submittedForm.limit || ((result?.results?.length || 0) < submittedForm.limit) || !result?.results?.length} title="Next {form.limit} items">
|
||||
<button class="btn" on:click={next} disabled={!submittedForm.limit || ((result?.results?.length || 0) < submittedForm.limit) || !result?.results || !lastPage || (activePage >= lastPage)} title="Next {submittedForm.limit} items">
|
||||
<Icon name="chev-r" />
|
||||
</button>
|
||||
<button class="btn" on:click={last} disabled={!submittedForm.limit || ((result?.results?.length || 0) < submittedForm.limit) || !result?.results || !lastPage || (activePage >= lastPage)} title="Last page">
|
||||
<Icon name="chevs-r" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ObjectViewer bind:data={objectViewerData} />
|
||||
<FindViewConfigModal bind:show={viewConfigModalOpen} activeView={view} bind:config={viewConfig} />
|
||||
<FindViewConfigModal bind:show={viewConfigModalOpen} activeView={view} bind:config={viewConfig} firstItem={result.results?.[0]} />
|
||||
|
||||
<datalist id="limits">
|
||||
{#each [ 1, 5, 10, 25, 50, 100, 200 ] as value}
|
||||
<option {value} />
|
||||
{/each}
|
||||
</datalist>
|
||||
|
||||
{#if submittedForm?.limit}
|
||||
<datalist id="skipstops">
|
||||
{#each Array(lastPage).fill('').map((_, i) => i * submittedForm.limit) as value}
|
||||
<option {value} />
|
||||
{/each}
|
||||
</datalist>
|
||||
{/if}
|
||||
|
||||
<style>
|
||||
.find {
|
||||
|
@ -2,6 +2,7 @@
|
||||
import ObjectViewer from '../../../components/objectviewer.svelte';
|
||||
import ObjectGrid from '../../../components/objectgrid.svelte';
|
||||
import { DropIndex, GetIndexes } from '../../../../wailsjs/go/app/App';
|
||||
import Icon from '../../../components/icon.svelte';
|
||||
|
||||
export let collection;
|
||||
|
||||
@ -9,6 +10,8 @@
|
||||
let activePath = [];
|
||||
let objectViewerData = '';
|
||||
|
||||
$: collection && getIndexes();
|
||||
|
||||
async function getIndexes() {
|
||||
const result = await GetIndexes(collection.hostKey, collection.dbKey, collection.key);
|
||||
if (result) {
|
||||
@ -35,11 +38,15 @@
|
||||
|
||||
<div class="indexes">
|
||||
<div class="actions">
|
||||
<button class="btn" on:click={getIndexes}>Get indexes</button>
|
||||
<button class="btn danger" on:click={drop} disabled={!indexes?.length || !activePath[0]}>
|
||||
Drop selected
|
||||
<button class="btn" on:click={getIndexes}>
|
||||
<Icon name="reload" /> Reload
|
||||
</button>
|
||||
<button class="btn">
|
||||
<Icon name="+" /> Create index…
|
||||
</button>
|
||||
<button class="btn danger" on:click={drop} disabled={!indexes?.length || !activePath[0]}>
|
||||
<Icon name="x" /> Drop selected
|
||||
</button>
|
||||
<button class="btn">Create…</button>
|
||||
</div>
|
||||
|
||||
<div class="grid">
|
||||
|
@ -2,6 +2,7 @@
|
||||
import { input } from '../../../actions';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
import { InsertItems } from '../../../../wailsjs/go/app/App';
|
||||
import Icon from '../../../components/icon.svelte';
|
||||
|
||||
export let collection;
|
||||
|
||||
@ -44,7 +45,9 @@
|
||||
{#if insertedIds}
|
||||
<button class="btn" type="button" on:click={showDocs}>View inserted docs</button>
|
||||
{/if}
|
||||
<button type="submit" class="btn" disabled={!json}>Insert</button>
|
||||
<button type="submit" class="btn" disabled={!json}>
|
||||
<Icon name="+" /> Insert
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -2,6 +2,7 @@
|
||||
import { input } from '../../../actions';
|
||||
import { RemoveItems } from '../../../../wailsjs/go/app/App';
|
||||
import CodeExample from '../../../components/code-example.svelte';
|
||||
import Icon from '../../../components/icon.svelte';
|
||||
|
||||
export let collection;
|
||||
|
||||
@ -45,7 +46,9 @@
|
||||
{/if}
|
||||
{/key}
|
||||
</div>
|
||||
<button type="submit" class="btn">Remove</button>
|
||||
<button type="submit" class="btn danger">
|
||||
<Icon name="-" /> Remove
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
|
@ -114,7 +114,9 @@
|
||||
{/if}
|
||||
{/key}
|
||||
|
||||
<button class="btn" type="submit">Update</button>
|
||||
<button class="btn" type="submit">
|
||||
<Icon name="check" /> Update
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<label class="field">
|
||||
|
Reference in New Issue
Block a user