add topics and channels strips

This commit is contained in:
byte[] 2019-10-04 18:52:44 -04:00
parent 7508456919
commit 83b63bbd4b
11 changed files with 447 additions and 23 deletions

200
lib/philomena/channels.ex Normal file
View file

@ -0,0 +1,200 @@
defmodule Philomena.Channels do
@moduledoc """
The Channels context.
"""
import Ecto.Query, warn: false
alias Philomena.Repo
alias Philomena.Channels.Channel
@doc """
Returns the list of channels.
## Examples
iex> list_channels()
[%Channel{}, ...]
"""
def list_channels do
Repo.all(Channel)
end
@doc """
Gets a single channel.
Raises `Ecto.NoResultsError` if the Channel does not exist.
## Examples
iex> get_channel!(123)
%Channel{}
iex> get_channel!(456)
** (Ecto.NoResultsError)
"""
def get_channel!(id), do: Repo.get!(Channel, id)
@doc """
Creates a channel.
## Examples
iex> create_channel(%{field: value})
{:ok, %Channel{}}
iex> create_channel(%{field: bad_value})
{:error, %Ecto.Changeset{}}
"""
def create_channel(attrs \\ %{}) do
%Channel{}
|> Channel.changeset(attrs)
|> Repo.insert()
end
@doc """
Updates a channel.
## Examples
iex> update_channel(channel, %{field: new_value})
{:ok, %Channel{}}
iex> update_channel(channel, %{field: bad_value})
{:error, %Ecto.Changeset{}}
"""
def update_channel(%Channel{} = channel, attrs) do
channel
|> Channel.changeset(attrs)
|> Repo.update()
end
@doc """
Deletes a Channel.
## Examples
iex> delete_channel(channel)
{:ok, %Channel{}}
iex> delete_channel(channel)
{:error, %Ecto.Changeset{}}
"""
def delete_channel(%Channel{} = channel) do
Repo.delete(channel)
end
@doc """
Returns an `%Ecto.Changeset{}` for tracking channel changes.
## Examples
iex> change_channel(channel)
%Ecto.Changeset{source: %Channel{}}
"""
def change_channel(%Channel{} = channel) do
Channel.changeset(channel, %{})
end
alias Philomena.Channels.Subscription
@doc """
Returns the list of channel_subscriptions.
## Examples
iex> list_channel_subscriptions()
[%Subscription{}, ...]
"""
def list_channel_subscriptions do
Repo.all(Subscription)
end
@doc """
Gets a single subscription.
Raises `Ecto.NoResultsError` if the Subscription does not exist.
## Examples
iex> get_subscription!(123)
%Subscription{}
iex> get_subscription!(456)
** (Ecto.NoResultsError)
"""
def get_subscription!(id), do: Repo.get!(Subscription, id)
@doc """
Creates a subscription.
## Examples
iex> create_subscription(%{field: value})
{:ok, %Subscription{}}
iex> create_subscription(%{field: bad_value})
{:error, %Ecto.Changeset{}}
"""
def create_subscription(attrs \\ %{}) do
%Subscription{}
|> Subscription.changeset(attrs)
|> Repo.insert()
end
@doc """
Updates a subscription.
## Examples
iex> update_subscription(subscription, %{field: new_value})
{:ok, %Subscription{}}
iex> update_subscription(subscription, %{field: bad_value})
{:error, %Ecto.Changeset{}}
"""
def update_subscription(%Subscription{} = subscription, attrs) do
subscription
|> Subscription.changeset(attrs)
|> Repo.update()
end
@doc """
Deletes a Subscription.
## Examples
iex> delete_subscription(subscription)
{:ok, %Subscription{}}
iex> delete_subscription(subscription)
{:error, %Ecto.Changeset{}}
"""
def delete_subscription(%Subscription{} = subscription) do
Repo.delete(subscription)
end
@doc """
Returns an `%Ecto.Changeset{}` for tracking subscription changes.
## Examples
iex> change_subscription(subscription)
%Ecto.Changeset{source: %Subscription{}}
"""
def change_subscription(%Subscription{} = subscription) do
Subscription.changeset(subscription, %{})
end
end

View file

