Skip to content

Commit cf35665

Browse files
committed
frontend: refactor log download in the settings menu
1 parent a84a115 commit cf35665

File tree

4 files changed

+191
-26
lines changed

4 files changed

+191
-26
lines changed

core/frontend/src/components/app/SettingsMenu.vue

Lines changed: 38 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
<v-btn
6363
v-tooltip="'Download log for all services in BlueOS'"
6464
class="ma-2"
65+
:disabled="system_folder_manager.inProgress || deletion_in_progress"
6566
@click="download_service_log_files"
6667
>
6768
<v-icon left>
@@ -73,7 +74,7 @@
7374
<v-btn
7475
v-tooltip="'Frees up space on the SD card'"
7576
class="ma-2"
76-
:disabled="disable_remove || deletion_in_progress"
77+
:disabled="disable_remove || deletion_in_progress || system_folder_manager.inProgress"
7778
@click="remove_service_log_files"
7879
>
7980
<v-icon left>
@@ -85,24 +86,22 @@
8586

8687
<v-expand-transition>
8788
<div v-if="deletion_in_progress" class="pa-4">
88-
<v-progress-linear
89-
indeterminate
90-
color="primary"
89+
<progress-information
90+
:type="'deletion'"
91+
:current-size="current_deletion_size"
92+
:total-size="current_deletion_total_size"
93+
:current-path="current_deletion_path"
94+
:status="current_deletion_status"
95+
/>
96+
</div>
97+
<div v-else-if="system_folder_manager.inProgress" class="pa-4">
98+
<progress-information
99+
:type="'download'"
100+
:operation="'Downloading system log files...'"
101+
:current-size="system_folder_manager.downloadedBytes"
102+
:total-size="system_folder_manager.totalBytes"
103+
:download-speed="system_folder_manager.downloadSpeed"
91104
/>
92-
<div class="mt-2">
93-
<div class="text-subtitle-2">
94-
Deleting: {{ current_deletion_path }}
95-
</div>
96-
<div class="text-caption">
97-
Size: {{ formatSize(current_deletion_size / 1024) }}
98-
</div>
99-
<div class="text-caption">
100-
Total: {{ formatSize(current_deletion_total_size / 1024) }}
101-
</div>
102-
<div class="text-caption">
103-
Status: {{ current_deletion_status }}
104-
</div>
105-
</div>
106105
</div>
107106
</v-expand-transition>
108107

@@ -116,6 +115,7 @@
116115
<v-btn
117116
v-tooltip="'Download logs from MAVLink'"
118117
class="ma-2"
118+
:disabled="mavlink_folder_manager.inProgress || operation_in_progress"
119119
@click="download_mavlink_log_files"
120120
>
121121
<v-icon left>
@@ -127,7 +127,7 @@
127127
<v-btn
128128
v-tooltip="'Frees up space on the SD card deleting MAVLink logs'"
129129
class="ma-2"
130-
:disabled="disable_remove_mavlink"
130+
:disabled="disable_remove_mavlink || mavlink_folder_manager.inProgress"
131131
@click="remove_mavlink_log_files"
132132
>
133133
<v-icon left>
@@ -137,6 +137,18 @@
137137
</v-btn>
138138
</v-card-actions>
139139

140+
<v-expand-transition>
141+
<div v-if="mavlink_folder_manager.inProgress" class="pa-4">
142+
<progress-information
143+
:type="'download'"
144+
:operation="'Downloading MAVLink log files...'"
145+
:current-size="mavlink_folder_manager.downloadedBytes"
146+
:total-size="mavlink_folder_manager.totalBytes"
147+
:download-speed="mavlink_folder_manager.downloadSpeed"
148+
/>
149+
</div>
150+
</v-expand-transition>
151+
140152
<v-divider />
141153

