Studio: fix presets

This commit is contained in:
Pieter Vander Vennet 2023-06-20 01:32:24 +02:00
parent 223acee29c
commit 4c59f4482d
17 changed files with 244 additions and 62 deletions

View file

@ -8,6 +8,7 @@
import {Validator} from "./Validator"
import {Unit} from "../../Models/Unit"
import UnitInput from "../Popup/UnitInput.svelte"
import {Utils} from "../../Utils";
export let type: ValidatorType
export let feedback: UIEventSource<Translation> | undefined = undefined
@ -25,6 +26,9 @@
let _value = new UIEventSource(value.data ?? "")
let validator: Validator = Validators.get(type ?? "string")
if(validator === undefined){
console.warn("Didn't find a validator for type", type)
}
let selectedUnit: UIEventSource<string> = new UIEventSource<string>(undefined)
let _placeholder = placeholder ?? validator?.getPlaceholder() ?? type
@ -47,6 +51,7 @@
$: {
// The type changed -> reset some values
validator = Validators.get(type ?? "string")
_placeholder = placeholder ?? validator?.getPlaceholder() ?? type
feedback = feedback?.setData(validator?.getFeedback(_value.data, getCountry))
@ -56,9 +61,9 @@
function setValues() {
// Update the value stores
const v = _value.data
if (!validator.isValid(v, getCountry) || v === "") {
if (!validator?.isValid(v, getCountry) || v === "") {
value.setData(undefined)
feedback?.setData(validator.getFeedback(v, getCountry))
feedback?.setData(validator?.getFeedback(v, getCountry))
return
}
@ -74,10 +79,10 @@
onDestroy(_value.addCallbackAndRun((_) => setValues()))
onDestroy(selectedUnit.addCallback((_) => setValues()))
if (validator === undefined) {
throw "Not a valid type for a validator:" + type
throw "Not a valid type (no validator found) for type '" + type+"'; did you perhaps mean one of: "+Utils.sortedByLevenshteinDistance(type, Validators.AllValidators.map(v => v.name), v => v).slice(0, 5).join(", ")
}
const isValid = _value.map((v) => validator.isValid(v, getCountry))
const isValid = _value.map((v) => validator?.isValid(v, getCountry) ?? true)
let htmlElem: HTMLInputElement
@ -89,13 +94,13 @@
}
</script>
{#if validator.textArea}
{#if validator?.textArea}
<form on:submit|preventDefault={() => dispatch("submit")}>
<textarea
class="w-full"
bind:value={$_value}
inputmode={validator.inputmode ?? "text"}
inputmode={validator?.inputmode ?? "text"}
placeholder={_placeholder}></textarea>
</form>
{:else}
@ -104,7 +109,7 @@
bind:this={htmlElem}
bind:value={$_value}
class="w-full"
inputmode={validator.inputmode ?? "text"}
inputmode={validator?.inputmode ?? "text"}
placeholder={_placeholder}
/>
{#if !$isValid}

View file

@ -61,7 +61,7 @@ export abstract class Validator {
return Translations.t.validation[this.name].description
}
public isValid(_: string, __?: () => string): boolean {
public isValid(key: string, getCountry?: () => string): boolean {
return true
}

View file

@ -18,6 +18,8 @@ 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"
export type ValidatorType = (typeof Validators.availableTypes)[number]
@ -58,6 +60,8 @@ export default class Validators {
new PhoneValidator(),
new OpeningHoursValidator(),
new ColorValidator(),
new SimpleTagValidator(),
new ImageUrlValidator(),
]
private static _byType = Validators._byTypeConstructor()

View file

@ -0,0 +1,39 @@
import UrlValidator from "./UrlValidator"
import { Translation } from "../../i18n/Translation"
export default class ImageUrlValidator extends UrlValidator {
private static readonly allowedExtensions = ["jpg", "jpeg", "svg", "png"]
constructor() {
super(
"image",
"Same as the URL-parameter, except that it checks that the URL ends with `.jpg`, `.png` or some other typical image format"
)
}
private static hasValidExternsion(str: string): boolean {
str = str.toLowerCase()
return ImageUrlValidator.allowedExtensions.some((ext) => str.endsWith(ext))
}
getFeedback(s: string, _?: () => string): Translation | undefined {
const superF = super.getFeedback(s, _)
if (superF) {
return superF
}
if (!ImageUrlValidator.hasValidExternsion(s)) {
return new Translation(
"This URL does not end with one of the allowed extensions. These are: " +
ImageUrlValidator.allowedExtensions.join(", ")
)
}
return undefined
}
isValid(str: string): boolean {
if (!super.isValid(str)) {
return false
}
return ImageUrlValidator.hasValidExternsion(str)
}
}

View file

@ -0,0 +1,57 @@
import { Validator } from "../Validator"
import { Translation } from "../../i18n/Translation"
import Translations from "../../i18n/Translations"
/**
* Checks that the input conforms `key=value`, where `key` and `value` don't have too much weird characters
*/
export default class SimpleTagValidator extends Validator {
constructor() {
super(
"simple_tag",
"A simple tag of the format `key=value` where `key` conforms to a normal key `"
)
}
getFeedback(tag: string): Translation | undefined {
const parts = tag.split("=")
if (parts.length < 2) {
return Translations.T("A tag should contain a = to separate the 'key' and 'value'")
}
if (parts.length > 2) {
return Translations.T(
"A tag should contain precisely one `=` to separate the 'key' and 'value', but " +
(parts.length - 1) +
" equal signs were found"
)
}
const [key, value] = parts
if (key.length > 255) {
return Translations.T("A `key` should be at most 255 characters")
}
if (value.length > 255) {
return Translations.T("A `value should be at most 255 characters")
}
if (key.length == 0) {
return Translations.T("A `key` should not be empty")
}
if (value.length == 0) {
return Translations.T("A `value should not be empty")
}
const keyRegex = /[a-zA-Z0-9:_]+/
if (!key.match(keyRegex)) {
return Translations.T(
"A `key` should only have the characters `a-zA-Z0-9`, `:` or `_`"
)
}
return undefined
}
isValid(tag: string): boolean {
return this.getFeedback(tag) === undefined
}
}

View file

@ -1,10 +1,10 @@
import { Validator } from "../Validator"
export default class UrlValidator extends Validator {
constructor() {
constructor(name?: string, explanation?: string) {
super(
"url",
"The validatedTextField will format URLs to always be valid and have a https://-header (even though the 'https'-part will be hidden from the user. Furthermore, some tracking parameters will be removed",
name ??"url",
explanation?? "The validatedTextField will format URLs to always be valid and have a https://-header (even though the 'https'-part will be hidden from the user. Furthermore, some tracking parameters will be removed",
"url"
)
}