Reuse filter drawer component to allow full table filtering on any type in data UI

This commit is contained in:
Andrew Kingston 2021-09-29 09:05:04 +01:00
parent 7527c19a8c
commit 745aff0c44
7 changed files with 79 additions and 77 deletions

View File

@ -7,17 +7,16 @@
import EditRolesButton from "./buttons/EditRolesButton.svelte" import EditRolesButton from "./buttons/EditRolesButton.svelte"
import ManageAccessButton from "./buttons/ManageAccessButton.svelte" import ManageAccessButton from "./buttons/ManageAccessButton.svelte"
import HideAutocolumnButton from "./buttons/HideAutocolumnButton.svelte" import HideAutocolumnButton from "./buttons/HideAutocolumnButton.svelte"
import TableFilterButton from "./buttons/TableFilterButton.svelte"
import Table from "./Table.svelte" import Table from "./Table.svelte"
import { TableNames } from "constants" import { TableNames } from "constants"
import CreateEditRow from "./modals/CreateEditRow.svelte" import CreateEditRow from "./modals/CreateEditRow.svelte"
import { fetchTableData } from "helpers/fetchTableData" import { fetchTableData } from "helpers/fetchTableData"
import { Layout, Pagination, Select, Input } from "@budibase/bbui" import { Pagination } from "@budibase/bbui"
import { OperatorOptions } from "constants/lucene"
const search = fetchTableData() const search = fetchTableData()
let hideAutocolumns = true let hideAutocolumns = true
let searchColumn let filters
let searchValue
$: isUsersTable = $tables.selected?._id === TableNames.USERS $: isUsersTable = $tables.selected?._id === TableNames.USERS
$: title = $tables.selected?.name $: title = $tables.selected?.name
@ -26,15 +25,14 @@
$: isInternal = type !== "external" $: isInternal = type !== "external"
$: id = $tables.selected?._id $: id = $tables.selected?._id
$: columnOptions = Object.keys($search.schema || {}) $: columnOptions = Object.keys($search.schema || {})
$: filter = buildFilter(searchColumn, searchValue) $: fetchTable(id, filters)
$: fetchTable(id, filter)
// Fetches new data whenever the table changes // Fetches new data whenever the table changes
const fetchTable = (tableId, filter) => { const fetchTable = (tableId, filters) => {
search.update({ search.update({
tableId, tableId,
schema, schema,
filter, filters,
limit: 10, limit: 10,
paginate: true, paginate: true,
}) })
@ -47,23 +45,6 @@
sortOrder: e.detail.order, sortOrder: e.detail.order,
}) })
} }
// Builds a filter expression to search with
const buildFilter = (column, value) => {
if (!column || !value) {
return null
}
return [
{
type: "string",
field: column,
operator: OperatorOptions.StartsWith.value,
value,
},
]
}
$: console.log(filter)
</script> </script>
<div> <div>
@ -79,39 +60,32 @@
allowEditing allowEditing
disableSorting disableSorting
> >
<Layout noPadding gap="S"> {#if isInternal}
<div class="buttons"> <CreateColumnButton />
{#if isInternal} {/if}
<CreateColumnButton /> {#if schema && Object.keys(schema).length > 0}
{/if} {#if !isUsersTable}
{#if schema && Object.keys(schema).length > 0} <CreateRowButton
{#if !isUsersTable} title={"Create row"}
<CreateRowButton modalContentComponent={CreateEditRow}
title={"Create row"}
modalContentComponent={CreateEditRow}
/>
{/if}
{#if isInternal}
<CreateViewButton />
{/if}
<ManageAccessButton resourceId={$tables.selected?._id} />
{#if isUsersTable}
<EditRolesButton />
{/if}
<HideAutocolumnButton bind:hideAutocolumns />
<!-- always have the export last -->
<ExportButton view={$tables.selected?._id} />
{/if}
</div>
<div class="search">
<Select bind:value={searchColumn} options={columnOptions} />
<Input
updateOnChange={false}
on:change={e => (searchValue = e.detail)}
placeholder="Search"
/> />
</div> {/if}
</Layout> {#if isInternal}
<CreateViewButton />
{/if}
<ManageAccessButton resourceId={$tables.selected?._id} />
{#if isUsersTable}
<EditRolesButton />
{/if}
<HideAutocolumnButton bind:hideAutocolumns />
<!-- always have the export last -->
<ExportButton view={$tables.selected?._id} />
<TableFilterButton
{schema}
{filters}
on:change={e => (filters = e.detail)}
/>
{/if}
</Table> </Table>
<div class="pagination"> <div class="pagination">
<Pagination <Pagination
@ -125,19 +99,6 @@
</div> </div>
<style> <style>
.buttons {
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: center;
gap: var(--spacing-s);
}
.search {
display: grid;
align-items: center;
grid-template-columns: 200px 200px;
gap: var(--spacing-s);
}
.pagination { .pagination {
display: flex; display: flex;
flex-direction: row; flex-direction: row;

View File

@ -164,7 +164,7 @@
align-items: center; align-items: center;
gap: var(--spacing-s); gap: var(--spacing-s);
} }
.popovers :global(.spectrum-ActionButton) { .popovers :global(button) {
font-weight: 600; font-weight: 600;
margin-top: var(--spacing-l); margin-top: var(--spacing-l);
} }

View File

@ -5,7 +5,7 @@
import Table from "./Table.svelte" import Table from "./Table.svelte"
import CalculateButton from "./buttons/CalculateButton.svelte" import CalculateButton from "./buttons/CalculateButton.svelte"
import GroupByButton from "./buttons/GroupByButton.svelte" import GroupByButton from "./buttons/GroupByButton.svelte"
import FilterButton from "./buttons/FilterButton.svelte" import ViewFilterButton from "./buttons/ViewFilterButton.svelte"
import ExportButton from "./buttons/ExportButton.svelte" import ExportButton from "./buttons/ExportButton.svelte"
import ManageAccessButton from "./buttons/ManageAccessButton.svelte" import ManageAccessButton from "./buttons/ManageAccessButton.svelte"
import HideAutocolumnButton from "./buttons/HideAutocolumnButton.svelte" import HideAutocolumnButton from "./buttons/HideAutocolumnButton.svelte"
@ -61,7 +61,7 @@
allowEditing={!view?.calculation} allowEditing={!view?.calculation}
bind:hideAutocolumns bind:hideAutocolumns
> >
<FilterButton {view} /> <ViewFilterButton {view} />
<CalculateButton {view} /> <CalculateButton {view} />
{#if view.calculation} {#if view.calculation}
<GroupByButton {view} /> <GroupByButton {view} />

View File

@ -0,0 +1,42 @@
<script>
import { createEventDispatcher } from "svelte"
import { ActionButton, Modal, ModalContent } from "@budibase/bbui"
import FilterDrawer from "components/design/PropertiesPanel/PropertyControls/FilterEditor/FilterDrawer.svelte"
export let schema
export let filters
const dispatch = createEventDispatcher()
let modal
let tempValue = filters || []
$: schemaFields = Object.values(schema || {})
</script>
<ActionButton
icon="Filter"
size="S"
quiet
on:click={modal.show}
active={tempValue?.length > 0}
>
Filter
</ActionButton>
<Modal bind:this={modal}>
<ModalContent
title="Filter"
confirmText="Save"
size="XL"
onConfirm={() => dispatch("change", tempValue)}
>
<div class="wrapper">
<FilterDrawer bind:filters={tempValue} {schemaFields} />
</div>
</ModalContent>
</Modal>
<style>
.wrapper :global(.main) {
padding: 0;
}
</style>

View File

@ -20,7 +20,6 @@
$: dataSource = getDatasourceForProvider($currentAsset, componentInstance) $: dataSource = getDatasourceForProvider($currentAsset, componentInstance)
$: schema = getSchemaForDatasource($currentAsset, dataSource)?.schema $: schema = getSchemaForDatasource($currentAsset, dataSource)?.schema
$: schemaFields = Object.values(schema || {}) $: schemaFields = Object.values(schema || {})
$: internalTable = dataSource?.type === "table"
const saveFilter = async () => { const saveFilter = async () => {
dispatch("change", tempValue) dispatch("change", tempValue)

View File

@ -6,7 +6,7 @@ import { buildLuceneQuery } from "./lucene"
const defaultOptions = { const defaultOptions = {
tableId: null, tableId: null,
filter: null, filters: null,
limit: 10, limit: 10,
sortColumn: null, sortColumn: null,
sortOrder: "ascending", sortOrder: "ascending",
@ -65,7 +65,7 @@ export const fetchTableData = opts => {
// Fetches a fresh set of results from the server // Fetches a fresh set of results from the server
const fetchData = async () => { const fetchData = async () => {
const { tableId, schema, sortColumn, filter } = options const { tableId, schema, sortColumn, filters } = options
// Ensure table ID exists // Ensure table ID exists
if (!tableId) { if (!tableId) {
@ -113,7 +113,7 @@ export const fetchTableData = opts => {
sortType = type === "number" ? "number" : "string" sortType = type === "number" ? "number" : "string"
// Build the lucene query // Build the lucene query
query = buildLuceneQuery(filter) query = buildLuceneQuery(filters)
// Actually fetch data // Actually fetch data
const page = await fetchPage() const page = await fetchPage()