Просмотр исходного кода

Added ability to reorder ingredients the same as steps.

Thomas Flucke 2 лет назад
Родитель
Сommit
c236bc7758
1 измененных файлов с 60 добавлено и 29 удалено
  1. 60 29
      webClient/src/main/scala/com/weEat/models/RecipeVar.scala

+ 60 - 29
webClient/src/main/scala/com/weEat/models/RecipeVar.scala

@@ -222,30 +222,67 @@ case class RecipeVar(recipe: Option[RecipeNode])
     }
   }
 
-  private def _presentFoodNode(idx: Int)(ingredientSig: Signal[Ingredient]) =
-    li(children <-- ingredientSig.flatMap { (ingredient: Ingredient) =>
-      Signal.fromFuture(ingredient.food).optionMap { (food) =>
-        Seq(
-          span(cls := "ui-icon ui-icon-pencil",
-            onClick --> { (e: Event) =>
-              _editIngredient(ingredient) { (in) =>
-                _ingredients.update(_.updated(idx, in))
-                Future.successful(())
-              }
+  private def _presentFoodNode(ingredient: Ingredient, idx: Int) =
+    li(children <-- Signal.fromFuture(ingredient.food).optionMap({ (food) =>
+      Seq(
+        span(cls := "ui-icon ui-icon-pencil",
+          onClick --> { (e: Event) =>
+            _editIngredient(ingredient) { (in) =>
+              _ingredients.update(_.updated(idx, in))
+              Future.successful(())
             }
-          ),
-          span(cls := "ui-icon ui-icon-close",
-            onClick --> { (e: Event) =>
-              _ingredients.update(_.filterNot(_ == ingredient))
-            }
-          ),
-          span(f"${ingredient.amount}%.02f${ingredient.unit.abr} ${food.name}")
-        )
-      } withDefault(Nil)
-    })
+          }
+        ),
+        span(cls := "ui-icon ui-icon-close",
+          onClick --> { (e: Event) =>
+            _ingredients.update(_.filterNot(_ == ingredient))
+          }
+        ),
+        span(f"${ingredient.amount}%.02f${ingredient.unit.abr} ${food.name}")
+      )
+    }).withDefault(Nil)
+    )
 
   private val _ENTER_KEY_CODE = 13
 
+  private val _ingredientList =  ul(
+    listStyleType := "none",
+    paddingLeft := "0",
+    // Do not use zipWithIndex.  It conflicts with the Sortable interface.
+    children <-- ingredients.map(_.zipWithIndex.map((_presentFoodNode _).tupled)),
+    onMountCallback({(ctx) =>
+      Sortable.create(ctx.thisNode.ref, SortableOptions.onUpdate({
+        (event: SortableEvent) =>
+        _ingredients.update({ (ingredients) =>
+          (event.oldIndex.toOption, event.newIndex.toOption) match {
+            case (Some(old), Some(ne)) if (old < ne) =>
+              moveBackwards(ingredients, old, ne)
+            case (Some(old), Some(ne)) =>
+              moveBackwards(
+                ingredients.reverse,
+                ingredients.size - old - 1,
+                ingredients.size - ne - 1
+              ).reverse
+            case (None, Some(ne)) =>
+              val (first, second) = ingredients.splitAt(ne)
+              (first :+ ???) ++ second
+            case (Some(old), None) =>
+              _removeFromList(ingredients, old)
+          }
+        })
+        // If the added element is still in the parent, remove it since the
+        // Rx.update will have generated a new one.
+        Option(event.item.parentElement).map(_.removeChild(event.item))
+
+        def moveBackwards(ingredients: Seq[Ingredient], old: Int, ne: Int) =
+          (ingredients.take(old) ++
+            ingredients.take(ne+1).drop(old + 1) :+
+            ingredients(old)) ++
+        ingredients.drop(ne+1)
+      }))
+    })
+  )
+
   private val _steps = Var[Seq[String]](_defaultRecipe.steps)
   val steps = _steps.signal
   private val _stepIn = input(idAttr := "step",
@@ -263,11 +300,12 @@ case class RecipeVar(recipe: Option[RecipeNode])
   private val _stepList = ol(
     listStyleType := "none",
     paddingLeft := "0",
+    // Do not use zipWithIndex.  It conflicts with the Sortable interface.
     children <-- _steps.signal.map(_.zipWithIndex.map((_presentStep _).tupled)),
     onMountCallback({(ctx) =>
       Sortable.create(ctx.thisNode.ref, SortableOptions.onUpdate({
       (event: SortableEvent) => 
-        _steps.update({ steps =>
+        _steps.update({ (steps) =>
           (event.oldIndex.toOption, event.newIndex.toOption) match {
             case (Some(old), Some(ne)) if (old < ne) =>
               moveBackwards(steps, old, ne)
@@ -381,14 +419,7 @@ case class RecipeVar(recipe: Option[RecipeNode])
           div(cls := "col-md-6",
             h2("Ingredients"),
             _ingredientSearch,
-            ul(
-              listStyleType := "none",
-              paddingLeft := "0",
-              children <-- ingredients.splitByIndex {
-                case (idx, _, ingredientStream) =>
-                  _presentFoodNode(idx)(ingredientStream)
-              }
-            )
+            _ingredientList
           ),
           div(cls := "col-md-6",
             h2("Steps"),