1
0
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:
Romein van Buren 2023-01-18 16:31:13 +01:00
parent f5a89cf019
commit 2603e6350e
Signed by: romein
GPG Key ID: 0EFF8478ADDF6C49
6 changed files with 52 additions and 74 deletions

View File

@ -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}

View File

@ -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>

View File

@ -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}

View File

@ -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}
/> />

View File

@ -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}>

View File

@ -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}