Reuse filter drawer component to allow full table filtering on any type in data UI
This commit is contained in:
parent
7527c19a8c
commit
745aff0c44
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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} />
|
||||||
|
|
|
@ -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>
|
|
@ -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)
|
||||||
|
|
|
@ -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()
|
||||||
|
|
Loading…
Reference in New Issue