forked from platypush/platypush
Support for entity scan timeout errors and visual error handling
This commit is contained in:
parent
548d487e73
commit
595ebe49ca
3 changed files with 58 additions and 5 deletions
|
@ -2,6 +2,7 @@
|
||||||
<div class="row item entity">
|
<div class="row item entity">
|
||||||
<div class="status-container">
|
<div class="status-container">
|
||||||
<img src="@/assets/img/spinner.gif" class="loading" v-if="loading">
|
<img src="@/assets/img/spinner.gif" class="loading" v-if="loading">
|
||||||
|
<i class="fas fa-circle-exclamation error" v-else-if="error" />
|
||||||
<Icon v-bind="value.meta?.icon || {}" v-else />
|
<Icon v-bind="value.meta?.icon || {}" v-else />
|
||||||
</div>
|
</div>
|
||||||
<div class="component-container">
|
<div class="component-container">
|
||||||
|
@ -31,6 +32,11 @@ export default {
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
error: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
|
||||||
value: {
|
value: {
|
||||||
type: Object,
|
type: Object,
|
||||||
required: true,
|
required: true,
|
||||||
|
@ -80,6 +86,11 @@ export default {
|
||||||
width: 1em;
|
width: 1em;
|
||||||
height: 1em;
|
height: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.error {
|
||||||
|
color: $error-fg;
|
||||||
|
margin-left: .5em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-container,
|
.icon-container,
|
||||||
|
|
|
@ -41,6 +41,7 @@
|
||||||
<Entity
|
<Entity
|
||||||
:value="entity"
|
:value="entity"
|
||||||
@input="onEntityInput"
|
@input="onEntityInput"
|
||||||
|
:error="!!errorEntities[entity.id]"
|
||||||
:loading="!!loadingEntities[entity.id]"
|
:loading="!!loadingEntities[entity.id]"
|
||||||
@loading="loadingEntities[entity.id] = $event"
|
@loading="loadingEntities[entity.id] = $event"
|
||||||
/>
|
/>
|
||||||
|
@ -68,10 +69,20 @@ export default {
|
||||||
components: {Loading, Icon, Entity, Selector, NoItems},
|
components: {Loading, Icon, Entity, Selector, NoItems},
|
||||||
mixins: [Utils],
|
mixins: [Utils],
|
||||||
|
|
||||||
|
props: {
|
||||||
|
// Entity scan timeout in seconds
|
||||||
|
entityScanTimeout: {
|
||||||
|
type: Number,
|
||||||
|
default: 30,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
loading: false,
|
loading: false,
|
||||||
loadingEntities: {},
|
loadingEntities: {},
|
||||||
|
errorEntities: {},
|
||||||
|
entityTimeouts: {},
|
||||||
entities: {},
|
entities: {},
|
||||||
selector: {
|
selector: {
|
||||||
grouping: 'type',
|
grouping: 'type',
|
||||||
|
@ -143,6 +154,26 @@ export default {
|
||||||
this.loadingEntities = {
|
this.loadingEntities = {
|
||||||
...this.loadingEntities,
|
...this.loadingEntities,
|
||||||
...Object.keys(this.selector.selectedEntities).reduce((obj, id) => {
|
...Object.keys(this.selector.selectedEntities).reduce((obj, id) => {
|
||||||
|
const self = this
|
||||||
|
const entity = this.entities[id]
|
||||||
|
|
||||||
|
if (this.entityTimeouts[id])
|
||||||
|
clearTimeout(this.entityTimeouts[id])
|
||||||
|
|
||||||
|
this.entityTimeouts[id] = setTimeout(() => {
|
||||||
|
if (self.loadingEntities[id])
|
||||||
|
delete self.loadingEntities[id]
|
||||||
|
if (self.entityTimeouts[id])
|
||||||
|
delete self.entityTimeouts[id]
|
||||||
|
|
||||||
|
self.errorEntities[id] = entity
|
||||||
|
self.notify({
|
||||||
|
error: true,
|
||||||
|
title: entity.plugin,
|
||||||
|
text: `Scan timeout for ${entity.name}`,
|
||||||
|
})
|
||||||
|
}, this.entityScanTimeout * 1000)
|
||||||
|
|
||||||
obj[id] = true
|
obj[id] = true
|
||||||
return obj
|
return obj
|
||||||
}, {}),
|
}, {}),
|
||||||
|
@ -172,9 +203,20 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
clearEntityTimeouts(entityId) {
|
||||||
|
if (this.errorEntities[entityId])
|
||||||
|
delete this.errorEntities[entityId]
|
||||||
|
if (this.loadingEntities[entityId])
|
||||||
|
delete this.loadingEntities[entityId]
|
||||||
|
if (this.entityTimeouts[entityId]) {
|
||||||
|
clearTimeout(this.entityTimeouts[entityId])
|
||||||
|
delete this.entityTimeouts[entityId]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
onEntityInput(entity) {
|
onEntityInput(entity) {
|
||||||
const entityId = entity.id
|
this.entities[entity.id] = entity
|
||||||
this.entities[entityId] = entity
|
this.clearEntityTimeouts(entity.id)
|
||||||
if (this.loadingEntities[entity.id])
|
if (this.loadingEntities[entity.id])
|
||||||
delete this.loadingEntities[entity.id]
|
delete this.loadingEntities[entity.id]
|
||||||
},
|
},
|
||||||
|
@ -183,14 +225,13 @@ export default {
|
||||||
const entityId = event.entity.id
|
const entityId = event.entity.id
|
||||||
if (entityId == null)
|
if (entityId == null)
|
||||||
return
|
return
|
||||||
if (this.loadingEntities[entityId])
|
|
||||||
delete this.loadingEntities[entityId]
|
|
||||||
|
|
||||||
|
this.clearEntityTimeouts(entityId)
|
||||||
this.entities[entityId] = {
|
this.entities[entityId] = {
|
||||||
...event.entity,
|
...event.entity,
|
||||||
meta: {
|
meta: {
|
||||||
...(this.entities[entityId]?.meta || {}),
|
|
||||||
...(event.entity?.meta || {}),
|
...(event.entity?.meta || {}),
|
||||||
|
...(this.entities[entityId]?.meta || {}),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -6,6 +6,7 @@ $default-bg-4: #f1f3f2 !default;
|
||||||
$default-bg-5: #edf0ee !default;
|
$default-bg-5: #edf0ee !default;
|
||||||
$default-bg-6: #e4eae8 !default;
|
$default-bg-6: #e4eae8 !default;
|
||||||
$default-bg-7: #e4e4e4 !default;
|
$default-bg-7: #e4e4e4 !default;
|
||||||
|
$error-fg: #ad1717 !default;
|
||||||
|
|
||||||
$default-fg: black !default;
|
$default-fg: black !default;
|
||||||
$default-fg-2: #23513a !default;
|
$default-fg-2: #23513a !default;
|
||||||
|
|
Loading…
Reference in a new issue