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>
8 <span class="down monospace">
9 <p class="fas fa-download "></p> {{ downRate }}
11 <span class="up monospace">
12 <p class="fas fa-upload"></p> {{ upRate }}
18 <span v-if="!error" class="count">{{ count }}
19 <template v-if="count === 1">torrent</template>
20 <template v-else>torrents</template>
27 import service from "@/mixins/service.js";
28 import Generic from "./Generic.vue";
29 const units = ["B", "KB", "MB", "GB"];
31 // Take the rate in bytes and keep dividing it by 1k until the lowest
32 // value for which we have a unit is determined. Return the value with
33 // up to two decimals as a string and unit/s appended.
34 const displayRate = (rate) => {
37 while (rate > 1000 && i < units.length) {
42 Intl.NumberFormat(undefined, { maximumFractionDigits: 2 }).format(
51 props: { item: Object },
52 components: { Generic },
53 data: () => ({ dl: null, ul: null, count: null, error: null }),
55 downRate: function () {
56 return displayRate(this.dl);
59 return displayRate(this.ul);
63 const rateInterval = parseInt(this.item.rateInterval, 10) || 0;
64 const torrentInterval = parseInt(this.item.torrentInterval, 10) || 0;
65 if (rateInterval > 0) {
66 setInterval(() => this.getRate(), rateInterval);
68 if (torrentInterval > 0) {
69 setInterval(() => this.fetchCount(), torrentInterval);
76 fetchCount: async function () {
78 const body = await this.fetch('/api/v2/torrents/info');
80 this.count = body.length;
86 getRate: async function () {
88 const body = await this.fetch('/api/v2/transfer/info');
90 this.dl = body.dl_info_speed;
91 this.ul = body.up_info_speed;
102 <style scoped lang="scss">
104 color: #e51111 !important;
118 font-family: monospace;