| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136 |
- package com.weEat.view
- import com.raquo.laminar.api.L._
- import io.laminext.syntax.core._
- import com.raquo.waypoint._
- import play.api.libs.json.{JsValue,Json}
- import com.weEat.controllers.{FoodController,USDAController}
- import com.weEat.modules._
- import com.weEat.shared.models.USDANodeNoId
- import gov.usda.nal.fdc.models._
- import gov.usda.nal.fdc.models.DataType._
- import org.scalajs.dom.Event
- import scala.concurrent.Future
- import scala.util.Success
- object UsdaImporter extends View[Option[String]] {
- import com.weEat.Main.headers
- implicit val ctx = com.weEat.shared.ctx
- val navName = Some("Usda Import")
- val tag = "importer"
- override val permissions = Set("admin")
- case class ViewPage(val q: Option[String] = None) extends P {
- val title = "USDA Import" + q.map((q) => s" - $q").getOrElse("")
- def jsonValue = Json.toJson(q)
- }
- def parseJson(jsVal: JsValue) = ViewPage(jsVal.asOpt[String])
- def route = Route.onlyQuery(
- encode = (page: ViewPage) => page.q,
- decode = (q: Option[String]) => ViewPage(q = q),
- pattern = (root / tag / endOfSegments) ? param[String]("q").?
- )
- def defaultPage = ViewPage()
- import com.raquo.airstream.custom.CustomSource._
- def lazyFutureSignal[T](fut: => Future[T]) =
- Signal.fromCustomSource(
- Success(fut),
- (_: SetCurrentValue[Future[T]], _: GetCurrentValue[Future[T]], _, _) => (),
- (_) => ()
- ).flatMap { (fut) =>
- Signal.fromFuture(fut)
- }
- def lazyFutureSignal[T](fut: => Future[T], default: => T) =
- Signal.fromCustomSource(
- Success(fut),
- (_: SetCurrentValue[Future[T]], _: GetCurrentValue[Future[T]], _, _) => (),
- (_) => ()
- ).flatMap { (fut) =>
- Signal.fromFuture(fut)
- }
- private val SEARCH_PAGE_SIZE = 40.asInstanceOf[Short]
- def content(queryPage: Signal[ViewPage]) = {
- val searchBar: SearchBar[Seq[Signal[Option[Seq[SearchResultFood]]]]] =
- SearchBar((term) =>
- USDAController.getFoodsSearch(term, Seq(
- Foundation, Survey, SRLegacy
- ).map(_.toString), pageSize = Some(SEARCH_PAGE_SIZE))().map {
- case SearchResult(criteria, n, cur, tot, baseList) =>
- Val(Some(baseList)) +:
- (cur + 1 to tot).map({ (c) => lazyFutureSignal(
- USDAController.postFoodsSearch()(
- criteria.copy(pageNumber = Some(c))
- ).map(_.foods),
- Nil
- ) })
- },
- inSignal = queryPage.map(_.q).withDefault("")
- )
- val searchResults = searchBar.result
- val pageSizeSel = Select(Val((10 to SEARCH_PAGE_SIZE by 10)))
- val numPages = pageSizeSel.value.combineWithFn(searchResults) {
- case (_, None) => 0
- case (size, Some(results)) => results.length * SEARCH_PAGE_SIZE / size
- }
- val pageSel = PageSelect(numPages)
- val currentSearchPageNum = pageSel.page.combineWithFn(pageSizeSel.value) {
- case (pageNum, pageSize) => pageNum * pageSize / SEARCH_PAGE_SIZE
- }
- val currentSearchPageOffset = pageSel.page.combineWithFn(pageSizeSel.value) {
- case (pageNum, pageSize) => pageNum % (SEARCH_PAGE_SIZE / pageSize)
- }
- val currentSearchPage = searchResults.combineWithFn(currentSearchPageNum) {
- case (Some(Nil), _) => Val(Nil)
- case (None, _) => Val(Nil)
- // [2023-09-26]@tflucke TODO: implement loading UI instead of default
- case (Some(res), pageNum) => res(pageNum).withDefault(Nil)
- }.flatMap(identity)
- // TODO: Prefetch next page
- div(
- h2("USDA Importer"),
- div(cls := "form-group",
- label(forId := "search", "Search: "),
- searchBar.render
- ),
- searchBar.searchTerm --> { (str: Option[String]) =>
- val oldQ = View.router.currentPageSignal.now().asInstanceOf[ViewPage].q
- if (oldQ != str)
- View.router.pushState(ViewPage(q = str))
- },
- PaginatedTable[SearchResultFood](Seq(
- ("", 1, { (x) => button(cls := "btn btn-light",
- onClick --> {(e: Event) =>
- val editor = USDAEditor(USDANodeNoId.fromSearchResult(x), true)
- Overlay.confirm(editor.render) { () =>
- import com.weEat.Main.headers
- FoodController.add()(editor.getUSDANode())
- }
- },
- "Add"
- )}),
- ("ID", 1, { (x) => span(x.fdcId.toString)}),
- ("Name", 3, { (x) => span(x.description)}),
- ("Desc", 4, { (x) => span(x.additionalDescriptions)}),
- ("Brand", 3, { (x) => span(x.brandOwner)})
- ),
- currentSearchPage,
- currentSearchPageOffset,
- pageSizeSel.value
- ).render,
- (pageSel.render).amendThis(
- (elm) => cls := s"${elm.ref.className} col-3 float-left"
- ),
- (pageSizeSel.render).amendThis(
- (elm) => cls := s"${elm.ref.className} col-1 float-right"
- )
- )
- }
- }
|