Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a new settings menu for persistence #2229

Merged
merged 10 commits into from
Dec 29, 2023
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,8 @@
"addons.text": "Add-ons add functionality to your openHAB system.<br><br>Install them with the button below.",

"page.unavailable.title": "Page Unavailable",
"page.unavailable.text": "You are not allowed to view this page because of visibility restrictions."
"page.unavailable.text": "You are not allowed to view this page because of visibility restrictions.",

"persistence.title": "No persistence add-on installed",
"persistence.text": "With persistence you can store Item states over time, no matter they are historic or future values. To configure persistence, you need at least one persistence add-on to be installed."
}
4 changes: 4 additions & 0 deletions bundles/org.openhab.ui/web/src/js/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ const InboxListPage = () => import(/* webpackChunkName: "admin-config" */ '../pa
const TransformationsListPage = () => import(/* webpackChunkName: "admin-config" */ '../pages/settings/transformations/transformations-list.vue')
const TransformationsEditPage = () => import(/* webpackChunkName: "admin-rules" */ '../pages/settings/transformations/transformation-edit.vue')

const PersistenceSettingsPage = () => import(/* webpackChunkName: "admin-config" */ '../pages/settings/persistence/persistence-settings.vue')
const PersistenceEditPage = () => import(/* webpackChunkName: "admin-config" */ '../pages/settings/persistence/persistence-edit.vue')

const SemanticModelPage = () => import(/* webpackChunkName: "admin-config" */ '../pages/settings/model/model.vue')
Expand Down Expand Up @@ -279,6 +280,9 @@ export default [
},
{
path: 'persistence/',
beforeEnter: [enforceAdminForRoute],
beforeLeave: [checkDirtyBeforeLeave],
async: loadAsync(PersistenceSettingsPage),
routes: [
{
path: ':serviceId',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,9 @@
</f7-navbar>
<f7-block v-if="type === 'persistence'" class="service-config block-narrow">
<f7-col>
<f7-block-title medium>
<f7-link color="blue" :href="'/settings/persistence/' + name">
Persistence configuration
</f7-link>
</f7-block-title>
<f7-button large fill color="blue" :href="'/settings/persistence/' + name">
Configure Persistence Policies
</f7-button>
</f7-col>
</f7-block>
<f7-block form v-if="configDescription && config" class="service-config block-narrow">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,14 @@
:footer="objectsSubtitles.transform">
<f7-icon slot="media" f7="function" color="gray" />
</f7-list-item>
<f7-list-item
media-item
link="persistence/"
title="Persistence"
badge-color="blue"
:footer="objectsSubtitles.persistence">
<f7-icon slot="media" f7="tray-arrow-down" color="gray" />
</f7-list-item>
</f7-list>
<f7-block-title v-if="$store.getters.apiEndpoint('rules')">
Automation
Expand Down Expand Up @@ -157,6 +165,7 @@ export default {
addonsLoaded: false,
servicesLoaded: false,
addonsInstalled: [],
persistenceAddonsInstalled: [],
addonsServices: [],
systemServices: [],
objectsSubtitles: {
Expand All @@ -165,6 +174,7 @@ export default {
items: 'Manage the functional layer',
pages: 'Design displays for user control & monitoring',
transform: 'Make raw data human-readable',
persistence: 'Persist data for future use',
rules: 'Automate with triggers and actions',
scenes: 'Store a set of desired states as a scene',
scripts: 'Rules dedicated to running code',
Expand Down Expand Up @@ -219,15 +229,23 @@ export default {

// can be done in parallel!
servicesPromise.then((data) => {
this.systemServices = data.filter(s => s.category === 'system')
this.addonsServices = data.filter(s => s.category !== 'system')
this.systemServices = data
.filter(s => (s.category === 'system') && (s.id !== 'org.openhab.persistence'))
.sort((s1, s2) => this.sortByLabel(s1, s2))
this.addonsServices = data.filter(s => s.category !== 'system').sort((s1, s2) => this.sortByLabel(s1, s2))
this.servicesLoaded = true
})
addonsPromise.then((data) => {
this.addonsInstalled = data.filter(a => a.installed && !['application/vnd.openhab.ruletemplate', 'application/vnd.openhab.uicomponent;type=widget', 'application/vnd.openhab.uicomponent;type=blocks'].includes(a.contentType))
this.addonsInstalled = data
.filter(a => a.installed && !['application/vnd.openhab.ruletemplate', 'application/vnd.openhab.uicomponent;type=widget', 'application/vnd.openhab.uicomponent;type=blocks'].includes(a.contentType))
.sort((s1, s2) => this.sortByLabel(s1, s2))
this.persistenceAddonsInstalled = this.addonsInstalled.filter(a => a.installed && a.type === 'persistence')
this.addonsLoaded = true
})
},
sortByLabel (s1, s2) {
return s1.label.toLowerCase() > s2.label.toLowerCase() ? 1 : -1
},
loadCounters () {
if (!this.apiEndpoints) return
if (this.$store.getters.apiEndpoint('inbox')) this.$oh.api.get('/rest/inbox').then((data) => { this.inboxCount = data.filter((e) => e.flag === 'NEW').length.toString() })
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
<template>
<f7-page @page:afterin="onPageAfterIn" @page:beforeout="onPageBeforeOut">
<f7-navbar title="Persistence Settings" back-link="Settings" back-link-url="/settings/" back-link-force>
<f7-nav-right v-if="persistenceList.length > 0">
<f7-link @click="save()" v-if="$theme.md" icon-md="material:save" icon-only />
<f7-link @click="save()" v-if="!$theme.md">
Save<span v-if="$device.desktop">&nbsp;(Ctrl-S)</span>
</f7-link>
</f7-nav-right>
</f7-navbar>

<f7-block form v-if="ready && persistenceList.length" class="block-narrow">
<f7-col>
<f7-block-title medium>
General Settings
</f7-block-title>
<config-sheet
:parameter-groups="configDescriptions.parameterGroups"
:parameters="configDescriptions.parameters"
:configuration="config"
:set-empty-config-as-null="true" />
</f7-col>
</f7-block>
<f7-block v-if="ready && persistenceList.length" class="block-narrow">
<f7-col>
<f7-block-title medium>
Configure Persistence Policies
</f7-block-title>
<f7-list style="margin-top: 15px">
<f7-list-item
v-for="persistence in persistenceList"
media-item
:key="persistence.id"
:link="persistence.id"
:title="persistence.label"
:footer="persistence.id" />
<f7-list-item link="/addons/other/" no-chevron media-item :color="($theme.dark) ? 'black' : 'white'" subtitle="Install more persistence add-ons">
<f7-icon slot="media" color="green" aurora="f7:plus_circle_fill" ios="f7:plus_circle_fill" md="material:control_point" />
</f7-list-item>
</f7-list>
</f7-col>
</f7-block>

<f7-block v-if="ready && !persistenceList.length" class="service-config block-narrow">
<empty-state-placeholder icon="tray-arrow-down" title="persistence.title" text="persistence.text" />
<f7-row class="display-flex justify-content-center">
<f7-button large fill color="blue" external :href="documentationLink" target="_blank" v-t="'home.overview.button.documentation'" />
<span style="width: 8px" />
<f7-button large fill color="blue" href="/addons/other/">
Install a persistence add-on
</f7-button>
</f7-row>
</f7-block>
</f7-page>
</template>

<script>
import DirtyMixin from '../dirty-mixin'
import ConfigSheet from '@/components/config/config-sheet.vue'

export default {
mixins: [DirtyMixin],
components: {
'empty-state-placeholder': () => import('@/components/empty-state-placeholder.vue'),
ConfigSheet
},
data () {
return {
loading: false,
ready: false,
serviceId: 'org.openhab.persistence',
persistenceList: [],
configDescriptions: null,
config: null
}
},
computed: {
documentationLink () {
return `https://${this.$store.state.runtimeInfo.buildString === 'Release Build' ? 'www' : 'next'}.openhab.org/link/persistence`
}
},
watch: {
config: {
handler: function () {
if (!this.loading) {
this.dirty = true
}
},
deep: true
}
},
methods: {
onPageAfterIn () {
if (window) {
window.addEventListener('keydown', this.keyDown)
}
this.load()
},
onPageBeforeOut () {
if (window) {
window.removeEventListener('keydown', this.keyDown)
}
},
load () {
if (this.loading) return
this.loading = true

this.$oh.api.get('/rest/persistence').then((data) => {
this.$set(this, 'persistenceList', data)
})
this.$oh.api.get('/rest/services/' + this.serviceId).then(data => {
if (data.configDescriptionURI) {
this.$oh.api.get('/rest/config-descriptions/' + data.configDescriptionURI).then(data2 => {
this.$set(this, 'configDescriptions', data2)
this.$oh.api.get('/rest/services/' + this.serviceId + '/config').then(data3 => {
this.$set(this, 'config', data3)
this.$nextTick(() => {
this.loading = false
this.ready = true
})
})
})
}
})
},
save () {
this.$oh.api.put('/rest/services/' + this.serviceId + '/config', this.config).then(() => {
this.$f7.toast.create({
text: 'Default persistence setting saved',
destroyOnClose: true,
closeTimeout: 2000
}).open()
})
this.dirty = false
},
keyDown (ev) {
if ((ev.ctrlKey || ev.metaKey) && !(ev.altKey || ev.shiftKey)) {
switch (ev.keyCode) {
case 83:
this.save()
ev.stopPropagation()
ev.preventDefault()
break
}
}
}
}
}
</script>