Skip to content

Commit

Permalink
Add filter parsing/serializing with UI
Browse files Browse the repository at this point in the history
  • Loading branch information
tfwright committed Nov 17, 2024
1 parent b36c4f5 commit ff9ffad
Show file tree
Hide file tree
Showing 7 changed files with 191 additions and 38 deletions.
45 changes: 41 additions & 4 deletions assets/css/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -490,11 +490,21 @@ input[type="submit"] {
@apply font-semibold;
}

#pagination-modal label {
#settings-modal label {
@apply bg-inherit;
@apply w-1/2;
}

#list-filters > div > div {
@apply flex;
@apply justify-evenly;
}

#list-filters div > div > * {
@apply w-1/4;
@apply leading-5;
}

.resource__table dd {
@apply mb-5;
}
Expand Down Expand Up @@ -670,6 +680,10 @@ input[type="submit"] {
@apply pb-6;
}

.field__array--row input:not(first-of-type) {
@apply mr-2;
}

.field__array--group a.button__add {
@apply absolute;
@apply -left-0;
Expand Down Expand Up @@ -841,21 +855,44 @@ input[type="submit"] {
@apply mr-2;
}

.modal input {
@apply grow;
.modal__title {
@apply text-lg;
@apply font-bold;
@apply border-b-2;
}

.modal__title {
.modal__tabs {
@apply border-b-2;
}

.modal__tabs > .modal__title--active {
@apply text-lg;
@apply font-bold;
@apply border-b-2;
@apply inline-block;
@apply mr-2;
@apply border-0;
}

.modal__tabs > .modal__title {
@apply inline-block;
@apply mr-2;
@apply border-0;
@apply cursor-pointer;
}

.modal form > div {
@apply flex;
@apply my-1;
@apply items-center;
}

.modal form > input[type="submit"] {
@apply w-24;
@apply mx-auto;
}


.modal form > div:last-of-type {
@apply mb-3;
}
Expand Down
50 changes: 46 additions & 4 deletions dist/css/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -1242,11 +1242,21 @@ input[class$="-loading"] + div nav:before {
font-weight: 600;
}

#pagination-modal label {
#settings-modal label {
background-color: inherit;
width: 50%;
}

#list-filters > div > div {
display: flex;
justify-content: space-evenly;
}

#list-filters div > div > * {
width: 25%;
line-height: 1.25rem;
}

.resource__table dd {
margin-bottom: 1.25rem;
}
Expand Down Expand Up @@ -1448,6 +1458,10 @@ input[class$="-loading"] + div nav:before {
padding-bottom: 1.5rem;
}

.field__array--row input:not(first-of-type) {
margin-right: 0.5rem;
}

