]>
Commit | Line | Data |
---|---|---|
bdad8933 BW |
1 | <template> |
2 | <Generic :item="item"> | |
3 | <template #content> | |
4 | <p class="title is-4">{{ item.name }}</p> | |
5 | <p class="subtitle is-6"> | |
6 | <span v-if="error" class="error">An error has occurred.</span> | |
7 | <template v-else> | |
8 | <span class="down monospace"> | |
9 | <p class="fas fa-download"></p> | |
10 | {{ downRate }} | |
11 | </span> | |
12 | <span class="up monospace"> | |
13 | <p class="fas fa-upload"></p> | |
14 | {{ upRate }} | |
15 | </span> | |
16 | </template> | |
17 | </p> | |
18 | </template> | |
19 | <template #indicator> | |
20 | <span v-if="!error" class="count" | |
21 | >{{ count }} | |
22 | <template v-if="count === 1">torrent</template> | |
23 | <template v-else>torrents</template> | |
24 | </span> | |
25 | </template> | |
26 | </Generic> | |
27 | </template> | |
28 | ||
29 | <script> | |
30 | import service from "@/mixins/service.js"; | |
31 | import Generic from "./Generic.vue"; | |
32 | const units = ["B", "KB", "MB", "GB"]; | |
33 | ||
34 | // Take the rate in bytes and keep dividing it by 1k until the lowest | |
35 | // value for which we have a unit is determined. Return the value with | |
36 | // up to two decimals as a string and unit/s appended. | |
37 | const displayRate = (rate) => { | |
38 | let i = 0; | |
39 | ||
40 | while (rate > 1000 && i < units.length) { | |
41 | rate /= 1000; | |
42 | i++; | |
43 | } | |
44 | return ( | |
45 | Intl.NumberFormat(undefined, { maximumFractionDigits: 2 }).format( | |
46 | rate || 0 | |
47 | ) + ` ${units[i]}/s` | |
48 | ); | |
49 | }; | |
50 | ||
51 | export default { | |
52 | name: "qBittorrent", | |
53 | mixins: [service], | |
54 | props: { item: Object }, | |
55 | components: { Generic }, | |
56 | data: () => ({ dl: null, ul: null, count: null, error: null }), | |
57 | computed: { | |
58 | downRate: function () { | |
59 | return displayRate(this.dl); | |
60 | }, | |
61 | upRate: function () { | |
62 | return displayRate(this.ul); | |
63 | }, | |
64 | }, | |
65 | created() { | |
66 | const rateInterval = parseInt(this.item.rateInterval, 10) || 0; | |
67 | const torrentInterval = parseInt(this.item.torrentInterval, 10) || 0; | |
68 | if (rateInterval > 0) { | |
69 | setInterval(() => this.getRate(), rateInterval); | |
70 | } | |
71 | if (torrentInterval > 0) { | |
72 | setInterval(() => this.fetchCount(), torrentInterval); | |
73 | } | |
74 | ||
75 | this.getRate(); | |
76 | this.fetchCount(); | |
77 | }, | |
78 | methods: { | |
79 | fetchCount: async function () { | |
80 | try { | |
81 | const body = await this.fetch("/api/v2/torrents/info"); | |
82 | this.error = false; | |
83 | this.count = body.length; | |
84 | } catch (e) { | |
85 | this.error = true; | |
86 | console.error(e); | |
87 | } | |
88 | }, | |
89 | getRate: async function () { | |
90 | try { | |
91 | const body = await this.fetch("/api/v2/transfer/info"); | |
92 | this.error = false; | |
93 | this.dl = body.dl_info_speed; | |
94 | this.ul = body.up_info_speed; | |
95 | } catch (e) { | |
96 | this.error = true; | |
97 | console.error(e); | |
98 | } | |
99 | }, | |
100 | }, | |
101 | }; | |
102 | </script> | |
103 | ||
104 | <style scoped lang="scss"> | |
105 | .error { | |
106 | color: #e51111 !important; | |
107 | } | |
108 | ||
109 | .down { | |
110 | margin-right: 1em; | |
111 | } | |
112 | ||
113 | .count { | |
114 | color: var(--text); | |
115 | font-size: 0.8em; | |
116 | } | |
117 | ||
118 | .monospace { | |
119 | font-weight: 300; | |
120 | font-family: monospace; | |
121 | } | |
122 | </style> |