ycdl/frontends/ycdl_flask/templates/channel.html
Ethan Dalool 6b24b7416c Modifying search box reapplies download filter, removes cards.
Example: If you are using the /pending filter, and use the search
box to find some videos and ignore them, then those videos will
be removed from the DOM. That way they aren't still there when you
clear the text box to see the other pending videos.
2019-01-25 15:54:31 -08:00

408 lines
13 KiB
HTML

<!DOCTYPE html5>
<html>
<head>
{% import "header.html" as header %}
<title>{{channel['name']}}</title>
<meta charset="UTF-8">
<link rel="stylesheet" href="/static/common.css">
<script src="/static/common.js"></script>
<style>
#content_body
{
display: flex;
flex-direction: column;
min-width: 200px;
width: 100%;
max-width: 1440px;
margin-left: auto;
margin-right: auto;
}
.video_card
{
position: relative;
margin: 8px;
padding: 10px;
border-radius: 4px;
border: 1px solid #000;
}
.video_card:hover
{
box-shadow: 2px 2px 5px 0px rgba(0,0,0,0.25);
}
.video_card_pending
{
background-color: #ffffaa;
}
.video_card_ignored
{
background-color: #ffc886;
}
.video_card_selected
{
background-color: #13f4ff !important;
}
.video_card_downloaded
{
background-color: #aaffaa;
}
.action_toolbox
{
float: right;
display: inline-flex;
flex-direction: row;
position: relative;
}
.video_action_dropdown
{
z-index: 1;
background-color: #fff;
padding: 4px;
border: 1px solid #000;
position: absolute;
top: 100%;
right: 0;
display: none;
flex-direction: column;
}
</style>
</head>
<body>
{{header.make_header()}}
<div id="content_body">
{% if channel is not none %}
<span><button class="refresh_button"
onclick="refresh_channel('{{channel['id']}}', false, function(){location.reload()})">Refresh new videos</button></span>
<span><button class="refresh_button"
onclick="refresh_channel('{{channel['id']}}', true, function(){location.reload()})">Refresh everything</button></span>
<span><a href="/channel/{{channel['id']}}">All</a> <a href="/channel/{{channel['id']}}{{query_string}}">(?q)</a></span>
<span><a href="/channel/{{channel['id']}}/pending">Pending</a> <a href="/channel/{{channel['id']}}/pending{{query_string}}">(?q)</a></span>
<span><a href="/channel/{{channel['id']}}/ignored">Ignored</a> <a href="/channel/{{channel['id']}}/ignored{{query_string}}">(?q)</a></span>
<span><a href="/channel/{{channel['id']}}/downloaded">Downloaded</a> <a href="/channel/{{channel['id']}}/downloaded{{query_string}}">(?q)</a></span>
{% else %}
<span><a href="/videos">All</a> <a href="/videos{{query_string}}">(?q)</a></span>
<span><a href="/videos/pending">Pending</a> <a href="/videos/pending{{query_string}}">(?q)</a></span>
<span><a href="/videos/ignored">Ignored</a> <a href="/videos/ignored{{query_string}}">(?q)</a></span>
<span><a href="/videos/downloaded">Downloaded</a> <a href="/videos/downloaded{{query_string}}">(?q)</a></span>
{% endif %}
<center><input type="text" id="search_filter"/></center>
<center><span id="search_filter_count">{{videos|length}}</span> items</center>
<div id="video_cards">
{% for video in videos %}
<div id="video_card_{{video['id']}}"
data-ytid="{{video['id']}}"
onclick="onclick_select(event)"
class="video_card video_card_{{video['download']}}"
>
<img src="http://i3.ytimg.com/vi/{{video['id']}}/default.jpg" height="100px">
<a class="video_title" href="https://www.youtube.com/watch?v={{video['id']}}">{{video['_published_str']}} - {{video['title']}}</a>
<span>({{video['duration'] | seconds_to_hms}})</span>
{% if channel is none %}
<a href="/channel/{{video['author_id']}}">(Chan)</a>
{% endif %}
<div class="action_toolbox">
<button
{% if video['download'] == "pending" %}
class="video_action_pending hidden"
{% else %}
class="video_action_pending"
{% endif %}
onclick="action_button_passthrough(event, mark_video_state, 'pending')"
>Revert to Pending</button>
<button
{% if video['download'] == "pending" %}
class="video_action_download"
{% else %}
class="video_action_download hidden"
{% endif %}
onclick="action_button_passthrough(event, start_download)"
>Download</button>
<button
{% if video['download'] == "pending" %}
class="video_action_ignore"
{% else %}
class="video_action_ignore hidden"
{% endif %}
onclick="action_button_passthrough(event, mark_video_state, 'ignored')"
>Ignore</button>
</div>
<br>
<button class="show_embed_button" onclick="toggle_embed_video('{{video.id}}');">Embed</button>
<button class="hide_embed_button hidden" onclick="toggle_embed_video('{{video.id}}');">Unembed</button>
<br>
</div>
{% endfor %}
</div>
</div>
</body>
<script type="text/javascript">
var DOWNLOAD_FILTER = "{{download_filter if download_filter else ""}}";
var video_card_first_selected = null;
var video_card_selections = [];
var search_filter_box = document.getElementById("search_filter");
var search_filter_hook = function(event)
{
filter_video_cards(search_filter_box.value);
}
search_filter_box.addEventListener("keyup", search_filter_hook);
function filter_video_cards(search_term)
{
/*
Apply the current download filter (pending, ignored, downloaded) by removing
mismatched cards from the dom.
Apply the search filter textbox by hiding the mismatched cards.
*/
var count = 0;
video_cards = document.getElementById("video_cards");
video_cards.classList.add("hidden");
search_term = search_term.toLocaleLowerCase();
var cards = video_cards.children;
var download_filter_class = "video_card_" + DOWNLOAD_FILTER;
for (var index = 0; index < video_cards.children.length; index += 1)
{
var video_card = video_cards.children[index];
var title = video_card.getElementsByClassName("video_title")[0].innerText.toLocaleLowerCase();
if (DOWNLOAD_FILTER && !video_card.classList.contains(download_filter_class))
{
video_cards.removeChild(video_card);
index -= 1;
}
else if (search_term !== "" && title.indexOf(search_term) == -1)
{
video_card.classList.add("hidden");
}
else
{
video_card.classList.remove("hidden");
count += 1;
}
}
video_cards.classList.remove("hidden");
document.getElementById("search_filter_count").innerText = count;
}
function toggle_embed_video(video_id)
{
var video_card = document.getElementById("video_card_" + video_id);
var show_button = video_card.getElementsByClassName("show_embed_button")[0];
var hide_button = video_card.getElementsByClassName("hide_embed_button")[0];
var embeds = video_card.getElementsByTagName("iframe");
if (embeds.length == 0)
{
var html = `<iframe width="711" height="400" src="https://www.youtube.com/embed/${video_id}" frameborder="0" allow="encrypted-media" allowfullscreen></iframe>`
var embed = html_to_element(html);
video_card.appendChild(embed);
show_button.classList.add("hidden");
hide_button.classList.remove("hidden");
}
else
{
video_card.removeChild(embeds[0]);
show_button.classList.remove("hidden");
hide_button.classList.add("hidden");
}
}
function deselect_all()
{
var video_card_first_selected = null;
for (var index = 0; index < video_card_selections.length; index +=1)
{
video_card_selections[index].classList.remove("video_card_selected");
}
video_card_selections = [];
}
function html_to_element(html)
{
var template = document.createElement("template");
template.innerHTML = html;
return template.content.firstChild;
}
function onclick_select(event)
{
if (!event.target.classList.contains("video_card"))
{
return;
}
if (video_card_first_selected === null)
{
video_card_first_selected = event.target;
}
var video_cards = Array.from(document.getElementById("video_cards").children);
if (event.shiftKey === false && event.ctrlKey === false)
{
video_card_selections = [];
video_card_selections.push(event.target);
video_card_first_selected = event.target;
}
else if (event.shiftKey === true)
{
video_card_selections = [];
var start_index = video_cards.indexOf(video_card_first_selected);
var end_index = video_cards.indexOf(event.target);
if (end_index < start_index)
{
var temp = start_index;
start_index = end_index;
end_index = temp;
}
for (var index = start_index; index <= end_index; index += 1)
{
if (video_cards[index].classList.contains("hidden"))
{
continue;
}
video_card_selections.push(video_cards[index]);
}
}
else if (event.ctrlKey === true)
{
var existing_index = video_card_selections.indexOf(event.target)
if (existing_index == -1)
{
video_card_first_selected = event.target;
video_card_selections.push(event.target);
}
else
{
video_card_selections.splice(existing_index, 1);
}
}
for (var index = 0; index < video_cards.length; index += 1)
{
card = video_cards[index];
if (video_card_selections.indexOf(card) > -1)
{
card.classList.add("video_card_selected");
}
else
{
card.classList.remove("video_card_selected");
}
}
return false;
}
function action_button_passthrough(event, action_function, action_argument)
{
var elements;
var this_card = event.target.parentElement.parentElement;
if (video_card_selections.length > 0 && video_card_selections.indexOf(this_card) > -1)
{
elements = video_card_selections;
}
else
{
// Button -> button toolbox -> video card
elements = [this_card];
}
var video_ids = [];
for (var index = 0; index < elements.length; index += 1)
{
video_ids.push(elements[index].dataset["ytid"]);
}
video_ids = video_ids.join(",");
if (action_argument === undefined)
{
action_function(video_ids, receive_action_response);
}
else
{
action_function(video_ids, action_argument, receive_action_response);
}
deselect_all();
}
function give_action_buttons(video_card_div)
{
var button_pending = video_card_div.getElementsByClassName("video_action_pending")[0];
var button_download = video_card_div.getElementsByClassName("video_action_download")[0];
var button_ignore = video_card_div.getElementsByClassName("video_action_ignore")[0];
if (video_card_div.classList.contains("video_card_pending"))
{
button_download.classList.remove("hidden");
button_ignore.classList.remove("hidden");
button_pending.classList.add("hidden");
}
else
{
button_download.classList.add("hidden");
button_ignore.classList.add("hidden");
button_pending.classList.remove("hidden");
}
}
function receive_action_response(response)
{
var video_ids = response['video_ids'];
for (var index = 0; index < video_ids.length; index += 1)
{
var video_id = video_ids[index];
var state = response['state'];
var card = document.getElementById("video_card_" + video_id);
if (state == 'pending')
{
card.classList = ["video_card", "video_card_pending"].join(" ");
card.style.backgroundColor = "#ffffaa";
}
else if (state == 'ignored')
{
card.classList = ["video_card", "video_card_ignored"].join(" ");
card.style.backgroundColor = "#ffc886";
}
else if (state == 'downloaded')
{
card.classList = ["video_card", "video_card_downloaded"].join(" ");
card.style.backgroundColor = "#aaffaa";
}
give_action_buttons(card);
}
}
function refresh_channel(channel_id, force, callback)
{
var url = "/refresh_channel";
data = new FormData();
data.append("channel_id", channel_id);
data.append("force", force)
return post(url, data, callback);
}
function mark_video_state(video_ids, state, callback)
{
var url = "/mark_video_state";
data = new FormData();
data.append("video_ids", video_ids);
data.append("state", state);
return post(url, data, callback);
}
function start_download(video_ids, callback)
{
var url = "/start_download";
data = new FormData();
data.append("video_ids", video_ids);
return post(url, data, callback);
}
</script>
</html>