mirror of https://github.com/Budibase/budibase.git
8 changed files with 343 additions and 63 deletions
@ -0,0 +1,162 @@ |
|||
<script> |
|||
import { |
|||
Popover, |
|||
TextButton, |
|||
Button, |
|||
Icon, |
|||
Input, |
|||
Select, |
|||
} from "@budibase/bbui" |
|||
import { backendUiStore } from "builderStore" |
|||
import { notifier } from "builderStore/store/notifications" |
|||
import CreateEditRecord from "../modals/CreateEditRecord.svelte" |
|||
|
|||
const CONDITIONS = [ |
|||
{ |
|||
name: "Equals", |
|||
key: "EQUALS", |
|||
}, |
|||
{ |
|||
name: "Less Than", |
|||
key: "LT", |
|||
}, |
|||
{ |
|||
name: "Less Than Or Equal", |
|||
key: "LTE", |
|||
}, |
|||
{ |
|||
name: "More Than", |
|||
key: "MT", |
|||
}, |
|||
{ |
|||
name: "More Than Or Equal", |
|||
key: "MTE", |
|||
}, |
|||
{ |
|||
name: "Contains", |
|||
key: "CONTAINS", |
|||
}, |
|||
] |
|||
|
|||
const CONJUNCTIONS = [ |
|||
{ |
|||
name: "Or", |
|||
key: "OR", |
|||
}, |
|||
{ |
|||
name: "And", |
|||
key: "AND", |
|||
}, |
|||
] |
|||
|
|||
export let view = {} |
|||
|
|||
let anchor |
|||
let dropdown |
|||
let filters = view.filters |
|||
|
|||
$: viewModel = $backendUiStore.models.find( |
|||
({ _id }) => _id === $backendUiStore.selectedView.modelId |
|||
) |
|||
$: fields = viewModel && Object.keys(viewModel.schema) |
|||
|
|||
function saveView() { |
|||
view.filters = filters |
|||
backendUiStore.actions.views.save(view) |
|||
notifier.success(`View ${view.name} saved.`) |
|||
dropdown.hide() |
|||
} |
|||
|
|||
function removeFilter(idx) { |
|||
filters.splice(idx, 1) |
|||
filters = filters |
|||
} |
|||
|
|||
function addFilter() { |
|||
filters = [...filters, {}] |
|||
} |
|||
</script> |
|||
|
|||
<div bind:this={anchor}> |
|||
<TextButton |
|||
text |
|||
small |
|||
on:click={dropdown.show} |
|||
active={filters && filters.length}> |
|||
<Icon name="filter" /> |
|||
Filter |
|||
</TextButton> |
|||
</div> |
|||
<Popover bind:this={dropdown} {anchor} align="left"> |
|||
<h5>Filter</h5> |
|||
<div class="input-group-row"> |
|||
{#each filters as filter, idx} |
|||
{#if idx === 0} |
|||
<p>Where</p> |
|||
{:else} |
|||
<Select secondary thin bind:value={filter.conjunction}> |
|||
{#each CONJUNCTIONS as conjunction} |
|||
<option value={conjunction.key}>{conjunction.name}</option> |
|||
{/each} |
|||
</Select> |
|||
{/if} |
|||
<Select secondary thin bind:value={filter.key}> |
|||
{#each fields as field} |
|||
<option value={field}>{field}</option> |
|||
{/each} |
|||
</Select> |
|||
<Select secondary thin bind:value={filter.condition}> |
|||
{#each CONDITIONS as condition} |
|||
<option value={condition.key}>{condition.name}</option> |
|||
{/each} |
|||
</Select> |
|||
<Input |
|||
thin |
|||
placeholder={filter.key || fields[0]} |
|||
bind:value={filter.value} /> |
|||
<i class="ri-close-circle-fill" on:click={() => removeFilter(idx)} /> |
|||
{/each} |
|||
</div> |
|||
<div class="button-group"> |
|||
<Button text on:click={addFilter}>Add Filter</Button> |
|||
<div> |
|||
<Button secondary on:click={dropdown.hide}>Cancel</Button> |
|||
<Button primary on:click={saveView}>Save</Button> |
|||
</div> |
|||
</div> |
|||
</Popover> |
|||
|
|||
<style> |
|||
h5 { |
|||
margin-bottom: var(--spacing-l); |
|||
font-weight: 500; |
|||
} |
|||
|
|||
.button-group { |
|||
margin-top: var(--spacing-l); |
|||
display: flex; |
|||
justify-content: space-between; |
|||
align-items: center; |
|||
} |
|||
|
|||
:global(.button-group > div > button) { |
|||
margin-left: var(--spacing-m); |
|||
} |
|||
|
|||
.ri-close-circle-fill { |
|||
cursor: pointer; |
|||
} |
|||
|
|||
.input-group-row { |
|||
display: grid; |
|||
grid-template-columns: minmax(50px, auto) 1fr 1fr 1fr 15px; |
|||
gap: var(--spacing-s); |
|||
margin-bottom: var(--spacing-l); |
|||
align-items: center; |
|||
} |
|||
|
|||
p { |
|||
margin: 0; |
|||
font-size: var(--font-size-xs); |
|||
} |
|||
</style> |
|||
@ -0,0 +1,63 @@ |
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP |
|||
|
|||
exports[`viewBuilder Filter creates a view with multiple filters and conjunctions 1`] = ` |
|||
Object { |
|||
"map": "function (doc) { |
|||
if (doc.modelId === \\"14f1c4e94d6a47b682ce89d35d4c78b0\\" && doc[\\"Name\\"] === \\"Test\\" || doc[\\"Yes\\"] > \\"Value\\") { |
|||
emit(doc._id); |
|||
} |
|||
}", |
|||
"meta": Object { |
|||
"field": undefined, |
|||
"filters": Array [ |
|||
Object { |
|||
"condition": "EQUALS", |
|||
"key": "Name", |
|||
"value": "Test", |
|||
}, |
|||
Object { |
|||
"condition": "MT", |
|||
"conjunction": "OR", |
|||
"key": "Yes", |
|||
"value": "Value", |
|||
}, |
|||
], |
|||
"groupBy": undefined, |
|||
"modelId": "14f1c4e94d6a47b682ce89d35d4c78b0", |
|||
"schema": Object { |
|||
"avg": "number", |
|||
"count": "number", |
|||
"max": "number", |
|||
"min": "number", |
|||
"sum": "number", |
|||
"sumsqr": "number", |
|||
}, |
|||
}, |
|||
"reduce": "_stats", |
|||
} |
|||
`; |
|||
|
|||
exports[`viewBuilder Group By creates a view emitting the group by field 1`] = ` |
|||
Object { |
|||
"map": "function (doc) { |
|||
if (doc.modelId === \\"14f1c4e94d6a47b682ce89d35d4c78b0\\" ) { |
|||
emit(doc[\\"age\\"], doc[\\"score\\"]); |
|||
} |
|||
}", |
|||
"meta": Object { |
|||
"field": "score", |
|||
"filters": Array [], |
|||
"groupBy": "age", |
|||
"modelId": "14f1c4e94d6a47b682ce89d35d4c78b0", |
|||
"schema": Object { |
|||
"avg": "number", |
|||
"count": "number", |
|||
"max": "number", |
|||
"min": "number", |
|||
"sum": "number", |
|||
"sumsqr": "number", |
|||
}, |
|||
}, |
|||
"reduce": "_stats", |
|||
} |
|||
`; |
|||
@ -0,0 +1,39 @@ |
|||
const statsViewTemplate = require("../viewBuilder"); |
|||
|
|||
describe("viewBuilder", () => { |
|||
|
|||
describe("Filter", () => { |
|||
it("creates a view with multiple filters and conjunctions", () => { |
|||
expect(statsViewTemplate({ |
|||
"name": "yeety", |
|||
"modelId": "14f1c4e94d6a47b682ce89d35d4c78b0", |
|||
"filters": [{ |
|||
"value": "Test", |
|||
"condition": "EQUALS", |
|||
"key": "Name" |
|||
}, { |
|||
"value": "Value", |
|||
"condition": "MT", |
|||
"key": "Yes", |
|||
"conjunction": "OR" |
|||
}] |
|||
})).toMatchSnapshot() |
|||
}) |
|||
}) |
|||
|
|||
describe("Calculate", () => { |
|||
|
|||
}) |
|||
|
|||
describe("Group By", () => { |
|||
it("creates a view emitting the group by field", () => { |
|||
expect(statsViewTemplate({ |
|||
"name": "Test Scores Grouped By Age", |
|||
"modelId": "14f1c4e94d6a47b682ce89d35d4c78b0", |
|||
"groupBy": "age", |
|||
"field": "score", |
|||
"filters": [], |
|||
})).toMatchSnapshot() |
|||
}) |
|||
}) |
|||
}); |
|||
Loading…
Reference in new issue