Skip to content

Commit cb6442b

Browse files
authored
feat: show disk info per registered directory (#1660)
Signed-off-by: Pedro Lamas <[email protected]>
1 parent a8b4581 commit cb6442b

File tree

11 files changed

+145
-59
lines changed

11 files changed

+145
-59
lines changed

src/components/widgets/filesystem/FileSystemToolbar.vue

+2-3
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
<v-spacer />
1212

1313
<v-tooltip
14-
v-if="lowOnSpace && !loading"
14+
v-if="klippyReady && !loading && lowOnSpace"
1515
bottom
1616
>
1717
<template #activator="{ on, attrs }">
@@ -209,8 +209,7 @@ export default class FileSystemToolbar extends Mixins(StatesMixin) {
209209
}
210210
211211
get lowOnSpace (): boolean {
212-
if (!this.klippyReady) return false
213-
return this.$typedGetters['files/getLowOnSpace']
212+
return this.$typedGetters['files/getLowOnSpace'](this.root)
214213
}
215214
216215
// Properties of the current root.
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,46 @@
11
<template>
22
<collapsable-card
3+
v-if="roots.length > 0"
34
:title="$t('app.file_system.label.diskinfo')"
45
icon="$harddisk"
56
>
6-
<v-card-text v-if="diskUsage">
7+
<v-toolbar dense>
8+
<v-tabs
9+
v-model="tab"
10+
show-arrows
11+
>
12+
<v-tab
13+
v-for="(root, index) in roots"
14+
:key="index"
15+
>
16+
{{ root }}
17+
</v-tab>
18+
</v-tabs>
19+
20+
<v-spacer />
21+
22+
<v-tooltip bottom>
23+
<template #activator="{ on, attrs }">
24+
<app-btn
25+
v-bind="attrs"
26+
icon
27+
:disabled="!diskUsage || loading"
28+
@click.prevent.stop="handleRefresh()"
29+
v-on="on"
30+
>
31+
<v-icon
32+
dense
33+
:class="{ 'spin-alt': loading }"
34+
>
35+
$refresh
36+
</v-icon>
37+
</app-btn>
38+
</template>
39+
<span>{{ $t('app.general.btn.refresh') }}</span>
40+
</v-tooltip>
41+
</v-toolbar>
42+
43+
<v-card-text>
744
<v-layout justify-space-between>
845
<div>
946
{{ $t('app.file_system.label.disk_usage') }}
@@ -21,79 +58,75 @@
2158
<v-layout justify-space-between>
2259
<div>
2360
<span class="focus--text">
24-
{{ $filters.getReadableFileSizeString(diskUsage.used) }}
61+
{{
62+
diskUsage != null
63+
? $filters.getReadableFileSizeString(diskUsage.used)
64+
: '?'
65+
}}
2566
</span>
2667
<span class="secondary--text">{{ $t('app.general.label.used') }}</span>
2768
</div>
2869
<div>
2970
<span class="focus--text">
30-
{{ $filters.getReadableFileSizeString(diskUsage.free) }}
71+
{{
72+
diskUsage != null
73+
? $filters.getReadableFileSizeString(diskUsage.free)
74+
: '?'
75+
}}
3176
</span>
3277
<span class="secondary--text">{{ $t('app.general.label.free') }}</span>
3378
</div>
3479
</v-layout>
3580
</v-card-text>
36-
37-
<v-simple-table
38-
v-if="sdInfo"
39-
dense
40-
>
41-
<tbody>
42-
<tr v-if="sdInfo.manufacturer">
43-
<th>{{ $t('app.system_info.label.manufacturer') }}</th>
44-
<td>{{ sdInfo.manufacturer }}</td>
45-
</tr>
46-
<tr v-if="sdInfo.manufacturer_date">
47-
<th>{{ $t('app.system_info.label.manufactured') }}</th>
48-
<td>{{ sdInfo.manufacturer_date }}</td>
49-
</tr>
50-
<tr v-if="sdInfo.product_name">
51-
<th>{{ $t('app.system_info.label.product_name') }}</th>
52-
<td>{{ sdInfo.product_name }} {{ sdInfo.product_revision }}</td>
53-
</tr>
54-
<tr v-if="sdInfo.capacity">
55-
<th>{{ $t('app.system_info.label.capacity') }}</th>
56-
<td>{{ sdInfo.capacity }}</td>
57-
</tr>
58-
<tr v-if="sdInfo.serial_number">
59-
<th>{{ $t('app.system_info.label.serial_number') }}</th>
60-
<td>{{ sdInfo.serial_number }}</td>
61-
</tr>
62-
</tbody>
63-
</v-simple-table>
6481
</collapsable-card>
6582
</template>
6683

6784
<script lang="ts">
68-
import { Component, Vue } from 'vue-property-decorator'
69-
import type { SystemInfo } from '@/store/server/types'
85+
import { Component, Mixins } from 'vue-property-decorator'
7086
import type { DiskUsage } from '@/store/files/types'
7187
import { SocketActions } from '@/api/socketActions'
88+
import StateMixin from '@/mixins/state'
7289
7390
@Component({})
74-
export default class PrinterStatsCard extends Vue {
75-
get sdInfo () {
76-
const info: SystemInfo | null = this.$typedState.server.system_info
91+
export default class DiskUsageCard extends Mixins(StateMixin) {
92+
tab: number | null = null
7793
78-
return info?.sd_info
94+
get roots (): string[] {
95+
return this.$typedState.server.info.registered_directories
7996
}
8097
81-
get fileSystemUsedPercent () {
82-
const diskUsage = this.diskUsage
98+
get currentRoot (): string | null {
99+
return this.tab != null
100+
? this.roots[this.tab] ?? null
101+
: null
102+
}
83103
84-
return diskUsage == null
85-
? 0
86-
: Math.floor((diskUsage.used / diskUsage.total) * 100)
104+
get loading (): boolean {
105+
return this.hasWait(`${this.$waits.onFileSystem}/${this.currentRoot}/`)
87106
}
88107
89-
get diskUsage (): DiskUsage | null {
90-
const diskUsage: DiskUsage | null = this.$typedState.files.diskUsage
108+
get diskUsage (): DiskUsage | undefined {
109+
if (this.currentRoot != null) {
110+
const diskUsage: DiskUsage | undefined = this.$typedState.files.diskUsage[this.currentRoot]
91111
92-
if (diskUsage == null) {
93-
SocketActions.serverFilesGetDirectory('config')
112+
if (diskUsage == null) {
113+
SocketActions.serverFilesGetDirectory(this.currentRoot)
114+
}
115+
116+
return diskUsage
94117
}
118+
}
119+
120+
get fileSystemUsedPercent (): number {
121+
return this.diskUsage == null
122+
? 0
123+
: Math.floor((this.diskUsage.used / this.diskUsage.total) * 100)
124+
}
95125
96-
return diskUsage
126+
handleRefresh () {
127+
if (this.currentRoot != null) {
128+
SocketActions.serverFilesGetDirectory(this.currentRoot)
129+
}
97130
}
98131
}
99132
</script>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<template>
2+
<collapsable-card
3+
v-if="sdInfo != null && Object.keys(sdInfo).length > 0"
4+
:title="$t('app.file_system.label.sd_card_info')"
5+
icon="$microSd"
6+
>
7+
<v-simple-table dense>
8+
<tbody>
9+
<tr v-if="sdInfo.manufacturer">
10+
<th>{{ $t('app.system_info.label.manufacturer') }}</th>
11+
<td>{{ sdInfo.manufacturer }}</td>
12+
</tr>
13+
<tr v-if="sdInfo.manufacturer_date">
14+
<th>{{ $t('app.system_info.label.manufactured') }}</th>
15+
<td>{{ sdInfo.manufacturer_date }}</td>
16+
</tr>
17+
<tr v-if="sdInfo.product_name">
18+
<th>{{ $t('app.system_info.label.product_name') }}</th>
19+
<td>{{ sdInfo.product_name }} {{ sdInfo.product_revision }}</td>
20+
</tr>
21+
<tr v-if="sdInfo.capacity">
22+
<th>{{ $t('app.system_info.label.capacity') }}</th>
23+
<td>{{ sdInfo.capacity }}</td>
24+
</tr>
25+
<tr v-if="sdInfo.serial_number">
26+
<th>{{ $t('app.system_info.label.serial_number') }}</th>
27+
<td>{{ sdInfo.serial_number }}</td>
28+
</tr>
29+
</tbody>
30+
</v-simple-table>
31+
</collapsable-card>
32+
</template>
33+
<script lang="ts">
34+
import { Component, Vue } from 'vue-property-decorator'
35+
import type { SystemInfo } from '@/store/server/types'
36+
37+
@Component({})
38+
export default class SdInfoCard extends Vue {
39+
get sdInfo () {
40+
const info: SystemInfo | null = this.$typedState.server.system_info
41+
42+
return info?.sd_info
43+
}
44+
}
45+
</script>

src/globals.ts

+2
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ import {
117117
mdiCircleSlice3,
118118
mdiCodeJson,
119119
mdiHarddisk,
120+
mdiMicroSd,
120121
mdiLayersTripleOutline,
121122
mdiMessageTextOutline,
122123
mdiFormatListBulleted,
@@ -414,6 +415,7 @@ export const Icons = Object.freeze({
414415
codeJson: mdiCodeJson,
415416
desktopTower: mdiDesktopTower,
416417
harddisk: mdiHarddisk,
418+
microSd: mdiMicroSd,
417419
message: mdiMessageTextOutline,
418420
list: mdiFormatListBulleted,
419421
fullScreen: mdiFullscreen,

src/locales/en.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ app:
9191
dir_name: Directory name
9292
disk_usage: Disk Usage
9393
diskinfo: Disk Information
94+
sd_card_info: SD Card Information
9495
downloaded: Downloaded
9596
file_name: Filename
9697
transfer_rate: Transfer rate

src/store/files/actions.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ export const actions = {
3131
async onServerFilesGetDirectory ({ commit }, payload: ObjectWithRequest<DirectoryInformation>) {
3232
const { disk_usage, files, dirs } = payload
3333
const { path } = payload.__request__.params ?? {}
34+
const [root] = path.split('/', 1)
3435

3536
const filteredDirs = dirs
3637
.filter(file =>
@@ -39,7 +40,7 @@ export const actions = {
3940
!Globals.FILTERED_FILES_EXTENSION.some(e => file.dirname.endsWith(e))
4041
)
4142

42-
commit('setDiskUsage', disk_usage)
43+
commit('setDiskUsage', { root, disk_usage })
4344
commit('setServerFilesGetDirectory', { path, content: { files, dirs: filteredDirs } })
4445
},
4546

src/store/files/getters.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -230,8 +230,9 @@ export const getters = {
230230
/**
231231
* Returns a boolean indicating if we're low on disk space.
232232
*/
233-
getLowOnSpace: (state) => {
233+
getLowOnSpace: (state) => (root: string) => {
234+
const diskUsage = state.diskUsage[root]
234235
// 1073741824 = 1gb
235-
return state.diskUsage != null && state.diskUsage.free < 1073741824
236+
return diskUsage != null && diskUsage.free < 1073741824
236237
}
237238
} satisfies GetterTree<FilesState, RootState>

src/store/files/mutations.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import Vue from 'vue'
22
import type { MutationTree } from 'vuex'
3-
import type { FilesState, MoonrakerRootFile, MoonrakerPathContent, MoonrakerFile, MoonrakerFileWithMeta, FilePaths, MoonrakerDir } from './types'
3+
import type { FilesState, MoonrakerRootFile, MoonrakerPathContent, MoonrakerFile, MoonrakerFileWithMeta, FilePaths, MoonrakerDir, DiskUsage } from './types'
44
import { defaultState } from './state'
55
import { Globals } from '@/globals'
66

@@ -171,7 +171,7 @@ export const mutations = {
171171
Vue.set(state.currentPaths, payload.root, payload.path)
172172
},
173173

174-
setDiskUsage (state, payload) {
175-
Vue.set(state, 'diskUsage', payload)
174+
setDiskUsage (state, payload: { root: string, disk_usage: DiskUsage }) {
175+
Vue.set(state.diskUsage, payload.root, payload.disk_usage)
176176
}
177177
} satisfies MutationTree<FilesState>

src/store/files/state.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ export const defaultState = (): FilesState => {
55
uploads: [],
66
download: null,
77
currentPaths: {},
8-
diskUsage: null,
8+
diskUsage: {},
99
rootFiles: {},
1010
pathContent: {}
1111
}

src/store/files/types.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ export interface FilesState {
77
uploads: FileUpload[];
88
download: FileDownload | null;
99
currentPaths: Record<string, string>;
10-
diskUsage: DiskUsage | null;
10+
diskUsage: Record<string, DiskUsage | undefined>;
1111
rootFiles: Record<string, MoonrakerRootFile[] | undefined>;
1212
pathContent: Record<string, MoonrakerPathContent | undefined>;
1313
}

src/views/System.vue

+5-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
>
77
<system-overview-card class="mb-2 mb-md-4" />
88

9+
<sd-info-card class="mb-2 mb-md-4" />
10+
911
<disk-usage-card />
1012
</v-col>
1113

@@ -35,6 +37,7 @@ import SystemOverviewCard from '@/components/widgets/system/SystemOverviewCard.v
3537
import McuCard from '@/components/widgets/system/McuCard.vue'
3638
import SystemUsageCard from '@/components/widgets/system/SystemUsageCard.vue'
3739
import DiskUsageCard from '@/components/widgets/system/DiskUsageCard.vue'
40+
import SdInfoCard from '@/components/widgets/system/SdInfoCard.vue'
3841
import type { MCU } from '@/store/printer/types'
3942
4043
@Component({
@@ -43,7 +46,8 @@ import type { MCU } from '@/store/printer/types'
4346
SystemOverviewCard,
4447
McuCard,
4548
SystemUsageCard,
46-
DiskUsageCard
49+
DiskUsageCard,
50+
SdInfoCard
4751
}
4852
})
4953
export default class Configure extends Mixins(StateMixin) {

0 commit comments

Comments
 (0)