budibase/packages/client/src/components/app/pdf/PDFTable.svelte

137 lines
3.5 KiB
Svelte

<script lang="ts">
import type {
DataFetchDatasource,
FieldSchema,
GroupUserDatasource,
SortOrder,
TableSchema,
UISearchFilter,
UserDatasource,
} from "@budibase/types"
import { fetchData, QueryUtils, stringifyRow } from "@budibase/frontend-core"
import { getContext } from "svelte"
type ProviderDatasource = Exclude<
DataFetchDatasource,
UserDatasource | GroupUserDatasource
>
type ChosenColumns = Array<{ name: string; displayName?: string }> | undefined
type Schema = { [key: string]: FieldSchema & { displayName: string } }
export let datasource: ProviderDatasource
export let filter: UISearchFilter | undefined = undefined
export let sortColumn: string | undefined = undefined
export let sortOrder: SortOrder | undefined = undefined
export let columns: ChosenColumns = undefined
const component = getContext("component")
const { styleable, API } = getContext("sdk")
$: query = QueryUtils.buildQuery(filter)
$: fetch = createFetch(datasource)
$: fetch.update({
query,
sortColumn,
sortOrder,
limit: 100,
paginate: false,
})
$: schema = sanitizeSchema($fetch.schema, columns)
$: columnCount = Object.keys(schema).length
$: rowCount = $fetch.rows?.length || 0
$: stringifiedRows = ($fetch?.rows || []).map(row =>
stringifyRow(row, schema)
)
const createFetch = (datasource: ProviderDatasource) => {
return fetchData({
API,
datasource,
options: {
query,
sortColumn,
sortOrder,
},
})
}
const sanitizeSchema = (
schema: TableSchema | null,
columns: ChosenColumns
): Schema => {
if (!schema) {
return {}
}
let sanitized: Schema = {}
// Clean out hidden fields and ensure we have
Object.entries(schema).forEach(([field, fieldSchema]) => {
if (fieldSchema.visible !== false) {
sanitized[field] = {
...fieldSchema,
displayName: field,
}
}
})
// Clean out unselected columns
if (columns?.length) {
let pruned: Schema = {}
for (let col of columns) {
if (sanitized[col.name]) {
pruned[col.name] = {
...sanitized[col.name],
displayName: col.displayName || sanitized[col.name].displayName,
}
}
}
sanitized = pruned
}
return sanitized
}
</script>
<div class="vars" style="--cols:{columnCount}; --rows:{rowCount};">
<div class="table" class:valid={!!schema} use:styleable={$component.styles}>
{#if schema}
{#each Object.keys(schema) as col}
<div class="cell header">{schema[col].displayName}</div>
{/each}
{#each stringifiedRows as row}
{#each Object.keys(schema) as col}
<div class="cell">{row[col]}</div>
{/each}
{/each}
{/if}
</div>
</div>
<style>
.vars {
display: contents;
--border-color: var(--spectrum-global-color-gray-300);
}
.table {
display: grid;
grid-template-columns: repeat(var(--cols), minmax(20px, auto));
grid-template-rows: repeat(var(--rows), max-content);
overflow: hidden;
background: white;
}
.table.valid {
border-left: 1px solid var(--border-color);
border-top: 1px solid var(--border-color);
}
.cell {
border-right: 1px solid var(--border-color);
border-bottom: 1px solid var(--border-color);
padding: var(--spacing-xs) var(--spacing-s);
overflow: hidden;
word-break: break-word;
}
.cell.header {
font-weight: 600;
}
</style>