more ag grid styling
This commit is contained in:
parent
fdc944741c
commit
4714416e24
|
@ -2,19 +2,9 @@
|
||||||
import { goto, params } from "@sveltech/routify"
|
import { goto, params } from "@sveltech/routify"
|
||||||
import { onMount } from "svelte"
|
import { onMount } from "svelte"
|
||||||
import { fade } from "svelte/transition"
|
import { fade } from "svelte/transition"
|
||||||
import fsort from "fast-sort"
|
|
||||||
import getOr from "lodash/fp/getOr"
|
|
||||||
import { store, backendUiStore } from "builderStore"
|
import { store, backendUiStore } from "builderStore"
|
||||||
import api from "builderStore/api"
|
import api from "builderStore/api"
|
||||||
import { Button, Icon } from "@budibase/bbui"
|
import { Button, Icon } from "@budibase/bbui"
|
||||||
import ActionButton from "components/common/ActionButton.svelte"
|
|
||||||
import CreateEditRowModal from "./modals/CreateEditRowModal.svelte"
|
|
||||||
import RowPopover from "./buttons/CreateRowButton.svelte"
|
|
||||||
import ColumnPopover from "./buttons/CreateColumnButton.svelte"
|
|
||||||
import ViewPopover from "./buttons/CreateViewButton.svelte"
|
|
||||||
import ColumnHeaderPopover from "./popovers/ColumnPopover.svelte"
|
|
||||||
import EditRowPopover from "./popovers/RowPopover.svelte"
|
|
||||||
import CalculationPopover from "./buttons/CalculateButton.svelte"
|
|
||||||
import Spinner from "components/common/Spinner.svelte"
|
import Spinner from "components/common/Spinner.svelte"
|
||||||
|
|
||||||
// New
|
// New
|
||||||
|
@ -28,7 +18,6 @@
|
||||||
export let allowEditing = false
|
export let allowEditing = false
|
||||||
export let loading = false
|
export let loading = false
|
||||||
|
|
||||||
// New stuff
|
|
||||||
export let theme = "alpine"
|
export let theme = "alpine"
|
||||||
|
|
||||||
let columnDefs = []
|
let columnDefs = []
|
||||||
|
@ -93,21 +82,6 @@
|
||||||
// `/${$params.application}/data/table/${tableId}/relationship/${row._id}/${fieldName}`
|
// `/${$params.application}/data/table/${tableId}/relationship/${row._id}/${fieldName}`
|
||||||
// )
|
// )
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// New stuff
|
|
||||||
// const deleteRows = async () => {
|
|
||||||
// const response = await api.post(`/api/${tableId}/rows`, {
|
|
||||||
// rows: selectedRows,
|
|
||||||
// type: "delete",
|
|
||||||
// })
|
|
||||||
// data = data.filter(row => !selectedRows.includes(row))
|
|
||||||
// selectedRows = []
|
|
||||||
// }
|
|
||||||
|
|
||||||
// const handleUpdate = ({ detail }) => {
|
|
||||||
// data[detail.row] = detail.data
|
|
||||||
// updateRow(detail.data)
|
|
||||||
// }
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
|
@ -159,4 +133,10 @@
|
||||||
margin-right: var(--spacing-m);
|
margin-right: var(--spacing-m);
|
||||||
margin-bottom: var(--spacing-xl);
|
margin-bottom: var(--spacing-xl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:global(.ag-header-cell-text) {
|
||||||
|
font-family: Inter;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--ink);
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -40,19 +40,6 @@
|
||||||
modal.show()
|
modal.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
async function saveColumn() {
|
|
||||||
backendUiStore.update(state => {
|
|
||||||
backendUiStore.actions.tables.saveField({
|
|
||||||
originalName,
|
|
||||||
field,
|
|
||||||
primaryDisplay,
|
|
||||||
})
|
|
||||||
return state
|
|
||||||
})
|
|
||||||
notifier.success(`Column ${field.name} saved successfully.`)
|
|
||||||
modal.hide()
|
|
||||||
}
|
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
column.addEventListener("sortChanged", () => {
|
column.addEventListener("sortChanged", () => {
|
||||||
sortDirection = column.getSort()
|
sortDirection = column.getSort()
|
||||||
|
@ -64,15 +51,15 @@
|
||||||
<div>
|
<div>
|
||||||
<span>{field.name}</span>
|
<span>{field.name}</span>
|
||||||
{#if enableSorting && sortDirection}
|
{#if enableSorting && sortDirection}
|
||||||
<i class={SORT_ICON_MAP[sortDirection]} />
|
<i class={`${SORT_ICON_MAP[sortDirection]} sort-icon`} />
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
<Modal bind:this={modal}>
|
<Modal bind:this={modal}>
|
||||||
<ModalContent
|
<ModalContent
|
||||||
title={`Edit Column: ${field.name}`}
|
showCancelButton={false}
|
||||||
confirmText={'Save Column'}
|
showConfirmButton={false}
|
||||||
onConfirm={saveColumn}>
|
title={`Edit Column: ${field.name}`}>
|
||||||
<CreateEditColumnPopover {field} />
|
<CreateEditColumnPopover onClosed={modal.hide} {field} />
|
||||||
</ModalContent>
|
</ModalContent>
|
||||||
</Modal>
|
</Modal>
|
||||||
<div>
|
<div>
|
||||||
|
@ -88,10 +75,31 @@
|
||||||
<style>
|
<style>
|
||||||
header {
|
header {
|
||||||
font-family: Inter;
|
font-family: Inter;
|
||||||
|
font-weight: 600;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
color: var(--ink);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sort-icon {
|
||||||
|
position: relative;
|
||||||
|
top: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
i {
|
||||||
|
transition: 0.2s all;
|
||||||
|
font-size: var(--font-size-m);
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
i:hover {
|
||||||
|
color: var(--blue);
|
||||||
|
}
|
||||||
|
|
||||||
|
i:active {
|
||||||
|
color: var(--blue);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -20,9 +20,9 @@
|
||||||
</div>
|
</div>
|
||||||
<Modal bind:this={modal}>
|
<Modal bind:this={modal}>
|
||||||
<ModalContent
|
<ModalContent
|
||||||
title={'Create Column'}
|
showCancelButton={false}
|
||||||
confirmText={'Save Column'}
|
showConfirmButton={false}
|
||||||
onConfirm={console.log}>
|
title={'Create Column'}>
|
||||||
<CreateEditColumnPopover />
|
<CreateEditColumnPopover onClosed={modal.hide} />
|
||||||
</ModalContent>
|
</ModalContent>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
import ActionButton from "components/common/ActionButton.svelte"
|
import ActionButton from "components/common/ActionButton.svelte"
|
||||||
import DatePicker from "components/common/DatePicker.svelte"
|
import DatePicker from "components/common/DatePicker.svelte"
|
||||||
import LinkedRowSelector from "components/common/LinkedRowSelector.svelte"
|
import LinkedRowSelector from "components/common/LinkedRowSelector.svelte"
|
||||||
|
import ConfirmDialog from "components/common/ConfirmDialog.svelte"
|
||||||
import * as api from "../api"
|
import * as api from "../api"
|
||||||
|
|
||||||
let fieldDefinitions = cloneDeep(FIELDS)
|
let fieldDefinitions = cloneDeep(FIELDS)
|
||||||
|
@ -37,6 +38,8 @@
|
||||||
let primaryDisplay =
|
let primaryDisplay =
|
||||||
$backendUiStore.selectedTable.primaryDisplay == null ||
|
$backendUiStore.selectedTable.primaryDisplay == null ||
|
||||||
$backendUiStore.selectedTable.primaryDisplay === field.name
|
$backendUiStore.selectedTable.primaryDisplay === field.name
|
||||||
|
let confirmDeleteDialog
|
||||||
|
|
||||||
$: tableOptions = $backendUiStore.tables.filter(
|
$: tableOptions = $backendUiStore.tables.filter(
|
||||||
table => table._id !== $backendUiStore.draftTable._id
|
table => table._id !== $backendUiStore.draftTable._id
|
||||||
)
|
)
|
||||||
|
@ -54,6 +57,17 @@
|
||||||
onClosed()
|
onClosed()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function deleteColumn() {
|
||||||
|
if (field.name === $backendUiStore.selectedTable.primaryDisplay) {
|
||||||
|
notifier.danger("You cannot delete the display column")
|
||||||
|
} else {
|
||||||
|
backendUiStore.actions.tables.deleteField(field)
|
||||||
|
notifier.success("Column deleted")
|
||||||
|
}
|
||||||
|
onClosed()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function handleFieldConstraints(event) {
|
function handleFieldConstraints(event) {
|
||||||
const { type, constraints } = fieldDefinitions[
|
const { type, constraints } = fieldDefinitions[
|
||||||
event.target.value.toUpperCase()
|
event.target.value.toUpperCase()
|
||||||
|
@ -75,6 +89,11 @@
|
||||||
field.constraints.presence = { allowEmpty: false }
|
field.constraints.presence = { allowEmpty: false }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function confirmDelete() {
|
||||||
|
onClosed()
|
||||||
|
confirmDeleteDialog.show()
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="actions">
|
<div class="actions">
|
||||||
|
@ -147,11 +166,20 @@
|
||||||
thin
|
thin
|
||||||
bind:value={field.fieldName} />
|
bind:value={field.fieldName} />
|
||||||
{/if}
|
{/if}
|
||||||
<!-- <footer>
|
<footer>
|
||||||
|
{#if originalName}
|
||||||
<Button secondary on:click={onClosed}>Cancel</Button>
|
<Button secondary on:click={onClosed}>Cancel</Button>
|
||||||
|
{/if}
|
||||||
|
<Button red on:click={confirmDelete}>Delete Column</Button>
|
||||||
<Button primary on:click={saveColumn}>Save Column</Button>
|
<Button primary on:click={saveColumn}>Save Column</Button>
|
||||||
</footer> -->
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
|
<ConfirmDialog
|
||||||
|
bind:this={confirmDeleteDialog}
|
||||||
|
body={`Are you sure you wish to delete this column? Your data will be deleted and this action cannot be undone.`}
|
||||||
|
okText="Delete Column"
|
||||||
|
onOk={deleteColumn}
|
||||||
|
title="Confirm Delete" />
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.actions {
|
.actions {
|
||||||
|
|
|
@ -1,201 +0,0 @@
|
||||||
<script>
|
|
||||||
import { onMount } from "svelte"
|
|
||||||
import { cssVars } from "./cssVars"
|
|
||||||
import ArrowUp from "./icons/ArrowUp.svelte"
|
|
||||||
import ArrowDown from "./icons/ArrowDown.svelte"
|
|
||||||
import fsort from "fast-sort"
|
|
||||||
import fetchData from "./fetchData.js"
|
|
||||||
import { isEmpty } from "lodash/fp"
|
|
||||||
import AttachmentList from "./attachments/AttachmentList.svelte"
|
|
||||||
|
|
||||||
export let backgroundColor
|
|
||||||
export let color
|
|
||||||
export let stripeColor
|
|
||||||
export let borderColor
|
|
||||||
export let datasource
|
|
||||||
export let _bb
|
|
||||||
|
|
||||||
let data = []
|
|
||||||
let headers = []
|
|
||||||
let sort = {}
|
|
||||||
let sorted = []
|
|
||||||
let schema = {}
|
|
||||||
let store = _bb.store
|
|
||||||
|
|
||||||
$: cssVariables = {
|
|
||||||
backgroundColor,
|
|
||||||
color,
|
|
||||||
stripeColor,
|
|
||||||
borderColor,
|
|
||||||
}
|
|
||||||
|
|
||||||
$: sorted = sort.direction ? fsort(data)[sort.direction](sort.column) : data
|
|
||||||
|
|
||||||
async function fetchTable(tableId) {
|
|
||||||
const FETCH_TABLE_URL = `/api/tables/${tableId}`
|
|
||||||
const response = await _bb.api.get(FETCH_TABLE_URL)
|
|
||||||
const table = await response.json()
|
|
||||||
return table.schema
|
|
||||||
}
|
|
||||||
|
|
||||||
onMount(async () => {
|
|
||||||
if (!isEmpty(datasource)) {
|
|
||||||
data = await fetchData(datasource, $store)
|
|
||||||
|
|
||||||
// Get schema for datasource
|
|
||||||
// Views with "Calculate" applied provide their own schema.
|
|
||||||
// For everything else, use the tableId property to pull to table schema
|
|
||||||
if (datasource.schema) {
|
|
||||||
schema = datasource.schema
|
|
||||||
headers = Object.keys(schema).filter(shouldDisplayField)
|
|
||||||
} else {
|
|
||||||
schema = await fetchTable(datasource.tableId)
|
|
||||||
headers = Object.keys(schema).filter(shouldDisplayField)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const shouldDisplayField = name => {
|
|
||||||
if (name.startsWith("_")) return false
|
|
||||||
// always 'row'
|
|
||||||
if (name === "type") return false
|
|
||||||
// tables are always tied to a single tableId, this is irrelevant
|
|
||||||
if (name === "tableId") return false
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
function sortColumn(column) {
|
|
||||||
if (column === sort.column) {
|
|
||||||
sort = {
|
|
||||||
direction: sort.direction === "asc" ? "desc" : null,
|
|
||||||
column: sort.direction === "asc" ? sort.column : null,
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
sort = {
|
|
||||||
column,
|
|
||||||
direction: "asc",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<table use:cssVars={cssVariables}>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
{#each headers as header}
|
|
||||||
<th on:click={() => sortColumn(header)}>
|
|
||||||
<span>
|
|
||||||
{header}
|
|
||||||
{#if sort.column === header}
|
|
||||||
<svelte:component
|
|
||||||
this={sort.direction === 'asc' ? ArrowDown : ArrowUp}
|
|
||||||
style="height: 1em;" />
|
|
||||||
{/if}
|
|
||||||
</span>
|
|
||||||
</th>
|
|
||||||
{/each}
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{#each sorted as row (row._id)}
|
|
||||||
<tr>
|
|
||||||
{#each headers as header}
|
|
||||||
{#if schema[header] !== undefined}
|
|
||||||
<!-- Rudimentary solution for attachments on array given this entire table will be replaced by AG Grid -->
|
|
||||||
{#if schema[header] && schema[header].type === 'attachment'}
|
|
||||||
<AttachmentList files={row[header]} />
|
|
||||||
{:else if schema[header] && schema[header].type === 'link'}
|
|
||||||
<td>{row[header] ? row[header].length : 0} related row(s)</td>
|
|
||||||
{:else}
|
|
||||||
<td>{row[header] == null ? '' : row[header]}</td>
|
|
||||||
{/if}
|
|
||||||
{/if}
|
|
||||||
{/each}
|
|
||||||
</tr>
|
|
||||||
{/each}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
table {
|
|
||||||
width: 100%;
|
|
||||||
border-collapse: collapse;
|
|
||||||
overflow: scroll; /* Scrollbar are always visible */
|
|
||||||
overflow: auto; /* Scrollbar is displayed as it's needed */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Zebra striping */
|
|
||||||
tr:nth-of-type(odd) {
|
|
||||||
background: var(--stripeColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
th {
|
|
||||||
background-color: var(--backgroundColor);
|
|
||||||
color: var(--color);
|
|
||||||
font-weight: bold;
|
|
||||||
text-transform: capitalize;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
th span {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
td,
|
|
||||||
th {
|
|
||||||
padding: 16px;
|
|
||||||
border: 1px solid var(--borderColor);
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media only screen and (max-width: 760px),
|
|
||||||
(min-device-width: 768px) and (max-device-width: 1024px) {
|
|
||||||
table {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Force table to not be like tables anymore */
|
|
||||||
table,
|
|
||||||
thead,
|
|
||||||
tbody,
|
|
||||||
th,
|
|
||||||
td,
|
|
||||||
tr {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Hide table headers (but not display: none;, for accessibility) */
|
|
||||||
thead tr {
|
|
||||||
position: absolute;
|
|
||||||
top: -9999px;
|
|
||||||
left: -9999px;
|
|
||||||
}
|
|
||||||
|
|
||||||
tr {
|
|
||||||
border: 1px solid var(--borderColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
td {
|
|
||||||
/* Behave like a "row" */
|
|
||||||
border: none;
|
|
||||||
border-bottom: 1px solid #eee;
|
|
||||||
position: relative;
|
|
||||||
padding-left: 10%;
|
|
||||||
}
|
|
||||||
|
|
||||||
td:before {
|
|
||||||
/* Now like a table header */
|
|
||||||
position: absolute;
|
|
||||||
/* Top/left values mimic padding */
|
|
||||||
top: 6px;
|
|
||||||
left: 6px;
|
|
||||||
width: 45%;
|
|
||||||
padding-right: 10px;
|
|
||||||
white-space: nowrap;
|
|
||||||
/* Label the data */
|
|
||||||
content: attr(data-column);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
Loading…
Reference in New Issue