Add functional backend UI for navigating relationships
This commit is contained in:
parent
9a9430e0cf
commit
7aa040d314
|
@ -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}
|
|
@ -1,5 +1,5 @@
|
|||
<script>
|
||||
import { goto } from "@sveltech/routify"
|
||||
import { goto, params } from "@sveltech/routify"
|
||||
import { onMount } from "svelte"
|
||||
import fsort from "fast-sort"
|
||||
import getOr from "lodash/fp/getOr"
|
||||
|
@ -32,13 +32,17 @@
|
|||
$: paginatedData =
|
||||
sorted && sorted.length
|
||||
? sorted.slice(
|
||||
currentPage * ITEMS_PER_PAGE,
|
||||
currentPage * ITEMS_PER_PAGE + ITEMS_PER_PAGE
|
||||
)
|
||||
currentPage * ITEMS_PER_PAGE,
|
||||
currentPage * ITEMS_PER_PAGE + ITEMS_PER_PAGE,
|
||||
)
|
||||
: []
|
||||
$: modelId = data?.length ? data[0].modelId : null
|
||||
|
||||
function selectRelationship(recordId, fieldName) {
|
||||
$goto(`../relationship/${recordId}/${fieldName}`)
|
||||
function selectRelationship(record, fieldName) {
|
||||
if (!record?.[fieldName]?.length) {
|
||||
return
|
||||
}
|
||||
$goto(`/${$params.application}/backend/model/${modelId}/relationship/${record._id}/${fieldName}`)
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@ -46,66 +50,68 @@
|
|||
<div class="table-controls">
|
||||
<h2 class="title">{title}</h2>
|
||||
<div class="popovers">
|
||||
<slot />
|
||||
<slot/>
|
||||
</div>
|
||||
</div>
|
||||
<table class="bb-table">
|
||||
<thead>
|
||||
<tr>
|
||||
{#if allowEditing}
|
||||
<th class="edit-header">
|
||||
<div>Edit</div>
|
||||
</th>
|
||||
{/if}
|
||||
{#each columns as header}
|
||||
<th>
|
||||
{#if allowEditing}
|
||||
<ColumnHeaderPopover field={schema[header]} />
|
||||
{:else}{header}{/if}
|
||||
</th>
|
||||
{/each}
|
||||
</tr>
|
||||
<tr>
|
||||
{#if allowEditing}
|
||||
<th class="edit-header">
|
||||
<div>Edit</div>
|
||||
</th>
|
||||
{/if}
|
||||
{#each columns as header}
|
||||
<th>
|
||||
{#if allowEditing}
|
||||
<ColumnHeaderPopover field={schema[header]}/>
|
||||
{:else}
|
||||
<div class="header">{header}</div>
|
||||
{/if}
|
||||
</th>
|
||||
{/each}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{#if paginatedData.length === 0}
|
||||
{#if paginatedData.length === 0}
|
||||
{#if allowEditing}
|
||||
<td class="no-border">No data.</td>
|
||||
{/if}
|
||||
{#each columns as header, idx}
|
||||
<td class="no-border">
|
||||
{#if idx === 0}No data.{/if}
|
||||
</td>
|
||||
{/each}
|
||||
{/if}
|
||||
{#each paginatedData as row}
|
||||
<tr>
|
||||
{#if allowEditing}
|
||||
<td class="no-border">No data.</td>
|
||||
<td>
|
||||
<EditRowPopover {row}/>
|
||||
</td>
|
||||
{/if}
|
||||
{#each columns as header, idx}
|
||||
<td class="no-border">
|
||||
{#if idx === 0}No data.{/if}
|
||||
{#each columns as header}
|
||||
<td>
|
||||
{#if schema[header].type === 'link'}
|
||||
<div
|
||||
class:link={row[header] && row[header].length}
|
||||
on:click={() => selectRelationship(row, header)}>
|
||||
{row[header] ? row[header].length : 0} linked row(s)
|
||||
</div>
|
||||
{:else if schema[header].type === 'attachment'}
|
||||
<AttachmentList files={row[header] || []}/>
|
||||
{:else}{getOr('', header, row)}{/if}
|
||||
</td>
|
||||
{/each}
|
||||
{/if}
|
||||
{#each paginatedData as row}
|
||||
<tr>
|
||||
{#if allowEditing}
|
||||
<td>
|
||||
<EditRowPopover {row} />
|
||||
</td>
|
||||
{/if}
|
||||
{#each columns as header}
|
||||
<td>
|
||||
{#if schema[header].type === 'link'}
|
||||
<div
|
||||
class="link"
|
||||
on:click={() => selectRelationship(row._id, header)}>
|
||||
{row[header] ? row[header].length : 0} linked row(s)
|
||||
</div>
|
||||
{:else if schema[header].type === 'attachment'}
|
||||
<AttachmentList files={row[header] || []} />
|
||||
{:else}{getOr('', header, row)}{/if}
|
||||
</td>
|
||||
{/each}
|
||||
</tr>
|
||||
{/each}
|
||||
</tr>
|
||||
{/each}
|
||||
</tbody>
|
||||
</table>
|
||||
<TablePagination
|
||||
{data}
|
||||
bind:currentPage
|
||||
pageItemCount={paginatedData.length}
|
||||
{ITEMS_PER_PAGE} />
|
||||
{data}
|
||||
bind:currentPage
|
||||
pageItemCount={paginatedData.length}
|
||||
{ITEMS_PER_PAGE}/>
|
||||
</section>
|
||||
|
||||
<style>
|
||||
|
@ -121,12 +127,14 @@
|
|||
border: 1px solid var(--grey-4);
|
||||
background: #fff;
|
||||
border-collapse: collapse;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
thead {
|
||||
background: var(--grey-3);
|
||||
border: 1px solid var(--grey-4);
|
||||
}
|
||||
|
||||
thead th {
|
||||
color: var(--ink);
|
||||
font-weight: 500;
|
||||
|
@ -138,11 +146,16 @@
|
|||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
thead th:hover {
|
||||
color: var(--blue);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.header {
|
||||
text-transform: capitalize;
|
||||
}
|
||||
|
||||
td {
|
||||
max-width: 200px;
|
||||
text-overflow: ellipsis;
|
||||
|
@ -152,6 +165,7 @@
|
|||
padding: var(--spacing-l) var(--spacing-m);
|
||||
font-size: var(--font-size-xs);
|
||||
}
|
||||
|
||||
td.no-border {
|
||||
border: none;
|
||||
}
|
||||
|
@ -161,6 +175,7 @@
|
|||
transition: 0.3s background-color;
|
||||
color: var(--ink);
|
||||
}
|
||||
|
||||
tbody tr:hover {
|
||||
background: var(--grey-1);
|
||||
}
|
||||
|
@ -175,11 +190,13 @@
|
|||
|
||||
:global(.popovers > div) {
|
||||
margin-right: var(--spacing-m);
|
||||
margin-bottom: var(--spacing-xl);
|
||||
}
|
||||
|
||||
.edit-header {
|
||||
width: 60px;
|
||||
}
|
||||
|
||||
.edit-header:hover {
|
||||
cursor: default;
|
||||
color: var(--ink);
|
||||
|
@ -188,6 +205,7 @@
|
|||
.link {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.link:hover {
|
||||
color: var(--grey-6);
|
||||
cursor: pointer;
|
||||
|
|
|
@ -69,11 +69,13 @@
|
|||
{/each}
|
||||
</Select>
|
||||
|
||||
<Toggle
|
||||
checked={!field.constraints.presence.allowEmpty}
|
||||
on:change={e => (field.constraints.presence.allowEmpty = !e.target.checked)}
|
||||
thin
|
||||
text="Required" />
|
||||
{#if field.type !== 'link'}
|
||||
<Toggle
|
||||
checked={!field.constraints.presence.allowEmpty}
|
||||
on:change={e => (field.constraints.presence.allowEmpty = !e.target.checked)}
|
||||
thin
|
||||
text="Required" />
|
||||
{/if}
|
||||
|
||||
{#if field.type === 'string'}
|
||||
<Input
|
||||
|
|
|
@ -13,19 +13,17 @@
|
|||
export let onClosed
|
||||
|
||||
let errors = []
|
||||
let selectedModel
|
||||
|
||||
$: modelSchema = $backendUiStore.selectedModel
|
||||
? Object.entries($backendUiStore.selectedModel.schema)
|
||||
: []
|
||||
$: model = record.modelId ? $backendUiStore.models.find(model => model._id === record?.modelId) : $backendUiStore.selectedModel
|
||||
$: modelSchema = Object.entries(model?.schema ?? {})
|
||||
$: console.log(modelSchema)
|
||||
|
||||
async function saveRecord() {
|
||||
const recordResponse = await api.saveRecord(
|
||||
{
|
||||
...record,
|
||||
modelId: $backendUiStore.selectedModel._id,
|
||||
modelId: model._id,
|
||||
},
|
||||
$backendUiStore.selectedModel._id
|
||||
model._id
|
||||
)
|
||||
if (recordResponse.errors) {
|
||||
errors = Object.keys(recordResponse.errors)
|
||||
|
|
|
@ -1,18 +1,7 @@
|
|||
<script>
|
||||
import { onMount } from "svelte"
|
||||
import { params } from "@sveltech/routify"
|
||||
import { backendUiStore } from "builderStore"
|
||||
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)
|
||||
})
|
||||
import RelationshipDataTable from "components/backend/DataTable/RelationshipDataTable.svelte"
|
||||
</script>
|
||||
|
||||
<div>hello world!</div>
|
||||
<RelationshipDataTable modelId={$params.selectedModel} recordId={$params.selectedRecord}
|
||||
fieldName={$params.selectedField}/>
|
||||
|
|
Loading…
Reference in New Issue