Add custom renderers to table and improve table sorting
This commit is contained in:
parent
563158da72
commit
00d47905a8
|
@ -4,10 +4,15 @@
|
||||||
const displayLimit = 5
|
const displayLimit = 5
|
||||||
$: attachments = value?.slice(0, displayLimit) ?? []
|
$: attachments = value?.slice(0, displayLimit) ?? []
|
||||||
$: leftover = (value?.length ?? 0) - attachments.length
|
$: leftover = (value?.length ?? 0) - attachments.length
|
||||||
|
|
||||||
|
const imageExtensions = ["png", "tiff", "gif", "raw", "jpg", "jpeg"]
|
||||||
|
const isImage = extension => {
|
||||||
|
return imageExtensions.includes(extension?.toLowerCase())
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#each attachments as attachment}
|
{#each attachments as attachment}
|
||||||
{#if attachment.type?.startsWith('image')}
|
{#if isImage(attachment.extension)}
|
||||||
<img src={attachment.url} alt={attachment.extension} />
|
<img src={attachment.url} alt={attachment.extension} />
|
||||||
{:else}
|
{:else}
|
||||||
<div class="file">{attachment.extension}</div>
|
<div class="file">{attachment.extension}</div>
|
||||||
|
|
|
@ -7,13 +7,17 @@
|
||||||
|
|
||||||
export let schema
|
export let schema
|
||||||
export let value
|
export let value
|
||||||
|
export let customRenderers = []
|
||||||
|
|
||||||
const plainTypes = ["string", "options", "number", "longform"]
|
const plainTypes = ["string", "options", "number", "longform"]
|
||||||
$: type = schema?.type ?? "string"
|
$: type = schema?.type ?? "string"
|
||||||
|
$: customRenderer = customRenderers?.find(x => x.column === schema?.name)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if value != null && value !== ''}
|
{#if value != null && value !== ''}
|
||||||
{#if plainTypes.includes(type)}
|
{#if customRenderer}
|
||||||
|
<svelte:component this={customRenderer.component} {value} />
|
||||||
|
{:else if plainTypes.includes(type)}
|
||||||
<StringRenderer {value} />
|
<StringRenderer {value} />
|
||||||
{:else if type === 'boolean'}
|
{:else if type === 'boolean'}
|
||||||
<BooleanRenderer {value} />
|
<BooleanRenderer {value} />
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
export let selectedRows = []
|
export let selectedRows = []
|
||||||
export let customColumnRenderer = SelectEditRenderer
|
export let customColumnRenderer = SelectEditRenderer
|
||||||
export let customColumnTitle
|
export let customColumnTitle
|
||||||
|
export let customRenderers = []
|
||||||
|
|
||||||
const dispatch = createEventDispatcher()
|
const dispatch = createEventDispatcher()
|
||||||
|
|
||||||
|
@ -93,7 +94,11 @@
|
||||||
autoColumns.push(field)
|
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 => {
|
const onScroll = event => {
|
||||||
|
@ -181,7 +186,7 @@
|
||||||
<use xlink:href="#spectrum-css-icon-Arrow100" />
|
<use xlink:href="#spectrum-css-icon-Arrow100" />
|
||||||
</svg>
|
</svg>
|
||||||
{/if}
|
{/if}
|
||||||
{#if allowEditColumns}
|
{#if allowEditColumns && schema[field]?.editable !== false}
|
||||||
<svg
|
<svg
|
||||||
class="spectrum-Icon spectrum-Table-editIcon"
|
class="spectrum-Icon spectrum-Table-editIcon"
|
||||||
focusable="false"
|
focusable="false"
|
||||||
|
@ -218,7 +223,10 @@
|
||||||
{#each fields as field}
|
{#each fields as field}
|
||||||
<td class="spectrum-Table-cell">
|
<td class="spectrum-Table-cell">
|
||||||
<div class="spectrum-Table-cell-content">
|
<div class="spectrum-Table-cell-content">
|
||||||
<CellRenderer schema={schema[field]} value={row[field]} />
|
<CellRenderer
|
||||||
|
{customRenderers}
|
||||||
|
schema={schema[field]}
|
||||||
|
value={row[field]} />
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
{/each}
|
{/each}
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
import CreateEditColumn from "./modals/CreateEditColumn.svelte"
|
import CreateEditColumn from "./modals/CreateEditColumn.svelte"
|
||||||
import "@budibase/svelte-ag-grid/dist/index.css"
|
import "@budibase/svelte-ag-grid/dist/index.css"
|
||||||
import { TableNames, UNEDITABLE_USER_FIELDS } from "constants"
|
import { TableNames, UNEDITABLE_USER_FIELDS } from "constants"
|
||||||
|
import RoleCell from "./cells/RoleCell.svelte"
|
||||||
|
|
||||||
export let schema = {}
|
export let schema = {}
|
||||||
export let data = []
|
export let data = []
|
||||||
|
@ -28,12 +29,23 @@
|
||||||
let editableRow
|
let editableRow
|
||||||
let editRowModal
|
let editRowModal
|
||||||
let editColumnModal
|
let editColumnModal
|
||||||
|
let customRenderers = []
|
||||||
|
|
||||||
$: isUsersTable = tableId === TableNames.USERS
|
$: isUsersTable = tableId === TableNames.USERS
|
||||||
$: editRowComponent = isUsersTable ? CreateEditUser : CreateEditRow
|
$: editRowComponent = isUsersTable ? CreateEditUser : CreateEditRow
|
||||||
$: {
|
$: {
|
||||||
if (isUsersTable) {
|
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.email.displayName = "Email"
|
||||||
schema.roleId.displayName = "Role"
|
schema.roleId.displayName = "Role"
|
||||||
if (schema.status) {
|
if (schema.status) {
|
||||||
|
@ -97,6 +109,7 @@
|
||||||
{data}
|
{data}
|
||||||
{schema}
|
{schema}
|
||||||
{loading}
|
{loading}
|
||||||
|
{customRenderers}
|
||||||
customColumnTitle="Edit"
|
customColumnTitle="Edit"
|
||||||
bind:selectedRows
|
bind:selectedRows
|
||||||
showAutoColumns={!hideAutocolumns}
|
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>
|
<script>
|
||||||
import { roles } from "stores/backend"
|
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"
|
$: roleName = role?.name ?? "Unknown role"
|
||||||
</script>
|
</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