@ -0,0 +1,39 @@
defmodule Philomena.Channels.Channel do
use Ecto.Schema
import Ecto.Changeset
schema "channels" do
belongs_to :associated_artist_tag, Philomena.Tags.Tag
# fixme: rails STI
field :type, :string
field :short_name, :string
field :title, :string
field :description, :string
field :tags, :string
field :viewers, :integer, default: 0
field :nsfw, :boolean, default: false
field :is_live, :boolean, default: false
field :last_fetched_at, :naive_datetime
field :next_check_at, :naive_datetime
field :last_live_at, :naive_datetime
field :viewer_minutes_today, :integer, default: 0
field :viewer_minutes_thisweek, :integer, default: 0
field :viewer_minutes_thismonth, :integer, default: 0
field :total_viewer_minutes, :integer, default: 0
field :banner_image, :string
field :channel_image, :string
field :remote_stream_id, :integer
field :thumbnail_url, :string, default: ""
end
@doc false
def changeset(channel, attrs) do
channel
|> cast(attrs, [])
|> validate_required([])
end
end

View file

@ -0,0 +1,18 @@
defmodule Philomena.Channels.Subscription do
use Ecto.Schema
import Ecto.Changeset
@primary_key false
schema "channel_subscriptions" do
belongs_to :channel, Philomena.Channels.Channel, primary_key: true
belongs_to :user, Philomena.Users.User, primary_key: true
end
@doc false
def changeset(subscription, attrs) do
subscription
|> cast(attrs, [])
|> validate_required([])
end
end

View file

@ -7,6 +7,7 @@ defmodule Philomena.Topics.Topic do
belongs_to :deleted_by, Philomena.Users.User
belongs_to :locked_by, Philomena.Users.User
belongs_to :last_post, Philomena.Posts.Post
belongs_to :forum, Philomena.Forums.Forum
field :title, :string
field :post_count, :integer, default: 0

View file

@ -21,6 +21,7 @@ defmodule PhilomenaWeb.ActivityController do
must: image_query
}
},
size: 25,
sort: %{created_at: :desc}
},
Image |> preload([:tags])
@ -42,8 +43,8 @@ defmodule PhilomenaWeb.ActivityController do
Image |> preload([:tags])
)
watched = if user do
{:ok, watched_query} = if !!user, do: Images.Query.compile(user, "my:watched")
watched = if !!user do
{:ok, watched_query} = Images.Query.compile(user, "my:watched")
Image.search_records(
%{
@ -53,6 +54,7 @@ defmodule PhilomenaWeb.ActivityController do
must: watched_query
}
},
size: 25,
sort: %{created_at: :desc}
},
Image |> preload([:tags])
@ -66,23 +68,24 @@ defmodule PhilomenaWeb.ActivityController do
|> limit(1)
|> Repo.one()
#streams =
# Channel
# |> where([c], c.nsfw == false)
# |> where([c], not is_nil(c.last_fetched_at))
# |> order_by(desc: :is_live, asc: :title)
# |> limit(6)
# |> Repo.all()
streams =
Channel
|> where([c], c.nsfw == false)
|> where([c], not is_nil(c.last_fetched_at))
|> order_by(desc: :is_live, asc: :title)
|> limit(6)
|> Repo.all()
topics =
Topic
|> join(:inner, [t], f in Forum, on: [forum_id: f.id])
|> join(:inner, [t], f in Forum, on: [id: t.forum_id])
|> where([t, _f], t.hidden_from_users == false)
|> where([t, _f], not ilike(t.title, "NSFW"))
|> where([_t, f], f.access_level == "normal")
|> order_by(desc: :last_replied_to_at)
|> preload([:forum, last_post: :user])
|> limit(6)
|> Repo.all()
render(
conn,
@ -91,7 +94,7 @@ defmodule PhilomenaWeb.ActivityController do
top_scoring: top_scoring,
watched: watched,
featured_image: featured_image,
#streams: streams,
streams: streams,
topics: topics
)
end

View file

@ -0,0 +1,18 @@
.block__content.flex.alternating-color
.flex__grow
/ TODO
a href="/"
/- if channel.channel_image.present?
/ => image_tag channel.uploaded_channel_image.url, width: 32, height: 32, alt: "#{channel.title}'s logo'", class: 'channel-strip__image'
/- else
/ => image_tag 'no_avatar_original.svg', width: 32, height: 32, alt: "#{channel.title}'s logo'", class: 'channel-strip__image'
= @channel.title || @channel.short_name
.flex__fixed.flex__right
= if @channel.is_live do
span.channel-strip__state.label.label--narrow.label--success
' LIVE NOW
br
= if @channel.viewers == 1, do: "viewer", else: "viewers"
- else
span.channel-strip__state.label.label--narrow.label--danger
' OFF AIR

