Skip to content

Commit

Permalink
feat(History): add option to show stats in different values (#2007)
Browse files Browse the repository at this point in the history
* refactor: refactor getters in HistoryAllPrintStatus

Signed-off-by: Stefan Dej <[email protected]>

* feat: add option to switch the stats between amount, filament and time

Signed-off-by: Stefan Dej <[email protected]>

* feat: add option to switch the stats between amount, filament and time

Signed-off-by: Stefan Dej <[email protected]>

* refactor: extract HistoryStatsValueNames to history types

Signed-off-by: Stefan Dej <[email protected]>

* refactor: remove complexity in historyStatsMixin

Signed-off-by: Stefan Dej <[email protected]>

* refactor: extract some logic into a separate methods

Signed-off-by: Stefan Dej <[email protected]>

* refactor: rename option amount to jobs

Signed-off-by: Stefan Dej <[email protected]>

* fix: fix status groups in print history filter

Signed-off-by: Stefan Dej <[email protected]>

* fix: fix decimals in filament length output of HistoryAllPrintStatusTableItem

Signed-off-by: Stefan Dej <[email protected]>

* refactor: remove unused imports

Signed-off-by: Stefan Dej <[email protected]>

* fix: add minAngle to chart

Signed-off-by: Stefan Dej <[email protected]>

---------

Signed-off-by: Stefan Dej <[email protected]>
  • Loading branch information
meteyou authored Nov 9, 2024
1 parent a81672f commit fbeecb0
Show file tree
Hide file tree
Showing 9 changed files with 236 additions and 210 deletions.
63 changes: 27 additions & 36 deletions src/components/charts/HistoryAllPrintStatusChart.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,27 @@
:option="chartOptions"
:autoresize="true"
:init-options="{ renderer: 'svg' }"
style="height: 200px; width: 100%"></e-chart>
style="height: 200px; width: 100%" />
</template>

<script lang="ts">
import Component from 'vue-class-component'
import { Mixins, Watch } from 'vue-property-decorator'
import { Mixins, Prop, Ref, Watch } from 'vue-property-decorator'
import BaseMixin from '@/components/mixins/base'
import ThemeMixin from '@/components/mixins/theme'
import HistoryStatsMixin from '@/components/mixins/historyStats'
import VueECharts from 'vue-echarts'
import type { ECharts } from 'echarts/core'
import { ECBasicOption } from 'echarts/types/dist/shared.d'
import { ServerHistoryStateAllPrintStatusEntry } from '@/store/server/history/types'
import { formatPrintTime } from '@/plugins/helpers'
import { HistoryStatsValueNames } from '@/store/server/history/types'
@Component({
components: {},
})
export default class HistoryAllPrintStatusChart extends Mixins(BaseMixin, ThemeMixin) {
declare $refs: {
historyAllPrintStatus: any
}
export default class HistoryAllPrintStatusChart extends Mixins(BaseMixin, ThemeMixin, HistoryStatsMixin) {
@Prop({ type: String, default: 'jobs' }) valueName!: HistoryStatsValueNames
@Ref('historyAllPrintStatus') historyAllPrintStatus!: typeof VueECharts
get chartOptions(): ECBasicOption {
return {
Expand All @@ -37,12 +39,26 @@ export default class HistoryAllPrintStatusChart extends Mixins(BaseMixin, ThemeM
tooltip: {
trigger: 'item',
borderWidth: 0,
valueFormatter: (value: number) => {
if (this.valueName === 'filament') {
if (value > 1000) return Math.round(value / 1000).toString() + ' m'
return value.toString() + ' mm'
}
if (this.valueName === 'time') {
return formatPrintTime(value, false)
}
return value.toString()
},
},
series: [
{
type: 'pie',
data: this.printStatusArray,
data: this.groupedPrintStatusArray,
avoidLabelOverlap: false,
minAngle: 5,
radius: ['35%', '60%'],
emphasis: {
itemStyle: {
Expand All @@ -59,42 +75,17 @@ export default class HistoryAllPrintStatusChart extends Mixins(BaseMixin, ThemeM
}
}
get selectedJobs() {
return this.$store.getters['server/history/getSelectedJobs']
}
get allPrintStatusArray() {
return this.$store.getters['server/history/getAllPrintStatusArray']
}
get selectedPrintStatusArray() {
return this.$store.getters['server/history/getSelectedPrintStatusArray']
}
get printStatusArray() {
const output: ServerHistoryStateAllPrintStatusEntry[] = []
const orgArray = this.selectedJobs.length ? this.selectedPrintStatusArray : this.allPrintStatusArray
orgArray.forEach((status: ServerHistoryStateAllPrintStatusEntry) => {
const tmp = { ...status }
tmp.name = status.displayName
output.push(tmp)
})
return output
}
get chart(): ECharts | null {
return this.$refs.historyAllPrintStatus?.chart ?? null
return this.historyAllPrintStatus?.chart ?? null
}
beforeDestroy() {
if (typeof window === 'undefined') return
if (this.chart) this.chart.dispose()
}
@Watch('printStatusArray')
printStatusArrayChanged(newVal: any) {
@Watch('groupedPrintStatusArray')
groupedPrintStatusArrayChanged(newVal: any) {
this.chart?.setOption(
{
series: {
Expand Down
44 changes: 12 additions & 32 deletions src/components/charts/HistoryAllPrintStatusTable.vue
Original file line number Diff line number Diff line change
@@ -1,47 +1,27 @@
<template>
<v-simple-table>
<tbody>
<tr v-for="status in printStatusArray" :key="status.name">
<td>{{ status.displayName }}</td>
<td class="text-right">{{ status.value }}</td>
</tr>
<history-all-print-status-table-item
v-for="status in printStatusArray"
:key="status.name"
:item="status"
:value-name="valueName" />
</tbody>
</v-simple-table>
</template>

<script lang="ts">
import Component from 'vue-class-component'
import { Mixins } from 'vue-property-decorator'
import { Mixins, Prop } from 'vue-property-decorator'
import BaseMixin from '@/components/mixins/base'
import { ServerHistoryStateAllPrintStatusEntry } from '@/store/server/history/types'
import HistoryStatsMixin from '@/components/mixins/historyStats'
import HistoryAllPrintStatusTableItem from '@/components/charts/HistoryAllPrintStatusTableItem.vue'
import { HistoryStatsValueNames } from '@/store/server/history/types'
@Component({
components: {},
components: { HistoryAllPrintStatusTableItem },
})
export default class HistoryAllPrintStatusTable extends Mixins(BaseMixin) {
get selectedJobs() {
return this.$store.getters['server/history/getSelectedJobs']
}
get allPrintStatusArray() {
return this.$store.getters['server/history/getAllPrintStatusArrayAll']
}
get selectedPrintStatusArray() {
return this.$store.getters['server/history/getSelectedPrintStatusArray']
}
get printStatusArray() {
const output: ServerHistoryStateAllPrintStatusEntry[] = []
const orgArray = this.selectedJobs.length ? this.selectedPrintStatusArray : this.allPrintStatusArray
orgArray.forEach((status: ServerHistoryStateAllPrintStatusEntry) => {
const tmp = { ...status }
tmp.name = status.displayName
output.push(tmp)
})
return output
}
export default class HistoryAllPrintStatusTable extends Mixins(BaseMixin, HistoryStatsMixin) {
@Prop({ type: String, default: 'amount' }) valueName!: HistoryStatsValueNames
}
</script>
36 changes: 36 additions & 0 deletions src/components/charts/HistoryAllPrintStatusTableItem.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<template>
<tr>
<td>{{ item.displayName }}</td>
<td class="text-right">{{ value }}</td>
</tr>
</template>

<script lang="ts">
import Component from 'vue-class-component'
import { Mixins, Prop } from 'vue-property-decorator'
import BaseMixin from '@/components/mixins/base'
import { HistoryStatsValueNames, ServerHistoryStateAllPrintStatusEntry } from '@/store/server/history/types'
import { formatPrintTime } from '@/plugins/helpers'
@Component({
components: {},
})
export default class HistoryAllPrintStatusTableItem extends Mixins(BaseMixin) {
@Prop({ type: Object }) item!: ServerHistoryStateAllPrintStatusEntry
@Prop({ type: String, default: 'amount' }) valueName!: HistoryStatsValueNames
get value() {
if (this.valueName === 'filament') {
if (this.item.value > 1000) return Math.round(this.item.value / 1000).toFixed(2) + ' m'
return this.item.value.toFixed(0) + ' mm'
}
if (this.valueName === 'time') {
return formatPrintTime(this.item.value, false)
}
return this.item.value.toString()
}
}
</script>
124 changes: 124 additions & 0 deletions src/components/mixins/historyStats.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import Vue from 'vue'
import Component from 'vue-class-component'
import {
HistoryStatsValueNames,
ServerHistoryStateAllPrintStatusEntry,
ServerHistoryStateJob,
} from '@/store/server/history/types'
import i18n from '@/plugins/i18n'

@Component
export default class HistoryStatsMixin extends Vue {
valueName!: HistoryStatsValueNames

get allPrintStatusChartData() {
return this.getChartData(this.$store.state.server.history.jobs ?? [])
}

get selectedPrintStatusChartData() {
return this.getChartData(this.$store.getters['server/history/getSelectedJobs'])
}

private getStatusColor(status: string) {
const colorMap: Record<string, string> = {
completed: '#BDBDBD',
in_progress: '#EEEEEE',
cancelled: '#616161',
default: '#424242',
}

return colorMap[status] ?? colorMap.default
}

private getLocalizedStatusName(status: string) {
return i18n.te(`History.StatusValues.${status}`, 'en')
? i18n.t(`History.StatusValues.${status}`).toString()
: status
}

private getChartData(jobs: ServerHistoryStateJob[]) {
const output: ServerHistoryStateAllPrintStatusEntry[] = []
const hidePrintStatus = this.$store.state.gui.view.history.hidePrintStatus ?? []

jobs.forEach((current: ServerHistoryStateJob) => {
const index = output.findIndex((element) => element.name === current.status)
if (index !== -1) {
output[index].value += 1
output[index].valueFilament += current.filament_used
output[index].valueTime += current.print_duration
return
}

output.push({
name: current.status,
displayName: this.getLocalizedStatusName(current.status),
value: 1,
valueFilament: current.filament_used,
valueTime: current.print_duration,
itemStyle: {
opacity: 0.9,
color: this.getStatusColor(current.status),
borderColor: '#1E1E1E',
borderWidth: 2,
borderRadius: 3,
},
showInTable: !hidePrintStatus.includes(current.status),
})
})

return output
}

private groupSmallEntries(
entries: ServerHistoryStateAllPrintStatusEntry[],
threshold: number
): ServerHistoryStateAllPrintStatusEntry[] {
const totalCount = entries.reduce((acc, cur) => acc + cur.value, 0)
const otherLimit = totalCount * threshold
const others = entries.filter((entry) => entry.value < otherLimit)

if (others.length < 2) return entries

const value = others.reduce((acc, cur) => acc + cur.value, 0)
const remaining = entries.filter((entry) => entry.value >= otherLimit)
const displayName = i18n.t(`History.StatusValues.Others`).toString() + ` (${others.length})`

remaining.push({
name: displayName,
displayName,
value,
valueFilament: 0,
valueTime: 0,
itemStyle: {
opacity: 0.9,
color: '#616161',
borderColor: '#1E1E1E',
borderWidth: 2,
borderRadius: 3,
},
showInTable: true,
})

return remaining
}

get printStatusArray() {
const countSelected = this.$store.getters['server/history/getSelectedJobs'].length
const orgArray = countSelected ? this.selectedPrintStatusChartData : this.allPrintStatusChartData

return orgArray.map((status) => ({
...status,
name: status.displayName,
value:
this.valueName === 'filament'
? status.valueFilament
: this.valueName === 'time'
? status.valueTime
: status.value,
}))
}

get groupedPrintStatusArray() {
return this.groupSmallEntries(this.printStatusArray, 0.05)
}
}
10 changes: 4 additions & 6 deletions src/components/panels/HistoryListPanel.vue
Original file line number Diff line number Diff line change
Expand Up @@ -89,11 +89,8 @@
@change="showPrintJobs = !showPrintJobs" />
</v-list-item>
<v-divider />
<template v-if="allPrintStatusArray.length">
<v-list-item
v-for="status of allPrintStatusArray"
:key="status.key"
class="minHeight36">
<template v-if="printStatusArray.length">
<v-list-item v-for="status of printStatusArray" :key="status.key" class="minHeight36">
<v-checkbox
class="mt-0"
hide-details
Expand Down Expand Up @@ -188,6 +185,7 @@ import { GuiMaintenanceStateEntry, HistoryListRowMaintenance } from '@/store/gui
import HistoryListEntryMaintenance from '@/components/panels/History/HistoryListEntryMaintenance.vue'
import HistoryListPanelDeleteSelectedDialog from '@/components/dialogs/HistoryListPanelDeleteSelectedDialog.vue'
import HistoryMixin from '@/components/mixins/history'
import HistoryStatsMixin from '@/components/mixins/historyStats'
export type HistoryListPanelRow = HistoryListRowJob | HistoryListRowMaintenance
Expand All @@ -211,7 +209,7 @@ export interface HistoryListPanelCol {
Panel,
},
})
export default class HistoryListPanel extends Mixins(BaseMixin, HistoryMixin) {
export default class HistoryListPanel extends Mixins(BaseMixin, HistoryMixin, HistoryStatsMixin) {
mdiCloseThick = mdiCloseThick
mdiCog = mdiCog
mdiDatabaseArrowDownOutline = mdiDatabaseArrowDownOutline
Expand Down
Loading

0 comments on commit fbeecb0

Please sign in to comment.