1
0
mirror of https://github.com/garraflavatra/rolens.git synced 2025-04-04 03:21:03 +00:00
2023-02-15 19:27:51 +01:00

190 lines
5.4 KiB
Svelte

<script>
import Details from '$components/details.svelte';
import Grid from '$components/grid.svelte';
import Icon from '$components/icon.svelte';
import ObjectViewer from '$components/objectviewer.svelte';
import input from '$lib/actions/input';
import { randomString } from '$lib/math';
import { inputTypes } from '$lib/mongo';
import views from '$lib/stores/views';
import { InsertItems } from '$wails/go/app/App';
import { EJSON } from 'bson';
import { createEventDispatcher } from 'svelte';
import Form from './components/form.svelte';
export let collection;
const dispatch = createEventDispatcher();
const formValidity = {};
let json = '';
let newItems = [];
let insertedIds;
let objectViewerData = '';
let viewType = 'form';
let allValid = false;
$: viewsForCollection = views.forCollection(collection.hostKey, collection.dbKey, collection.key);
$: oppositeViewType = viewType === 'table' ? 'form' : 'table';
$: allValid = Object.values(formValidity).every(v => v !== false);
$: {
if (collection.viewKey === 'list') {
try {
newItems = EJSON.parse(json, { relaxed: false });
}
catch { /* ok */ }
}
else {
json = EJSON.stringify(newItems, undefined, 2, { relaxed: false });
}
}
async function insert() {
insertedIds = await InsertItems(collection.hostKey, collection.dbKey, collection.key, json);
if ((collection.viewKey === 'list') && insertedIds) {
newItems = [];
}
}
function showDocs() {
dispatch('performFind', {
query: insertedIds.length === 1
? `{ "_id": ${JSON.stringify(insertedIds[0])} }`
: `{ "_id": { "$in": [ ${insertedIds.map(id => JSON.stringify(id)).join(', ')} ] } }`,
});
}
function switchViewType() {
viewType = oppositeViewType;
}
function showJson() {
if (viewType === 'form') {
objectViewerData = { ...(newItems[0] || {}) };
}
else if (viewType === 'table') {
objectViewerData = [ ...newItems ];
}
}
function addRow() {
newItems = [ ...newItems, {} ];
}
function deleteRow(index) {
newItems.splice(index, 1);
newItems = newItems;
}
</script>
<form on:submit|preventDefault={insert}>
<div class="items">
{#if collection.viewKey === 'list'}
<label class="field">
<textarea
cols="30"
rows="10"
placeholder="[]"
class="code"
bind:value={json}
use:input={{ type: 'json', autofocus: true }}
></textarea>
</label>
{:else if viewType === 'form'}
<div class="form">
{#each newItems as item, index}
<Details
title="Item #{index + 1} {(item._id !== undefined) ? `(${item._id})` : ''}"
initiallyOpen={index === 0}
deletable={true}
on:delete={() => deleteRow(index)}
>
<fieldset>
<Form bind:item={newItems[index]} bind:valid={formValidity[index]} view={$views[collection.viewKey]} />
</fieldset>
</Details>
{/each}
</div>
{:else if viewType === 'table'}
<div class="table">
<Grid
key="id"
items={newItems}
columns={
$views[collection.viewKey]?.columns
?.filter(c => inputTypes.includes(c.inputType))
.map(c => ({ ...c, id: randomString(8), title: c.key })) || []
}
showHeaders={true}
canSelect={false}
canRemoveItems={true}
hideChildrenToggles={true}
on:addRow={addRow}
bind:inputsValid={allValid}
/>
</div>
{/if}
</div>
<div class="flex">
<div>
{#if collection.viewKey !== 'list'}
<button class="btn" type="button" on:click={addRow}>
<Icon name="+" /> Add item
</button>
{/if}
{#if insertedIds}
<span class="flash-green">Success! {insertedIds.length} document{insertedIds.length > 1 ? 's' : ''} inserted</span>
{/if}
</div>
<div>
{#if insertedIds}
<button class="btn" type="button" on:click={showDocs}>View inserted docs</button>
{/if}
{#if collection.viewKey !== 'list'}
<button class="btn" type="button" on:click={showJson} title="Show JSON">
<Icon name="code" />
</button>
<button class="btn" type="button" on:click={switchViewType} title="Edit as {oppositeViewType}">
<Icon name={oppositeViewType} />
</button>
{/if}
<label class="field inline">
<select bind:value={collection.viewKey}>
{#each Object.entries(viewsForCollection) as [key, view]}
<option value={key}>{key === 'list' ? 'Raw JSON' : view.name}</option>
{/each}
</select>
<button class="btn" type="button" on:click={() => dispatch('openViewConfig')} title="Configure view">
<Icon name="cog" />
</button>
</label>
<button type="submit" class="btn" disabled={$views[collection.viewKey]?.type === 'list' ? !json : !allValid}>
<Icon name="+" /> Insert
</button>
</div>
</div>
</form>
<ObjectViewer data={objectViewerData} />
<style>
form {
display: grid;
grid-template: 1fr auto / 1fr;
gap: 0.5rem;
}
.items {
overflow: auto;
}
.items .table {
background-color: #fff;
border: 1px solid #ccc;
}
.flex {
display: flex;
justify-content: space-between;
}
</style>