View file

@ -0,0 +1,13 @@
.block__content.alternating-color
= if @topic.sticky do
i.fa.fa-thumbtack>
= if @topic.last_post do
span.hyphenate-breaks
= render PhilomenaWeb.UserAttributionView, "_anon_user.html", object: @topic.last_post
' replied to
/=> link_to 'replied to', short_topic_post_path(topic.forum, topic, topic.last_post, anchor: "post_#{topic.last_post.id}") TODO
=> @topic.title
/=<> link_to topic.title, short_topic_path(topic.forum, topic)
' in
=> @topic.forum.name
/=< link_to topic.forum.name, short_forum_path(topic.forum)

View file

@ -3,7 +3,7 @@
= if @featured_image do
.center
h4.remove-top-margin Featured Image
= render PhilomenaWeb.ImageView, "index.html", images: [@featured_image]
= render PhilomenaWeb.ImageView, "_image_box.html", image: @featured_image, size: :medium
.block.block--fixed.block--fixed--sub.block--success.center.hide-mobile
' Enjoy the site?
a href="/pages/donations"
@ -13,17 +13,20 @@
a< href="/pages/contact" Contact us!
.block.hide-mobile
.block__content.flex.flex--centered.flex--wrap.image-flex-grid
= render PhilomenaWeb.ImageView, "index.html", images: @top_scoring
/a.block__header--single-item.center href=search_path(q: '*', sf: 'score', sd: 'desc') All Time Top Scoring
/a.block__header--single-item.center href='/lists' More Lists
= for image <- @top_scoring do
= render PhilomenaWeb.ImageView, "_image_box.html", image: image, size: :thumb_small
a.block__header--single-item.center href="/search?q=*&sf=score&sd=desc"
' All Time Top Scoring
.block.hide-mobile
a.block__header--single-item.center href="/channels"
' Streams
/= render partial: 'channels/channel_strip', collection: @streams
= for channel <- @streams do
= render PhilomenaWeb.ActivityView, "_channel_strip.html", channel: channel
.block.hide-mobile
a.block__header--single-item.center href="/forums"
' Forum Activity
/= render partial: 'topics/topic_slim', collection: @topics
= for topic <- @topics do
= render PhilomenaWeb.ActivityView, "_topic_strip.html", topic: topic
.block.hide-mobile
a.block__header--single-item.center href="/lists/recent_comments"
' Recent Comments
@ -31,8 +34,7 @@
/a.block__header--single-item.center href=search_path(q: 'first_seen_at.gt:3 days ago', sf: 'comments', sd: 'desc') Most Commented-on Images
.column-layout__main
/- @pagination_params = { params: { controller: :images, action: :index } }
= render PhilomenaWeb.ImageView, "index.html", images: @images
= render PhilomenaWeb.ImageView, "index.html", images: @images, size: :thumb
= if !!@watched and @watched != [] do
.block
.block__header
@ -43,4 +45,4 @@
span.hide-mobile
' Browse Watched Images
.block__content.js-resizable-media-container
= render PhilomenaWeb.ImageView, "index.html", images: @watched
= render PhilomenaWeb.ImageView, "index.html", images: @watched, size: :thumb_small

View file

@ -1,3 +1,14 @@
elixir:
size =
case @size do
:thumb ->
"media-box__content--large"
:medium ->
"media-box__content--featured"
_ ->
"media-box__content--small"
end
.media-box data-image-id=@image.id
.media-box__header.media-box__header--link-row data-image-id=@image.id
a.interaction--fave href="#" rel="nofollow" data-image-id=@image.id
@ -14,5 +25,5 @@
span.comments_count data-image-id=@image.id = @image.comments_count
a.interaction--hide href="#" rel="nofollow" data-image-id=@image.id
i.fa.fa-eye-slash title='Hide'
.media-box__content.media-box__content--large.flex.flex--centered.flex--center-distributed
= render PhilomenaWeb.ImageView, "_image_container.html", image: @image, size: :thumb
.media-box__content.flex.flex--centered.flex--center-distributed class=size
= render PhilomenaWeb.ImageView, "_image_container.html", image: @image, size: @size

