Add custom renderers to table and improve table sorting

This commit is contained in:
Andrew Kingston 2021-04-09 14:21:27 +01:00
parent 2b46f8bfbc
commit b699573941
8 changed files with 39 additions and 251 deletions

View File

@ -4,10 +4,15 @@
const displayLimit = 5
$: attachments = value?.slice(0, displayLimit) ?? []
$: leftover = (value?.length ?? 0) - attachments.length
const imageExtensions = ["png", "tiff", "gif", "raw", "jpg", "jpeg"]
const isImage = extension => {
return imageExtensions.includes(extension?.toLowerCase())
}
</script>
{#each attachments as attachment}
{#if attachment.type?.startsWith('image')}
{#if isImage(attachment.extension)}
<img src={attachment.url} alt={attachment.extension} />
{:else}
<div class="file">{attachment.extension}</div>

View File

@ -7,13 +7,17 @@
export let schema
export let value
export let customRenderers = []
const plainTypes = ["string", "options", "number", "longform"]
$: type = schema?.type ?? "string"
$: customRenderer = customRenderers?.find(x => x.column === schema?.name)
</script>
{#if value != null && value !== ''}
{#if plainTypes.includes(type)}
{#if customRenderer}
<svelte:component this={customRenderer.component} {value} />
{:else if plainTypes.includes(type)}
<StringRenderer {value} />
{:else if type === 'boolean'}
<BooleanRenderer {value} />

View File

@ -16,6 +16,7 @@
export let selectedRows = []
export let customColumnRenderer = SelectEditRenderer
export let customColumnTitle
export let customRenderers = []
const dispatch = createEventDispatcher()
@ -93,7 +94,11 @@
autoColumns.push(field)
}
})
return columns.sort().concat(autoColumns)
return columns
.sort((a, b) => {
return a.toLowerCase() < b.toLowerCase() ? a : b
})
.concat(autoColumns)
}
const onScroll = event => {
@ -181,7 +186,7 @@
<use xlink:href="#spectrum-css-icon-Arrow100" />
</svg>
{/if}
{#if allowEditColumns}
{#if allowEditColumns && schema[field]?.editable !== false}
<svg
class="spectrum-Icon spectrum-Table-editIcon"
focusable="false"
@ -218,7 +223,10 @@
{#each fields as field}
<td class="spectrum-Table-cell">
<div class="spectrum-Table-cell-content">
<CellRenderer schema={schema[field]} value={row[field]} />
<CellRenderer
{customRenderers}
schema={schema[field]}
value={row[field]} />
</div>
</td>
{/each}

View File

@ -12,6 +12,7 @@
import CreateEditColumn from "./modals/CreateEditColumn.svelte"
import "@budibase/svelte-ag-grid/dist/index.css"
import { TableNames, UNEDITABLE_USER_FIELDS } from "constants"
import RoleCell from "./cells/RoleCell.svelte"
export let schema = {}
export let data = []
@ -28,12 +29,23 @@
let editableRow
let editRowModal
let editColumnModal
let customRenderers = []
$: isUsersTable = tableId === TableNames.USERS
$: editRowComponent = isUsersTable ? CreateEditUser : CreateEditRow
$: {
if (isUsersTable) {
console.log(schema)
customRenderers = [
{
column: "roleId",
component: RoleCell,
},
]
UNEDITABLE_USER_FIELDS.forEach(field => {
if (schema[field]) {
schema[field].editable = false
}
})
schema.email.displayName = "Email"
schema.roleId.displayName = "Role"
if (schema.status) {
@ -97,6 +109,7 @@
{data}
{schema}
{loading}
{customRenderers}
customColumnTitle="Edit"
bind:selectedRows
showAutoColumns={!hideAutocolumns}

View File

@ -1,69 +0,0 @@
<script>
import { FILE_TYPES } from "constants/backend"
export let files
export let height = "70"
export let width = "70"
</script>
<div class="file-list">
{#each files as file}
<div class="file">
{#if FILE_TYPES.IMAGE.includes(file.extension.toLowerCase())}
<img {width} {height} src={file.url} />
{:else}
<span class="extension">.{file.extension}</span>
<i class="ri-file-line" />
<span>{file.name}</span>
{/if}
</div>
{/each}
</div>
<style>
.file-list {
display: grid;
grid-auto-flow: column;
grid-gap: var(--spacing-m);
grid-template-columns: repeat(10, 1fr);
}
img {
object-fit: contain;
}
i {
font-size: 24px;
position: relative;
top: 5px;
}
.file {
height: 75px;
width: 75px;
border: 2px dashed var(--grey-7);
padding: var(--spacing-m);
display: flex;
flex-direction: column;
align-items: center;
position: relative;
justify-content: center;
overflow: hidden;
text-overflow: ellipsis;
}
.extension {
position: absolute;
top: -5px;
font-size: var(--font-size-xs);
font-weight: 500;
}
span {
font-size: var(--font-size-xs);
width: 75px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
</style>

View File

@ -1,45 +0,0 @@
<script>
export let columnName
export let row
export let selectRelationship
$: items = row?.[columnName] || []
</script>
<div
class="container"
class:link={!!items.length}
on:click={() => selectRelationship(row, columnName)}>
{#each items as item}
<div class="item">{item?.primaryDisplay ?? ''}</div>
{/each}
</div>
<style>
.container {
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: center;
gap: var(--spacing-xs);
}
.link:hover {
color: var(--grey-6);
cursor: pointer;
}
.link:hover .item {
color: var(--ink);
border-color: var(--ink);
}
.item {
font-size: var(--font-size-xs);
padding: var(--spacing-xs) var(--spacing-s);
border: 1px solid var(--grey-5);
color: var(--grey-7);
line-height: normal;
border-radius: 4px;
text-decoration: none;
}
</style>

View File

@ -1,10 +1,10 @@
<script>
import { roles } from "stores/backend"
export let roleId
export let value
$: role = $roles.find(role => role._id === roleId)
$: role = $roles.find(role => role._id === value)
$: roleName = role?.name ?? "Unknown role"
</script>
<div>{roleName}</div>
{roleName}

View File

@ -1,128 +0,0 @@
import AttachmentList from "./AttachmentCell.svelte"
import EditRow from "../modals/EditRow.svelte"
import CreateEditUser from "../modals/CreateEditUser.svelte"
import DeleteRow from "../modals/DeleteRow.svelte"
import RelationshipDisplay from "./RelationshipCell.svelte"
import RoleCell from "./RoleCell.svelte"
const renderers = {
attachment: attachmentRenderer,
link: linkedRowRenderer,
}
export function getRenderer({ schema, editable, isUsersTable }) {
const rendererParams = {
options: schema.options,
constraints: schema.constraints,
editable,
}
if (renderers[schema.type]) {
return renderers[schema.type](rendererParams)
} else if (isUsersTable && schema.name === "roleId") {
return roleRenderer(rendererParams)
} else {
return false
}
}
export function deleteRowRenderer(params) {
const container = document.createElement("div")
new DeleteRow({
target: container,
props: {
row: params.data,
},
})
return container
}
export function editRowRenderer(params) {
const container = document.createElement("div")
container.style.height = "100%"
container.style.display = "flex"
container.style.alignItems = "center"
new EditRow({
target: container,
props: {
row: params.data,
},
})
return container
}
export function userRowRenderer(params) {
const container = document.createElement("div")
container.style.height = "100%"
container.style.display = "flex"
container.style.alignItems = "center"
new EditRow({
target: container,
props: {
row: params.data,
modalContentComponent: CreateEditUser,
},
})
return container
}
function attachmentRenderer() {
return params => {
const container = document.createElement("div")
container.style.height = "100%"
container.style.display = "flex"
container.style.alignItems = "center"
new AttachmentList({
target: container,
props: {
files: params.value || [],
},
})
return container
}
}
function linkedRowRenderer() {
return params => {
let container = document.createElement("div")
container.style.display = "grid"
container.style.height = "100%"
container.style.alignItems = "center"
new RelationshipDisplay({
target: container,
props: {
row: params.data,
columnName: params.column.colId,
selectRelationship: params.selectRelationship,
},
})
return container
}
}
function roleRenderer() {
return params => {
let container = document.createElement("div")
container.style.display = "grid"
container.style.height = "100%"
container.style.alignItems = "center"
new RoleCell({
target: container,
props: {
roleId: params.value,
},
})
return container
}
}