2023-01-18 11:22:02 +01:00
|
|
|
<script>
|
2023-02-15 19:27:51 +01:00
|
|
|
import Icon from '$components/icon.svelte';
|
2023-08-07 18:21:45 +02:00
|
|
|
import input from '$lib/actions/input.js';
|
|
|
|
import { atomicUpdateOperators } from '$lib/mongo/index.js';
|
|
|
|
import { deepClone } from '$lib/objects.js';
|
|
|
|
import { convertLooseJson, jsonLooseParse } from '$lib/strings.js';
|
|
|
|
import { UpdateItems } from '$wails/go/app/App.js';
|
2023-01-18 11:22:02 +01:00
|
|
|
|
|
|
|
export let collection = {};
|
|
|
|
|
2023-01-18 13:38:31 +01:00
|
|
|
const allOperators = Object.values(atomicUpdateOperators).map(Object.keys).flat();
|
|
|
|
const form = { query: '{}', parameters: [ { type: '$set' } ] };
|
|
|
|
let updatedCount;
|
2023-06-11 09:34:00 +02:00
|
|
|
// $: code = buildCode(form);
|
2023-02-19 17:26:32 +01:00
|
|
|
$: invalid = !form.query || form.parameters?.some(param => {
|
|
|
|
if (!param.value) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
jsonLooseParse(param.value);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
catch {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
});
|
2023-01-18 11:22:02 +01:00
|
|
|
|
2023-06-11 09:34:00 +02:00
|
|
|
// function buildCode(form) {
|
2023-08-07 18:21:45 +02:00
|
|
|
// let operation = '{ ' + form.parameters.filter(p => p.type).map(p =>
|
|
|
|
// `${p.type}: ${p.value || '{}'}`).join(', ') + ' }';
|
2023-06-11 09:34:00 +02:00
|
|
|
// if (operation === '{ }') {
|
|
|
|
// operation = '{}';
|
|
|
|
// }
|
2023-01-18 11:22:02 +01:00
|
|
|
|
2023-06-11 09:34:00 +02:00
|
|
|
// let options = (form.upsert || form.many) ? ', { ' : '';
|
|
|
|
// form.upsert && (options += 'upsert: true');
|
|
|
|
// form.upsert && form.many && (options += ', ');
|
|
|
|
// form.many && (options += 'multi: true');
|
|
|
|
// (form.upsert || form.many) && (options += ' }');
|
2023-01-21 10:45:44 +01:00
|
|
|
|
2023-08-07 18:21:45 +02:00
|
|
|
// const code = `db.${collection.key}.update(${form.query || '{}'},
|
|
|
|
// ${operation}${options});`;
|
2023-06-11 09:34:00 +02:00
|
|
|
// return code;
|
|
|
|
// }
|
2023-01-18 13:38:31 +01:00
|
|
|
|
|
|
|
async function submitQuery() {
|
2023-02-19 17:26:32 +01:00
|
|
|
const f = deepClone(form);
|
|
|
|
f.query = convertLooseJson(f.query);
|
2023-06-11 09:34:00 +02:00
|
|
|
f.parameters = f.parameters.map(param => {
|
|
|
|
return { ...param, value: convertLooseJson(param.value) };
|
|
|
|
});
|
2023-08-07 18:21:45 +02:00
|
|
|
|
|
|
|
updatedCount = await UpdateItems(
|
|
|
|
collection.hostKey,
|
|
|
|
collection.dbKey,
|
|
|
|
collection.key,
|
|
|
|
JSON.stringify(f)
|
|
|
|
);
|
2023-01-18 11:22:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
function removeParam(index) {
|
|
|
|
if (form.parameters.length < 2) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
form.parameters.splice(index, 1);
|
|
|
|
form.parameters = form.parameters;
|
|
|
|
}
|
|
|
|
|
|
|
|
function addParameter(index) {
|
2023-01-18 13:38:31 +01:00
|
|
|
const usedOperators = form.parameters.map(p => p.type);
|
|
|
|
const operator = allOperators.find(o => !usedOperators.includes(o));
|
|
|
|
|
|
|
|
if (!operator) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const newItem = { type: operator };
|
2023-01-18 11:22:02 +01:00
|
|
|
if (typeof index !== 'number') {
|
2023-01-18 13:38:31 +01:00
|
|
|
form.parameters = [ ...form.parameters, newItem ];
|
2023-01-18 11:22:02 +01:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
form.parameters = [
|
|
|
|
...form.parameters.slice(0, index),
|
2023-01-18 13:38:31 +01:00
|
|
|
newItem,
|
2023-01-18 11:22:02 +01:00
|
|
|
...form.parameters.slice(index),
|
|
|
|
];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
</script>
|
|
|
|
|
|
|
|
<form class="update" on:submit|preventDefault={submitQuery}>
|
2023-02-19 17:26:32 +01:00
|
|
|
<!-- <CodeExample language="json" {code} /> -->
|
2023-01-18 11:22:02 +01:00
|
|
|
|
|
|
|
<div class="options">
|
|
|
|
<label class="field">
|
|
|
|
<span class="label">Upsert</span>
|
|
|
|
<span class="checkbox">
|
|
|
|
<input type="checkbox" bind:checked={form.upsert} />
|
|
|
|
</span>
|
|
|
|
</label>
|
|
|
|
|
|
|
|
<label class="field">
|
|
|
|
<span class="label">Many</span>
|
|
|
|
<span class="checkbox">
|
|
|
|
<input type="checkbox" bind:checked={form.many} />
|
|
|
|
</span>
|
|
|
|
</label>
|
2023-01-18 13:38:31 +01:00
|
|
|
|
|
|
|
{#key updatedCount}
|
|
|
|
{#if typeof updatedCount === 'number'}
|
|
|
|
<div class="flash-green">
|
|
|
|
Updated {updatedCount} item{updatedCount === 1 ? '' : 's'}
|
|
|
|
</div>
|
|
|
|
{/if}
|
|
|
|
{/key}
|
|
|
|
|
2023-06-27 17:21:54 +02:00
|
|
|
<button class="button" type="submit" disabled={invalid}>
|
2023-01-20 13:54:57 +01:00
|
|
|
<Icon name="check" /> Update
|
|
|
|
</button>
|
2023-01-18 11:22:02 +01:00
|
|
|
</div>
|
|
|
|
|
|
|
|
<label class="field">
|
|
|
|
<span class="label">Filter</span>
|
2023-08-07 18:21:45 +02:00
|
|
|
<input
|
|
|
|
type="text"
|
|
|
|
class="code"
|
|
|
|
bind:value={form.query}
|
|
|
|
use:input={{ type: 'json', autofocus: true }}
|
|
|
|
placeholder={'{}'} />
|
2023-01-18 11:22:02 +01:00
|
|
|
</label>
|
|
|
|
|
|
|
|
<fieldset class="parameters">
|
|
|
|
{#each form.parameters as param, index}
|
|
|
|
<fieldset class="parameter">
|
|
|
|
<label class="field">
|
2023-01-29 20:00:15 +01:00
|
|
|
<select bind:value={param.type} class="type">
|
2023-06-11 09:34:00 +02:00
|
|
|
{#each Object.entries(atomicUpdateOperators) as [ groupName, options ]}
|
2023-01-18 11:22:02 +01:00
|
|
|
<optgroup label={groupName}>
|
2023-06-11 09:34:00 +02:00
|
|
|
{#each Object.entries(options) as [ key, label ]}
|
2023-02-19 17:26:32 +01:00
|
|
|
<option value={key} disabled={form.parameters.some(p => p.type === key) && (key !== param.type)}>
|
2023-01-18 11:22:02 +01:00
|
|
|
{label}
|
|
|
|
</option>
|
|
|
|
{/each}
|
|
|
|
</optgroup>
|
|
|
|
{/each}
|
|
|
|
</select>
|
2023-08-07 18:21:45 +02:00
|
|
|
<input
|
|
|
|
type="text"
|
|
|
|
class="code"
|
|
|
|
bind:value={param.value}
|
|
|
|
placeholder={'{}'}
|
|
|
|
use:input={{ type: 'json' }}
|
|
|
|
/>
|
2023-01-18 11:22:02 +01:00
|
|
|
</label>
|
|
|
|
|
2023-06-27 17:21:54 +02:00
|
|
|
<button class="button" disabled={form.parameters.length >= allOperators.length} on:click={() => addParameter()} type="button">
|
2023-02-19 17:26:32 +01:00
|
|
|
<Icon name="+" />
|
|
|
|
</button>
|
|
|
|
|
2023-06-27 17:21:54 +02:00
|
|
|
<button class="button" disabled={form.parameters.length < 2} on:click={() => removeParam(index)} type="button">
|
2023-02-19 17:26:32 +01:00
|
|
|
<Icon name="-" />
|
|
|
|
</button>
|
2023-01-18 11:22:02 +01:00
|
|
|
</fieldset>
|
|
|
|
{/each}
|
|
|
|
</fieldset>
|
|
|
|
</form>
|
|
|
|
|
|
|
|
<style>
|
|
|
|
.update {
|
|
|
|
display: grid;
|
|
|
|
gap: 0.5rem;
|
2023-02-19 17:26:32 +01:00
|
|
|
grid-template: auto auto 1fr / 1fr;
|
2023-01-18 11:22:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
.options {
|
|
|
|
display: flex;
|
|
|
|
gap: 0.5rem;
|
2023-01-18 13:38:31 +01:00
|
|
|
align-items: center;
|
|
|
|
}
|
|
|
|
.options button {
|
|
|
|
margin-left: auto;
|
2023-01-18 11:22:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
.parameters {
|
|
|
|
display: flex;
|
|
|
|
flex-direction: column;
|
|
|
|
gap: 0.5rem;
|
|
|
|
}
|
|
|
|
.parameter {
|
|
|
|
display: grid;
|
2023-02-19 17:26:32 +01:00
|
|
|
grid-template: 1fr / 1fr auto auto;
|
2023-01-18 11:22:02 +01:00
|
|
|
gap: 0.5rem;
|
|
|
|
}
|
2023-01-29 20:00:15 +01:00
|
|
|
|
|
|
|
select.type {
|
|
|
|
max-width: 150px;
|
|
|
|
}
|
2023-01-18 11:22:02 +01:00
|
|
|
</style>
|