From 637f85a32c857ec3fe39453185459648440da6d1 Mon Sep 17 00:00:00 2001 From: Olivier NOUGUIER Date: Thu, 29 Aug 2024 10:07:10 +0200 Subject: [PATCH] feat: Add sealed classes example and update sample component --- .../src/main/scala/samples/EitherSample.scala | 36 +++---- .../src/main/scala/samples/EnumSample.scala | 65 ++++++------- .../src/main/scala/samples/ListElement.scala | 46 ++++----- .../src/main/scala/samples/Persons.scala | 95 ++++++++++--------- .../src/main/scala/samples/Sealed.scala | 44 +++++---- .../src/main/scala/samples/SimpleSample.scala | 29 +++--- .../client/src/main/scala/samples/Tree.scala | 84 ++++++++-------- .../src/main/scala/samples/Validation.scala | 63 ++++++------ .../scala/samples/model/CurrencyCode.scala | 6 -- .../scala/samples/model/LoginPassword.scala | 11 --- .../src/main/scala/samples/package.scala | 14 ++- 11 files changed, 246 insertions(+), 247 deletions(-) delete mode 100644 examples/client/src/main/scala/samples/model/CurrencyCode.scala delete mode 100644 examples/client/src/main/scala/samples/model/LoginPassword.scala diff --git a/examples/client/src/main/scala/samples/EitherSample.scala b/examples/client/src/main/scala/samples/EitherSample.scala index 52d9f63..e2bf7cf 100644 --- a/examples/client/src/main/scala/samples/EitherSample.scala +++ b/examples/client/src/main/scala/samples/EitherSample.scala @@ -6,23 +6,25 @@ import com.raquo.laminar.api.L.* import com.raquo.airstream.state.Var -val either = Sample( - "Either", { +val either = { - case class EitherSample( - either: Either[Cat, Dog], - optionalInt: Option[Int] - ) + case class EitherSample( + either: Either[Cat, Dog], + optionalInt: Option[Int] + ) - val eitherVar = Var(EitherSample(Left(Cat("Scala le chat", 6)), Some(1))) + val eitherVar = Var(EitherSample(Left(Cat("Scala le chat", 6)), Some(1))) + Sample( + "Either", { - div( - child <-- eitherVar.signal.map { item => - div( - s"$item" - ) - }, - eitherVar.asForm - ) - } -) + div( + child <-- eitherVar.signal.map { item => + div( + s"$item" + ) + }, + eitherVar.asForm + ) + } + ) +} diff --git a/examples/client/src/main/scala/samples/EnumSample.scala b/examples/client/src/main/scala/samples/EnumSample.scala index bd7568b..a5668d5 100644 --- a/examples/client/src/main/scala/samples/EnumSample.scala +++ b/examples/client/src/main/scala/samples/EnumSample.scala @@ -8,35 +8,36 @@ import com.raquo.airstream.state.Var import com.raquo.laminar.api.L -val enums = Sample( - "Enums", { - - enum Color(val code: String): - case Black extends Color("000") - case White extends Color("FFF") - case Isabelle extends Color("???") - - case class Basket(color: Color, cat: Cat) - - given colorForm: Form[Color] = enumForm(Color.values, Color.fromOrdinal) - - case class Cat( - name: String, - age: Int, - color: Color - ) - - val eitherVar = Var( - Basket(Color.Black, Cat("Scala", 10, Color.White)) - ) - - div( - child <-- eitherVar.signal.map { item => - div( - s"$item" - ) - }, - eitherVar.asForm - ) - } -) +val enums = { + enum Color(val code: String): + case Black extends Color("000") + case White extends Color("FFF") + case Isabelle extends Color("???") + + case class Basket(color: Color, cat: Cat) + + given colorForm: Form[Color] = enumForm(Color.values, Color.fromOrdinal) + + case class Cat( + name: String, + age: Int, + color: Color + ) + + val eitherVar = Var( + Basket(Color.Black, Cat("Scala", 10, Color.White)) + ) + Sample( + "Enums", { + + div( + child <-- eitherVar.signal.map { item => + div( + s"$item" + ) + }, + eitherVar.asForm + ) + } + ) +} diff --git a/examples/client/src/main/scala/samples/ListElement.scala b/examples/client/src/main/scala/samples/ListElement.scala index e420390..d19a4a7 100644 --- a/examples/client/src/main/scala/samples/ListElement.scala +++ b/examples/client/src/main/scala/samples/ListElement.scala @@ -4,33 +4,27 @@ import dev.cheleb.scalamigen.{*, given} import com.raquo.laminar.api.L.* -case class Person2(id: Int, name: String, age: Int) +val list = { + case class Person2(id: Int, name: String, age: Int) -case class ListElement( - ints: List[Person2] -) - -val listPersonVar = Var( - ListElement(List(1, 2, 3).map(id => Person2(id, "Vlad", 20))) -) -val listIntVar = Var(List(1, 2, 3)) + case class ListElement( + ints: List[Person2] + ) -given (Person2 => Int) = _.id + val listPersonVar = Var( + ListElement(List(1, 2, 3).map(id => Person2(id, "Vlad", 20))) + ) -val list = Sample( - "List", - div( - child <-- listPersonVar.signal.map { item => - div( - s"$item" - ) - }, - listPersonVar.asForm, - child <-- listIntVar.signal.map { item => - div( - s"$item" - ) - } - // Form.renderVar(listIntVar) + given (Person2 => Int) = _.id + Sample( + "List", + div( + child <-- listPersonVar.signal.map { item => + div( + s"$item" + ) + }, + listPersonVar.asForm + ) ) -) +} diff --git a/examples/client/src/main/scala/samples/Persons.scala b/examples/client/src/main/scala/samples/Persons.scala index 692733c..921af5c 100644 --- a/examples/client/src/main/scala/samples/Persons.scala +++ b/examples/client/src/main/scala/samples/Persons.scala @@ -7,58 +7,59 @@ import magnolia1.* import io.github.iltotore.iron.* import io.github.iltotore.iron.constraint.all.* -import samples.model.Password import java.time.LocalDate -// Define some models -@NoPanel -case class Person( - @FieldName("First Name") - name: String, - password: Password, - birthDate: LocalDate, - fav: Pet, - pet: Option[Pet], - email: Option[String], - age: BigInt, - size: Double -) -case class Pet( - name: String, - age: BigInt, - House: House, - size: Double :| Positive -) +val person = { + // Define some models -case class House(capacity: Int) + @NoPanel + case class Person( + @FieldName("First Name") + name: String, + password: Password, + birthDate: LocalDate, + fav: Pet, + pet: Option[Pet], + email: Option[String], + age: BigInt, + size: Double + ) + case class Pet( + name: String, + age: BigInt, + House: House, + size: Double :| Positive + ) -// Provide default for optional -given Defaultable[Pet] with - def default = Pet("No pet", 0, House(0), 1) + case class House(capacity: Int) -// Instance your model -val vlad = - Person( - "", - Password("not a password"), - LocalDate.of(1431, 11, 8), - Pet("Batman", 666, House(2), 169), - Some(Pet("Wolfy", 12, House(1), 42)), - Some("vlad.dracul@gmail.com"), - 48, - 1.85 - ) + // Provide default for optional + given Defaultable[Pet] with + def default = Pet("No pet", 0, House(0), 1) -val personVar = Var(vlad) + // Instance your model + val vlad = + Person( + "", + Password("not a password"), + LocalDate.of(1431, 11, 8), + Pet("Batman", 666, House(2), 169), + Some(Pet("Wolfy", 12, House(1), 42)), + Some("vlad.dracul@gmail.com"), + 48, + 1.85 + ) -val person = Sample( - "Person", - div( - child <-- personVar.signal.map { item => - div( - s"$item" - ) - }, - personVar.asForm + val personVar = Var(vlad) + Sample( + "Person", + div( + child <-- personVar.signal.map { item => + div( + s"$item" + ) + }, + personVar.asForm + ) ) -) +} diff --git a/examples/client/src/main/scala/samples/Sealed.scala b/examples/client/src/main/scala/samples/Sealed.scala index 9de337e..d96c781 100644 --- a/examples/client/src/main/scala/samples/Sealed.scala +++ b/examples/client/src/main/scala/samples/Sealed.scala @@ -6,24 +6,26 @@ import com.raquo.laminar.api.L.* import com.raquo.airstream.state.Var -sealed trait Animal -case class Horse(name: String, age: Int) extends Animal -case class Lama(name: String, age: Int, splitDistance: Int) extends Animal - -case class Owner(name: String, pet: Animal) - -val sealedClasses = Sample( - "Sealed", { - - val eitherVar = Var(Owner("Agnes", Horse("Niram <3", 6))) - - div( - child <-- eitherVar.signal.map { item => - div( - s"$item" - ) - }, - eitherVar.asForm - ) - } -) +val sealedClasses = { + sealed trait Animal + case class Horse(name: String, age: Int) extends Animal + case class Lama(name: String, age: Int, splitDistance: Int) extends Animal + + case class Owner(name: String, pet: Animal) + + Sample( + "Sealed", { + + val eitherVar = Var(Owner("Agnes", Horse("Niram <3", 6))) + + div( + child <-- eitherVar.signal.map { item => + div( + s"$item" + ) + }, + eitherVar.asForm + ) + } + ) +} diff --git a/examples/client/src/main/scala/samples/SimpleSample.scala b/examples/client/src/main/scala/samples/SimpleSample.scala index 4e00d6e..dfc5d1f 100644 --- a/examples/client/src/main/scala/samples/SimpleSample.scala +++ b/examples/client/src/main/scala/samples/SimpleSample.scala @@ -6,18 +6,19 @@ import com.raquo.laminar.api.L.* import com.raquo.airstream.state.Var -val simple = Sample( - "Simple", { +val simple = { + val eitherVar = Var(Cat("Scala le chat", 6)) + Sample( + "Simple", { - val eitherVar = Var(Cat("Scala le chat", 6)) - - div( - child <-- eitherVar.signal.map { item => - div( - s"$item" - ) - }, - eitherVar.asForm - ) - } -) + div( + child <-- eitherVar.signal.map { item => + div( + s"$item" + ) + }, + eitherVar.asForm + ) + } + ) +} diff --git a/examples/client/src/main/scala/samples/Tree.scala b/examples/client/src/main/scala/samples/Tree.scala index 830bec6..861208c 100644 --- a/examples/client/src/main/scala/samples/Tree.scala +++ b/examples/client/src/main/scala/samples/Tree.scala @@ -6,22 +6,23 @@ import com.raquo.laminar.api.L.* import com.raquo.airstream.state.Var -enum Tree[+T]: - case Empty extends Tree[Nothing] - case Node(value: T, left: Tree[T], right: Tree[T]) -object Tree: - def isSameStructure(tree1: Tree[?], tree2: Tree[?]): Boolean = - (tree1, tree2) match - case (Empty, Empty) => true - case (Node(_, _, _), Empty) => false - case (Empty, Node(_, _, _)) => false - case (Node(_, left1, right1), Node(_, left2, right2)) => - isSameStructure(left1, left2) && isSameStructure(right1, right2) +val tree = { -given treeInstance[A](using - default: Defaultable[A] -)(using Form[A]): Form[Tree[A]] = - new Form[Tree[A]] { self => + enum Tree[+T]: + case Empty extends Tree[Nothing] + case Node(value: T, left: Tree[T], right: Tree[T]) + object Tree: + def isSameStructure(tree1: Tree[?], tree2: Tree[?]): Boolean = + (tree1, tree2) match + case (Empty, Empty) => true + case (Node(_, _, _), Empty) => false + case (Empty, Node(_, _, _)) => false + case (Node(_, left1, right1), Node(_, left2, right2)) => + isSameStructure(left1, left2) && isSameStructure(right1, right2) + + given treeInstance[A](using + default: Defaultable[A] + )(using Form[A]): Form[Tree[A]] = new Form[Tree[A]] { self => override def isAnyRef = true override def render( variable: Var[Tree[A]], @@ -88,30 +89,35 @@ given treeInstance[A](using ) } -val tree = Sample( - "Tree", { + Sample( + "Tree", { - import Tree.* + import Tree.* - case class Person(name: String, age: Int) - object Person { - given Defaultable[Person] with - def default = Person("--", 0) - } - val treeVar2 = Var( - Node(Person("agnes", 50), Node(Person("Zozo", 53), Empty, Empty), Empty) - ) - div( - child <-- treeVar2.signal.map { item => - div( - s"$item zozo" + case class Person(name: String, age: Int) + object Person { + given Defaultable[Person] with + def default = Person("--", 0) + } + val treeVar2 = Var( + Node( + Person("agnes", 50), + Node(Person("Zozo", 53), Empty, Empty), + Empty ) - }, - child <-- treeVar2.signal - .distinctByFn(Tree.isSameStructure) - .map { item => - treeVar2.asForm - } - ) - } -) + ) + div( + child <-- treeVar2.signal.map { item => + div( + s"$item zozo" + ) + }, + child <-- treeVar2.signal + .distinctByFn(Tree.isSameStructure) + .map { item => + treeVar2.asForm + } + ) + } + ) +} diff --git a/examples/client/src/main/scala/samples/Validation.scala b/examples/client/src/main/scala/samples/Validation.scala index c2f5a44..4e3b3e1 100644 --- a/examples/client/src/main/scala/samples/Validation.scala +++ b/examples/client/src/main/scala/samples/Validation.scala @@ -9,35 +9,36 @@ import io.github.iltotore.iron.constraint.all.* import com.raquo.airstream.state.Var -import samples.model.CurrencyCode - -given Form[CurrencyCode] = stringForm(CurrencyCode(_)) - -case class IronSample( - curenncyCode: CurrencyCode, - optional: Option[String], - optionalInt: Option[Int], - doubleGreaterThanEight: Double :| GreaterEqual[8.0], - optionalDoublePositive: Option[Double :| Positive] -) - -given IronTypeValidator[Double, GreaterEqual[8.0]] = - _.toDoubleOption match - case None => Left("Nots a number") - case Some(double) => double.refineEither[GreaterEqual[8.0]] - -val ironSampleVar = Var( - IronSample(CurrencyCode("Eur"), Some("name"), Some(1), 9.1, Some(1)) -) - -val validation = Sample( - "Validation", - div( - child <-- ironSampleVar.signal.map { item => - div( - s"$item" - ) - }, - ironSampleVar.asForm +val validation = { + + given Form[CurrencyCode] = stringForm(CurrencyCode(_)) + + case class IronSample( + curenncyCode: CurrencyCode, + optional: Option[String], + optionalInt: Option[Int], + doubleGreaterThanEight: Double :| GreaterEqual[8.0], + optionalDoublePositive: Option[Double :| Positive] + ) + + given IronTypeValidator[Double, GreaterEqual[8.0]] = + _.toDoubleOption match + case None => Left("Nots a number") + case Some(double) => double.refineEither[GreaterEqual[8.0]] + + val ironSampleVar = Var( + IronSample(CurrencyCode("Eur"), Some("name"), Some(1), 9.1, Some(1)) + ) + + Sample( + "Validation", + div( + child <-- ironSampleVar.signal.map { item => + div( + s"$item" + ) + }, + ironSampleVar.asForm + ) ) -) +} diff --git a/examples/client/src/main/scala/samples/model/CurrencyCode.scala b/examples/client/src/main/scala/samples/model/CurrencyCode.scala deleted file mode 100644 index e049f52..0000000 --- a/examples/client/src/main/scala/samples/model/CurrencyCode.scala +++ /dev/null @@ -1,6 +0,0 @@ -package samples.model - -opaque type CurrencyCode = String - -object CurrencyCode: - def apply(code: String): CurrencyCode = code diff --git a/examples/client/src/main/scala/samples/model/LoginPassword.scala b/examples/client/src/main/scala/samples/model/LoginPassword.scala deleted file mode 100644 index cc4c1c6..0000000 --- a/examples/client/src/main/scala/samples/model/LoginPassword.scala +++ /dev/null @@ -1,11 +0,0 @@ -package samples.model - -import dev.cheleb.scalamigen.Form - -import dev.cheleb.scalamigen.secretForm - -opaque type Password = String - -object Password: - def apply(password: String): Password = password - given Form[Password] = secretForm(apply) diff --git a/examples/client/src/main/scala/samples/package.scala b/examples/client/src/main/scala/samples/package.scala index 6a4febe..8913ad4 100644 --- a/examples/client/src/main/scala/samples/package.scala +++ b/examples/client/src/main/scala/samples/package.scala @@ -1,9 +1,17 @@ package samples -import dev.cheleb.scalamigen.Defaultable +import dev.cheleb.scalamigen.* import dev.cheleb.scalamigen.ui5.UI5WidgetFactory -import dev.cheleb.scalamigen.WidgetFactory -import dev.cheleb.scalamigen.LaminarWidgetFactory + +opaque type CurrencyCode = String + +object CurrencyCode: + def apply(code: String): CurrencyCode = code + +opaque type Password = String +object Password: + def apply(password: String): Password = password + given Form[Password] = secretForm(apply) case class Cat(name: String, weight: Int) case class Dog(name: String, weight: Int)