.field__array--group a.button__add {
position: absolute;
left: -0px;
Expand Down Expand Up @@ -1717,6 +1731,10 @@ input[class$="-loading"] + div nav:before {
opacity: 1;
}

.opacity-30 {
opacity: 0.3;
}

.filter {
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
}
Expand Down Expand Up @@ -1837,21 +1855,45 @@ input[type="submit"] {
margin-right: 0.5rem;
}

.modal input {
flex-grow: 1;
.modal__title {
font-size: 1.125rem;
line-height: 1.75rem;
font-weight: 700;
border-bottom-width: 2px;
}

.modal__title {
.modal__tabs {
border-bottom-width: 2px;
}

.modal__tabs > .modal__title--active {
font-size: 1.125rem;
line-height: 1.75rem;
font-weight: 700;
border-bottom-width: 2px;
display: inline-block;
margin-right: 0.5rem;
border-width: 0px;
}

.modal__tabs > .modal__title {
display: inline-block;
margin-right: 0.5rem;
border-width: 0px;
cursor: pointer;
}

.modal form > div {
display: flex;
margin-top: 0.25rem;
margin-bottom: 0.25rem;
align-items: center;
}

.modal form > input[type="submit"] {
width: 6rem;
margin-left: auto;
margin-right: auto;
}

.modal form > div:last-of-type {
Expand Down
82 changes: 65 additions & 17 deletions lib/live_admin/components/resource/index.ex
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,13 @@ defmodule LiveAdmin.Components.Container.Index do
/>
</form>
<button
phx-click="search"
phx-value-query=""
phx-target={@myself}
phx-click={
JS.show(to: "#settings-modal")
|> JS.add_class("hidden", to: "#settings-modal div:nth-child(2)")
|> JS.remove_class("hidden", to: "#settings-modal div:nth-child(3)")
|> JS.remove_class("opacity-30")
|> JS.add_class("opacity-30", to: "#settings-modal .modal__title:nth-child(1)")
}
class="flex items-center justify-center px-2 border-l"
>
<svg fill="currentColor" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
Expand Down Expand Up @@ -229,7 +233,7 @@ defmodule LiveAdmin.Components.Container.Index do
class="resource__action--secondary"
phx-click={
JS.show(
to: "#pagination-modal",
to: "#settings-modal",
transition: {"ease-in duration-300", "opacity-0", "opacity-100"}
)
}
Expand Down Expand Up @@ -296,19 +300,63 @@ defmodule LiveAdmin.Components.Container.Index do
</div>
</div>
</div>
<.modal id="pagination-modal">
<div class="modal__title"><%= trans("Page") %></div>
<form phx-submit="go" phx-target={@myself}>
<div>
<label><%= trans("Number") %></label>
<input type="number" name="page" value={@page} />
</div>
<div>
<label><%= trans("Size") %></label>
<input type="number" name="per" value={@per} />
</div>
<input type="submit" value="Go" phx-click={JS.hide(to: "#pagination-modal")} />
</form>
<.modal id="settings-modal">
<div class="modal__tabs">
<a
class="modal__title"
phx-click={
JS.add_class("hidden", to: "#settings-modal div:nth-child(3)")
|> JS.remove_class("hidden", to: "#settings-modal div:nth-child(2)")
|> JS.remove_class("opacity-30")
|> JS.add_class("opacity-30", to: "#settings-modal .modal__title:nth-child(2)")
}
>
<%= trans("Page") %>
</a>
<a
class="modal__title opacity-30"
phx-click={
JS.add_class("hidden", to: "#settings-modal div:nth-child(2)")
|> JS.remove_class("hidden", to: "#settings-modal div:nth-child(3)")
|> JS.remove_class("opacity-30")
|> JS.add_class("opacity-30", to: "#settings-modal .modal__title:nth-child(1)")
}
>
<%= trans("Filters") %>
</a>
</div>
<div>
<form phx-submit="go" phx-target={@myself}>
<div>
<label><%= trans("Number") %></label>
<input type="number" name="page" value={@page} />
</div>
<div>
<label><%= trans("Size") %></label>
<input type="number" name="per" value={@per} />
</div>
<input type="submit" value={trans("Go")} phx-click={JS.hide(to: "#settings-modal")} />
</form>
</div>
<div class="hidden">
<form phx-submit="set_filters" phx-target={@myself} id="list-filters">
<div>
<a href="#" class="button__remove" phx-click={JS.exec("alert('hi')")} />
<div>
<select name="field">
<%= for {field, _, _} <- Resource.fields(@resource, @config) do %>
<option><%= to_string(field) %></option>
<% end %>
</select>
<select name="operator">
<option>contains</option>
</select>
<input type="text" name="param" />
</div>
</div>
<input type="submit" value={trans("Apply")} phx-click={JS.hide(to: "#settings-modal")} />
</form>
</div>
</.modal>
</div>
"""
Expand Down
8 changes: 3 additions & 5 deletions lib/live_admin/resource.ex
Original file line number Diff line number Diff line change
Expand Up @@ -261,9 +261,9 @@ defmodule LiveAdmin.Resource do

defp apply_search(query, q, fields) do
q
|> String.split(~r{[^\s]*:}, include_captures: true, trim: true)
|> LiveAdmin.View.parse_search()
|> case do
[q] ->
[[q]] ->
matcher = if String.contains?(q, "%"), do: q, else: "%#{q}%"

Enum.reduce(fields, query, fn {field_name, _, _}, query ->
Expand All @@ -279,13 +279,11 @@ defmodule LiveAdmin.Resource do

field_queries ->
field_queries
|> Enum.map(&String.trim/1)
|> Enum.chunk_every(2)
|> Enum.reduce(query, fn
[field_key, q], query ->
fields
|> Enum.find_value(fn {field_name, _, _} ->
if "#{field_name}:" == field_key, do: field_name
if to_string(field_name) == field_key, do: field_name
end)
|> case do
nil ->
Expand Down
7 changes: 7 additions & 0 deletions lib/live_admin/view.ex
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,13 @@ defmodule LiveAdmin.View do
def supported_type?({_, {Ecto.Enum, _}}), do: true
def supported_type?(_), do: false

def parse_search(q) do
q
|> String.split(~r{[^\s]*:}, include_captures: true, trim: true)
|> Enum.map(&String.replace(&1, [" ", ":"], ""))
|> Enum.chunk_every(2)
end

def get_function_keys(resource, config, function) do
resource
|> LiveAdmin.fetch_config(function, config)
Expand Down
8 changes: 0 additions & 8 deletions test/live_admin/components/container_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -82,14 +82,6 @@ defmodule LiveAdmin.Components.ContainerTest do
test "filters results", %{view: view} do
assert render_async(view) =~ "0-0/0"
end

test "clears search", %{view: view} do
view
|> element("button[phx-click='search']")
|> render_click()

assert render_async(view) =~ "1-1/1"
end
end

describe "list resource with prefix param" do
Expand Down
29 changes: 29 additions & 0 deletions test/live_admin/view_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
defmodule LiveAdmin.ViewTest do
use ExUnit.Case, async: true

alias LiveAdmin.View

setup do
Ecto.Adapters.SQL.Sandbox.checkout(LiveAdminTest.Repo)
end

describe "parse_search/1 with a field token" do
setup do
%{result: View.parse_search("test:test")}
end

test "returns a list", %{result: result} do
assert [["test", "test"]] = result
end
end

describe "parse_search/1 with a general token" do
setup do
%{result: View.parse_search("test")}
end

test "returns a singleton item", %{result: result} do
assert [["test"]] = result
end
end
end

0 comments on commit ff9ffad

Please sign in to comment.