View file

@ -1,4 +1,4 @@
.block#imagelist-container
.block__content.js-resizable-media-container
= for image <- @images do
= render PhilomenaWeb.ImageView, "_image_box.html", image: image
= render PhilomenaWeb.ImageView, "_image_box.html", image: image, size: assigns[:size] || :thumb

View file

@ -0,0 +1,119 @@
defmodule Philomena.ChannelsTest do
use Philomena.DataCase
alias Philomena.Channels
describe "channels" do
alias Philomena.Channels.Channel
@valid_attrs %{}
@update_attrs %{}
@invalid_attrs %{}
def channel_fixture(attrs \\ %{}) do
{:ok, channel} =
attrs
|> Enum.into(@valid_attrs)
|> Channels.create_channel()
channel
end
test "list_channels/0 returns all channels" do
channel = channel_fixture()
assert Channels.list_channels() == [channel]
end
test "get_channel!/1 returns the channel with given id" do
channel = channel_fixture()
assert Channels.get_channel!(channel.id) == channel
end
test "create_channel/1 with valid data creates a channel" do
assert {:ok, %Channel{} = channel} = Channels.create_channel(@valid_attrs)
end
test "create_channel/1 with invalid data returns error changeset" do
assert {:error, %Ecto.Changeset{}} = Channels.create_channel(@invalid_attrs)
end
test "update_channel/2 with valid data updates the channel" do
channel = channel_fixture()
assert {:ok, %Channel{} = channel} = Channels.update_channel(channel, @update_attrs)
end
test "update_channel/2 with invalid data returns error changeset" do
channel = channel_fixture()
assert {:error, %Ecto.Changeset{}} = Channels.update_channel(channel, @invalid_attrs)
assert channel == Channels.get_channel!(channel.id)
end
test "delete_channel/1 deletes the channel" do
channel = channel_fixture()
assert {:ok, %Channel{}} = Channels.delete_channel(channel)
assert_raise Ecto.NoResultsError, fn -> Channels.get_channel!(channel.id) end
end
test "change_channel/1 returns a channel changeset" do
channel = channel_fixture()
assert %Ecto.Changeset{} = Channels.change_channel(channel)
end
end
describe "channel_subscriptions" do
alias Philomena.Channels.Subscription
@valid_attrs %{}
@update_attrs %{}
@invalid_attrs %{}
def subscription_fixture(attrs \\ %{}) do
{:ok, subscription} =
attrs
|> Enum.into(@valid_attrs)
|> Channels.create_subscription()
subscription
end
test "list_channel_subscriptions/0 returns all channel_subscriptions" do
subscription = subscription_fixture()
assert Channels.list_channel_subscriptions() == [subscription]
end
test "get_subscription!/1 returns the subscription with given id" do
subscription = subscription_fixture()
assert Channels.get_subscription!(subscription.id) == subscription
end
test "create_subscription/1 with valid data creates a subscription" do
assert {:ok, %Subscription{} = subscription} = Channels.create_subscription(@valid_attrs)
end
test "create_subscription/1 with invalid data returns error changeset" do
assert {:error, %Ecto.Changeset{}} = Channels.create_subscription(@invalid_attrs)
end
test "update_subscription/2 with valid data updates the subscription" do
subscription = subscription_fixture()
assert {:ok, %Subscription{} = subscription} = Channels.update_subscription(subscription, @update_attrs)
end
test "update_subscription/2 with invalid data returns error changeset" do
subscription = subscription_fixture()
assert {:error, %Ecto.Changeset{}} = Channels.update_subscription(subscription, @invalid_attrs)
assert subscription == Channels.get_subscription!(subscription.id)
end
test "delete_subscription/1 deletes the subscription" do
subscription = subscription_fixture()
assert {:ok, %Subscription{}} = Channels.delete_subscription(subscription)
assert_raise Ecto.NoResultsError, fn -> Channels.get_subscription!(subscription.id) end
end
test "change_subscription/1 returns a subscription changeset" do
subscription = subscription_fixture()
assert %Ecto.Changeset{} = Channels.change_subscription(subscription)
end
end
end