142154
<v-card-title class="align-center">
@@ -175,12 +187,13 @@
175187
<script lang="ts">
176188
import Vue from 'vue'
177189
190+
import ProgressInformation from '@/components/common/ProgressInformation.vue'
178191
import SpinningLogo from '@/components/common/SpinningLogo.vue'
179-
import filebrowser from '@/libs/filebrowser'
180192
import Notifier from '@/libs/notifier'
181193
import bag from '@/store/bag'
182194
import { commander_service } from '@/types/frontend_services'
183195
import back_axios from '@/utils/api'
196+
import { FolderManager } from '@/utils/folder_manager'
184197
import { prettifySize } from '@/utils/helper_functions'
185198
import { parseStreamingResponse } from '@/utils/streaming'
186199
@@ -192,6 +205,7 @@ export default Vue.extend({
192205
name: 'SettingsMenu',
193206
components: {
194207
SpinningLogo,
208+
ProgressInformation,
195209
},
196210
data() {
197211
return {
@@ -210,6 +224,8 @@ export default Vue.extend({
210224
current_deletion_size: 0,
211225
current_deletion_total_size: 0,
212226
current_deletion_status: '',
227+
system_folder_manager: new FolderManager(),
228+
mavlink_folder_manager: new FolderManager(),
213229
}
214230
},
215231
computed: {
@@ -241,12 +257,10 @@ export default Vue.extend({
241257
return prettifySize(bytes)
242258
},
243259
async download_service_log_files(): Promise<void> {
244-
const folder = await filebrowser.fetchFolder('system_logs')
245-
await filebrowser.downloadFolder(folder)
260+
await this.system_folder_manager.downloadFolder('system_logs')
246261
},
247262
async download_mavlink_log_files(): Promise<void> {
248-
const folder = await filebrowser.fetchFolder('ardupilot_logs/logs')
249-
await filebrowser.downloadFolder(folder)
263+
await this.mavlink_folder_manager.downloadFolder('ardupilot_logs/logs')
250264
},
251265
async get_log_folder_size(): Promise<void> {
252266
this.prepare_operation('Checking system log size...')
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
<template>
2+
<v-container>
3+
<v-progress-linear
4+
indeterminate
5+
color="primary"
6+
/>
7+
<div v-if="type === 'download'" class="mt-2">
8+
<div class="text-subtitle-2">
9+
{{ operation }}
10+
</div>
11+
<div class="text-caption">
12+
Size: {{ formatSize(currentSize / 1024) }}
13+
</div>
14+
<div class="text-caption">
15+
Total: {{ formatSize(totalSize / 1024) }}
16+
</div>
17+
<div class="text-caption">
18+
Speed: {{ formatSize(downloadSpeed / 1024) }}/ms
19+
</div>
20+
</div>
21+
<div v-else-if="type === 'deletion'" class="mt-2">
22+
<div class="text-subtitle-2">
23+
Deleting: {{ currentPath }}
24+
</div>
25+
<div class="text-caption">
26+
Size: {{ formatSize(currentSize / 1024) }}
27+
</div>
28+
<div class="text-caption">
29+
Total: {{ formatSize(totalSize / 1024) }}
30+
</div>
31+
<div class="text-caption">
32+
Status: {{ status }}
33+
</div>
34+
</div>
35+
</v-container>
36+
</template>
37+
38+
<script lang="ts">
39+
import Vue from 'vue'
40+
41+
import { prettifySize } from '@/utils/helper_functions'
42+
43+
export default Vue.extend({
44+
name: 'ProgressInformation',
45+
props: {
46+
type: {
47+
type: String,
48+
required: true,
49+
validator: (value: string) => ['download', 'deletion'].includes(value),
50+
},
51+
operation: {
52+
type: String,
53+
required: false,
54+
default: '',
55+
},
56+
currentSize: {
57+
type: Number,
58+
required: true,
59+
},
60+
totalSize: {
61+
type: Number,
62+
required: true,
63+
},
64+
downloadSpeed: {
65+
type: Number,
66+
required: false,
67+
default: 0,
68+
},
69+
currentPath: {
70+
type: String,
71+
required: false,
72+
default: '',
73+
},
74+
status: {
75+
type: String,
76+
required: false,
77+
default: '',
78+
},
79+
},
80+
methods: {
81+
formatSize(kb_bytes: number): string {
82+
return prettifySize(kb_bytes)
83+
},
84+
},
85+
})
86+
</script>

core/frontend/src/libs/filebrowser.ts

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,10 +168,37 @@ class Filebrowser {
168168
/* Download folder */
169169
/**
170170
* @param folder - FilebrowserFolder
171+
* @param progressHandler - The progress handler for the download
171172
* */
172-
async downloadFolder(folder: FilebrowserFolder): Promise<void> {
173+
async downloadFolder(
174+
folder: FilebrowserFolder,
175+
progressHandler: (event: any) => void,
176+
): Promise<void> {
173177
const url = `${filebrowser_url}/raw/${folder.path}/?algo=zip&auth=${await this.filebrowserToken()}`
174-
window.open(url)
178+
179+
await back_axios({
180+
method: 'get',
181+
url: url,
182+
onDownloadProgress: progressHandler,
183+
})
184+
.then((response) => {
185+
const blob = new Blob([response.data], { type: 'application/zip' })
186+
const blobURL = window.URL.createObjectURL(blob)
187+
const a = document.createElement('a')
188+
a.href = blobURL
189+
a.download = `${folder.name}.zip`
190+
document.body.appendChild(a)
191+
a.click()
192+
document.body.removeChild(a)
193+
window.URL.revokeObjectURL(blobURL)
194+
195+
notifier.pushSuccess('DOWNLOAD_COMPLETE', `Folder ${folder.path} downloaded successfully`)
196+
})
197+
.catch((error) => {
198+
notifier.pushError('DOWNLOAD_FAIL', `Could not download folder ${folder.path}: ${error.message}`)
199+
throw error
200+
})
201+
175202
}
176203
}
177204

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import filebrowser from "@/libs/filebrowser";
2+
3+
export class FolderManager {
4+
public downloadedBytes: number = 0;
5+
public totalBytes: number = 0;
6+
public startTime: number = 0;
7+
public downloadSpeed: number = 0;
8+
9+
public inProgress: boolean = false;
10+
11+
async downloadFolder(
12+
logs: string,
13+
): Promise<void> {
14+
const folder = await filebrowser.fetchFolder(logs);
15+
this.inProgress = true;
16+
await filebrowser.downloadFolder(folder, (event) => {
17+
if (this.startTime === 0) this.startTime = Date.now()
18+
const current_time = Date.now()
19+
const elapsed = (current_time - this.startTime) / 1000
20+
this.startTime = current_time
21+
22+
this.downloadedBytes = event.bytes
23+
this.totalBytes = event.loaded
24+
this.downloadSpeed = event.bytes / elapsed
25+
})
26+
.finally(() => {
27+
this.resetDownloadVariables()
28+
this.inProgress = false;
29+
})
30+
}
31+
32+
resetDownloadVariables(): void {
33+
this.downloadedBytes = 0;
34+
this.totalBytes = 0;
35+
this.startTime = 0;
36+
this.downloadSpeed = 0;
37+
}
38+
}

0 commit comments

Comments
 (0)