Add custom renderers to table and improve table sorting
This commit is contained in:
parent
2b46f8bfbc
commit
b699573941
|
@ -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>
|
||||
|
|
|
@ -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} />
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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>
|
|
@ -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>
|
|
@ -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}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue