diff --git a/core/shared/src/main/scala/works/iterative/core/QueryResult.scala b/core/shared/src/main/scala/works/iterative/core/QueryResult.scala new file mode 100644 index 0000000..a3ce61e --- /dev/null +++ b/core/shared/src/main/scala/works/iterative/core/QueryResult.scala @@ -0,0 +1,3 @@ +package works.iterative.core + +type QueryResult[+A] = Option[Validated[A]] diff --git a/core/shared/src/main/scala/works/iterative/core/QueryResult.scala b/core/shared/src/main/scala/works/iterative/core/QueryResult.scala new file mode 100644 index 0000000..a3ce61e --- /dev/null +++ b/core/shared/src/main/scala/works/iterative/core/QueryResult.scala @@ -0,0 +1,3 @@ +package works.iterative.core + +type QueryResult[+A] = Option[Validated[A]] diff --git a/ui/js/src/main/scala/works/iterative/ui/components/laminar/HtmlRenderable.scala b/ui/js/src/main/scala/works/iterative/ui/components/laminar/HtmlRenderable.scala index 3cebcf2..13f8891 100644 --- a/ui/js/src/main/scala/works/iterative/ui/components/laminar/HtmlRenderable.scala +++ b/ui/js/src/main/scala/works/iterative/ui/components/laminar/HtmlRenderable.scala @@ -41,3 +41,9 @@ ): HtmlRenderable[Option[A]] with def toHtml(v: Option[A]): Modifier[HtmlElement] = v.map(r.toHtml) + + given signalRenderable[A](using + r: HtmlRenderable[A] + ): HtmlRenderable[Signal[A]] with + def toHtml(v: Signal[A]): Modifier[HtmlElement] = + child <-- v.map(a => div(r.toHtml(a))) diff --git a/core/shared/src/main/scala/works/iterative/core/QueryResult.scala b/core/shared/src/main/scala/works/iterative/core/QueryResult.scala new file mode 100644 index 0000000..a3ce61e --- /dev/null +++ b/core/shared/src/main/scala/works/iterative/core/QueryResult.scala @@ -0,0 +1,3 @@ +package works.iterative.core + +type QueryResult[+A] = Option[Validated[A]] diff --git a/ui/js/src/main/scala/works/iterative/ui/components/laminar/HtmlRenderable.scala b/ui/js/src/main/scala/works/iterative/ui/components/laminar/HtmlRenderable.scala index 3cebcf2..13f8891 100644 --- a/ui/js/src/main/scala/works/iterative/ui/components/laminar/HtmlRenderable.scala +++ b/ui/js/src/main/scala/works/iterative/ui/components/laminar/HtmlRenderable.scala @@ -41,3 +41,9 @@ ): HtmlRenderable[Option[A]] with def toHtml(v: Option[A]): Modifier[HtmlElement] = v.map(r.toHtml) + + given signalRenderable[A](using + r: HtmlRenderable[A] + ): HtmlRenderable[Signal[A]] with + def toHtml(v: Signal[A]): Modifier[HtmlElement] = + child <-- v.map(a => div(r.toHtml(a))) diff --git a/ui/shared/src/main/scala/works/iterative/ui/model/Computable.scala b/ui/shared/src/main/scala/works/iterative/ui/model/Computable.scala index 53d226b..e196a62 100644 --- a/ui/shared/src/main/scala/works/iterative/ui/model/Computable.scala +++ b/ui/shared/src/main/scala/works/iterative/ui/model/Computable.scala @@ -3,6 +3,8 @@ import works.iterative.core.UserMessage import java.time.Instant import zio.prelude.Covariant +import zio.prelude.Validation +import works.iterative.core.Validated /** A class representing the states of a model that needs computation */ @@ -11,10 +13,32 @@ */ def update[B >: Model](m: B): Computable[B] + def update[B >: Model](m: Validated[B]): Computable[B] = + m match + case Validation.Success(_, model) => update(model) + case Validation.Failure(_, errors) => fail(errors.head) + + /** Fail the computation */ + def fail(error: UserMessage): Computable[Nothing] = Computable.Failed(error) + /** Mark the computation as started */ def started: Computable[Model] + def isFailed: Boolean = this match + case Computable.Failed(_) => true + case _ => false + + def isDefined: Boolean = this match + case Computable.Ready(_) => true + case Computable.Recomputing(_, _) => true + case _ => false + + def isComputing: Boolean = this match + case Computable.Computing(_) => true + case Computable.Recomputing(_, _) => true + case _ => false + object Computable: /** The initial state of a computable model */