add archive% to /vtubers

This commit is contained in:
CJ_Clippy 2025-03-17 21:46:09 -08:00
parent 3f199a86fe
commit 856070cca1
7 changed files with 108 additions and 10 deletions
apps/bright
lib
bright
bright_web
components
controllers
test

@ -11,7 +11,6 @@ defmodule Bright.Streams do
alias Bright.Vtubers.Vtuber
alias Bright.Tags.Tag
alias Bright.Platforms.Platform
alias Bright.Socials.XPost
alias Bright.{
Cache,
@ -568,4 +567,39 @@ defmodule Bright.Streams do
max_attempts: max_attempts
})
end
def get_streams_count_for_vtuber(vtuber_id) do
query =
from(s in Stream,
join: sv in "streams_vtubers",
on: sv.stream_id == s.id,
where: sv.vtuber_id == ^vtuber_id,
preload: [:vtubers, :vods]
)
Repo.aggregate(
query,
:count,
:id
)
end
def get_streams_with_vods_count_for_vtuber(vtuber_id) do
query =
from(s in Stream,
join: sv in "streams_vtubers",
on: sv.stream_id == s.id,
# Join with Vod to ensure there are vods
join: v in Vod,
on: v.stream_id == s.id,
# Filter by the specific vtuber
where: sv.vtuber_id == ^vtuber_id,
# Ensure distinct streams
distinct: s.id,
# Preload vods association
preload: [:vtubers, :vods]
)
Repo.aggregate(query, :count, :id)
end
end

@ -7,6 +7,8 @@ defmodule Bright.Vtubers do
alias Bright.Repo
alias Bright.Vtubers.Vtuber
alias Bright.Streams.Stream
alias Bright.Streams.Vod
@doc """
Returns the list of vtubers.
@ -106,4 +108,49 @@ defmodule Bright.Vtubers do
# def to_string(%Bright.Auth.User{name: name}) when not is_nil(name), do: name
# def to_string(%Bright.Auth.User{}), do: "Anonymous"
# end
def get_stream_count(vtuber_id) do
from(s in Stream,
where: s.vtuber_id == ^vtuber_id
)
|> Repo.aggregate(:count, :id)
end
def vtuber_archive_percentage(%Vtuber{id: id}), do: vtuber_archive_percentage(id)
def vtuber_archive_percentage(vtuber_id) do
total_streams =
from(s in Stream,
# Join the association table
join: sv in "streams_vtubers",
on: sv.stream_id == s.id,
where: sv.vtuber_id == ^vtuber_id
)
|> Repo.aggregate(:count, :id)
streams_with_vods =
from(s in Stream,
join: sv in "streams_vtubers",
on: sv.stream_id == s.id,
join: v in Vod,
on: v.stream_id == s.id,
where: sv.vtuber_id == ^vtuber_id,
distinct: s.id,
preload: [:vtubers, :vods]
)
|> Repo.aggregate(:count, :id)
percentage =
if total_streams > 0 do
Float.round(streams_with_vods / total_streams * 100, 2)
else
0.0
end
%{
total_streams: total_streams,
streams_with_vods: streams_with_vods,
percentage: percentage
}
end
end

@ -442,7 +442,7 @@ defmodule BrightWeb.CoreComponents do
def error(assigns) do
~H"""
<p class="help is-danger">
<.icon name="circle-exclamation" />
<.icon type="solid" name="person_digging" />
{render_slot(@inner_block)}
</p>
"""

@ -1,5 +1,6 @@
defmodule BrightWeb.VtuberHTML do
use BrightWeb, :html
alias Bright.Vtubers
embed_templates "vtuber_html/*"

@ -8,10 +8,26 @@
</.header>
<.table id="vtubers" rows={@vtubers} row_click={&JS.navigate(~p"/vtubers/#{&1}")}>
<:col :let={vtuber} label="ID">{vtuber.id}</:col>
<:col :let={vtuber} label="Image">{vtuber.image}</:col>
<:col :let={vtuber} label="Slug">{vtuber.slug}</:col>
<:col :let={vtuber} label="Display Name">{vtuber.display_name}</:col>
<:col :let={vtuber} label="Name">{vtuber.display_name}</:col>
<:col :let={vtuber} label="Image">
<figure class="image is-24x24">
<img src={vtuber.image} alt={vtuber.display_name} class="is-rounded" />
</figure>
</:col>
<:col :let={vtuber} label="Archival">
<% %{total_streams: total_streams, streams_with_vods: streams_with_vods, percentage: percentage} = Vtubers.vtuber_archive_percentage(vtuber) %>
<div class="columns is-mobile">
<div class="column is-two-thirds">
<progress class="progress is-success" value={percentage} max="100">
<%= percentage %>%
</progress>
</div>
<div class="column is-one-third">
<%= streams_with_vods %> of <%= total_streams %> (<%= percentage %>%)
</div>
</div>
</:col>
<:action :let={vtuber}>
<div class="sr-only">

@ -20,7 +20,7 @@ defmodule Bright.PlatformsTest do
end
test "create_platform/1 with valid data creates a platform" do
valid_attrs = %{name: "some name", url: "some url", slug: "some_slug"}
valid_attrs = %{name: "some name", url: "some url", slug: "some_slug", nsfw: true}
assert {:ok, %Platform{} = platform} = Platforms.create_platform(valid_attrs)
assert platform.name == "some name"

@ -3,9 +3,9 @@ defmodule BrightWeb.PlatformControllerTest do
import Bright.PlatformsFixtures
@create_attrs %{name: "some name", url: "some url", icon: "some icon"}
@update_attrs %{name: "some updated name", url: "some updated url", icon: "some updated icon"}
@invalid_attrs %{name: nil, url: nil, icon: nil}
@create_attrs %{name: "some name", url: "some url", slug: "some slug"}
@update_attrs %{name: "some updated name", url: "some updated url", slug: "some updated slug"}
@invalid_attrs %{name: nil, url: nil, slug: nil}
describe "index" do
test "lists all platforms", %{conn: conn} do