LibreNMS/resources/js/components/LibrenmsSettings.vue

198 lines
7.5 KiB
Vue

<!--
- LibrenmsSettings.vue
-
- Description-
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-
- @package LibreNMS
- @link http://librenms.org
- @copyright 2019 Tony Murray
- @author Tony Murray <murraytony@gmail.com>
-->
<template>
<tabs @tab-selected="tabChanged" :selected="this.tab">
<template v-slot:header>
<form class="form-inline" @submit.prevent>
<div class="input-group">
<input id="settings-search" type="search" class="form-control" :placeholder="$t('Filter Settings')" v-model.trim="search_phrase">
</div>
</form>
</template>
<tab name="global" :selected="'global' === tab" :text="$t('settings.groups.global')">
<ul class="settings-list">
<li v-for="setting in settings"><strong>{{ setting.name }}</strong> <code>{{ setting.value }}</code></li>
</ul>
</tab>
<tab v-for="(sections, group) in groups" :key="group" :name="group" :selected="group === tab" :text="$t('settings.groups.' + group)">
<accordion @expanded="sectionExpanded" @collapsed="sectionCollapsed">
<accordion-item v-for="(items, item) in groups[group]" :key="item" :name="item" :text="$t('settings.sections.' + group + '.' + item)" :active="item === section">
<form class="form-horizontal" @submit.prevent>
<librenms-setting
v-for="setting in items"
:key="setting"
:setting="settings[setting]"
v-show="settingShown(setting)"
@setting-updated="updateSetting($event.name, $event.value)"
></librenms-setting>
</form>
</accordion-item>
</accordion>
</tab>
</tabs>
</template>
<script>
export default {
name: "LibrenmsSettings",
props: {
prefix: String,
initialTab: {type: String, default: 'alerting'},
initialSection: String,
tabs: {type: Array}
},
data() {
return {
tab: this.initialTab,
section: this.initialSection,
search_phrase: '',
settings: {}
}
},
methods: {
tabChanged(group) {
if (this.tab !== group) {
this.tab = group;
this.section = null;
this.updateUrl();
}
},
sectionExpanded(section) {
this.section = section;
this.updateUrl()
},
sectionCollapsed(section) {
if (this.section === section) { // don't do anything if section was changed instead of just closed
this.section = null;
this.updateUrl();
}
},
updateUrl() {
let slug = this.tab;
if (this.section) {
slug += '/' + this.section
}
window.history.pushState(slug, '', this.prefix + '/' + slug)
},
handleBack(event) {
[this.tab, this.section] = event.state.split('/');
},
updateSetting(name, value) {
this.$set(this.settings[name], 'value', value)
},
settingShown(setting_name) {
let setting = this.settings[setting_name];
if (setting.when === null) {
return true;
}
if (setting.when.hasOwnProperty('and')) {
return setting.when.and.reduce((result, logic) => this.checkLogic(logic) && result, true)
} else if (setting.when.hasOwnProperty('or')) {
return setting.when.or.reduce((result, logic) => this.checkLogic(logic) || result, false)
}
return this.checkLogic(setting.when);
},
translatedCompare(prefix, a, b) {
return this.$t(prefix + a).localeCompare(this.$t(prefix + b))
},
checkLogic(logic) {
switch (logic.operator) {
case 'equals':
return this.settings[logic.setting].value === logic.value;
case 'in':
return logic.value.includes(this.settings[logic.setting].value);
default:
return true;
}
}
},
mounted() {
window.onpopstate = this.handleBack; // handle back button
axios.get(route('settings.list')).then((response) => this.settings = response.data)
},
computed: {
groups() {
if (_.isEmpty(this.settings)) {
let sorted_tabs = {};
this.tabs.sort((a, b) => this.translatedCompare('settings.groups.', a, b)).forEach(function (tab) {
sorted_tabs[tab] = [];
});
return sorted_tabs;
}
// group data
let groups = {};
for (const key of Object.keys(this.settings)) {
let setting = this.settings[key];
// filter
if (!setting.name.includes(this.search_phrase)) {
continue
}
if (setting.group) {
if (!(setting.group in groups)) {
groups[setting.group] = {};
}
if (setting.section) {
if (!(setting.section in groups[setting.group])) {
groups[setting.group][setting.section] = [];
}
groups[setting.group][setting.section].push(setting);
}
}
}
// sort groups
let sorted = {};
Object.keys(groups).sort((a, b) => this.translatedCompare('settings.groups.', a, b)).forEach(group_key => {
sorted[group_key] = {};
Object.keys(groups[group_key]).sort((a, b) => this.translatedCompare('settings.sections.' + group_key + '.', a , b)).forEach(section_key => {
sorted[group_key][section_key] = _.sortBy(groups[group_key][section_key], 'order').map(a => a.name);
});
});
return sorted;
}
}
}
</script>
<style scoped>
#settings-search {
border-radius: 4px
}
#settings-search::-webkit-search-cancel-button {
-webkit-appearance: searchfield-cancel-button;
}
ul.settings-list {
list-style-type: none;
}
</style>