Initial commit
This commit is contained in:
commit
7523a19d1f
40 changed files with 3984 additions and 0 deletions
236
templates/qbittorrent/details.html
Normal file
236
templates/qbittorrent/details.html
Normal file
|
@ -0,0 +1,236 @@
|
|||
{% extends "base.html" %}
|
||||
{% from "utils.html" import render_tree %}
|
||||
|
||||
|
||||
{% block scripts %}
|
||||
{{super()}}
|
||||
<script lang="text/javascript">
|
||||
var toggler = document.getElementsByClassName("custom_caret");
|
||||
var i;
|
||||
for (i = 0; i < toggler.length; i++) {
|
||||
toggler[i].addEventListener("click", function () {
|
||||
this.parentElement.querySelector(".nested").classList.toggle("active");
|
||||
this.classList.toggle("custom_caret-down");
|
||||
});
|
||||
}
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
{% block app_content %}
|
||||
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h1>
|
||||
<a href="{{qbt.info.magnet_uri}}" title="{{qbt.info.hash}}">{{qbt.info.name}}</a>
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<div class="progress" style="width: 100%;">
|
||||
<div class="progress-bar progress-bar-striped progress-bar-animated"
|
||||
style="width: {{(qbt.info.progress*100)|round(2)}}%;" role="progressbar"
|
||||
aria-valuenow="{{(qbt.info.progress*100)|round(2)}}" aria-valuemin="0" aria-valuemax="100">
|
||||
{{(qbt.info.progress*100)|round(2)}} %
|
||||
</div>
|
||||
<div class="progress-bar progress-bar-striped progress-bar-animated bg-primary"
|
||||
style="width: {{((([qbt.info.availability,1]|min)-qbt.info.progress)*100)|round(2)}}%;" role="progressbar"
|
||||
aria-valuenow="{{((([qbt.info.availability,1]|min)-qbt.info.progress)*100)|round(2)}}" aria-valuemin="0" aria-valuemax="100">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<span class="badge badge-{{qbt.info.state[1]}}">
|
||||
{{qbt.info.state[0]}}
|
||||
</span>
|
||||
{% if qbt.info.category %}
|
||||
<span class="badge badge-light">{{qbt.info.category}}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2>Info</h2>
|
||||
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
Total Size
|
||||
</div>
|
||||
<div class="col">
|
||||
{{qbt.info.size|filesizeformat(binary=True)}} ({{[0,qbt.info.size-qbt.info.downloaded]|max|filesizeformat(binary=True)}} left)
|
||||
</div>
|
||||
<div class="col">
|
||||
Files
|
||||
</div>
|
||||
<div class="col">
|
||||
{{qbt.files|count}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
Downloaded
|
||||
</div>
|
||||
<div class="col">
|
||||
{{qbt.info.downloaded|filesizeformat(binary=True)}} ({{qbt.info.dlspeed|filesizeformat(binary=True)}}/s)
|
||||
</div>
|
||||
<div class="col">
|
||||
Uploaded
|
||||
</div>
|
||||
<div class="col">
|
||||
{{qbt.info.uploaded|filesizeformat(binary=True)}} ({{qbt.info.upspeed|filesizeformat(binary=True)}}/s)
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2>Health</h2>
|
||||
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
Last Active
|
||||
</div>
|
||||
<div class="col">
|
||||
{{qbt.info.last_activity|ago(clamp=True)}} Ago
|
||||
</div>
|
||||
<div class="col">
|
||||
Age
|
||||
</div>
|
||||
<div class="col">
|
||||
{{qbt.info.added_on|ago}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="row">
|
||||
|
||||
<div class="col">
|
||||
Avg. DL rate
|
||||
</div>
|
||||
<div class="col">
|
||||
{{(qbt.info.downloaded/((qbt.info.added_on|ago).total_seconds()))|filesizeformat(binary=True)}}/s
|
||||
(A: {{(qbt.info.downloaded/qbt.info.time_active)|filesizeformat(binary=True)}}/s)
|
||||
</div>
|
||||
<div class="col">
|
||||
Avg. UL rate
|
||||
</div>
|
||||
<div class="col">
|
||||
{{(qbt.info.uploaded/((qbt.info.added_on|ago).total_seconds()))|filesizeformat(binary=True)}}/s
|
||||
(A: {{(qbt.info.uploaded/qbt.info.time_active)|filesizeformat(binary=True)}}/s)
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="row">
|
||||
|
||||
<div class="col">
|
||||
ETC (DL rate while active)
|
||||
</div>
|
||||
|
||||
<div class="col">
|
||||
{% set dl_rate_act = (qbt.info.downloaded/qbt.info.time_active) %}
|
||||
{% if dl_rate_act>0 %}
|
||||
{{((qbt.info.size-qbt.info.downloaded)/dl_rate_act)|round(0)|timedelta(clamp=true)}}
|
||||
{% else %}
|
||||
N/A
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="col">
|
||||
ETC (avg. DL rate)
|
||||
</div>
|
||||
<div class="col">
|
||||
{% set dl_rate = (qbt.info.downloaded/((qbt.info.added_on|ago(clamp=True)).total_seconds())) %}
|
||||
{% if dl_rate>0 %}
|
||||
{{((qbt.info.size-qbt.info.downloaded)/dl_rate)|round(0)|timedelta(clamp=true)}}
|
||||
{% else %}
|
||||
N/A
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
Total active time
|
||||
</div>
|
||||
<div class="col">
|
||||
{{qbt.info.time_active|timedelta}}
|
||||
</div>
|
||||
|
||||
<div class="col">
|
||||
Availability
|
||||
</div>
|
||||
<div class="col">
|
||||
{% if qbt.info.availability==-1 %}
|
||||
N/A
|
||||
{% else %}
|
||||
{{(qbt.info.availability*100)|round(2)}} %
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2>Swarm</h2>
|
||||
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
Seeds
|
||||
</div>
|
||||
<div class="col">
|
||||
{{qbt.info.num_seeds}}
|
||||
</div>
|
||||
<div class="col">
|
||||
Leechers
|
||||
</div>
|
||||
<div class="col">
|
||||
{{qbt.info.num_leechs}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
Last seen completed
|
||||
</div>
|
||||
<div class="col">
|
||||
{{qbt.info.seen_complete|ago}} Ago
|
||||
</div>
|
||||
<div class="col"></div>
|
||||
<div class="col"></div>
|
||||
</div>
|
||||
|
||||
|
||||
<h2>Files</h2>
|
||||
|
||||
{{render_tree(qbt.files|sort(attribute='name')|list|make_tree)}}
|
||||
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h2>Trackers</h2>
|
||||
<a href="{{url_for('qbittorent_add_trackers',infohash=qbt.info.hash)}}">
|
||||
<span class="badge badge-primary">Add default trackers</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% for tracker in qbt.trackers|sort(attribute='total_peers', reverse=true) %}
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
{% if tracker.has_url %}
|
||||
<a href="{{tracker.url}}">{{tracker.name}}</a>
|
||||
{% else %}
|
||||
{{tracker.name}}
|
||||
{% endif %}
|
||||
{% if tracker.message %}
|
||||
<code>{{tracker.message}}</code>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="col">
|
||||
<span class="badge badge-{{tracker.status[1]}}">{{tracker.status[0]}}</span>
|
||||
(S: {{tracker.num_seeds[1]}}, L: {{tracker.num_leeches[1]}}, P: {{tracker.num_peers[1]}}, D: {{tracker.num_downloaded[1]}})
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
{% endblock %}
|
138
templates/qbittorrent/index.html
Normal file
138
templates/qbittorrent/index.html
Normal file
|
@ -0,0 +1,138 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% macro torrent_entry(torrent) %}
|
||||
{% set state_label,badge_type = status_map[torrent.state] or (torrent.state,'light') %}
|
||||
|
||||
<li class="list-group-item">
|
||||
<a href="{{url_for('qbittorrent_details',infohash=torrent.hash)}}">{{torrent.name|truncate(75)}}</a>
|
||||
(DL: {{torrent.dlspeed|filesizeformat(binary=true)}}/s, UL: {{torrent.upspeed|filesizeformat(binary=true)}}/s)
|
||||
<span class="badge badge-{{badge_type}}">{{state_label}}</span>
|
||||
{% if torrent.category %}
|
||||
<span class="badge badge-light">{{torrent.category}}</span>
|
||||
{% endif %}
|
||||
<div style="margin-top: 5px"></div>
|
||||
<div class="progress" style="width: 100%;">
|
||||
<div class="progress-bar progress-bar-striped progress-bar-animated"
|
||||
style="width: {{(torrent.progress*100)|round(2)}}%;" role="progressbar"
|
||||
aria-valuenow="{{(torrent.progress*100)|round(2)}}" aria-valuemin="0" aria-valuemax="100">
|
||||
</div>
|
||||
<div class="progress-bar progress-bar-striped progress-bar-animated bg-primary"
|
||||
style="width: {{((([torrent.availability,1]|min)-torrent.progress)*100)|round(2)}}%;" role="progressbar"
|
||||
aria-valuenow="{{((([torrent.availability,1]|min)-torrent.progress)*100)|round(2)}}" aria-valuemin="0" aria-valuemax="100">
|
||||
</div>
|
||||
<small class="justify-content-center d-flex position-absolute w-100">{{(torrent.progress*100)|round(2)}} % (ETA: {{[torrent.eta,torrent.eta_act]|min|round(0)|timedelta(clamp=true)}})</small>
|
||||
</div>
|
||||
</li>
|
||||
{% endmacro %}
|
||||
|
||||
{% block app_content %}
|
||||
|
||||
<h2>
|
||||
<a href="{{config.APP_CONFIG.qbt_url}}">QBittorrent</a>
|
||||
{{qbt.version}}
|
||||
(DL: {{qbt.server_state.dl_info_speed|filesizeformat(binary=True)}}/s,
|
||||
UL: {{qbt.server_state.up_info_speed|filesizeformat(binary=True)}}/s)
|
||||
</h2>
|
||||
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
Total Uploaded
|
||||
</div>
|
||||
<div class="col">
|
||||
{{qbt.server_state.alltime_ul|filesizeformat(binary=True)}}
|
||||
</div>
|
||||
<div class="col">
|
||||
Total Downloaded
|
||||
</div>
|
||||
<div class="col">
|
||||
{{qbt.server_state.alltime_dl|filesizeformat(binary=True)}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
Session Uploaded
|
||||
</div>
|
||||
<div class="col">
|
||||
{{qbt.server_state.up_info_data|filesizeformat(binary=True)}}
|
||||
</div>
|
||||
<div class="col">
|
||||
Session Downloaded
|
||||
</div>
|
||||
<div class="col">
|
||||
{{qbt.server_state.dl_info_data|filesizeformat(binary=True)}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
Torrents
|
||||
</div>
|
||||
<div class="col">
|
||||
{{qbt.torrents|length}}
|
||||
</div>
|
||||
<div class="col">
|
||||
Total Queue Size
|
||||
</div>
|
||||
<div class="col">
|
||||
{{qbt.torrents.values()|map(attribute='size')|sum|filesizeformat(binary=true)}}
|
||||
</div>
|
||||
</div>
|
||||
<hr />
|
||||
|
||||
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<form method="GET">
|
||||
<select class="form-control" name="sort" onchange="this.parentElement.submit()">
|
||||
<option value="">Sort by</option>
|
||||
{% for key,value in sort_by_choices.items() %}
|
||||
<option value="{{key}}">{{value}}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% for state,torrents in qbt.torrents.values()|sort(attribute='state')|groupby('state') %}
|
||||
{% set state_label,badge_type = status_map[state] or (state,'light') %}
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<a href={{url_for("qbittorrent",state=state)}} >{{state_label}}</a>
|
||||
</div>
|
||||
<div class="col">
|
||||
{{torrents|length}}
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
{% if state_filter %}
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<a href={{url_for("qbittorrent")}}>[Clear filter]</a>
|
||||
</div>
|
||||
<div class="col">
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<ul style="padding-bottom: 10px;" class="list-group">
|
||||
{% for torrent in qbt.torrents.values()|sort(attribute=sort_by,reverse=True) %}
|
||||
{% set state_label,badge_type = status_map[torrent.state] or (torrent.state,'light') %}
|
||||
{% if state_filter %}
|
||||
{% if torrent.state==state_filter %}
|
||||
{{torrent_entry(torrent)}}
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{{torrent_entry(torrent)}}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
Loading…
Add table
Add a link
Reference in a new issue