All Downloads are FREE. Search and download functionalities are using the official Maven repository.

kreuzberg.extras.LazyLoader.scala Maven / Gradle / Ivy

The newest version!
package kreuzberg.extras

import kreuzberg.*

import scala.concurrent.Future
import scala.util.{Failure, Success}

/** A Base class for components which lazy load stuff from an external service. */
abstract class LazyLoader[T] extends SimpleComponentBase {
  import LazyLoader.*

  val model = Model.create[LazyState[T]](LazyState.Init)

  /** Event sink for refreshing the loader. */
  def refresh()(using HandlerContext): Unit = {
    model.set(LazyState.Init)
  }

  /** Event sink for refreshing (silently) */
  def silentRefresh()(using hc: HandlerContext): Unit = {
    load().andThen {
      case Success(value) => model.set(LazyState.Ok(value))
      case Failure(e)     => model.set(LazyState.Failed(e))
    }
  }

  override def assemble(using c: SimpleContext): Html = {
    val data = subscribe(model)
    data match {
      case LazyState.Init            =>
        add(
          EventSource.Assembled.handle { _ =>
            model.set(LazyState.WaitResponse)
            silentRefresh()
          }
        )
        waiting()
      case LazyState.WaitResponse    =>
        waiting()
      case LazyState.Ok(data)        =>
        ok(data)
      case LazyState.Failed(message) =>
        failed(message)
    }
  }

  /** Load from external service. */
  def load()(using handlerContext: HandlerContext): Future[T]

  /** Html which is rendered during loading. */
  def waiting()(using c: SimpleContext): Html = {
    SimpleHtml("div").addText("Loading...")
  }

  /** Html which is rendered on error. */
  def failed(error: Throwable)(using c: SimpleContext): Html = {
    SimpleHtml("div").addText(s"Error: ${error.getMessage}")
  }

  /** Html which is rendered after loading. */
  def ok(data: T)(using c: SimpleContext): Html
}

object LazyLoader {

  /** State of [[LazyLoader]] */
  sealed trait LazyState[+T]

  object LazyState {
    // Initial state
    object Init extends LazyState[Nothing]

    /** Waiting for Response */
    object WaitResponse extends LazyState[Nothing]

    /** Data available */
    case class Ok[T](data: T) extends LazyState[T]

    case class Failed(error: Throwable) extends LazyState[Nothing]
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy