budibase/packages/builder/src/components/backend/DataTable/ModelDataTable.svelte

188 lines
4.5 KiB
Svelte
Raw Normal View History

2020-03-10 14:53:23 +01:00
<script>
2020-08-07 19:31:40 +02:00
import { onMount } from "svelte"
2020-08-10 16:34:37 +02:00
import fsort from "fast-sort"
2020-08-14 17:31:53 +02:00
import getOr from "lodash/fp/getOr"
import { store, backendUiStore } from "builderStore"
2020-08-07 17:13:57 +02:00
import { Button, Icon } from "@budibase/bbui"
import ActionButton from "components/common/ActionButton.svelte"
2020-06-23 17:20:06 +02:00
import LinkedRecord from "./LinkedRecord.svelte"
2020-09-17 13:45:28 +02:00
import AttachmentList from "./AttachmentList.svelte"
2020-03-12 15:23:29 +01:00
import TablePagination from "./TablePagination.svelte"
import CreateEditRecordModal from "./popovers/CreateEditRecord.svelte"
2020-08-07 17:13:57 +02:00
import RowPopover from "./popovers/Row.svelte"
import ColumnPopover from "./popovers/Column.svelte"
2020-08-14 17:31:53 +02:00
import ViewPopover from "./popovers/View.svelte"
2020-08-07 17:13:57 +02:00
import ColumnHeaderPopover from "./popovers/ColumnHeader.svelte"
2020-08-07 19:31:40 +02:00
import EditRowPopover from "./popovers/EditRow.svelte"
2020-03-12 15:23:29 +01:00
import * as api from "./api"
2020-03-10 17:06:30 +01:00
const ITEMS_PER_PAGE = 10
2020-03-25 17:59:32 +01:00
// Internal headers we want to hide from the user
const INTERNAL_HEADERS = ["_id", "_rev", "modelId", "type"]
2020-03-22 10:21:18 +01:00
2020-03-12 15:23:29 +01:00
let modalOpen = false
2020-03-24 12:35:46 +01:00
let data = []
let headers = []
2020-03-22 10:21:18 +01:00
let currentPage = 0
2020-06-22 22:30:23 +02:00
let search
2020-03-12 15:23:29 +01:00
$: {
2020-08-18 18:14:26 +02:00
if (
$backendUiStore.selectedView &&
$backendUiStore.selectedView.name.startsWith("all_")
) {
2020-06-23 17:20:06 +02:00
api.fetchDataForView($backendUiStore.selectedView).then(records => {
data = records || []
})
}
}
2020-03-24 12:35:46 +01:00
2020-09-14 17:18:02 +02:00
$: sort = $backendUiStore.sort
$: sorted = sort ? fsort(data)[sort.direction](sort.column) : data
$: paginatedData = sorted
? sorted.slice(
2020-06-18 18:17:18 +02:00
currentPage * ITEMS_PER_PAGE,
currentPage * ITEMS_PER_PAGE + ITEMS_PER_PAGE
)
: []
2020-08-20 18:04:54 +02:00
$: headers = Object.keys($backendUiStore.selectedModel.schema)
.sort()
.filter(id => !INTERNAL_HEADERS.includes(id))
$: schema = $backendUiStore.selectedModel.schema
2020-03-10 14:53:23 +01:00
</script>
2020-03-23 11:43:34 +01:00
<section>
<h2 class="title">{$backendUiStore.selectedModel.name}</h2>
<div class="popovers">
<ColumnPopover />
{#if Object.keys($backendUiStore.selectedModel.schema).length > 0}
<RowPopover />
<ViewPopover />
{/if}
2020-03-23 11:43:34 +01:00
</div>
<table class="bb-table">
2020-03-23 11:43:34 +01:00
<thead>
<tr>
2020-08-10 16:34:37 +02:00
<th class="edit-header">
2020-08-07 17:13:57 +02:00
<div>Edit</div>
</th>
2020-03-23 11:43:34 +01:00
{#each headers as header}
2020-08-07 17:13:57 +02:00
<th>
<ColumnHeaderPopover
field={$backendUiStore.selectedModel.schema[header]} />
</th>
2020-03-10 17:06:30 +01:00
{/each}
2020-03-23 11:43:34 +01:00
</tr>
</thead>
<tbody>
2020-09-14 17:18:02 +02:00
{#if paginatedData.length === 0}
<td class="no-border">No data.</td>
{#each headers as header}
<td class="no-border" />
{/each}
2020-03-23 11:43:34 +01:00
{/if}
2020-09-14 17:18:02 +02:00
{#each paginatedData as row}
2020-08-07 17:13:57 +02:00
<tr>
2020-03-23 11:43:34 +01:00
<td>
2020-08-07 19:31:40 +02:00
<EditRowPopover {row} />
2020-03-23 11:43:34 +01:00
</td>
{#each headers as header}
2020-08-11 18:58:01 +02:00
<td>
2020-06-24 17:12:55 +02:00
{#if schema[header].type === 'link'}
{JSON.stringify(row[header])}
2020-09-11 16:09:56 +02:00
{:else if schema[header].type === 'attachment'}
2020-09-17 13:45:28 +02:00
<AttachmentList files={row[header] || []} />
{:else}{getOr('', header, row)}{/if}
2020-06-22 22:30:23 +02:00
</td>
2020-03-23 11:43:34 +01:00
{/each}
</tr>
{/each}
</tbody>
</table>
<TablePagination
2020-03-25 11:59:47 +01:00
{data}
2020-03-23 11:43:34 +01:00
bind:currentPage
2020-09-14 17:18:02 +02:00
pageItemCount={paginatedData.length}
2020-03-25 17:59:32 +01:00
{ITEMS_PER_PAGE} />
2020-03-23 11:43:34 +01:00
</section>
2020-03-10 14:53:23 +01:00
<style>
.title {
font-size: 24px;
font-weight: 600;
text-rendering: optimizeLegibility;
text-transform: capitalize;
margin-top: 0;
}
.popovers {
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: center;
}
2020-03-10 14:53:23 +01:00
table {
border: 1px solid var(--grey-4);
2020-03-10 17:06:30 +01:00
background: #fff;
2020-03-22 10:21:18 +01:00
border-collapse: collapse;
2020-03-10 14:53:23 +01:00
}
thead {
2020-08-07 17:13:57 +02:00
background: var(--grey-3);
border-bottom: 1px solid var(--grey-4);
2020-03-10 14:53:23 +01:00
}
thead th {
color: var(--ink);
2020-03-10 17:06:30 +01:00
font-weight: 500;
2020-04-06 16:38:33 +02:00
font-size: 14px;
text-rendering: optimizeLegibility;
2020-08-07 17:13:57 +02:00
transition: 0.5s all;
2020-08-10 16:34:37 +02:00
vertical-align: middle;
height: 48px;
padding-top: 0;
padding-bottom: 0;
2020-08-07 17:13:57 +02:00
}
2020-08-10 16:34:37 +02:00
.edit-header {
width: 100px;
cursor: default;
}
.edit-header:hover {
color: var(--ink);
}
2020-08-07 17:13:57 +02:00
th:hover {
color: var(--blue);
2020-08-10 16:34:37 +02:00
cursor: pointer;
2020-08-07 17:13:57 +02:00
}
td {
max-width: 200px;
text-overflow: ellipsis;
border: 1px solid var(--grey-4);
2020-08-13 09:58:48 +02:00
overflow: hidden;
white-space: nowrap;
2020-08-13 09:58:48 +02:00
box-sizing: border-box;
padding: var(--spacing-l) var(--spacing-m);
font-size: var(--font-size-xs);
}
td.no-border {
border: none;
2020-03-10 14:53:23 +01:00
}
2020-03-10 17:06:30 +01:00
tbody {
border: 1px solid var(--grey-4);
}
tbody tr {
border-bottom: 1px solid var(--grey-4);
transition: 0.3s background-color;
color: var(--ink);
}
tbody tr:hover {
background: var(--grey-1);
2020-03-10 14:53:23 +01:00
}
2020-03-10 17:06:30 +01:00
</style>