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>
12 <span class="up monospace">
13 <p class="fas fa-upload"></p>
20 <span v-if="!error" class="count"
22 <template v-if="count === 1">torrent</template>
23 <template v-else>torrents</template>
30 import service from "@/mixins/service.js";
31 import Generic from "./Generic.vue";
32 const units = ["B", "KB", "MB", "GB"];
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) => {
40 while (rate > 1000 && i < units.length) {
45 Intl.NumberFormat(undefined, { maximumFractionDigits: 2 }).format(
54 props: { item: Object },
55 components: { Generic },
56 data: () => ({ dl: null, ul: null, count: null, error: null }),
58 downRate: function () {
59 return displayRate(this.dl);
62 return displayRate(this.ul);
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);
71 if (torrentInterval > 0) {
72 setInterval(() => this.fetchCount(), torrentInterval);
79 fetchCount: async function () {
81 const body = await this.fetch("/api/v2/torrents/info");
83 this.count = body.length;
89 getRate: async function () {
91 const body = await this.fetch("/api/v2/transfer/info");
93 this.dl = body.dl_info_speed;
94 this.ul = body.up_info_speed;
104 <style scoped lang="scss">
106 color: #e51111 !important;
120 font-family: monospace;