Add a new dashboard page.
This commit is contained in:
parent
89150e1164
commit
fd24b1898e
133 changed files with 17303 additions and 11112 deletions
196
webui/src/components/dashboard/PanelChart.vue
Normal file
196
webui/src/components/dashboard/PanelChart.vue
Normal file
|
@ -0,0 +1,196 @@
|
|||
<template>
|
||||
<q-card flat bordered>
|
||||
<q-card-section>
|
||||
<div class="row items-center no-wrap">
|
||||
<div class="col">
|
||||
<div class="text-h6 text-weight-bold">{{getName}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</q-card-section>
|
||||
<q-card-section>
|
||||
<div class="row items-center q-col-gutter-md">
|
||||
<div class="col-12 col-sm-6">
|
||||
<ChartDoughnut
|
||||
:chartdata="getChartdata()"
|
||||
:options="options"/>
|
||||
</div>
|
||||
<div class="col-12 col-sm-6">
|
||||
<q-list>
|
||||
<q-item class="label-state">
|
||||
<q-item-section avatar>
|
||||
<avatar-state state="positive"/>
|
||||
</q-item-section>
|
||||
<q-item-section class="label-state-text">
|
||||
<q-item-label>Success</q-item-label>
|
||||
<q-item-label caption lines="1">{{getSuccess(true)}}%</q-item-label>
|
||||
</q-item-section>
|
||||
<q-item-section side class="label-state-side">
|
||||
{{getSuccess()}}
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
<q-item class="label-state">
|
||||
<q-item-section avatar>
|
||||
<avatar-state state="warning"/>
|
||||
</q-item-section>
|
||||
<q-item-section class="label-state-text">
|
||||
<q-item-label>Warnings</q-item-label>
|
||||
<q-item-label caption lines="1">{{getWarnings(true)}}%</q-item-label>
|
||||
</q-item-section>
|
||||
<q-item-section side class="label-state-side">
|
||||
{{getWarnings()}}
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
<q-item class="label-state">
|
||||
<q-item-section avatar>
|
||||
<avatar-state state="negative"/>
|
||||
</q-item-section>
|
||||
<q-item-section class="label-state-text">
|
||||
<q-item-label>Errors</q-item-label>
|
||||
<q-item-label caption lines="1">{{getErrors(true)}}%</q-item-label>
|
||||
</q-item-section>
|
||||
<q-item-section side class="label-state-side">
|
||||
{{getErrors()}}
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
</div>
|
||||
</div>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Helps from '../../_helpers/Helps'
|
||||
import ChartDoughnut from '../_commons/ChartDoughnut'
|
||||
import AvatarState from '../_commons/AvatarState'
|
||||
|
||||
export default {
|
||||
name: 'PanelChart',
|
||||
props: ['name', 'data', 'type'],
|
||||
components: {
|
||||
ChartDoughnut,
|
||||
AvatarState
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
loading: true,
|
||||
options: {
|
||||
legend: {
|
||||
display: false
|
||||
},
|
||||
animation: {
|
||||
duration: 1000
|
||||
},
|
||||
tooltips: {
|
||||
enabled: true
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
getName () {
|
||||
return Helps.capFirstLetter(this.name)
|
||||
},
|
||||
getUrl () {
|
||||
return `/${this.type}/${this.getName.toLowerCase()}`
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getSuccess (inPercent = false) {
|
||||
const num = this.data.total - (this.data.errors + this.data.warnings)
|
||||
let result = 0
|
||||
if (inPercent) {
|
||||
result = Helps.getPercent(num, this.data.total).toFixed(0)
|
||||
} else {
|
||||
result = num
|
||||
}
|
||||
return isNaN(result) ? 0 : result
|
||||
},
|
||||
getWarnings (inPercent = false) {
|
||||
const num = this.data.warnings
|
||||
let result = 0
|
||||
if (inPercent) {
|
||||
result = Helps.getPercent(num, this.data.total).toFixed(0)
|
||||
} else {
|
||||
result = num
|
||||
}
|
||||
return isNaN(result) ? 0 : result
|
||||
},
|
||||
getErrors (inPercent = false) {
|
||||
const num = this.data.errors
|
||||
let result = 0
|
||||
if (inPercent) {
|
||||
result = Helps.getPercent(num, this.data.total).toFixed(0)
|
||||
} else {
|
||||
result = num
|
||||
}
|
||||
return isNaN(result) ? 0 : result
|
||||
},
|
||||
getData () {
|
||||
return [this.getSuccess(), this.getWarnings(), this.getErrors()]
|
||||
},
|
||||
getChartdata () {
|
||||
if (this.getData()[0] === 0 && this.getData()[1] === 0 && this.getData()[2] === 0) {
|
||||
this.options.tooltips.enabled = false
|
||||
return {
|
||||
datasets: [{
|
||||
backgroundColor: [
|
||||
'#f2f3f5'
|
||||
],
|
||||
data: [1]
|
||||
}]
|
||||
}
|
||||
} else {
|
||||
this.options.tooltips.enabled = true
|
||||
return {
|
||||
datasets: [{
|
||||
backgroundColor: [
|
||||
'#00a697',
|
||||
'#db7d11',
|
||||
'#ff0039'
|
||||
],
|
||||
data: this.getData()
|
||||
}],
|
||||
labels: [
|
||||
'Success',
|
||||
'Warnings',
|
||||
'Errors'
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "../../css/sass/variables";
|
||||
|
||||
.label-state {
|
||||
min-height: 32px;
|
||||
padding: 8px;
|
||||
.q-item__section--avatar{
|
||||
min-width: 32px;
|
||||
padding: 0 8px 0 0;
|
||||
}
|
||||
&-text{
|
||||
.q-item__label{
|
||||
font-size: 16px;
|
||||
line-height: 16px !important;
|
||||
font-weight: 600;
|
||||
}
|
||||
.q-item__label--caption{
|
||||
font-size: 14px;
|
||||
line-height: 14px !important;
|
||||
font-weight: 500;
|
||||
color: $app-text-grey;
|
||||
}
|
||||
}
|
||||
&-side{
|
||||
font-size: 22px;
|
||||
font-weight: 700;
|
||||
padding: 0 0 0 8px;
|
||||
color: inherit;
|
||||
}
|
||||
}
|
||||
</style>
|
25
webui/src/components/dashboard/PanelEntry.vue
Normal file
25
webui/src/components/dashboard/PanelEntry.vue
Normal file
|
@ -0,0 +1,25 @@
|
|||
<template>
|
||||
<q-card flat bordered>
|
||||
<q-card-section>
|
||||
<div class="row items-center no-wrap">
|
||||
<div class="col">
|
||||
<div class="text-subtitle2 text-uppercase text-center text-app-grey" style="letter-spacing: 3px;">{{name}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</q-card-section>
|
||||
<q-card-section>
|
||||
<div class="text-h3 text-center text-weight-bold">{{address}}</div>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'PanelEntry',
|
||||
props: ['address', 'name']
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
78
webui/src/components/dashboard/PanelFeature.vue
Normal file
78
webui/src/components/dashboard/PanelFeature.vue
Normal file
|
@ -0,0 +1,78 @@
|
|||
<template>
|
||||
<q-card flat bordered>
|
||||
<q-card-section>
|
||||
<div class="row items-center no-wrap">
|
||||
<div class="col">
|
||||
<div class="text-subtitle2 text-uppercase text-center text-app-grey" style="letter-spacing: 3px;">{{featureKey}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</q-card-section>
|
||||
<q-card-section>
|
||||
<div class="text-h3 text-center text-weight-bold">
|
||||
<q-chip
|
||||
outline
|
||||
color="primary"
|
||||
text-color="white"
|
||||
v-bind:class="['feature-chip', {'feature-chip-string':isString}, {'feature-chip-boolean':isBoolean}, {'feature-chip-boolean-true':isTrue}]">
|
||||
{{getVal}}
|
||||
</q-chip>
|
||||
</div>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'PanelFeature',
|
||||
props: ['featureKey', 'featureVal'],
|
||||
computed: {
|
||||
isString () {
|
||||
return this.$_.isString(this.featureVal)
|
||||
},
|
||||
isBoolean () {
|
||||
return this.$_.isBoolean(this.featureVal) || this.featureVal === ''
|
||||
},
|
||||
isTrue () {
|
||||
return this.isBoolean && this.featureVal === true
|
||||
},
|
||||
getVal () {
|
||||
if (this.featureVal === true) {
|
||||
return 'ON'
|
||||
} else if (this.featureVal === false || this.featureVal === '') {
|
||||
return 'OFF'
|
||||
} else {
|
||||
return this.featureVal
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "../../css/sass/variables";
|
||||
|
||||
.feature-chip {
|
||||
border-radius: 12px;
|
||||
border-width: 2px;
|
||||
height: 56px;
|
||||
padding: 12px 24px;
|
||||
&-string{
|
||||
border-color: $app-text-grey;
|
||||
font-size: 24px;
|
||||
color: $app-text-grey !important;
|
||||
background-color: rgba( $app-text-grey, .1 );
|
||||
}
|
||||
&-boolean{
|
||||
font-size: 40px;
|
||||
font-weight: 700;
|
||||
border-color: $negative;
|
||||
color: $negative !important;
|
||||
background-color: rgba( $negative, .1 );
|
||||
&-true{
|
||||
border-color: $positive;
|
||||
color: $positive !important;
|
||||
background-color: rgba( $positive, .1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
46
webui/src/components/dashboard/PanelProvider.vue
Normal file
46
webui/src/components/dashboard/PanelProvider.vue
Normal file
|
@ -0,0 +1,46 @@
|
|||
<template>
|
||||
<q-card flat bordered>
|
||||
<q-card-section>
|
||||
<div class="row items-center no-wrap">
|
||||
<div class="col text-center">
|
||||
<q-avatar class="provider-logo">
|
||||
<q-icon :name="`img:statics/providers/${getNameLogo}.svg`" />
|
||||
</q-avatar>
|
||||
</div>
|
||||
</div>
|
||||
</q-card-section>
|
||||
<q-card-section>
|
||||
<div class="text-h6 text-center text-weight-bold">
|
||||
{{getName}}
|
||||
</div>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'PanelProvider',
|
||||
props: ['name'],
|
||||
computed: {
|
||||
getName () {
|
||||
return this.name
|
||||
},
|
||||
getNameLogo () {
|
||||
return this.getName.toLowerCase()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "../../css/sass/variables";
|
||||
|
||||
.provider-logo {
|
||||
width: 52px;
|
||||
height: 52px;
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
Loading…
Add table
Add a link
Reference in a new issue