mirror of
https://github.com/garraflavatra/rolens.git
synced 2024-12-01 13:20:54 +00:00
Major grid changes and bugfixes
This commit is contained in:
parent
f5a89cf019
commit
2603e6350e
@ -6,8 +6,9 @@
|
|||||||
export let items = [];
|
export let items = [];
|
||||||
export let columns = [];
|
export let columns = [];
|
||||||
export let key = '';
|
export let key = '';
|
||||||
|
export let path = [];
|
||||||
export let activeKey = '';
|
export let activeKey = '';
|
||||||
export let activeChildKey = '';
|
export let activePath = [];
|
||||||
export let level = 0;
|
export let level = 0;
|
||||||
export let striped = true;
|
export let striped = true;
|
||||||
|
|
||||||
@ -33,8 +34,13 @@
|
|||||||
|
|
||||||
function select(itemKey) {
|
function select(itemKey) {
|
||||||
activeKey = itemKey;
|
activeKey = itemKey;
|
||||||
activeChildKey = '';
|
if (level === 0) {
|
||||||
dispatch('select', itemKey);
|
activePath = [ itemKey ];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
activePath = [ ...path, itemKey ];
|
||||||
|
}
|
||||||
|
dispatch('select', { level, itemKey });
|
||||||
}
|
}
|
||||||
|
|
||||||
function closeAll() {
|
function closeAll() {
|
||||||
@ -42,12 +48,6 @@
|
|||||||
dispatch('closeAll');
|
dispatch('closeAll');
|
||||||
}
|
}
|
||||||
|
|
||||||
function selectChild(itemKey, childKey) {
|
|
||||||
select(itemKey);
|
|
||||||
activeChildKey = childKey;
|
|
||||||
dispatch('selectChild', childKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
function toggleChildren(itemKey, shift) {
|
function toggleChildren(itemKey, shift) {
|
||||||
childrenOpen[itemKey] = !childrenOpen[itemKey];
|
childrenOpen[itemKey] = !childrenOpen[itemKey];
|
||||||
if (shift) {
|
if (shift) {
|
||||||
@ -57,7 +57,7 @@
|
|||||||
|
|
||||||
function doubleClick(itemKey) {
|
function doubleClick(itemKey) {
|
||||||
toggleChildren(itemKey, false);
|
toggleChildren(itemKey, false);
|
||||||
dispatch('trigger', itemKey);
|
dispatch('trigger', { level, itemKey });
|
||||||
}
|
}
|
||||||
|
|
||||||
function showContextMenu(evt, item) {
|
function showContextMenu(evt, item) {
|
||||||
@ -85,12 +85,12 @@
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#each _items as item (item[key])}
|
{#each _items as item}
|
||||||
<tr
|
<tr
|
||||||
on:click={() => select(item[key])}
|
on:click={() => select(item[key])}
|
||||||
on:dblclick={() => doubleClick(item[key])}
|
on:dblclick={() => doubleClick(item[key])}
|
||||||
on:contextmenu|preventDefault={evt => showContextMenu(evt, item)}
|
on:contextmenu|preventDefault={evt => showContextMenu(evt, item)}
|
||||||
class:selected={activeKey === item[key] && !activeChildKey}
|
class:selected={!activePath[level + 1] && activePath.every(k => path.includes(k) || k === item[key]) && (activePath[level] === item[key])}
|
||||||
class:striped
|
class:striped
|
||||||
>
|
>
|
||||||
<td class="has-toggle">
|
<td class="has-toggle">
|
||||||
@ -120,12 +120,13 @@
|
|||||||
{columns}
|
{columns}
|
||||||
{key}
|
{key}
|
||||||
{striped}
|
{striped}
|
||||||
bind:activeKey={activeChildKey}
|
path={[ ...path, item[key] ]}
|
||||||
showHeaders={false}
|
|
||||||
items={item.children}
|
items={item.children}
|
||||||
level={level + 1}
|
level={level + 1}
|
||||||
on:select={e => selectChild(item[key], e.detail)}
|
bind:activePath
|
||||||
on:closeAll={closeAll}
|
on:closeAll={closeAll}
|
||||||
|
on:select
|
||||||
|
on:trigger
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
{/each}
|
{/each}
|
||||||
|
@ -6,9 +6,7 @@
|
|||||||
export let items = [];
|
export let items = [];
|
||||||
export let actions = [];
|
export let actions = [];
|
||||||
export let key = 'id';
|
export let key = 'id';
|
||||||
export let activeKey = '';
|
export let activePath = [];
|
||||||
export let activeChildKey = '';
|
|
||||||
export let showHeaders = true;
|
|
||||||
export let striped = true;
|
export let striped = true;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -25,19 +23,8 @@
|
|||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
{#if showHeaders && columns.some(col => col.title)}
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th class="has-toggle"></th>
|
|
||||||
{#each columns as column}
|
|
||||||
<th scope="col">{column.title || ''}</th>
|
|
||||||
{/each}
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
<tbody>
|
<tbody>
|
||||||
<GridItems {items} {columns} {key} {striped} bind:activeKey bind:activeChildKey on:select on:selectChild on:trigger />
|
<GridItems {items} {columns} {key} {striped} bind:activePath on:select on:trigger />
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
@ -63,22 +50,4 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
table thead {
|
|
||||||
border-bottom: 2px solid #ccc;
|
|
||||||
}
|
|
||||||
|
|
||||||
th {
|
|
||||||
font-weight: 600;
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
tr {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
th {
|
|
||||||
padding: 0.3rem;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
2
frontend/src/components/icon.svelte
vendored
2
frontend/src/components/icon.svelte
vendored
@ -24,4 +24,6 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-clipboard"><path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"></path><rect x="8" y="2" width="8" height="4" rx="1" ry="1"></rect></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-clipboard"><path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"></path><rect x="8" y="2" width="8" height="4" rx="1" ry="1"></rect></svg>
|
||||||
{:else if name === 'edit'}
|
{:else if name === 'edit'}
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-edit-3"><path d="M12 20h9"></path><path d="M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4L16.5 3.5z"></path></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-edit-3"><path d="M12 20h9"></path><path d="M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4L16.5 3.5z"></path></svg>
|
||||||
|
{:else if name === 'check'}
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-check-circle"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"></path><polyline points="22 4 12 14.01 9 11.01"></polyline></svg>
|
||||||
{/if}
|
{/if}
|
||||||
|
@ -3,8 +3,7 @@
|
|||||||
|
|
||||||
export let data = [];
|
export let data = [];
|
||||||
export let key = '_id';
|
export let key = '_id';
|
||||||
export let showHeaders = false;
|
export let activePath = [];
|
||||||
export let activeKey = '';
|
|
||||||
|
|
||||||
const columns = [
|
const columns = [
|
||||||
{ key: 'key', label: 'Key' },
|
{ key: 'key', label: 'Key' },
|
||||||
@ -20,10 +19,9 @@
|
|||||||
if (Array.isArray(data)) {
|
if (Array.isArray(data)) {
|
||||||
for (const item of data) {
|
for (const item of data) {
|
||||||
const newItem = {};
|
const newItem = {};
|
||||||
newItem.key = key;
|
newItem.key = item[key];
|
||||||
newItem.value = item[key];
|
|
||||||
newItem.type = getType(item[key]);
|
newItem.type = getType(item[key]);
|
||||||
newItem.children = dissectObject(item, key);
|
newItem.children = dissectObject(item);
|
||||||
newItem.menu = item.menu;
|
newItem.menu = item.menu;
|
||||||
items = [ ...items, newItem ];
|
items = [ ...items, newItem ];
|
||||||
}
|
}
|
||||||
@ -55,12 +53,12 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function dissectObject(object, exclude) {
|
function dissectObject(object) {
|
||||||
const entries = [ ...Array.isArray(object) ? object.entries() : Object.entries(object) ];
|
const entries = [ ...Array.isArray(object) ? object.entries() : Object.entries(object) ];
|
||||||
return entries.filter(([ key ]) => key != exclude).map(([ key, value ]) => {
|
return entries.map(([ key, value ]) => {
|
||||||
key = key + '';
|
key = key + '';
|
||||||
const type = getType(value);
|
const type = getType(value);
|
||||||
const child = { key, value, type, menu: value.menu };
|
const child = { key, value, type, menu: value?.menu };
|
||||||
|
|
||||||
if (type.startsWith('object') || type.startsWith('array')) {
|
if (type.startsWith('object') || type.startsWith('array')) {
|
||||||
child.children = dissectObject(value);
|
child.children = dissectObject(value);
|
||||||
@ -74,10 +72,8 @@
|
|||||||
<Grid
|
<Grid
|
||||||
key="key"
|
key="key"
|
||||||
on:select
|
on:select
|
||||||
on:selectChild
|
|
||||||
on:trigger
|
on:trigger
|
||||||
bind:activeKey
|
bind:activePath
|
||||||
{columns}
|
{columns}
|
||||||
{items}
|
{items}
|
||||||
{showHeaders}
|
|
||||||
/>
|
/>
|
||||||
|
@ -20,12 +20,12 @@
|
|||||||
let result = {};
|
let result = {};
|
||||||
let submittedForm = {};
|
let submittedForm = {};
|
||||||
let queryField;
|
let queryField;
|
||||||
let activeKey = '';
|
let activePath = '';
|
||||||
let json = '';
|
let json = '';
|
||||||
$: 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})` : ''};`;
|
||||||
|
|
||||||
async function submitQuery() {
|
async function submitQuery() {
|
||||||
activeKey = '';
|
activePath = [];
|
||||||
result = await FindItems(collection.hostKey, collection.dbKey, collection.key, JSON.stringify(form));
|
result = await FindItems(collection.hostKey, collection.dbKey, collection.key, JSON.stringify(form));
|
||||||
if (result) {
|
if (result) {
|
||||||
submittedForm = JSON.parse(JSON.stringify(form));
|
submittedForm = JSON.parse(JSON.stringify(form));
|
||||||
@ -47,8 +47,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function remove() {
|
function remove() {
|
||||||
// eslint-disable-next-line no-alert
|
// todo
|
||||||
alert('yet to be implemented');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function resetFocus() {
|
function resetFocus() {
|
||||||
@ -57,13 +56,15 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function openJson(itemId) {
|
function openJson(itemId) {
|
||||||
const item = result?.results?.filter(i => i._id == itemId);
|
const item = result?.results?.find(i => i._id == itemId);
|
||||||
|
if (!item) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
json = JSON.stringify(item, undefined, 2);
|
json = JSON.stringify(item, undefined, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function performQuery(q) {
|
export function performQuery(q) {
|
||||||
form = { ...defaults, ...q };
|
form = { ...defaults, ...q };
|
||||||
console.log(form);
|
|
||||||
submitQuery();
|
submitQuery();
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@ -107,7 +108,7 @@
|
|||||||
<div class="result">
|
<div class="result">
|
||||||
<div class="grid">
|
<div class="grid">
|
||||||
{#key result}
|
{#key result}
|
||||||
<ObjectGrid data={result.results} bind:activeKey on:trigger={e => openJson(e.detail)} />
|
<ObjectGrid data={result.results} bind:activePath on:trigger={e => openJson(e.detail?.itemKey)} />
|
||||||
{/key}
|
{/key}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -118,7 +119,7 @@
|
|||||||
{/key}
|
{/key}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<button class="btn danger" on:click={remove} disabled={!activeKey}>
|
<button class="btn danger" on:click={remove} disabled={!activePath?.length}>
|
||||||
<Icon name="-" />
|
<Icon name="-" />
|
||||||
</button>
|
</button>
|
||||||
<button class="btn" on:click={prev} disabled={!submittedForm.limit || (submittedForm.skip <= 0) || !result?.results?.length}>
|
<button class="btn" on:click={prev} disabled={!submittedForm.limit || (submittedForm.skip <= 0) || !result?.results?.length}>
|
||||||
|
@ -11,6 +11,9 @@
|
|||||||
export let activeCollKey = '';
|
export let activeCollKey = '';
|
||||||
|
|
||||||
const dispatch = createEventDispatcher();
|
const dispatch = createEventDispatcher();
|
||||||
|
let dbAndCollKeys = [];
|
||||||
|
$: activeDbKey = dbAndCollKeys[0];
|
||||||
|
$: activeCollKey = dbAndCollKeys[1];
|
||||||
$: host = hosts[activeHostKey];
|
$: host = hosts[activeHostKey];
|
||||||
$: connection = $connections[activeHostKey];
|
$: connection = $connections[activeHostKey];
|
||||||
$: database = connection?.databases[activeDbKey];
|
$: database = connection?.databases[activeDbKey];
|
||||||
@ -60,6 +63,7 @@
|
|||||||
async function openCollection(collKey) {
|
async function openCollection(collKey) {
|
||||||
busy.start();
|
busy.start();
|
||||||
const stats = await OpenCollection(activeHostKey, activeDbKey, collKey);
|
const stats = await OpenCollection(activeHostKey, activeDbKey, collKey);
|
||||||
|
$connections[activeHostKey].databases[activeDbKey].collections[collKey] = $connections[activeHostKey].databases[activeDbKey].collections[collKey] || {};
|
||||||
$connections[activeHostKey].databases[activeDbKey].collections[collKey].stats = stats;
|
$connections[activeHostKey].databases[activeDbKey].collections[collKey].stats = stats;
|
||||||
busy.end();
|
busy.end();
|
||||||
}
|
}
|
||||||
@ -76,10 +80,10 @@
|
|||||||
<Grid
|
<Grid
|
||||||
striped={false}
|
striped={false}
|
||||||
columns={[ { key: 'id' }, { key: 'collCount', right: true } ]}
|
columns={[ { key: 'id' }, { key: 'collCount', right: true } ]}
|
||||||
items={Object.keys(connection.databases).map(dbKey => ({
|
items={Object.keys(connection.databases).sort().map(dbKey => ({
|
||||||
id: dbKey,
|
id: dbKey,
|
||||||
collCount: Object.keys(connection.databases[dbKey].collections || {}).length || '',
|
collCount: Object.keys(connection.databases[dbKey].collections || {}).length || '',
|
||||||
children: Object.keys(connection.databases[dbKey].collections).map(collKey => ({
|
children: Object.keys(connection.databases[dbKey].collections).sort().map(collKey => ({
|
||||||
id: collKey,
|
id: collKey,
|
||||||
menu: [
|
menu: [
|
||||||
{ label: `Drop ${collKey}…`, fn: () => dropCollection(dbKey, collKey) },
|
{ label: `Drop ${collKey}…`, fn: () => dropCollection(dbKey, collKey) },
|
||||||
@ -88,7 +92,7 @@
|
|||||||
{ label: 'New database…', fn: () => dispatch('newDatabase') },
|
{ label: 'New database…', fn: () => dispatch('newDatabase') },
|
||||||
{ label: 'New collection…', fn: () => dispatch('newCollection') },
|
{ label: 'New collection…', fn: () => dispatch('newCollection') },
|
||||||
],
|
],
|
||||||
})).sort((a, b) => a.id.localeCompare(b)) || [],
|
})) || [],
|
||||||
menu: [
|
menu: [
|
||||||
{ label: `Drop ${dbKey}…`, fn: () => dropDatabase(dbKey) },
|
{ label: `Drop ${dbKey}…`, fn: () => dropDatabase(dbKey) },
|
||||||
{ separator: true },
|
{ separator: true },
|
||||||
@ -121,9 +125,14 @@
|
|||||||
}
|
}
|
||||||
}, disabled: !activeDbKey },
|
}, disabled: !activeDbKey },
|
||||||
]}
|
]}
|
||||||
bind:activeKey={activeDbKey}
|
bind:activePath={dbAndCollKeys}
|
||||||
bind:activeChildKey={activeCollKey}
|
on:select={e => {
|
||||||
on:select={e => openDatabase(e.detail)}
|
if (e.detail?.level === 0) {
|
||||||
on:selectChild={e => openCollection(e.detail)}
|
openDatabase(e.detail.itemKey);
|
||||||
|
}
|
||||||
|
else if (e.detail?.level === 1) {
|
||||||
|
openCollection(e.detail.itemKey);
|
||||||
|
}
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
|
Loading…
Reference in New Issue
Block a user