Browse Source

comboSearch loader

VictoryKS 2 years ago
parent
commit
e2a75cf368
7 changed files with 97 additions and 8 deletions
  1. 1 0
      include/comboLookup.hrl
  2. 23 2
      lib/combo.ex
  3. 6 2
      lib/comboSearch.ex
  4. 1 1
      mix.exs
  5. 63 1
      priv/css/sortable.css
  6. 2 1
      src/elements/combo/element_comboLookup.erl
  7. 1 1
      src/nitro.app.src

+ 1 - 0
include/comboLookup.hrl

@@ -14,6 +14,7 @@
 -record(comboGroup,  { dom=[], value=[], delegate=[] }).
 -record(comboDraft,  { dom=[], list=[], values=[], group=[], subtitle=[], delegate=[] }).
 -record(comboUpdate, { id=[], fields=[], module=[], action=[], value=[] }).
+-record(comboLoader, { dom=[], delegate=[], status=[] }).
 -record(comboLookup, { ?ELEMENT_BASE(element_comboLookup),
     value=[],
     disabled=false,

+ 23 - 2
lib/combo.ex

@@ -19,6 +19,7 @@ defmodule NITRO.Combo do
   def proto(NITRO.comboModify(delegate: []) = msg), do: comboModify(msg)
   def proto(NITRO.comboGroup(delegate: []) = msg), do: comboGroup(msg)
   def proto(NITRO.comboDraft(delegate: []) = msg), do: comboDraft(msg)
+  def proto(NITRO.comboLoader(delegate: []) = msg), do: comboLoader(msg)
 
   def proto(NITRO.comboKey(delegate: module) = msg) do
     case has_function(module, :keyUp) do
@@ -76,12 +77,22 @@ defmodule NITRO.Combo do
     end
   end
 
-  def select(NITRO.comboSelect(uid: uid, dom: field, value: value, update: NITRO.comboUpdate() = update)) do
+  def proto(NITRO.comboLoader(delegate: module) = msg) do
+    case has_function(module, :comboLoader) do
+      true -> module.comboLoader(msg)
+      false -> comboLoader(msg)
+    end
+  end
+
+  def select(NITRO.comboSelect(uid: uid, dom: field, value: value, delegate: m, update: NITRO.comboUpdate() = update)) do
     send(self(), {:direct, NITRO.comboUpdate(update, value: value)})
+    send(self(), {:direct, NITRO.comboLoader(dom: field, delegate: m, status: :finished)})
     NITRO.Combo.Search.stop(uid, field)
   end
-  def select(NITRO.comboSelect(uid: uid, dom: field)), do:
+  def select(NITRO.comboSelect(uid: uid, dom: field, delegate: m)) do
+    send(self(), {:direct, NITRO.comboLoader(dom: field, delegate: m, status: :finished)})
     NITRO.Combo.Search.stop(uid, field)
+  end
 
   def comboInsert(NITRO.comboInsert(chunks: 0, dom: field, status: :finished)) do
     :nitro.wire("activeCombo = undefined; currentItem = undefined;")
@@ -136,6 +147,9 @@ defmodule NITRO.Combo do
     end
   end
 
+  def comboLoader(NITRO.comboLoader(dom: dom, status: :finished)), do: :nitro.remove(:nitro.atom([dom, :loader]))
+  def comboLoader(NITRO.comboLoader(dom: dom)), do: :nitro.insert_bottom(:nitro.atom([:lookup, dom]), loader(:nitro.atom([dom, :loader])))
+
   def dropDown0(uid, obj, dom0, module, feed) do
     case has_function(module, :dropDown) do
       true ->
@@ -204,6 +218,13 @@ defmodule NITRO.Combo do
     end
   end
 
+  def loader(id), do:
+    NITRO.div(
+      id: id,
+      class: "search-loader",
+      body: [NITRO.span(), NITRO.span(), NITRO.span(), NITRO.span(), NITRO.span(), NITRO.span()]
+    )
+
   def update_comboVec(_parent, dom, feed, module, default, elem) do
     vector  = view_value(default, module, feed)
     clear   = "createSortable('##{dom}_list');"

+ 6 - 2
lib/comboSearch.ex

@@ -46,6 +46,7 @@ defmodule NITRO.Combo.Search do
     :nitro.wire("comboCloseFormById('#{:nitro.atom([:nitro.to_list(field), 'form'])}');")
     :nitro.wire("comboLookupChange('#{field}');")
     :nitro.wire(NITRO.bind(target: :nitro.to_binary(comboContainer), type: :scroll, postback: onscroll(uid, field, module)))
+    send(self(), {:direct, NITRO.comboLoader(dom: field, delegate: module, status: :finished)})
     start(uid, value, field, feed, opts)
   end
 
@@ -79,10 +80,12 @@ defmodule NITRO.Combo.Search do
     m = Keyword.get(opts, :delegate, [])
     field = Keyword.get(opts, :field, [])
     value = case cmd do :append -> prev; _ -> :string.lowercase(:unicode.characters_to_list(value0, :unicode)) end
+    cmd in [:init, :append] and send(pid, {:direct, NITRO.comboLoader(dom: field, delegate: m)})
     r1 = :erlang.apply(:kvs, :take, [:erlang.apply(:kvs, :setfield, [r, :args, 10])])
     case :erlang.apply(:kvs, :field, [r1, :args]) do
       [] ->
         send(pid, {:direct, NITRO.comboInsert(uid: uid, dom: field, delegate: m, chunks: chunks, status: :finished)})
+        send(pid, {:direct, NITRO.comboLoader(dom: field, delegate: m, status: :finished)})
         {:stop, :normal, NITRO.pi(pi, state: state(st, reader: :erlang.apply(:kvs, :setfield, [r1, :args, []])))}
       rows ->
         filtered =
@@ -97,8 +100,9 @@ defmodule NITRO.Combo.Search do
           end
         newChunks = chunks + length(filtered)
         send(pid, {:direct, NITRO.comboInsert(uid: uid, dom: field, delegate: m, chunks: newChunks, feed: feed, rows: filtered)})
-        chunks < 100 and
-          case :nitro_pi.pid(:async, "comboSearch#{uid}") do [] -> []; pid -> send(pid, {:filterComboValues, cmd, value0}) end
+        if chunks < 100, do:
+          (case :nitro_pi.pid(:async, "comboSearch#{uid}") do [] -> []; pid -> send(pid, {:filterComboValues, :continue, value0}) end),
+        else: send(pid, {:direct, NITRO.comboLoader(dom: field, delegate: m, status: :finished)})
         {:noreply, NITRO.pi(pi, state: state(st, lastMsg: :erlang.timestamp(), value: value, chunks: newChunks, reader: :erlang.apply(:kvs, :setfield, [r1, :args, []])))}
     end
   end

+ 1 - 1
mix.exs

@@ -4,7 +4,7 @@ defmodule NITRO.Mixfile do
   def project do
     [
       app: :nitro,
-      version: "7.8.0",
+      version: "7.8.1",
       description: "NITRO Nitrogen Web Framework",
       package: package(),
       deps: deps()

+ 63 - 1
priv/css/sortable.css

@@ -137,4 +137,66 @@ body {
 
 .group-button__edit {
   background-image: url("data:image/svg+xml,%3Csvg width='16' height='16' viewBox='0 0 16 16' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='m12.246 2.193 1.56 1.56c.26.26.26.68 0 .94l-1.22 1.22-2.5-2.5 1.22-1.22A.656.656 0 0 1 11.772 2c.174 0 .34.06.474.193ZM1.999 11.5V14h2.5l7.373-7.373-2.5-2.5L2 11.5Zm1.947 1.167h-.614v-.614l6.04-6.04.614.614-6.04 6.04Z' fill='%23757575'/%3E%3C/svg%3E");
-}
+}
+
+
+.search-loader {
+  --color: rgb(var(--blue2));
+  --fade-color: rgba(var(--blue2), 0.1);
+  --x-speed: 1;
+  position: absolute;
+  top: 1em;
+  right: 2em;
+  width: 1em;
+  display: block;
+  transform: rotateZ(0);
+  animation: ps-spin calc(15s / var(--x-speed)) linear infinite
+}
+
+@keyframes ps-spin {
+  from {
+    transform: rotateZ(0);
+  }
+  to {
+    transform: rotateZ(360deg);
+  }
+}
+
+.search-loader span {
+  display: block;
+  position: absolute;
+  width: 100%;
+  height: 100%;
+}
+
+.search-loader span::before,
+.search-loader span::after {
+  content: "";
+  position: absolute;
+  width: 3px;
+  height: 3px;
+  top: 50%;
+  transform: translateY(-50%);
+  border-radius: 50%;
+  animation: ps-spinner-scale calc(1.2s / var(--x-speed)) linear infinite
+}
+.search-loader span::before { left: 0; }
+.search-loader span::after { right: 0; }
+.search-loader span:nth-child(1) { transform: rotate(90deg); }
+.search-loader span:nth-child(1)::before { background: rgb(var(--blue2)); }
+.search-loader span:nth-child(1)::after { background: rgba(var(--blue2), 0.4); }
+.search-loader span:nth-child(2) { transform: rotate(120deg); }
+.search-loader span:nth-child(2)::before { background: rgba(var(--blue2), 0.9); }
+.search-loader span:nth-child(2)::after { background: rgba(var(--blue2), 0.3); }
+.search-loader span:nth-child(3) { transform: rotate(150deg); }
+.search-loader span:nth-child(3)::before { background: rgba(var(--blue2), 0.8); }
+.search-loader span:nth-child(3)::after { background: rgba(var(--blue2), 0.2); }
+.search-loader span:nth-child(4) { transform: rotate(180deg); }
+.search-loader span:nth-child(4)::before { background: rgba(var(--blue2), 0.7); }
+.search-loader span:nth-child(4)::after { background: rgba(var(--blue2), 0.1); }
+.search-loader span:nth-child(5) { transform: rotate(210deg); }
+.search-loader span:nth-child(5)::before { background: rgba(var(--blue2), 0.6); }
+.search-loader span:nth-child(5)::after { background: rgba(var(--blue2), 0.05); }
+.search-loader span:nth-child(6) { transform: rotate(240deg); }
+.search-loader span:nth-child(6)::before { background: rgba(var(--blue2), 0.5); }
+.search-loader span:nth-child(6)::after { background: rgba(var(--blue2), 0.02); }

+ 2 - 1
src/elements/combo/element_comboLookup.erl

@@ -11,7 +11,8 @@ proto(#comboInsert{delegate=Module}=Msg) -> Module:proto(Msg);
 proto(#comboAdd{delegate=Module}=Msg)    -> Module:proto(Msg);
 proto(#comboModify{delegate=Module}=Msg) -> Module:proto(Msg);
 proto(#comboGroup{delegate=Module}=Msg)  -> Module:proto(Msg);
-proto(#comboDraft{delegate=Module}=Msg)  -> Module:proto(Msg).
+proto(#comboDraft{delegate=Module}=Msg)  -> Module:proto(Msg);
+proto(#comboLoader{delegate=Module}=Msg) -> Module:proto(Msg).
 
 render_element(#comboLookup{id=Id, style=Style, value = Val, bind = Object,
   feed = Feed, disabled = Disabled, delegate = Module, class = Class, nested = Nested, update = Update} = Data) ->

+ 1 - 1
src/nitro.app.src

@@ -1,6 +1,6 @@
 {application, nitro, [
     {description,  "NITRO Nitrogen Web Framework"},
-    {vsn,          "7.8.0"},
+    {vsn,          "7.8.1"},
     {applications, [kernel, stdlib]},
     {modules, []},
     {registered,   []},