Update dashboard
This commit is contained in:
parent
6a62eaa885
commit
0060f4d8f6
2 changed files with 113 additions and 126 deletions
|
|
@ -7,7 +7,7 @@
|
|||
<main>
|
||||
<h1 id="page-title">Twitch Drops</h1>
|
||||
<pre>
|
||||
Drops are sorted alphabetically by organization and game. Click on a campaign or game title to see more details.
|
||||
Latest drops are shown first within each game. Click on a campaign or game title to see more details.
|
||||
Hover over the end time to see the exact date and time.
|
||||
</pre>
|
||||
<!-- RSS Feeds -->
|
||||
|
|
@ -18,99 +18,90 @@ Hover over the end time to see the exact date and time.
|
|||
</div>
|
||||
{% if campaigns_by_org_game %}
|
||||
{% for org_id, org_data in campaigns_by_org_game.items %}
|
||||
<section id="org-section-{{ org_id }}">
|
||||
<h2>
|
||||
{% if org_data.name %}
|
||||
{{ org_data.name }}
|
||||
{% else %}
|
||||
Organization {{ org_id }}
|
||||
{% endif %}
|
||||
</h2>
|
||||
{% for game_id, game_data in org_data.games.items %}
|
||||
<article id="game-article-{{ game_id }}">
|
||||
<header style="margin-bottom: 1rem;">
|
||||
<h3 style="margin: 0 0 0.5rem 0;">
|
||||
<a href="{% url 'twitch:game_detail' game_id %}">{{ game_data.name }}</a>
|
||||
</h3>
|
||||
</header>
|
||||
<div style="display: flex; gap: 1rem;">
|
||||
<div style="flex-shrink: 0;">
|
||||
<img src="{{ game_data.box_art }}"
|
||||
alt="Box art for {{ game_data.name }}"
|
||||
width="200"
|
||||
height="267"
|
||||
style="border-radius: 8px" />
|
||||
</div>
|
||||
<div style="flex: 1; overflow-x: auto;">
|
||||
<div style="display: flex; gap: 1rem; min-width: max-content;">
|
||||
{% for campaign in game_data.campaigns %}
|
||||
<article id="campaign-article-{{ campaign.twitch_id }}"
|
||||
style="display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 0.5rem;
|
||||
flex-shrink: 0">
|
||||
<div>
|
||||
<a href="{% url 'twitch:campaign_detail' campaign.twitch_id %}">
|
||||
<img src="{{ campaign.image_url }}"
|
||||
alt="Image for {{ campaign.name }}"
|
||||
width="120"
|
||||
height="120"
|
||||
style="border-radius: 4px" />
|
||||
<h4 style="margin: 0.5rem 0; text-align: left;">{{ campaign.clean_name }}</h4>
|
||||
</a>
|
||||
<time datetime="{{ campaign.end_at|date:'c' }}"
|
||||
title="{{ campaign.end_at|date:'DATETIME_FORMAT' }}"
|
||||
style="font-size: 0.9rem;
|
||||
display: block;
|
||||
text-align: left">
|
||||
Ends in {{ campaign.end_at|timeuntil }}
|
||||
</time>
|
||||
<time datetime="{{ campaign.start_at|date:'c' }}"
|
||||
title="{{ campaign.start_at|date:'DATETIME_FORMAT' }}"
|
||||
style="font-size: 0.9rem;
|
||||
display: block;
|
||||
text-align: left">
|
||||
Started {{ campaign.start_at|timesince }} ago
|
||||
</time>
|
||||
<time datetime="{{ campaign.added_at|date:'c' }}"
|
||||
title="{{ campaign.added_at|date:'DATETIME_FORMAT' }}"
|
||||
style="font-size: 0.9rem;
|
||||
display: block;
|
||||
text-align: left">
|
||||
Scraped {{ campaign.added_at|timesince }} ago
|
||||
</time>
|
||||
<time datetime="{{ campaign.start_at|date:'c' }} to {{ campaign.end_at|date:'c' }}"
|
||||
title="{{ campaign.start_at|date:'DATETIME_FORMAT' }} to {{ campaign.end_at|date:'DATETIME_FORMAT' }}"
|
||||
style="font-size: 0.9rem;
|
||||
display: block;
|
||||
text-align: left">
|
||||
Duration: {{ campaign.start_at|timesince:campaign.end_at }}
|
||||
</time>
|
||||
<div style="margin-top: 0.5rem; font-size: 0.8rem; ">
|
||||
<strong>Channels:</strong>
|
||||
<ul style="margin: 0.25rem 0 0 0;
|
||||
padding-left: 1rem;
|
||||
list-style-type: none">
|
||||
{% if campaign.allow_is_enabled %}
|
||||
{% if campaign.allow_channels.all %}
|
||||
{% for channel in campaign.allow_channels.all %}
|
||||
{% if forloop.counter <= 5 %}
|
||||
<li style="margin-bottom: 0.1rem;">
|
||||
<a href="https://twitch.tv/{{ channel.name }}"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
title="Watch {{ channel.display_name }} on Twitch">
|
||||
{{ channel.display_name }}
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% if campaign.allow_channels.all|length > 5 %}
|
||||
<li style="margin-bottom: 0.1rem; color: #666; font-style: italic;">
|
||||
... and {{ campaign.allow_channels.all|length|add:"-5" }} more
|
||||
{% for game_id, game_data in org_data.games.items %}
|
||||
<article id="game-article-{{ game_id }}" style="margin-bottom: 2rem;">
|
||||
<header style="margin-bottom: 1rem;">
|
||||
<h2 style="margin: 0 0 0.5rem 0;">
|
||||
<a href="{% url 'twitch:game_detail' game_id %}">{{ game_data.name }}</a>
|
||||
</h2>
|
||||
</header>
|
||||
<div style="display: flex; gap: 1rem;">
|
||||
<div style="flex-shrink: 0;">
|
||||
<img src="{{ game_data.box_art }}"
|
||||
alt="Box art for {{ game_data.name }}"
|
||||
width="200"
|
||||
height="267"
|
||||
style="border-radius: 8px" />
|
||||
</div>
|
||||
<div style="flex: 1; overflow-x: auto;">
|
||||
<div style="display: flex; gap: 1rem; min-width: max-content;">
|
||||
{% for campaign in game_data.campaigns %}
|
||||
<article id="campaign-article-{{ campaign.twitch_id }}"
|
||||
style="display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 0.5rem;
|
||||
flex-shrink: 0">
|
||||
<div>
|
||||
<a href="{% url 'twitch:campaign_detail' campaign.twitch_id %}">
|
||||
<img src="{{ campaign.image_url }}"
|
||||
alt="Image for {{ campaign.name }}"
|
||||
width="120"
|
||||
height="120"
|
||||
style="border-radius: 4px" />
|
||||
<h4 style="margin: 0.5rem 0; text-align: left;">{{ campaign.clean_name }}</h4>
|
||||
</a>
|
||||
<time datetime="{{ campaign.end_at|date:'c' }}"
|
||||
title="{{ campaign.end_at|date:'DATETIME_FORMAT' }}"
|
||||
style="font-size: 0.9rem;
|
||||
display: block;
|
||||
text-align: left">
|
||||
Ends in {{ campaign.end_at|timeuntil }}
|
||||
</time>
|
||||
<time datetime="{{ campaign.start_at|date:'c' }}"
|
||||
title="{{ campaign.start_at|date:'DATETIME_FORMAT' }}"
|
||||
style="font-size: 0.9rem;
|
||||
display: block;
|
||||
text-align: left">
|
||||
Started {{ campaign.start_at|timesince }} ago
|
||||
</time>
|
||||
<time datetime="{{ campaign.added_at|date:'c' }}"
|
||||
title="{{ campaign.added_at|date:'DATETIME_FORMAT' }}"
|
||||
style="font-size: 0.9rem;
|
||||
display: block;
|
||||
text-align: left">
|
||||
Scraped {{ campaign.added_at|timesince }} ago
|
||||
</time>
|
||||
<time datetime="{{ campaign.start_at|date:'c' }} to {{ campaign.end_at|date:'c' }}"
|
||||
title="{{ campaign.start_at|date:'DATETIME_FORMAT' }} to {{ campaign.end_at|date:'DATETIME_FORMAT' }}"
|
||||
style="font-size: 0.9rem;
|
||||
display: block;
|
||||
text-align: left">
|
||||
Duration: {{ campaign.start_at|timesince:campaign.end_at }}
|
||||
</time>
|
||||
<div style="margin-top: 0.5rem; font-size: 0.8rem; ">
|
||||
<strong>Channels:</strong>
|
||||
<ul style="margin: 0.25rem 0 0 0;
|
||||
padding-left: 1rem;
|
||||
list-style-type: none">
|
||||
{% if campaign.allow_is_enabled %}
|
||||
{% if campaign.allow_channels.all %}
|
||||
{% for channel in campaign.allow_channels.all %}
|
||||
{% if forloop.counter <= 5 %}
|
||||
<li style="margin-bottom: 0.1rem;">
|
||||
<a href="https://twitch.tv/{{ channel.name }}"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
title="Watch {{ channel.display_name }} on Twitch">
|
||||
{{ channel.display_name }}
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% if campaign.allow_channels.all|length > 5 %}
|
||||
<li style="margin-bottom: 0.1rem; color: #666; font-style: italic;">
|
||||
... and {{ campaign.allow_channels.all|length|add:"-5" }} more
|
||||
</li>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{% if campaign.game.twitch_directory_url %}
|
||||
|
|
@ -118,25 +109,38 @@ Hover over the end time to see the exact date and time.
|
|||
<a href="{{ campaign.game.twitch_directory_url }}"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
title="Find streamers playing {{ campaign.game.display_name }} with drops enabled">
|
||||
Go to a participating live channel
|
||||
title="Open Twitch category page for {{ campaign.game.display_name }} with Drops filter">
|
||||
Browse {{ campaign.game.display_name }} category
|
||||
</a>
|
||||
</li>
|
||||
{% else %}
|
||||
<li>Failed to get Twitch directory URL :(</li>
|
||||
<li>Failed to get Twitch category URL :(</li>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
{% else %}
|
||||
{% if campaign.game.twitch_directory_url %}
|
||||
<li>
|
||||
<a href="{{ campaign.game.twitch_directory_url }}"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
title="Find streamers playing {{ campaign.game.display_name }} with drops enabled">
|
||||
Go to a participating live channel
|
||||
</a>
|
||||
</li>
|
||||
{% else %}
|
||||
<li>Failed to get Twitch directory URL :(</li>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
</article>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
{% endfor %}
|
||||
</section>
|
||||
</div>
|
||||
</article>
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<p>No active campaigns at the moment.</p>
|
||||
|
|
|
|||
|
|
@ -641,9 +641,11 @@ def dashboard(request: HttpRequest) -> HttpResponse:
|
|||
.prefetch_related(
|
||||
"allow_channels",
|
||||
)
|
||||
.order_by("-start_at")
|
||||
)
|
||||
|
||||
campaigns_by_org_game: dict[str, Any] = {}
|
||||
# Use OrderedDict to preserve insertion order (newest campaigns first)
|
||||
campaigns_by_org_game: OrderedDict[str, Any] = OrderedDict()
|
||||
|
||||
for campaign in active_campaigns:
|
||||
owner: Organization | None = campaign.game.owner
|
||||
|
|
@ -654,7 +656,7 @@ def dashboard(request: HttpRequest) -> HttpResponse:
|
|||
game_name: str = campaign.game.display_name
|
||||
|
||||
if org_id not in campaigns_by_org_game:
|
||||
campaigns_by_org_game[org_id] = {"name": org_name, "games": {}}
|
||||
campaigns_by_org_game[org_id] = {"name": org_name, "games": OrderedDict()}
|
||||
|
||||
if game_id not in campaigns_by_org_game[org_id]["games"]:
|
||||
campaigns_by_org_game[org_id]["games"][game_id] = {
|
||||
|
|
@ -663,33 +665,14 @@ def dashboard(request: HttpRequest) -> HttpResponse:
|
|||
"campaigns": [],
|
||||
}
|
||||
|
||||
campaigns_by_org_game[org_id]["games"][game_id]["campaigns"].append(
|
||||
campaign,
|
||||
)
|
||||
|
||||
sorted_campaigns_by_org_game: dict[str, Any] = {
|
||||
org_id: campaigns_by_org_game[org_id]
|
||||
for org_id in sorted(
|
||||
campaigns_by_org_game.keys(),
|
||||
key=lambda k: campaigns_by_org_game[k]["name"],
|
||||
)
|
||||
}
|
||||
|
||||
for org_data in sorted_campaigns_by_org_game.values():
|
||||
org_data["games"] = {
|
||||
game_id: org_data["games"][game_id]
|
||||
for game_id in sorted(
|
||||
org_data["games"].keys(),
|
||||
key=lambda k: org_data["games"][k]["name"],
|
||||
)
|
||||
}
|
||||
campaigns_by_org_game[org_id]["games"][game_id]["campaigns"].append(campaign)
|
||||
|
||||
return render(
|
||||
request,
|
||||
"twitch/dashboard.html",
|
||||
{
|
||||
"active_campaigns": active_campaigns,
|
||||
"campaigns_by_org_game": sorted_campaigns_by_org_game,
|
||||
"campaigns_by_org_game": campaigns_by_org_game,
|
||||
"now": now,
|
||||
},
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue