forked from MapComplete/MapComplete
UX: indicate that a search field is actually a regex, add feedback to the filterview
This commit is contained in:
parent
5da63bf83a
commit
ebe7ff85f8
5 changed files with 39 additions and 7 deletions
|
@ -850,6 +850,9 @@
|
|||
"description": "a positive, whole number",
|
||||
"noZero": "Zero is not allowed"
|
||||
},
|
||||
"regex": {
|
||||
"description": "a regular expression"
|
||||
},
|
||||
"slope": {
|
||||
"inputExplanation": "Place your phone on the ground with the top side of your phone pointing towards the top of the slope.",
|
||||
"inputIncorrect": "For correct measurements, make sure the arrow is within the green area."
|
||||
|
|
|
@ -60,7 +60,7 @@ export default class FilterConfig {
|
|||
}
|
||||
|
||||
const fields: { name: string; type: ValidatorType }[] = (option.fields ?? []).map((f, i) => {
|
||||
const type = <ValidatorType> f.type ?? "string"
|
||||
const type = <ValidatorType> f.type ?? "regex"
|
||||
if(Validators.availableTypes.indexOf(type) < 0){
|
||||
throw `Invalid filter: type is not a valid validator. Did you mean one of ${Utils.sortedByLevenshteinDistance(type, <any>Validators.availableTypes, x => x).slice(0, 3)}`
|
||||
}
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
import { Utils } from "../../Utils"
|
||||
import type { ValidatorType } from "../InputElement/Validators"
|
||||
import InputHelper from "../InputElement/InputHelper.svelte"
|
||||
import { Translation } from "../i18n/Translation"
|
||||
import Tr from "../Base/Tr.svelte"
|
||||
|
||||
export let filteredLayer: FilteredLayer
|
||||
export let option: FilterConfigOption
|
||||
|
@ -36,7 +38,7 @@
|
|||
appliedFilter?.setData(FilteredLayer.fieldsToString(properties))
|
||||
}
|
||||
|
||||
let firstValue : UIEventSource<string>
|
||||
let firstValue: UIEventSource<string>
|
||||
for (const field of option.fields) {
|
||||
// A bit of cheating: the 'parts' will have '}' suffixed for fields
|
||||
const src = new UIEventSource<string>(initialState[field.name] ?? "")
|
||||
|
@ -47,9 +49,10 @@
|
|||
onDestroy(
|
||||
src.stabilized(200).addCallback(() => {
|
||||
setFields()
|
||||
}),
|
||||
})
|
||||
)
|
||||
}
|
||||
let feedback: UIEventSource<Translation> = new UIEventSource<Translation>(undefined)
|
||||
</script>
|
||||
|
||||
<div class="low-interaction p-1 rounded-2xl px-3" class:interactive={$firstValue?.length > 0}>
|
||||
|
@ -58,11 +61,15 @@
|
|||
<!-- This is a field! -->
|
||||
<span class="mx-1">
|
||||
<InputHelper value={fieldValues[part["subs"]]} type={fieldTypes[part["subs"]]}>
|
||||
<ValidatedInput slot="fallback" value={fieldValues[part["subs"]]} type={fieldTypes[part["subs"]]} />
|
||||
<ValidatedInput slot="fallback" value={fieldValues[part["subs"]]} type={fieldTypes[part["subs"]]}
|
||||
{feedback} />
|
||||
</InputHelper>
|
||||
</span>
|
||||
{:else}
|
||||
{@html part["message"]}
|
||||
{/if}
|
||||
{/each}
|
||||
{#if $feedback}
|
||||
<Tr cls="alert" t={$feedback}/>
|
||||
{/if}
|
||||
</div>
|
||||
|
|
|
@ -15,9 +15,6 @@ import UrlValidator from "./Validators/UrlValidator"
|
|||
import PhoneValidator from "./Validators/PhoneValidator"
|
||||
import OpeningHoursValidator from "./Validators/OpeningHoursValidator"
|
||||
import ColorValidator from "./Validators/ColorValidator"
|
||||
import BaseUIElement from "../BaseUIElement"
|
||||
import Combine from "../Base/Combine"
|
||||
import Title from "../Base/Title"
|
||||
import SimpleTagValidator from "./Validators/SimpleTagValidator"
|
||||
import ImageUrlValidator from "./Validators/ImageUrlValidator"
|
||||
import TagKeyValidator from "./Validators/TagKeyValidator"
|
||||
|
@ -30,6 +27,7 @@ import SlopeValidator from "./Validators/SlopeValidator"
|
|||
import VeloparkValidator from "./Validators/VeloparkValidator"
|
||||
import NameSuggestionIndexValidator from "./Validators/NameSuggestionIndexValidator"
|
||||
import CurrencyValidator from "./Validators/CurrencyValidator"
|
||||
import RegexValidator from "./Validators/RegexValidator"
|
||||
|
||||
export type ValidatorType = (typeof Validators.availableTypes)[number]
|
||||
|
||||
|
@ -64,6 +62,7 @@ export default class Validators {
|
|||
"velopark",
|
||||
"nsi",
|
||||
"currency",
|
||||
"regex"
|
||||
] as const
|
||||
|
||||
public static readonly AllValidators: ReadonlyArray<Validator> = [
|
||||
|
@ -95,6 +94,7 @@ export default class Validators {
|
|||
new VeloparkValidator(),
|
||||
new NameSuggestionIndexValidator(),
|
||||
new CurrencyValidator(),
|
||||
new RegexValidator()
|
||||
]
|
||||
|
||||
private static _byType = Validators._byTypeConstructor()
|
||||
|
|
22
src/UI/InputElement/Validators/RegexValidator.ts
Normal file
22
src/UI/InputElement/Validators/RegexValidator.ts
Normal file
|
@ -0,0 +1,22 @@
|
|||
import StringValidator from "./StringValidator"
|
||||
import { s } from "vitest/dist/env-afee91f0"
|
||||
import { Translation } from "../../i18n/Translation"
|
||||
import Translations from "../../i18n/Translations"
|
||||
|
||||
export default class RegexValidator extends StringValidator{
|
||||
constructor() {
|
||||
super("regex", "Validates a regex")
|
||||
}
|
||||
|
||||
getFeedback(s: string): Translation | undefined {
|
||||
try{
|
||||
new RegExp(s)
|
||||
}catch (e) {
|
||||
return Translations.T("Not a valid Regex: "+e)
|
||||
}
|
||||
}
|
||||
|
||||
isValid(s: string): boolean {
|
||||
return this.getFeedback(s) === undefined
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue