From 301827a6173ff16f9faeef81be05598620c57872 Mon Sep 17 00:00:00 2001 From: Olivier NOUGUIER Date: Sun, 6 Oct 2024 01:19:55 +0200 Subject: [PATCH] 217-missing-validator-for-common-type (#219) * fix: css issue * feat: include validators for additional types, such as Float, BigInt, and BigDecimal. These validators are used as base validations in Iron derivations. --- .../src/main/scala/samples/SimpleSample.scala | 20 ++++++++-- examples/client/style.css | 10 ++++- .../scala/dev/cheleb/scalamigen/Form.scala | 2 +- .../dev/cheleb/scalamigen/Validator.scala | 40 ++++++++++++++++++- .../scala/dev/cheleb/scalamigen/package.scala | 20 +++++----- .../scalamigen/ui5/UI5WidgetFactory.scala | 3 +- 6 files changed, 75 insertions(+), 20 deletions(-) diff --git a/examples/client/src/main/scala/samples/SimpleSample.scala b/examples/client/src/main/scala/samples/SimpleSample.scala index 564a966..b4f8708 100644 --- a/examples/client/src/main/scala/samples/SimpleSample.scala +++ b/examples/client/src/main/scala/samples/SimpleSample.scala @@ -3,11 +3,19 @@ package samples import com.raquo.laminar.api.L.* import dev.cheleb.scalamigen.* +import io.github.iltotore.iron.* +import io.github.iltotore.iron.constraint.all.* + val simple = { - case class Cat(name: String, weight: Int, kind: Boolean = true) + case class Cat( + name: String, + weight: Int, + hairsCount: BigInt :| GreaterEqual[100000], + kind: Boolean = true + ) - val simpleVar = Var(Cat("Scala le chat", 6)) + val simpleVar = Var(Cat("Scala le chat", 6, BigInt(100000).refineUnsafe)) Sample( "Simple", simpleVar.asForm, @@ -19,9 +27,13 @@ val simple = { } ), """ - |case class Cat(name: String, weight: Int, kind: Boolean = true) + |case class Cat( + | name: String, + | weight: Int, + | hairsCount: BigInt :| GreaterEqual[100000], + | kind: Boolean = true) | - |val simpleVar = Var(Cat("Scala le chat", 6)) + |val simpleVar = Var(Cat("Scala le chat", 6, BigInt(100000).refineUnsafe)) | |simpleVar.asForm """.stripMargin diff --git a/examples/client/style.css b/examples/client/style.css index 780b20a..a721cec 100644 --- a/examples/client/style.css +++ b/examples/client/style.css @@ -8,9 +8,17 @@ body { margin: 0; } +.srf-form { + border: 1px solid gray; +} + .srf-panel { + border: 1px solid gray; +} - border: 1px solid #d9d9d9; +.srf-table { + border: 1px solid gray; + border-radius: 10px; } .srf-field { diff --git a/modules/core/src/main/scala/dev/cheleb/scalamigen/Form.scala b/modules/core/src/main/scala/dev/cheleb/scalamigen/Form.scala index 3af762f..e39a2fd 100644 --- a/modules/core/src/main/scala/dev/cheleb/scalamigen/Form.scala +++ b/modules/core/src/main/scala/dev/cheleb/scalamigen/Form.scala @@ -609,7 +609,7 @@ object Form extends AutoDerivation[Form] { .renderPanel(panel.label) .amend( className := panel.panelCss, - cls := "srf-form", + // cls := "srf-form", if panel.asTable then renderAsTable() else renderAsPanel() ) diff --git a/modules/core/src/main/scala/dev/cheleb/scalamigen/Validator.scala b/modules/core/src/main/scala/dev/cheleb/scalamigen/Validator.scala index 5a27cf9..0fc8222 100644 --- a/modules/core/src/main/scala/dev/cheleb/scalamigen/Validator.scala +++ b/modules/core/src/main/scala/dev/cheleb/scalamigen/Validator.scala @@ -1,14 +1,50 @@ package dev.cheleb.scalamigen +import scala.util.Try + trait Validator[A] { def validate(str: String): Either[String, A] } +/** Validators for common types. They are the base validation used by Iron + * derivations. + */ object Validator { + + /** A validator for strings. + */ + given Validator[String] with + def validate(str: String): Either[String, String] = + Right(str) + + /** A validator for doubles. + */ given Validator[Double] with def validate(str: String): Either[String, Double] = - str.toDoubleOption.toRight("Not a number") + str.toDoubleOption.toRight("Not a double") + + /** A validator for integers. + */ given Validator[Int] with def validate(str: String): Either[String, Int] = - str.toIntOption.toRight("Not a number") + str.toIntOption.toRight("Not a int") + + /** A validator for longs. + */ + given Validator[Float] with + def validate(str: String): Either[String, Float] = + str.toFloatOption.toRight("Not a float") + + /** A validator for big integers. + */ + given Validator[BigInt] with + def validate(str: String): Either[String, BigInt] = + Try(BigInt.apply(str)).toEither.left.map(_.getMessage) + + /** A validator for big decimals. + */ + given Validator[BigDecimal] with + def validate(str: String): Either[String, BigDecimal] = + Try(BigDecimal.apply(str)).toEither.left.map(_.getMessage) + } diff --git a/modules/core/src/main/scala/dev/cheleb/scalamigen/package.scala b/modules/core/src/main/scala/dev/cheleb/scalamigen/package.scala index 92aa5ec..03370c5 100644 --- a/modules/core/src/main/scala/dev/cheleb/scalamigen/package.scala +++ b/modules/core/src/main/scala/dev/cheleb/scalamigen/package.scala @@ -3,8 +3,8 @@ package dev.cheleb.scalamigen import com.raquo.airstream.state.Var import com.raquo.laminar.api.L.* -import org.scalajs.dom.HTMLDivElement import com.raquo.laminar.nodes.ReactiveHtmlElement +import org.scalajs.dom.HTMLElement def stringForm[A](to: String => A) = new Form[A]: override def render( @@ -108,12 +108,11 @@ extension [A](va: Var[A]) */ def asForm(using wf: WidgetFactory)(using Form[A] - ): ReactiveHtmlElement[HTMLDivElement] = { + ): ReactiveHtmlElement[HTMLElement] = { val errorBus = new EventBus[(String, ValidationEvent)]() - div( - cls := "srf-form", - Form.renderVar(va, () => ())(using wf, errorBus) - ) + Form + .renderVar(va, () => ())(using wf, errorBus) + .amend(cls := "srf-form") } /** Render a form for the variable. @@ -126,11 +125,10 @@ extension [A](va: Var[A]) */ def asForm(errorBus: EventBus[(String, ValidationEvent)])(using wf: WidgetFactory - )(using Form[A]): ReactiveHtmlElement[HTMLDivElement] = - div( - cls := "srf-form", - Form.renderVar(va, () => ())(using wf, errorBus) - ) + )(using Form[A]): ReactiveHtmlElement[HTMLElement] = + Form + .renderVar(va, () => ())(using wf, errorBus) + .amend(cls := "srf-form") /** Buid an error bus for the variable that will be used to display errors. * diff --git a/modules/ui5/src/main/scala/dev/cheleb/scalamigen/ui5/UI5WidgetFactory.scala b/modules/ui5/src/main/scala/dev/cheleb/scalamigen/ui5/UI5WidgetFactory.scala index d638183..d4088b2 100644 --- a/modules/ui5/src/main/scala/dev/cheleb/scalamigen/ui5/UI5WidgetFactory.scala +++ b/modules/ui5/src/main/scala/dev/cheleb/scalamigen/ui5/UI5WidgetFactory.scala @@ -60,7 +60,8 @@ object UI5WidgetFactory extends WidgetFactory: _.headerText := headerText, _.headerLevel := TitleLevel.H3 ) - case None => Panel() + case None => + div(cls := "srf-table") override def renderSelect(f: Int => Unit): HtmlElement = Select( _.events.onChange