diff --git a/assets/js/app.js b/assets/js/app.js index 2ca06a5..aada76a 100644 --- a/assets/js/app.js +++ b/assets/js/app.js @@ -25,9 +25,18 @@ import "phoenix_html" import {Socket} from "phoenix" import {LiveSocket} from "phoenix_live_view" import topbar from "../vendor/topbar" +import InfinityScroll from "./infinity-scroll" + +let Hooks = {} +Hooks.InfinityScroll = InfinityScroll; let csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content") -let liveSocket = new LiveSocket("/live", Socket, {params: {_csrf_token: csrfToken}}) +let liveSocket = new LiveSocket("/live", Socket, { + params: { _csrf_token: csrfToken }, + hooks: Hooks, +}) + + // Show progress bar on live navigation and form submits topbar.config({barColors: {0: "#29d"}, shadowColor: "rgba(0, 0, 0, .3)"}) @@ -42,4 +51,3 @@ liveSocket.connect() // >> liveSocket.enableLatencySim(1000) // enabled for duration of browser session // >> liveSocket.disableLatencySim() window.liveSocket = liveSocket - diff --git a/assets/js/infinity-scroll.js b/assets/js/infinity-scroll.js new file mode 100644 index 0000000..8febfa5 --- /dev/null +++ b/assets/js/infinity-scroll.js @@ -0,0 +1,29 @@ +/*** + * Hook to send push event "load-more" to server on window scroll events + */ +export default { + rootElement() { + return ( + document.documentElement || document.body.parentNode || document.body + ); + }, + scrollPosition() { + const { scrollTop, clientHeight, scrollHeight } = this.rootElement(); + return ((scrollTop + clientHeight) / scrollHeight) * 100; + }, + + mounted() { + this.threshold = 95; + this.lastScrollPosition = 0; + + window.addEventListener("scroll", () => { + const currentScrollPosition = this.scrollPosition(); + const isCloseToBottom = + currentScrollPosition > this.threshold && + this.lastScrollPosition <= this.threshold; + + if (isCloseToBottom) this.pushEvent("load-more", {}); + this.lastScrollPosition = currentScrollPosition; + }); + }, +}; diff --git a/lib/ascend/hills.ex b/lib/ascend/hills.ex index bfdd84e..3cf49b4 100644 --- a/lib/ascend/hills.ex +++ b/lib/ascend/hills.ex @@ -16,13 +16,28 @@ defmodule Ascend.Hills do [%Hill{}, ...] """ - def list_hills(opts) do + def list_hills(opts \\ %{}) do from(h in Hill) |> filter(opts) |> sort(opts) |> Repo.all() end + @doc """ + Returns a count of hills. + + ## Examples + + iex> hill_count() + 10 + + """ + def hill_count(opts \\ %{}) do + from(h in Hill) + |> filter(opts) + |> Repo.aggregate(:count) + end + @doc """ Returns the list of hills with a total count @@ -32,7 +47,7 @@ defmodule Ascend.Hills do %{hills: [%Hill{}, ...], total_count: 2} """ - def list_hills_with_total_count(opts) do + def list_hills_with_total_count(opts \\ %{}) do query = from(h in Hill) |> filter(opts) total_count = Repo.aggregate(query, :count) @@ -46,6 +61,14 @@ defmodule Ascend.Hills do %{hills: result, total_count: total_count} end + def list_hills_with_pagination(offset, limit, opts \\ %{}) do + from(h in Hill) + |> filter(opts) + |> limit(^limit) + |> offset(^offset) + |> Repo.all() + end + defp paginate(query, %{page: page, page_size: page_size}) when is_integer(page) and is_integer(page_size) do offset = max(page - 1, 0) * page_size diff --git a/lib/ascend_web/live/filter_component.ex b/lib/ascend_web/live/filter_component.ex index b56f786..981d50d 100644 --- a/lib/ascend_web/live/filter_component.ex +++ b/lib/ascend_web/live/filter_component.ex @@ -27,7 +27,6 @@ defmodule AscendWeb.Live.FilterComponent do def handle_event("search", %{"filter" => filter}, socket) do case FilterForm.parse(filter) do {:ok, opts} -> - IO.puts("Send self 1") send(self(), {:update, opts}) {:noreply, socket} diff --git a/lib/ascend_web/live/infinity_live.ex b/lib/ascend_web/live/infinity_live.ex new file mode 100644 index 0000000..68584d9 --- /dev/null +++ b/lib/ascend_web/live/infinity_live.ex @@ -0,0 +1,117 @@ +defmodule AscendWeb.InfinityLive do + use AscendWeb, :live_view + + alias Ascend.Hills + alias AscendWeb.Forms.FilterForm + + def render(assigns) do + ~H""" +
+ <%= live_redirect "#{hill.name}", to: Routes.hill_show_path(@socket, :show, hill) %> + | +<%= hill.dobih_id %> | +<%= hill.metres %> | +<%= hill.feet %> | +<%= hill.grid_ref %> | +<%= hill.classification %> | +<%= hill.region %> | +<%= hill.area %> | +