Add functional backend UI for navigating relationships

This commit is contained in:
Andrew Kingston 2020-10-01 11:01:06 +01:00
parent 9a9430e0cf
commit 7aa040d314
5 changed files with 118 additions and 79 deletions

View File

@ -0,0 +1,32 @@
<script>
import api from "builderStore/api"
import Table from "./Table.svelte"
import { onMount } from "svelte"
import { backendUiStore } from "builderStore"
export let modelId
export let recordId
export let fieldName
let record
$: data = record?.[fieldName] ?? []
$: linkedModelId = data?.length ? data[0].modelId : null
$: linkedModel = $backendUiStore.models.find(
model => model._id === linkedModelId
)
$: schema = linkedModel?.schema
$: model = $backendUiStore.models.find(model => model._id === modelId)
$: title = `${record?.[model?.primaryDisplay]} - ${fieldName}`
$: fetchData(modelId, recordId)
async function fetchData(modelId, recordId) {
const QUERY_VIEW_URL = `/api/${modelId}/${recordId}/enrich`
const response = await api.get(QUERY_VIEW_URL)
record = await response.json()
}
</script>
{#if record && record._id === recordId}
<Table {title} {schema} {data} />
{/if}

View File

@ -1,5 +1,5 @@
<script> <script>
import { goto } from "@sveltech/routify" import { goto, params } from "@sveltech/routify"
import { onMount } from "svelte" import { onMount } from "svelte"
import fsort from "fast-sort" import fsort from "fast-sort"
import getOr from "lodash/fp/getOr" import getOr from "lodash/fp/getOr"
@ -33,12 +33,16 @@
sorted && sorted.length sorted && sorted.length
? sorted.slice( ? sorted.slice(
currentPage * ITEMS_PER_PAGE, currentPage * ITEMS_PER_PAGE,
currentPage * ITEMS_PER_PAGE + ITEMS_PER_PAGE currentPage * ITEMS_PER_PAGE + ITEMS_PER_PAGE,
) )
: [] : []
$: modelId = data?.length ? data[0].modelId : null
function selectRelationship(recordId, fieldName) { function selectRelationship(record, fieldName) {
$goto(`../relationship/${recordId}/${fieldName}`) if (!record?.[fieldName]?.length) {
return
}
$goto(`/${$params.application}/backend/model/${modelId}/relationship/${record._id}/${fieldName}`)
} }
</script> </script>
@ -61,7 +65,9 @@
<th> <th>
{#if allowEditing} {#if allowEditing}
<ColumnHeaderPopover field={schema[header]}/> <ColumnHeaderPopover field={schema[header]}/>
{:else}{header}{/if} {:else}
<div class="header">{header}</div>
{/if}
</th> </th>
{/each} {/each}
</tr> </tr>
@ -88,8 +94,8 @@
<td> <td>
{#if schema[header].type === 'link'} {#if schema[header].type === 'link'}
<div <div
class="link" class:link={row[header] && row[header].length}
on:click={() => selectRelationship(row._id, header)}> on:click={() => selectRelationship(row, header)}>
{row[header] ? row[header].length : 0} linked row(s) {row[header] ? row[header].length : 0} linked row(s)
</div> </div>
{:else if schema[header].type === 'attachment'} {:else if schema[header].type === 'attachment'}
@ -121,12 +127,14 @@
border: 1px solid var(--grey-4); border: 1px solid var(--grey-4);
background: #fff; background: #fff;
border-collapse: collapse; border-collapse: collapse;
margin-top: 0;
} }
thead { thead {
background: var(--grey-3); background: var(--grey-3);
border: 1px solid var(--grey-4); border: 1px solid var(--grey-4);
} }
thead th { thead th {
color: var(--ink); color: var(--ink);
font-weight: 500; font-weight: 500;
@ -138,11 +146,16 @@
padding-top: 0; padding-top: 0;
padding-bottom: 0; padding-bottom: 0;
} }
thead th:hover { thead th:hover {
color: var(--blue); color: var(--blue);
cursor: pointer; cursor: pointer;
} }
.header {
text-transform: capitalize;
}
td { td {
max-width: 200px; max-width: 200px;
text-overflow: ellipsis; text-overflow: ellipsis;
@ -152,6 +165,7 @@
padding: var(--spacing-l) var(--spacing-m); padding: var(--spacing-l) var(--spacing-m);
font-size: var(--font-size-xs); font-size: var(--font-size-xs);
} }
td.no-border { td.no-border {
border: none; border: none;
} }
@ -161,6 +175,7 @@
transition: 0.3s background-color; transition: 0.3s background-color;
color: var(--ink); color: var(--ink);
} }
tbody tr:hover { tbody tr:hover {
background: var(--grey-1); background: var(--grey-1);
} }
@ -175,11 +190,13 @@
:global(.popovers > div) { :global(.popovers > div) {
margin-right: var(--spacing-m); margin-right: var(--spacing-m);
margin-bottom: var(--spacing-xl);
} }
.edit-header { .edit-header {
width: 60px; width: 60px;
} }
.edit-header:hover { .edit-header:hover {
cursor: default; cursor: default;
color: var(--ink); color: var(--ink);
@ -188,6 +205,7 @@
.link { .link {
text-decoration: underline; text-decoration: underline;
} }
.link:hover { .link:hover {
color: var(--grey-6); color: var(--grey-6);
cursor: pointer; cursor: pointer;

View File

@ -69,11 +69,13 @@
{/each} {/each}
</Select> </Select>
{#if field.type !== 'link'}
<Toggle <Toggle
checked={!field.constraints.presence.allowEmpty} checked={!field.constraints.presence.allowEmpty}
on:change={e => (field.constraints.presence.allowEmpty = !e.target.checked)} on:change={e => (field.constraints.presence.allowEmpty = !e.target.checked)}
thin thin
text="Required" /> text="Required" />
{/if}
{#if field.type === 'string'} {#if field.type === 'string'}
<Input <Input

View File

@ -13,19 +13,17 @@
export let onClosed export let onClosed
let errors = [] let errors = []
let selectedModel $: model = record.modelId ? $backendUiStore.models.find(model => model._id === record?.modelId) : $backendUiStore.selectedModel
$: modelSchema = Object.entries(model?.schema ?? {})
$: modelSchema = $backendUiStore.selectedModel $: console.log(modelSchema)
? Object.entries($backendUiStore.selectedModel.schema)
: []
async function saveRecord() { async function saveRecord() {
const recordResponse = await api.saveRecord( const recordResponse = await api.saveRecord(
{ {
...record, ...record,
modelId: $backendUiStore.selectedModel._id, modelId: model._id,
}, },
$backendUiStore.selectedModel._id model._id
) )
if (recordResponse.errors) { if (recordResponse.errors) {
errors = Object.keys(recordResponse.errors) errors = Object.keys(recordResponse.errors)

View File

@ -1,18 +1,7 @@
<script> <script>
import { onMount } from "svelte"
import { params } from "@sveltech/routify" import { params } from "@sveltech/routify"
import { backendUiStore } from "builderStore" import RelationshipDataTable from "components/backend/DataTable/RelationshipDataTable.svelte"
import api from "../../../../../../../../builderStore/api"
console.log($params)
let data
onMount(async () => {
const QUERY_VIEW_URL = `/api/${$params.selectedModel}/${$params.selectedRecord}/enrich`
const response = await api.get(QUERY_VIEW_URL)
data = await response.json()
console.log(data)
})
</script> </script>
<div>hello world!</div> <RelationshipDataTable modelId={$params.selectedModel} recordId={$params.selectedRecord}
fieldName={$params.selectedField}/>