Add filter web UI
This commit is contained in:
parent
0ebaca4a83
commit
c90f2d48e2
|
@ -19,8 +19,10 @@ defmodule Frenzy.Feed do
|
||||||
field :last_updated, :utc_datetime
|
field :last_updated, :utc_datetime
|
||||||
field :site_url, :string
|
field :site_url, :string
|
||||||
field :title, :string
|
field :title, :string
|
||||||
|
field :filter_enabled, :boolean
|
||||||
|
|
||||||
has_many :items, Frenzy.Item, on_delete: :delete_all
|
has_many :items, Frenzy.Item, on_delete: :delete_all
|
||||||
|
has_one :filter, Frenzy.Filter, on_delete: :delete_all
|
||||||
|
|
||||||
timestamps()
|
timestamps()
|
||||||
end
|
end
|
||||||
|
@ -28,7 +30,8 @@ defmodule Frenzy.Feed do
|
||||||
@doc false
|
@doc false
|
||||||
def changeset(feed, attrs) do
|
def changeset(feed, attrs) do
|
||||||
feed
|
feed
|
||||||
|> cast(attrs, [:title, :feed_url, :site_url, :last_updated])
|
|> cast(attrs, [:title, :feed_url, :site_url, :last_updated, :filter_enabled])
|
||||||
|
|> cast_assoc(:filter, required: true)
|
||||||
|> validate_required([:feed_url])
|
|> validate_required([:feed_url])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
defmodule Frenzy.Filter do
|
||||||
|
use Ecto.Schema
|
||||||
|
import Ecto.Changeset
|
||||||
|
|
||||||
|
schema "filters" do
|
||||||
|
field :mode, :string
|
||||||
|
field :score, :integer
|
||||||
|
|
||||||
|
belongs_to :feed, Frenzy.Feed
|
||||||
|
has_many :rules, Frenzy.Rule, on_delete: :delete_all
|
||||||
|
|
||||||
|
timestamps()
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc false
|
||||||
|
def changeset(filter, attrs) do
|
||||||
|
filter
|
||||||
|
|> cast(attrs, [:mode, :score])
|
||||||
|
|> cast_assoc(:rules)
|
||||||
|
|> validate_required([:mode, :score])
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,22 @@
|
||||||
|
defmodule Frenzy.Rule do
|
||||||
|
use Ecto.Schema
|
||||||
|
import Ecto.Changeset
|
||||||
|
|
||||||
|
schema "rules" do
|
||||||
|
field :mode, :string
|
||||||
|
field :property, :string
|
||||||
|
field :param, :string
|
||||||
|
field :weight, :integer
|
||||||
|
|
||||||
|
belongs_to :filter, Frenzy.Filter
|
||||||
|
|
||||||
|
timestamps()
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc false
|
||||||
|
def changeset(rule, attrs) do
|
||||||
|
rule
|
||||||
|
|> cast(attrs, [:mode, :property, :param, :weight])
|
||||||
|
|> validate_required([:mode, :property, :param, :weight])
|
||||||
|
end
|
||||||
|
end
|
|
@ -81,6 +81,7 @@ defmodule Frenzy.UpdateFeeds do
|
||||||
feed = Repo.preload(feed, :items)
|
feed = Repo.preload(feed, :items)
|
||||||
|
|
||||||
Enum.map(rss.items, fn entry ->
|
Enum.map(rss.items, fn entry ->
|
||||||
|
# todo: use Repo.exists for this
|
||||||
if !Enum.any?(feed.items, fn item -> item.guid == entry.id end) do
|
if !Enum.any?(feed.items, fn item -> item.guid == entry.id end) do
|
||||||
create_item(feed, entry)
|
create_item(feed, entry)
|
||||||
end
|
end
|
||||||
|
@ -100,7 +101,7 @@ defmodule Frenzy.UpdateFeeds do
|
||||||
|
|
||||||
{:err, reason} ->
|
{:err, reason} ->
|
||||||
Logger.warn("Unable to fetch article for #{url}: #{reason}")
|
Logger.warn("Unable to fetch article for #{url}: #{reason}")
|
||||||
entry.content || entry.summary
|
entry.description
|
||||||
end
|
end
|
||||||
|
|
||||||
changeset =
|
changeset =
|
||||||
|
|
|
@ -1,34 +1,61 @@
|
||||||
defmodule FrenzyWeb.FeedController do
|
defmodule FrenzyWeb.FeedController do
|
||||||
use FrenzyWeb, :controller
|
use FrenzyWeb, :controller
|
||||||
alias Frenzy.{Repo, Feed, Item}
|
alias Frenzy.{Repo, Feed, Filter, Item}
|
||||||
alias FrenzyWeb.Router.Helpers, as: Routes
|
alias FrenzyWeb.Router.Helpers, as: Routes
|
||||||
alias FrenzyWeb.Endpoint
|
alias FrenzyWeb.Endpoint
|
||||||
import Ecto.Query
|
import Ecto.Query
|
||||||
|
|
||||||
def index(conn, _params) do
|
def index(conn, _params) do
|
||||||
render(conn, "index.html", feeds: Repo.all(Feed))
|
render(conn, "index.html", feeds: Repo.all(Feed))
|
||||||
end
|
end
|
||||||
|
|
||||||
def show(conn, %{"id" => id}) do
|
def show(conn, %{"id" => id}) do
|
||||||
feed = Repo.get(Feed, id)
|
feed = Repo.get(Feed, id) |> Repo.preload(:filter)
|
||||||
items = Repo.all(from Item, where: [feed_id: ^id], order_by: [desc: :date])
|
items = Repo.all(from Item, where: [feed_id: ^id], order_by: [desc: :date])
|
||||||
|
|
||||||
render(conn, "show.html", %{
|
render(conn, "show.html", %{
|
||||||
feed: feed,
|
feed: feed,
|
||||||
items: items
|
items: items
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
def new(conn, _params) do
|
def new(conn, _params) do
|
||||||
changeset = Feed.changeset(%Feed{}, %{})
|
changeset = Feed.changeset(%Feed{}, %{})
|
||||||
|
|
||||||
render(conn, "new.html", changeset: changeset)
|
render(conn, "new.html", changeset: changeset)
|
||||||
end
|
end
|
||||||
|
|
||||||
def create(conn, %{"feed" => feed}) do
|
def create(conn, %{"feed" => feed}) do
|
||||||
changeset = Feed.changeset(%Feed{}, feed)
|
changeset =
|
||||||
|
Feed.changeset(
|
||||||
|
%Feed{
|
||||||
|
filter: %Filter{
|
||||||
|
mode: "accept",
|
||||||
|
score: 0,
|
||||||
|
rules: []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
feed
|
||||||
|
)
|
||||||
|
|
||||||
{:ok, feed} = Repo.insert(changeset)
|
{:ok, feed} = Repo.insert(changeset)
|
||||||
redirect(conn, to: Routes.feed_path(Endpoint, :index))
|
redirect(conn, to: Routes.feed_path(Endpoint, :index))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def enable_filter(conn, %{"id" => id}) do
|
||||||
|
feed = Repo.get(Feed, id) |> Repo.preload(:filter)
|
||||||
|
changeset = Feed.changeset(feed, %{filter_enabled: true})
|
||||||
|
Repo.update(changeset)
|
||||||
|
redirect(conn, to: Routes.feed_path(Endpoint, :show, id))
|
||||||
|
end
|
||||||
|
|
||||||
|
def disable_filter(conn, %{"id" => id}) do
|
||||||
|
feed = Repo.get(Feed, id)
|
||||||
|
changeset = Feed.changeset(feed, %{filter_enabled: false})
|
||||||
|
Repo.update(changeset)
|
||||||
|
redirect(conn, to: Routes.feed_path(Endpoint, :show, id))
|
||||||
|
end
|
||||||
|
|
||||||
def delete(conn, %{"id" => id}) do
|
def delete(conn, %{"id" => id}) do
|
||||||
feed = Repo.get(Feed, id)
|
feed = Repo.get(Feed, id)
|
||||||
{:ok, _} = Repo.delete(feed)
|
{:ok, _} = Repo.delete(feed)
|
||||||
|
@ -40,4 +67,4 @@ defmodule FrenzyWeb.FeedController do
|
||||||
feed = Frenzy.UpdateFeeds.refresh(Frenzy.UpdateFeeds, feed)
|
feed = Frenzy.UpdateFeeds.refresh(Frenzy.UpdateFeeds, feed)
|
||||||
redirect(conn, to: Routes.feed_path(Endpoint, :show, feed.id))
|
redirect(conn, to: Routes.feed_path(Endpoint, :show, feed.id))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
defmodule FrenzyWeb.FilterController do
|
||||||
|
use FrenzyWeb, :controller
|
||||||
|
alias Frenzy.{Repo, Feed, Filter, Rule}
|
||||||
|
alias FrenzyWeb.Router.Helpers, as: Routes
|
||||||
|
alias FrenzyWeb.Endpoint
|
||||||
|
import Ecto.Query
|
||||||
|
|
||||||
|
def edit(conn, %{"id" => id}) do
|
||||||
|
filter = Repo.get(Filter, id) |> Repo.preload(:rules)
|
||||||
|
changeset = Filter.changeset(filter, %{})
|
||||||
|
render(conn, "edit.html", changeset: changeset)
|
||||||
|
end
|
||||||
|
|
||||||
|
def update(conn, %{"id" => id, "filter" => filter_params}) do
|
||||||
|
filter = Repo.get(Filter, id) |> Repo.preload(:rules)
|
||||||
|
changeset = Filter.changeset(filter, filter_params)
|
||||||
|
Repo.update(changeset)
|
||||||
|
redirect(conn, to: Routes.filter_path(Endpoint, :edit, id))
|
||||||
|
end
|
||||||
|
|
||||||
|
def add_rule(conn, %{"id" => id}) do
|
||||||
|
filter = Repo.get(Filter, id)
|
||||||
|
|
||||||
|
changeset =
|
||||||
|
Ecto.build_assoc(filter, :rules, %{
|
||||||
|
property: "title",
|
||||||
|
mode: "contains_string",
|
||||||
|
param: "",
|
||||||
|
weight: 5
|
||||||
|
})
|
||||||
|
|
||||||
|
Repo.insert(changeset)
|
||||||
|
|
||||||
|
redirect(conn, to: Routes.filter_path(Endpoint, :edit, id))
|
||||||
|
end
|
||||||
|
end
|
|
@ -12,7 +12,6 @@ defmodule FrenzyWeb.Router do
|
||||||
|
|
||||||
pipeline :api do
|
pipeline :api do
|
||||||
plug :accepts, ["json"]
|
plug :accepts, ["json"]
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
scope "/", FrenzyWeb do
|
scope "/", FrenzyWeb do
|
||||||
|
@ -23,6 +22,11 @@ defmodule FrenzyWeb.Router do
|
||||||
get "/", FeedController, :index
|
get "/", FeedController, :index
|
||||||
resources "/feeds", FeedController, except: [:edit, :update]
|
resources "/feeds", FeedController, except: [:edit, :update]
|
||||||
post "/feeds/:id/refresh", FeedController, :refresh
|
post "/feeds/:id/refresh", FeedController, :refresh
|
||||||
|
post "/feeds/:id/enable_filter", FeedController, :enable_filter
|
||||||
|
post "/feeds/:id/disable_filter", FeedController, :disable_filter
|
||||||
|
|
||||||
|
resources "/filters", FilterController, only: [:edit, :update]
|
||||||
|
post "/filters/:id/add_rule", FilterController, :add_rule
|
||||||
|
|
||||||
resources "/items", ItemController, only: [:show]
|
resources "/items", ItemController, only: [:show]
|
||||||
post "/items/:id/read", ItemController, :read
|
post "/items/:id/read", ItemController, :read
|
||||||
|
|
|
@ -2,10 +2,26 @@
|
||||||
<%= submit "Refresh Feed" %>
|
<%= submit "Refresh Feed" %>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
|
|
||||||
|
<%= if @feed.filter_enabled do %>
|
||||||
|
<%= form_tag Routes.feed_path(@conn, :disable_filter, @feed.id), method: :post do %>
|
||||||
|
<%= submit "Disable Filter" %>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<%= form_tag Routes.filter_path(@conn, :edit, @feed.filter.id), method: :get do %>
|
||||||
|
<%= submit "Edit Filter" %>
|
||||||
|
<% end %>
|
||||||
|
<% else %>
|
||||||
|
<%= form_tag Routes.feed_path(@conn, :enable_filter, @feed.id), method: :post do %>
|
||||||
|
<%= submit "Enable Filter" %>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
<%= form_tag Routes.feed_path(@conn, :delete, @feed.id), method: :delete do %>
|
<%= form_tag Routes.feed_path(@conn, :delete, @feed.id), method: :delete do %>
|
||||||
<%= submit "Delete Feed" %>
|
<%= submit "Delete Feed" %>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
<%= for item <- @items do %>
|
<%= for item <- @items do %>
|
||||||
<tr <%= if item.read do %>class="item-read"<% end %>>
|
<tr <%= if item.read do %>class="item-read"<% end %>>
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
<h2>Filter</h2>
|
||||||
|
<%= form_for @changeset, Routes.filter_path(@conn, :update, @changeset.data.id), fn form -> %>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="mode">Mode</label>
|
||||||
|
<%= select form, :mode, [{"Accept", :accept}, {"Reject", :reject}] %>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="score">Score</label>
|
||||||
|
<%= number_input form, :score %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<th>Property</th>
|
||||||
|
<th>Mode</th>
|
||||||
|
<th>Param</th>
|
||||||
|
<th>Weight</th>
|
||||||
|
</tr>
|
||||||
|
<%= inputs_for form, :rules, fn p -> %>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<%= select p, :property, [{"URL", :url}, {"Title", :title}, {"Author", :author}, {"Content", :content}] %>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<%= select p, :mode, [{"contains", :contains_string}, {"matches regex", :matches_regex}] %>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<%= text_input p, :param %>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<%= number_input p, :weight %>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<% end %>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<%= submit "Update Filter" %>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
<%= form_tag Routes.filter_path(@conn, :add_rule, @changeset.data.id), method: :post do %>
|
||||||
|
<%= submit "Add Rule" %>
|
||||||
|
<% end %>
|
|
@ -0,0 +1,3 @@
|
||||||
|
defmodule FrenzyWeb.FilterView do
|
||||||
|
use FrenzyWeb, :view
|
||||||
|
end
|
|
@ -10,6 +10,5 @@ defmodule Frenzy.Repo.Migrations.CreateFeeds do
|
||||||
|
|
||||||
timestamps()
|
timestamps()
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
defmodule Frenzy.Repo.Migrations.CreateRules do
|
||||||
|
use Ecto.Migration
|
||||||
|
|
||||||
|
def change do
|
||||||
|
create table(:filters) do
|
||||||
|
add :mode, :string
|
||||||
|
add :score, :integer
|
||||||
|
add :rules, :map
|
||||||
|
add :feed_id, references(:feeds)
|
||||||
|
|
||||||
|
timestamps()
|
||||||
|
end
|
||||||
|
|
||||||
|
# create index(:rules, [:filter])
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,9 @@
|
||||||
|
defmodule Frenzy.Repo.Migrations.FeedsAddFilter do
|
||||||
|
use Ecto.Migration
|
||||||
|
|
||||||
|
def change do
|
||||||
|
alter table(:feeds) do
|
||||||
|
add :filter_enabled, :boolean
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,15 @@
|
||||||
|
defmodule Frenzy.Repo.Migrations.CreateRules do
|
||||||
|
use Ecto.Migration
|
||||||
|
|
||||||
|
def change do
|
||||||
|
create table(:rules) do
|
||||||
|
add :mode, :string
|
||||||
|
add :property, :string
|
||||||
|
add :param, :string
|
||||||
|
add :weight, :integer
|
||||||
|
add :filter_id, references(:filters)
|
||||||
|
|
||||||
|
timestamps()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue