mirror of
https://github.com/philomena-dev/philomena.git
synced 2024-11-23 20:18:00 +01:00
add topics and channels strips
This commit is contained in:
parent
7508456919
commit
83b63bbd4b
11 changed files with 447 additions and 23 deletions
200
lib/philomena/channels.ex
Normal file
200
lib/philomena/channels.ex
Normal 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
|
39
lib/philomena/channels/channel.ex
Normal file
39
lib/philomena/channels/channel.ex
Normal 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
|
18
lib/philomena/channels/subscription.ex
Normal file
18
lib/philomena/channels/subscription.ex
Normal 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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
13
lib/philomena_web/templates/activity/_topic_strip.html.slime
Normal file
13
lib/philomena_web/templates/activity/_topic_strip.html.slime
Normal 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)
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
119
test/philomena/channels_test.exs
Normal file
119
test/philomena/channels_test.exs
Normal 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
|
Loading…
Reference in a new issue