mirror of
https://github.com/philomena-dev/philomena.git
synced 2025-01-19 22:27:59 +01:00
adverts
This commit is contained in:
parent
bc6965485a
commit
b1828ff68a
12 changed files with 305 additions and 16 deletions
|
@ -4,9 +4,11 @@ defmodule Philomena.Adverts do
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import Ecto.Query, warn: false
|
import Ecto.Query, warn: false
|
||||||
|
alias Ecto.Multi
|
||||||
alias Philomena.Repo
|
alias Philomena.Repo
|
||||||
|
|
||||||
alias Philomena.Adverts.Advert
|
alias Philomena.Adverts.Advert
|
||||||
|
alias Philomena.Adverts.Uploader
|
||||||
|
|
||||||
|
|
||||||
def random_live do
|
def random_live do
|
||||||
|
@ -104,9 +106,20 @@ defmodule Philomena.Adverts do
|
||||||
|
|
||||||
"""
|
"""
|
||||||
def create_advert(attrs \\ %{}) do
|
def create_advert(attrs \\ %{}) do
|
||||||
%Advert{}
|
advert =
|
||||||
|> Advert.changeset(attrs)
|
%Advert{}
|
||||||
|> Repo.insert()
|
|> Advert.save_changeset(attrs)
|
||||||
|
|> Uploader.analyze_upload(attrs)
|
||||||
|
|
||||||
|
Multi.new()
|
||||||
|
|> Multi.insert(:advert, advert)
|
||||||
|
|> Multi.run(:after, fn _repo, %{advert: advert} ->
|
||||||
|
Uploader.persist_upload(advert)
|
||||||
|
Uploader.unpersist_old_upload(advert)
|
||||||
|
|
||||||
|
{:ok, nil}
|
||||||
|
end)
|
||||||
|
|> Repo.isolated_transaction(:serializable)
|
||||||
end
|
end
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
|
@ -123,7 +136,7 @@ defmodule Philomena.Adverts do
|
||||||
"""
|
"""
|
||||||
def update_advert(%Advert{} = advert, attrs) do
|
def update_advert(%Advert{} = advert, attrs) do
|
||||||
advert
|
advert
|
||||||
|> Advert.changeset(attrs)
|
|> Advert.save_changeset(attrs)
|
||||||
|> Repo.update()
|
|> Repo.update()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,8 @@ defmodule Philomena.Adverts.Advert do
|
||||||
use Ecto.Schema
|
use Ecto.Schema
|
||||||
import Ecto.Changeset
|
import Ecto.Changeset
|
||||||
|
|
||||||
|
import Philomena.Schema.Time
|
||||||
|
|
||||||
schema "adverts" do
|
schema "adverts" do
|
||||||
field :image, :string
|
field :image, :string
|
||||||
field :link, :string
|
field :link, :string
|
||||||
|
@ -9,11 +11,22 @@ defmodule Philomena.Adverts.Advert do
|
||||||
field :clicks, :integer, default: 0
|
field :clicks, :integer, default: 0
|
||||||
field :impressions, :integer, default: 0
|
field :impressions, :integer, default: 0
|
||||||
field :live, :boolean, default: false
|
field :live, :boolean, default: false
|
||||||
field :start_date, :naive_datetime
|
field :start_date, :utc_datetime
|
||||||
field :finish_date, :naive_datetime
|
field :finish_date, :utc_datetime
|
||||||
field :restrictions, :string
|
field :restrictions, :string
|
||||||
field :notes, :string
|
field :notes, :string
|
||||||
|
|
||||||
|
field :image_mime_type, :string, virtual: true
|
||||||
|
field :image_size, :integer, virtual: true
|
||||||
|
field :image_width, :integer, virtual: true
|
||||||
|
field :image_height, :integer, virtual: true
|
||||||
|
|
||||||
|
field :uploaded_image, :string, virtual: true
|
||||||
|
field :removed_image, :string, virtual: true
|
||||||
|
|
||||||
|
field :start_time, :string, virtual: true
|
||||||
|
field :finish_time, :string, virtual: true
|
||||||
|
|
||||||
timestamps(inserted_at: :created_at)
|
timestamps(inserted_at: :created_at)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -21,6 +34,29 @@ defmodule Philomena.Adverts.Advert do
|
||||||
def changeset(advert, attrs) do
|
def changeset(advert, attrs) do
|
||||||
advert
|
advert
|
||||||
|> cast(attrs, [])
|
|> cast(attrs, [])
|
||||||
|> validate_required([])
|
|> propagate_time(:start_date, :start_time)
|
||||||
|
|> propagate_time(:finish_date, :finish_time)
|
||||||
|
end
|
||||||
|
|
||||||
|
def save_changeset(advert, attrs) do
|
||||||
|
advert
|
||||||
|
|> cast(attrs, [:title, :link, :start_time, :finish_time, :live, :restrictions, :notes])
|
||||||
|
|> assign_time(:start_time, :start_date)
|
||||||
|
|> assign_time(:finish_time, :finish_date)
|
||||||
|
|> validate_required([:title, :link, :start_date, :finish_date])
|
||||||
|
|> validate_inclusion(:restrictions, ["none", "nsfw", "sfw"])
|
||||||
|
end
|
||||||
|
|
||||||
|
def image_changeset(advert, attrs) do
|
||||||
|
advert
|
||||||
|
|> cast(attrs, [
|
||||||
|
:image, :image_mime_type, :image_size, :image_width, :image_height,
|
||||||
|
:uploaded_image, :removed_image
|
||||||
|
])
|
||||||
|
|> validate_required([:image])
|
||||||
|
|> validate_inclusion(:image_mime_type, ["image/png", "image/jpeg", "image/gif"])
|
||||||
|
|> validate_inclusion(:image_width, 699..729)
|
||||||
|
|> validate_inclusion(:image_height, 79..91)
|
||||||
|
|> validate_inclusion(:image_size, 0..750_000)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
24
lib/philomena/adverts/uploader.ex
Normal file
24
lib/philomena/adverts/uploader.ex
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
defmodule Philomena.Adverts.Uploader do
|
||||||
|
@moduledoc """
|
||||||
|
Upload and processing callback logic for Advert images.
|
||||||
|
"""
|
||||||
|
|
||||||
|
alias Philomena.Adverts.Advert
|
||||||
|
alias Philomena.Uploader
|
||||||
|
|
||||||
|
def analyze_upload(advert, params) do
|
||||||
|
Uploader.analyze_upload(advert, "image", params["image"], &Advert.image_changeset/2)
|
||||||
|
end
|
||||||
|
|
||||||
|
def persist_upload(advert) do
|
||||||
|
Uploader.persist_upload(advert, advert_file_root(), "image")
|
||||||
|
end
|
||||||
|
|
||||||
|
def unpersist_old_upload(advert) do
|
||||||
|
Uploader.unpersist_old_upload(advert, advert_file_root(), "image")
|
||||||
|
end
|
||||||
|
|
||||||
|
defp advert_file_root do
|
||||||
|
Application.get_env(:philomena, :advert_file_root)
|
||||||
|
end
|
||||||
|
end
|
|
@ -245,7 +245,6 @@ defmodule Philomena.Tags do
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|> IO.inspect()
|
|
||||||
|> Repo.update_all([])
|
|> Repo.update_all([])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
69
lib/philomena_web/controllers/admin/advert_controller.ex
Normal file
69
lib/philomena_web/controllers/admin/advert_controller.ex
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
defmodule PhilomenaWeb.Admin.AdvertController do
|
||||||
|
use PhilomenaWeb, :controller
|
||||||
|
|
||||||
|
alias Philomena.Adverts.Advert
|
||||||
|
alias Philomena.Adverts
|
||||||
|
alias Philomena.Repo
|
||||||
|
import Ecto.Query
|
||||||
|
|
||||||
|
plug :verify_authorized
|
||||||
|
plug :load_and_authorize_resource, model: Advert, only: [:edit, :update, :delete]
|
||||||
|
|
||||||
|
def index(conn, _params) do
|
||||||
|
adverts =
|
||||||
|
Advert
|
||||||
|
|> order_by(desc: :finish_date)
|
||||||
|
|> Repo.paginate(conn.assigns.scrivener)
|
||||||
|
|
||||||
|
render(conn, "index.html", layout_class: "layout--wide", adverts: adverts)
|
||||||
|
end
|
||||||
|
|
||||||
|
def new(conn, _params) do
|
||||||
|
changeset = Adverts.change_advert(%Advert{})
|
||||||
|
render(conn, "new.html", changeset: changeset)
|
||||||
|
end
|
||||||
|
|
||||||
|
def create(conn, %{"advert" => advert_params}) do
|
||||||
|
case Adverts.create_advert(advert_params) do
|
||||||
|
{:ok, _advert} ->
|
||||||
|
conn
|
||||||
|
|> put_flash(:info, "Advert was successfully created.")
|
||||||
|
|> redirect(to: Routes.admin_advert_path(conn, :index))
|
||||||
|
|
||||||
|
{:error, :advert, changeset, _changes} ->
|
||||||
|
render(conn, "new.html", changeset: changeset)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def edit(conn, _params) do
|
||||||
|
changeset = Adverts.change_advert(conn.assigns.advert)
|
||||||
|
render(conn, "edit.html", changeset: changeset)
|
||||||
|
end
|
||||||
|
|
||||||
|
def update(conn, %{"advert" => advert_params}) do
|
||||||
|
case Adverts.update_advert(conn.assigns.advert, advert_params) do
|
||||||
|
{:ok, _advert} ->
|
||||||
|
conn
|
||||||
|
|> put_flash(:info, "Advert was successfully updated.")
|
||||||
|
|> redirect(to: Routes.admin_advert_path(conn, :index))
|
||||||
|
|
||||||
|
{:error, changeset} ->
|
||||||
|
render(conn, "edit.html", changeset: changeset)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def delete(conn, _params) do
|
||||||
|
{:ok, _advert} = Adverts.delete_advert(conn.assigns.advert)
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> put_flash(:info, "Advert was successfully deleted.")
|
||||||
|
|> redirect(to: Routes.admin_advert_path(conn, :index))
|
||||||
|
end
|
||||||
|
|
||||||
|
defp verify_authorized(conn, _opts) do
|
||||||
|
case Canada.Can.can?(conn.assigns.current_user, :index, Advert) do
|
||||||
|
true -> conn
|
||||||
|
false -> PhilomenaWeb.NotAuthorizedPlug.call(conn)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -200,6 +200,7 @@ defmodule PhilomenaWeb.Router do
|
||||||
resources "/fingerprint_bans", FingerprintBanController, only: [:index, :new, :create, :edit, :update, :delete]
|
resources "/fingerprint_bans", FingerprintBanController, only: [:index, :new, :create, :edit, :update, :delete]
|
||||||
|
|
||||||
resources "/site_notices", SiteNoticeController, except: [:show]
|
resources "/site_notices", SiteNoticeController, except: [:show]
|
||||||
|
resources "/adverts", AdvertController, except: [:show]
|
||||||
end
|
end
|
||||||
|
|
||||||
resources "/duplicate_reports", DuplicateReportController, only: [] do
|
resources "/duplicate_reports", DuplicateReportController, only: [] do
|
||||||
|
|
50
lib/philomena_web/templates/admin/advert/_form.html.slime
Normal file
50
lib/philomena_web/templates/admin/advert/_form.html.slime
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
= form_for @changeset, @action, [multipart: true], fn f ->
|
||||||
|
= if @changeset.action do
|
||||||
|
.alert.alert-danger
|
||||||
|
p Oops, something went wrong! Please check the errors below.
|
||||||
|
|
||||||
|
= if @changeset.data.__meta__.state != :loaded do
|
||||||
|
.field
|
||||||
|
=> label f, :image, "Upload image:"
|
||||||
|
= file_input f, :image, class: "input input--wide"
|
||||||
|
= error_tag f, :image
|
||||||
|
= error_tag f, :image_mime_type
|
||||||
|
= error_tag f, :image_size
|
||||||
|
= error_tag f, :image_width
|
||||||
|
= error_tag f, :image_height
|
||||||
|
|
||||||
|
.field
|
||||||
|
=> label f, :link, "Link which the advert should take users to:"
|
||||||
|
= url_input f, :link, class: "input input--wide", placeholder: "Link", required: true
|
||||||
|
= error_tag f, :link
|
||||||
|
|
||||||
|
.field
|
||||||
|
=> label f, :title, "Title/alt-text for the advert:"
|
||||||
|
= text_input f, :title, class: "input input--wide", placeholder: "Title", required: true
|
||||||
|
= error_tag f, :title
|
||||||
|
|
||||||
|
.field
|
||||||
|
=> label f, :start_time, "Start time for the advert (usually \"now\"):"
|
||||||
|
= text_input f, :start_time, class: "input input--wide", placeholder: "Start"
|
||||||
|
= error_tag f, :start_time
|
||||||
|
|
||||||
|
.field
|
||||||
|
=> label f, :finish_time, "Finish time for the advert (e.g. \"2 weeks from now\"):"
|
||||||
|
= text_input f, :finish_time, class: "input input--wide", placeholder: "Finish"
|
||||||
|
= error_tag f, :finish_time
|
||||||
|
|
||||||
|
.field
|
||||||
|
=> label f, :notes, "Notes (Payment details, contact info, etc):"
|
||||||
|
= text_input f, :notes, class: "input input--wide", placeholder: "Notes"
|
||||||
|
= error_tag f, :notes
|
||||||
|
|
||||||
|
.field
|
||||||
|
=> label f, :restrictions, "Restriction:"
|
||||||
|
= select f, :restrictions, restrictions(), class: "input"
|
||||||
|
= error_tag f, :restrictions
|
||||||
|
|
||||||
|
.field
|
||||||
|
=> checkbox f, :live, class: "checkbox"
|
||||||
|
= label f, :live, "Live"
|
||||||
|
|
||||||
|
= submit "Save Advert", class: "button"
|
2
lib/philomena_web/templates/admin/advert/edit.html.slime
Normal file
2
lib/philomena_web/templates/admin/advert/edit.html.slime
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
h1 Editing advert
|
||||||
|
= render PhilomenaWeb.Admin.AdvertView, "_form.html", changeset: @changeset, action: Routes.admin_advert_path(@conn, :update, @advert), conn: @conn
|
73
lib/philomena_web/templates/admin/advert/index.html.slime
Normal file
73
lib/philomena_web/templates/admin/advert/index.html.slime
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
- route = fn p -> Routes.admin_advert_path(@conn, :index, p) end
|
||||||
|
- pagination = render PhilomenaWeb.PaginationView, "_pagination.html", page: @adverts, route: route
|
||||||
|
|
||||||
|
.block
|
||||||
|
.block__header
|
||||||
|
a href=Routes.admin_advert_path(@conn, :new)
|
||||||
|
i.fa.fa-plus>
|
||||||
|
' New advert
|
||||||
|
|
||||||
|
= pagination
|
||||||
|
|
||||||
|
.block__content
|
||||||
|
table.table
|
||||||
|
thead
|
||||||
|
tr
|
||||||
|
th.table--adverts__image Image
|
||||||
|
th Ad Information
|
||||||
|
th Start
|
||||||
|
th Finish
|
||||||
|
th Enabled
|
||||||
|
th Restriction
|
||||||
|
th Statistics
|
||||||
|
th Options
|
||||||
|
tbody
|
||||||
|
= for advert <- @adverts do
|
||||||
|
tr
|
||||||
|
td
|
||||||
|
img src=advert_image_url(advert)
|
||||||
|
|
||||||
|
td
|
||||||
|
strong
|
||||||
|
' URL:
|
||||||
|
= link advert.link, to: advert.link
|
||||||
|
br
|
||||||
|
|
||||||
|
strong
|
||||||
|
' Title:
|
||||||
|
em
|
||||||
|
= advert.title
|
||||||
|
|
||||||
|
= if present?(advert.notes) do
|
||||||
|
br
|
||||||
|
strong
|
||||||
|
' Notes:
|
||||||
|
= advert.notes
|
||||||
|
|
||||||
|
td class=time_column_class(advert.start_date)
|
||||||
|
= pretty_time advert.start_date
|
||||||
|
|
||||||
|
td class=time_column_class(advert.finish_date)
|
||||||
|
= pretty_time advert.finish_date
|
||||||
|
|
||||||
|
td
|
||||||
|
= live_text(advert)
|
||||||
|
|
||||||
|
td
|
||||||
|
= advert.restrictions
|
||||||
|
|
||||||
|
td
|
||||||
|
' Impressions:
|
||||||
|
= advert.impressions
|
||||||
|
|
||||||
|
br
|
||||||
|
' Clicks:
|
||||||
|
= advert.clicks
|
||||||
|
|
||||||
|
td
|
||||||
|
=> link "Edit", to: Routes.admin_advert_path(@conn, :edit, advert)
|
||||||
|
' •
|
||||||
|
= link "Destroy", to: Routes.admin_advert_path(@conn, :delete, advert), data: [confirm: "Are you really, really sure?", method: "delete"]
|
||||||
|
|
||||||
|
.block__header.block__header--light
|
||||||
|
= pagination
|
2
lib/philomena_web/templates/admin/advert/new.html.slime
Normal file
2
lib/philomena_web/templates/admin/advert/new.html.slime
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
h1 New advert
|
||||||
|
= render PhilomenaWeb.Admin.AdvertView, "_form.html", changeset: @changeset, action: Routes.admin_advert_path(@conn, :create), conn: @conn
|
|
@ -7,15 +7,10 @@
|
||||||
|
|
||||||
.dropdown__content.js-burger-links
|
.dropdown__content.js-burger-links
|
||||||
= if manages_site_notices?(@conn) do
|
= if manages_site_notices?(@conn) do
|
||||||
= link to: "/admin/site_notices", class: "header__link" do
|
= link to: Routes.admin_site_notice_path(@conn, :index), class: "header__link" do
|
||||||
i.fa.fa-fw.fa-info-circle>
|
i.fa.fa-fw.fa-info-circle>
|
||||||
' Site Notices
|
' Site Notices
|
||||||
|
|
||||||
= if manages_tags?(@conn) do
|
|
||||||
= link to: "#", class: "header__link" do
|
|
||||||
i.fa.fa-fw.fa-tags>
|
|
||||||
' Tags
|
|
||||||
|
|
||||||
= if manages_users?(@conn) do
|
= if manages_users?(@conn) do
|
||||||
= link to: "#", class: "header__link" do
|
= link to: "#", class: "header__link" do
|
||||||
i.fa.fa-fw.fa-users>
|
i.fa.fa-fw.fa-users>
|
||||||
|
@ -27,9 +22,9 @@
|
||||||
' Forums
|
' Forums
|
||||||
|
|
||||||
= if manages_ads?(@conn) do
|
= if manages_ads?(@conn) do
|
||||||
= link to: "#", class: "header__link" do
|
= link to: Routes.admin_advert_path(@conn, :index), class: "header__link" do
|
||||||
i.fa.fa-fw.fa-shopping-bag>
|
i.fa.fa-fw.fa-shopping-bag>
|
||||||
' Advertisements
|
' Adverts
|
||||||
|
|
||||||
= if manages_badges?(@conn) do
|
= if manages_badges?(@conn) do
|
||||||
= link to: "#", class: "header__link" do
|
= link to: "#", class: "header__link" do
|
||||||
|
|
25
lib/philomena_web/views/admin/advert_view.ex
Normal file
25
lib/philomena_web/views/admin/advert_view.ex
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
defmodule PhilomenaWeb.Admin.AdvertView do
|
||||||
|
use PhilomenaWeb, :view
|
||||||
|
|
||||||
|
import PhilomenaWeb.AdvertView, only: [advert_image_url: 1]
|
||||||
|
|
||||||
|
def time_column_class(other_time) do
|
||||||
|
now = DateTime.utc_now()
|
||||||
|
|
||||||
|
case DateTime.diff(other_time, now) > 0 do
|
||||||
|
true -> "success"
|
||||||
|
_false -> "danger"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def live_text(%{live: true}), do: "Yes"
|
||||||
|
def live_text(_advert), do: "No"
|
||||||
|
|
||||||
|
def restrictions do
|
||||||
|
[
|
||||||
|
[key: "Display on all images", value: "none"],
|
||||||
|
[key: "Display on NSFW images only", value: "nsfw"],
|
||||||
|
[key: "Display on SFW images only", value: "sfw"]
|
||||||
|
]
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in a new issue