Merge pull request #3104 from Budibase/view-not-set

Handle nulls / empty in views and tables
This commit is contained in:
Rory Powell 2021-10-25 10:16:23 +01:00 committed by GitHub
commit 81ca6d3b22
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 53 additions and 22 deletions

View File

@ -42,6 +42,14 @@
name: "Contains", name: "Contains",
key: "CONTAINS", key: "CONTAINS",
}, },
{
name: "Is Not Empty",
key: "NOT_EMPTY",
},
{
name: "Is Empty",
key: "EMPTY",
},
] ]
const CONJUNCTIONS = [ const CONJUNCTIONS = [
@ -112,6 +120,10 @@
const getOptionLabel = x => x.name const getOptionLabel = x => x.name
const getOptionValue = x => x.key const getOptionValue = x => x.key
const showValue = filter => {
return !(filter.condition === "EMPTY" || filter.condition === "NOT_EMPTY")
}
</script> </script>
<ModalContent title="Filter" confirmText="Save" onConfirm={saveView} size="L"> <ModalContent title="Filter" confirmText="Save" onConfirm={saveView} size="L">
@ -140,30 +152,36 @@
{getOptionLabel} {getOptionLabel}
{getOptionValue} {getOptionValue}
/> />
{#if filter.key && isMultipleChoice(filter.key)} {#if showValue(filter)}
<Select {#if filter.key && isMultipleChoice(filter.key)}
bind:value={filter.value} <Select
options={fieldOptions(filter.key)} bind:value={filter.value}
getOptionLabel={x => x.toString()} options={fieldOptions(filter.key)}
/> getOptionLabel={x => x.toString()}
{:else if filter.key && isDate(filter.key)} />
<DatePicker {:else if filter.key && isDate(filter.key)}
bind:value={filter.value} <DatePicker
placeholder={filter.key || fields[0]} bind:value={filter.value}
/> placeholder={filter.key || fields[0]}
{:else if filter.key && isNumber(filter.key)} />
<Input {:else if filter.key && isNumber(filter.key)}
bind:value={filter.value} <Input
placeholder={filter.key || fields[0]} bind:value={filter.value}
type="number" placeholder={filter.key || fields[0]}
/> type="number"
/>
{:else}
<Input
placeholder={filter.key || fields[0]}
bind:value={filter.value}
/>
{/if}
<Icon hoverable name="Close" on:click={() => removeFilter(idx)} />
{:else} {:else}
<Input <Icon hoverable name="Close" on:click={() => removeFilter(idx)} />
placeholder={filter.key || fields[0]} <!-- empty div to preserve spacing -->
bind:value={filter.value} <div />
/>
{/if} {/if}
<Icon hoverable name="Close" on:click={() => removeFilter(idx)} />
{/each} {/each}
</div> </div>
{:else} {:else}

View File

@ -10,6 +10,15 @@ const TOKEN_MAP = {
OR: "||", OR: "||",
} }
const isEmptyExpression = key => {
return `(
doc["${key}"] === undefined ||
doc["${key}"] === null ||
doc["${key}"] === "" ||
(Array.isArray(doc["${key}"]) && doc["${key}"].length === 0)
)`
}
const GROUP_PROPERTY = { const GROUP_PROPERTY = {
group: { group: {
type: "string", type: "string",
@ -72,6 +81,10 @@ function parseFilterExpression(filters) {
expression.push( expression.push(
`doc["${filter.key}"].${TOKEN_MAP[filter.condition]}("${filter.value}")` `doc["${filter.key}"].${TOKEN_MAP[filter.condition]}("${filter.value}")`
) )
} else if (filter.condition === "EMPTY") {
expression.push(isEmptyExpression(filter.key))
} else if (filter.condition === "NOT_EMPTY") {
expression.push(`!${isEmptyExpression(filter.key)}`)
} else { } else {
const value = const value =
typeof filter.value == "string" ? `"${filter.value}"` : filter.value typeof filter.value == "string" ? `"${filter.value}"` : filter.value