Giter VIP home page Giter VIP logo

dissolver's Introduction

Dissolver

NOTE: This is a wip repo. So be warned there maybe be bugs.

This project is a fork of https://github.com/elixirdrops/kerosene.
I thought to take it over because it does not look as if its being activly developed and I wanted more features.

TODO:

  • Lazy query - Instead of pagination calling Repo.all it will return an Ecto query. This is useful for subqueries where you will passying the query to something like a preload.
  • Custom themes - Now you can pass a module as the source of your theme.
  • Refactor all the test so that the modules only exposed required interfaces.
  • The way this lib queries for total counts is a bit odd since it's trying to account for groub_by and multi sourced froms. I'm going to see if we can't make this cleaner.
  • Refactor namespace of functions. General clean up of internal methods.

CI Coverage Status

Pagination for Ecto and Phoenix.

Installation

add Dissolver to your mix.exs dependencies:

def deps do
  [
    {:dissolver, "~> 0.9.4"}
  ]
end

Next provide Dissolver your Repo module via the config. Add the following to your config:

...
config :dissolver,
  repo: MyApp.Repo
  per_page: 2

import_config "\#{Mix.env()}.exs"

For more information about the configuration options look at the Configurations section

Now you are ready to start using Dissolver.

Usage

Start paginating your queries

def index(conn, params) do
  {products, paginator} =
  Product
  |> Product.with_lowest_price
  |> Dissolver.paginate(params)

  render(conn, "index.html", products: products, paginator: paginator)
end

Add the view helper to your view

defmodule MyApp.ProductView do
  use MyApp.Web, :view
  import Dissolver.HTML
end

Generate the links using the view helper in your template

<%= paginate @conn, @paginator %>

Importing Dissolver.HTML provides your template access to Dissolver.HTML.paginate/3 as the prior example shows. The Dissolver.HTML.paginate/3 can take a host of options to aid the theme from how many links to show (window: integer) to what the link labels should read.

By default the theme used to generate the html is the Dissolver.HTML.Simple theme. It will only provide the very basic prev|next buttons. For more theme options, including providing your own, read the following Configurations

Configuration

This module uses the following that can be set as globals in your config/config.ex configurations

  • :repo - Required Your app's Ecto Repo

  • :theme (default: Dissolver.HTML.Simple) - A module that implements the Dissolver.HTML.Theme behavior There are a few pre defiend theme modules found in dessolver/html/

  • :per_page (default: 20) - The global per page setting

  • :max_page - The limit of pages allow to navigate regardless of total pages found This option is ignored if not provided and defaults to total pages found in the query.

  • :lazy (default: false) - This option if enabled will result in all Dissolver.paginate/3 calls return an Ecto.Query rather than call Repo.all. This is useful for when you need to paginate on an association via a preload. TODO: provide example.

JSON API Support.

defmodule MyApp.ProductView do
  use MyApp.Web, :view
  import Dissolver.JSON

  def render("index.json", %{products: products, dissolver: dissolver, conn: conn}) do
    %{data: render_many(products, MyApp.ProductView, "product.json"),
      pagination: paginate(conn, dissolver)}
  end

  def render("product.json", %{product: product}) do
    %{id: product.id,
      name: product.name,
      description: product.description,
      price: product.price}
  end
end

Lazy Example.

Say you have a tag that has many posts and you want to paginate the post as they relate to a given tag.

Heres an example of using the lazy option so that Dissolver.paginate returns a query rather than a result.

def get_post_for_tag!(tag_name, params \\ %{}) do
    total_count =
      from(t in "tags",
        join: pt in "post_tags",
        on: pt.tag_id == t.id,
        where: t.name == ^tag_name,
        select: count()
      )
      |> Repo.one()

    {posts_query, paginator} =
      from(p in Post, order_by: [desc: :inserted_at], preload: [:tags])
      |> Dissolver.paginate(params, total_count: total_count, lazy: true)

    tag =
      from(t in Tag, where: t.name == ^tag_name, preload: [posts: ^posts_query])
      |> Repo.one!()

    {tag, paginator}
  end

You will notice that in this case I also have to supply total_count since Dissolver.paginate does not currently have a way to scope total_count of a given tag since they query is applied after Dissolver.paginate was called. So for this use case we just supply the total count up front.

For my controller it looks just like most.

def show_post(conn, %{"tag" => tag} = params) do
  {tag, paginator} = Blog.get_post_for_tag!(tag, params)
  render(conn, "show_posts.html", tag: tag, paginator: paginator)
end

You can also send in options to paginate helper look at the docs for more details.

Contributing

If you can start by writing an issue ticket. Then if you like feel free to fork and submit a PR for review.

Acknowledgement

I would like to Thank

  • Matt (@mgwidmann)
  • Drew Olson (@drewolson)
  • Akira Matsuda (@amatsuda)

License

Please take a look at LICENSE.md

dissolver's People

Contributors

allyraza avatar kovpack avatar abdulsattar avatar merqlove avatar scarfacedeb avatar m1dnight avatar danmaksimov avatar hoyon avatar ivanpetrovic avatar justinaiken avatar theangryangel avatar mtarnovan avatar feymartynov avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.