refactor of multi-option filtering and validation
This commit is contained in:
parent
544dd4ef1d
commit
ee830d0e85
|
@ -15,7 +15,6 @@
|
||||||
import { getSchemaForDatasource } from "builderStore/dataBinding"
|
import { getSchemaForDatasource } from "builderStore/dataBinding"
|
||||||
import DrawerBindableInput from "components/common/bindings/DrawerBindableInput.svelte"
|
import DrawerBindableInput from "components/common/bindings/DrawerBindableInput.svelte"
|
||||||
import { generate } from "shortid"
|
import { generate } from "shortid"
|
||||||
import Multiselect from "../../../../../../../bbui/src/Form/Core/Multiselect.svelte"
|
|
||||||
|
|
||||||
export let rules = []
|
export let rules = []
|
||||||
export let bindings = []
|
export let bindings = []
|
||||||
|
@ -59,11 +58,11 @@
|
||||||
value: "notRegex",
|
value: "notRegex",
|
||||||
},
|
},
|
||||||
Contains: {
|
Contains: {
|
||||||
label: "Must contain one",
|
label: "Must contain",
|
||||||
value: "contains",
|
value: "contains",
|
||||||
},
|
},
|
||||||
NotContains: {
|
NotContains: {
|
||||||
label: "Must not contain ",
|
label: "Must not contain",
|
||||||
value: "notContains",
|
value: "notContains",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -98,8 +97,8 @@
|
||||||
["attachment"]: [Constraints.Required],
|
["attachment"]: [Constraints.Required],
|
||||||
["link"]: [
|
["link"]: [
|
||||||
Constraints.Required,
|
Constraints.Required,
|
||||||
Constraints.ContainsRowID,
|
Constraints.Contains,
|
||||||
Constraints.NotContainsRowID,
|
Constraints.NotContains,
|
||||||
Constraints.MinLength,
|
Constraints.MinLength,
|
||||||
Constraints.MaxLength,
|
Constraints.MaxLength,
|
||||||
],
|
],
|
||||||
|
@ -283,7 +282,7 @@
|
||||||
disabled={rule.constraint === "required"}
|
disabled={rule.constraint === "required"}
|
||||||
on:change={e => (rule.value = e.detail)}
|
on:change={e => (rule.value = e.detail)}
|
||||||
/>
|
/>
|
||||||
{:else if ["maxLength", "minLength", "regex", "notRegex"].includes(rule.constraint)}
|
{:else if rule.type !== "array" && ["maxLength", "minLength", "regex", "notRegex", "contains", "notContains"].includes(rule.constraint)}
|
||||||
<!-- Certain constraints always need string values-->
|
<!-- Certain constraints always need string values-->
|
||||||
<Input
|
<Input
|
||||||
bind:value={rule.value}
|
bind:value={rule.value}
|
||||||
|
@ -297,15 +296,14 @@
|
||||||
bind:value={rule.value}
|
bind:value={rule.value}
|
||||||
placeholder="Constraint value"
|
placeholder="Constraint value"
|
||||||
/>
|
/>
|
||||||
{:else if rule.type === "array" && ["contains", "notContains"].includes(rule.constraint)}
|
{:else if rule.type === "array"}
|
||||||
<Multiselect
|
<Select
|
||||||
disabled={rule.constraint === "required"}
|
disabled={rule.constraint === "required"}
|
||||||
options={dataSourceSchema.schema[field].constraints
|
options={dataSourceSchema.schema[field].constraints
|
||||||
.inclusion}
|
.inclusion}
|
||||||
getOptionLabel={x => x}
|
getOptionLabel={x => x}
|
||||||
getOptionValue={x => x}
|
getOptionValue={x => x}
|
||||||
on:change={e => (rule.value = e.detail)}
|
value={rule.value}
|
||||||
bind:value={rule.value}
|
|
||||||
/>
|
/>
|
||||||
{:else if rule.type === "boolean"}
|
{:else if rule.type === "boolean"}
|
||||||
<Select
|
<Select
|
||||||
|
|
|
@ -32,11 +32,11 @@ export const OperatorOptions = {
|
||||||
label: "Less than",
|
label: "Less than",
|
||||||
},
|
},
|
||||||
Contains: {
|
Contains: {
|
||||||
value: "contains",
|
value: "equal",
|
||||||
label: "Contains",
|
label: "Contains",
|
||||||
},
|
},
|
||||||
NotContains: {
|
NotContains: {
|
||||||
value: "notContains",
|
value: "notEqual",
|
||||||
label: "Does Not Contain",
|
label: "Does Not Contain",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -64,7 +64,7 @@ export const getValidOperatorsForType = type => {
|
||||||
} else if (type === "options") {
|
} else if (type === "options") {
|
||||||
return [Op.Equals, Op.NotEquals, Op.Empty, Op.NotEmpty]
|
return [Op.Equals, Op.NotEquals, Op.Empty, Op.NotEmpty]
|
||||||
} else if (type === "array") {
|
} else if (type === "array") {
|
||||||
return [Op.Contains, Op.NotContains]
|
return [Op.Contains, Op.NotContains, Op.Empty, Op.NotEmpty]
|
||||||
} else if (type === "boolean") {
|
} else if (type === "boolean") {
|
||||||
return [Op.Equals, Op.NotEquals, Op.Empty, Op.NotEmpty]
|
return [Op.Equals, Op.NotEquals, Op.Empty, Op.NotEmpty]
|
||||||
} else if (type === "longform") {
|
} else if (type === "longform") {
|
||||||
|
|
|
@ -17,8 +17,6 @@ class QueryBuilder {
|
||||||
notEqual: {},
|
notEqual: {},
|
||||||
empty: {},
|
empty: {},
|
||||||
notEmpty: {},
|
notEmpty: {},
|
||||||
contains: {},
|
|
||||||
notContains: {},
|
|
||||||
...base,
|
...base,
|
||||||
}
|
}
|
||||||
this.limit = 50
|
this.limit = 50
|
||||||
|
@ -106,16 +104,6 @@ class QueryBuilder {
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
addContains(key, value) {
|
|
||||||
this.query.contains[key] = value
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
addNotContains(key, value) {
|
|
||||||
this.query.notContains[key] = value
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Preprocesses a value before going into a lucene search.
|
* Preprocesses a value before going into a lucene search.
|
||||||
* Transforms strings to lowercase and wraps strings and bools in quotes.
|
* Transforms strings to lowercase and wraps strings and bools in quotes.
|
||||||
|
@ -223,28 +211,6 @@ class QueryBuilder {
|
||||||
if (this.query.notEmpty) {
|
if (this.query.notEmpty) {
|
||||||
build(this.query.notEmpty, key => `${key}:["" TO *]`)
|
build(this.query.notEmpty, key => `${key}:["" TO *]`)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.query.contains) {
|
|
||||||
build(this.query.contains, (key, value) => {
|
|
||||||
if (!value) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
return `${key}:${builder.preprocess(value, allPreProcessingOpts)}`
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.query.notContains) {
|
|
||||||
build(this.query.notContains, (key, value) => {
|
|
||||||
if (!value) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
return `!${key}.${value}:${builder.preprocess(
|
|
||||||
value,
|
|
||||||
allPreProcessingOpts
|
|
||||||
)}`
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return query
|
return query
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,12 +43,12 @@
|
||||||
>
|
>
|
||||||
{#if fieldState}
|
{#if fieldState}
|
||||||
<CoreMultiselect
|
<CoreMultiselect
|
||||||
value={$fieldState.value}
|
value={fieldState.value || []}
|
||||||
error={$fieldState.error}
|
error={fieldState.error}
|
||||||
getOptionLabel={flatOptions ? x => x : x => x.label}
|
getOptionLabel={flatOptions ? x => x : x => x.label}
|
||||||
getOptionValue={flatOptions ? x => x : x => x.value}
|
getOptionValue={flatOptions ? x => x : x => x.value}
|
||||||
id={$fieldState.fieldId}
|
id={fieldState.fieldId}
|
||||||
disabled={$fieldState.disabled}
|
disabled={fieldState.disabled}
|
||||||
on:change={e => fieldApi.setValue(e.detail)}
|
on:change={e => fieldApi.setValue(e.detail)}
|
||||||
{placeholder}
|
{placeholder}
|
||||||
{options}
|
{options}
|
||||||
|
|
|
@ -76,19 +76,6 @@ export const createValidatorFromConstraints = (
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
|
||||||
schemaConstraints.type === "array" &&
|
|
||||||
exists(schemaConstraints.inclusion)
|
|
||||||
) {
|
|
||||||
const options = schemaConstraints.inclusion || []
|
|
||||||
rules.push({
|
|
||||||
type: "array",
|
|
||||||
constraint: "inclusion",
|
|
||||||
value: options,
|
|
||||||
error: "Invalid value",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Date constraint
|
// Date constraint
|
||||||
if (exists(schemaConstraints.datetime?.earliest)) {
|
if (exists(schemaConstraints.datetime?.earliest)) {
|
||||||
const limit = schemaConstraints.datetime.earliest
|
const limit = schemaConstraints.datetime.earliest
|
||||||
|
@ -262,9 +249,7 @@ const maxValueHandler = (value, rule) => {
|
||||||
|
|
||||||
// Evaluates an inclusion constraint
|
// Evaluates an inclusion constraint
|
||||||
const inclusionHandler = (value, rule) => {
|
const inclusionHandler = (value, rule) => {
|
||||||
return value == null || rule.type == "array"
|
return value == null || rule.value.includes(value)
|
||||||
? rule.value.map(val => val === value)
|
|
||||||
: rule.value.includes(value)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Evaluates an equal constraint
|
// Evaluates an equal constraint
|
||||||
|
@ -295,10 +280,6 @@ const notRegexHandler = (value, rule) => {
|
||||||
|
|
||||||
// Evaluates a contains constraint
|
// Evaluates a contains constraint
|
||||||
const containsHandler = (value, rule) => {
|
const containsHandler = (value, rule) => {
|
||||||
if (rule.type == "array") {
|
|
||||||
const expectedValue = parseType(rule.value, "array")
|
|
||||||
return value && value.some(val => expectedValue.includes(val))
|
|
||||||
}
|
|
||||||
const expectedValue = parseType(rule.value, "string")
|
const expectedValue = parseType(rule.value, "string")
|
||||||
return value && value.includes(expectedValue)
|
return value && value.includes(expectedValue)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue