summaryrefslogtreecommitdiff
path: root/src/views/Settings/SnmpAlerts
diff options
context:
space:
mode:
authorKonstantin Aladyshev <aladyshev22@gmail.com>2023-05-16 12:03:25 +0300
committerKonstantin Aladyshev <aladyshev22@gmail.com>2023-08-10 20:45:48 +0300
commit7c1cfe7e25957fc915fc9790bdf78887295b1fee (patch)
tree94531b73fdc1b3e42398502306ca78b3b89e39dc /src/views/Settings/SnmpAlerts
parentd3bb22153f47d5c1276d0f9ae2a916f5ab0df52d (diff)
downloadwebui-vue-7c1cfe7e25957fc915fc9790bdf78887295b1fee.tar.xz
Add SNMP alerts page and test hooks
This page will be included in Configuration section of the primary navigation. The user will be able to delete and add alert destination. Change-Id: I396d19a54ea11724f2c5aec67e20ba9abff947d3 Signed-off-by: Konstantin Aladyshev <aladyshev22@gmail.com>
Diffstat (limited to 'src/views/Settings/SnmpAlerts')
-rw-r--r--src/views/Settings/SnmpAlerts/ModalAddDestination.vue145
-rw-r--r--src/views/Settings/SnmpAlerts/SnmpAlerts.vue274
-rw-r--r--src/views/Settings/SnmpAlerts/index.js2
3 files changed, 421 insertions, 0 deletions
diff --git a/src/views/Settings/SnmpAlerts/ModalAddDestination.vue b/src/views/Settings/SnmpAlerts/ModalAddDestination.vue
new file mode 100644
index 00000000..9637652b
--- /dev/null
+++ b/src/views/Settings/SnmpAlerts/ModalAddDestination.vue
@@ -0,0 +1,145 @@
+<template>
+ <b-modal id="add-destination" ref="modal" @ok="onOk" @hidden="resetForm">
+ <template #modal-title>
+ {{ $t('pageSnmpAlerts.modal.addSnmpDestinationTitle') }}
+ </template>
+ <b-form id="form-destination">
+ <b-container>
+ <b-row>
+ <b-col sm="6">
+ <!-- Add new SNMP alert destination type -->
+ <b-form-group
+ :label="$t('pageSnmpAlerts.modal.ipaddress')"
+ label-for="ip-address"
+ >
+ <b-form-input
+ id="ip-Address"
+ v-model="form.ipAddress"
+ :state="getValidationState($v.form.ipAddress)"
+ data-test-id="snmpAlerts-input-ipAddress"
+ type="text"
+ @blur="$v.form.ipAddress.$touch()"
+ />
+
+ <b-form-invalid-feedback role="alert">
+ <template v-if="!$v.form.ipAddress.required">
+ {{ $t('global.form.fieldRequired') }}
+ </template>
+ <template v-if="!$v.form.ipAddress.ipAddress">
+ {{ $t('global.form.invalidFormat') }}
+ </template>
+ </b-form-invalid-feedback>
+ </b-form-group>
+ </b-col>
+ <b-col>
+ <b-form-group label-for="port">
+ <template #label>
+ {{ $t('pageSnmpAlerts.modal.port') }} -
+ <span class="form-text d-inline">
+ {{ $t('global.form.optional') }}
+ </span>
+ </template>
+ <b-form-input
+ id="port"
+ v-model="form.port"
+ type="text"
+ :state="getValidationState($v.form.port)"
+ data-test-id="snmpAlerts-input-port"
+ @blur="$v.form.port.$touch()"
+ />
+ <b-form-invalid-feedback role="alert">
+ <template
+ v-if="!$v.form.port.minLength || !$v.form.port.maxLength"
+ >
+ {{
+ $t('global.form.valueMustBeBetween', {
+ min: 0,
+ max: 65535,
+ })
+ }}
+ </template>
+ </b-form-invalid-feedback>
+ </b-form-group>
+ </b-col>
+ </b-row>
+ </b-container>
+ </b-form>
+ <template #modal-footer="{ cancel }">
+ <b-button variant="secondary" @click="cancel()">
+ {{ $t('global.action.cancel') }}
+ </b-button>
+ <b-button
+ form="form-user"
+ type="submit"
+ variant="primary"
+ data-test-id="snmpAlerts-button-ok"
+ @click="onOk"
+ >
+ {{ $t('pageSnmpAlerts.addDestination') }}
+ </b-button>
+ </template>
+ </b-modal>
+</template>
+
+<script>
+import {
+ required,
+ ipAddress,
+ minValue,
+ maxValue,
+} from 'vuelidate/lib/validators';
+import VuelidateMixin from '@/components/Mixins/VuelidateMixin.js';
+
+export default {
+ mixins: [VuelidateMixin],
+ data() {
+ return {
+ form: {
+ ipaddress: null,
+ port: null,
+ },
+ };
+ },
+ validations() {
+ return {
+ form: {
+ ipAddress: {
+ required,
+ ipAddress,
+ },
+ port: {
+ minValue: minValue(0),
+ maxValue: maxValue(65535),
+ },
+ },
+ };
+ },
+ methods: {
+ handleSubmit() {
+ this.$v.$touch();
+ if (this.$v.$invalid) return;
+ this.$emit('ok', {
+ ipAddress: this.form.ipAddress,
+ port: this.form.port,
+ });
+ this.closeModal();
+ },
+ closeModal() {
+ this.$nextTick(() => {
+ this.$refs.modal.hide();
+ });
+ },
+ resetForm() {
+ this.form.ipAddress = '';
+ this.form.port = '';
+ this.$v.$reset();
+ this.$emit('hidden');
+ },
+ onOk(bvModalEvt) {
+ // prevent modal close
+ bvModalEvt.preventDefault();
+ this.handleSubmit();
+ },
+ },
+};
+</script>
diff --git a/src/views/Settings/SnmpAlerts/SnmpAlerts.vue b/src/views/Settings/SnmpAlerts/SnmpAlerts.vue
new file mode 100644
index 00000000..8a9b8e73
--- /dev/null
+++ b/src/views/Settings/SnmpAlerts/SnmpAlerts.vue
@@ -0,0 +1,274 @@
+<template>
+ <b-container fluid="xl">
+ <page-title :description="$t('pageSnmpAlerts.pageDescription')" />
+ <b-row>
+ <b-col xl="9" class="text-right">
+ <b-button variant="primary" @click="initModalAddDestination">
+ <icon-add />
+ {{ $t('pageSnmpAlerts.addDestination') }}
+ </b-button>
+ </b-col>
+ </b-row>
+ <b-row>
+ <b-col xl="9">
+ <table-toolbar
+ ref="toolbar"
+ :selected-items-count="selectedRows.length"
+ :actions="tableToolbarActions"
+ @clear-selected="clearSelectedRows($refs.table)"
+ @batch-action="onBatchAction"
+ />
+ <b-table
+ ref="table"
+ responsive="md"
+ selectable
+ show-empty
+ no-select-on-click
+ hover
+ :fields="fields"
+ :items="tableItems"
+ :empty-text="$t('global.table.emptyMessage')"
+ @row-selected="onRowSelected($event, tableItems.length)"
+ >
+ <!-- Checkbox column -->
+ <template #head(checkbox)>
+ <b-form-checkbox
+ v-model="tableHeaderCheckboxModel"
+ data-test-id="snmpAlerts-checkbox-selectAll"
+ :indeterminate="tableHeaderCheckboxIndeterminate"
+ @change="onChangeHeaderCheckbox($refs.table)"
+ >
+ <span class="sr-only">{{ $t('global.table.selectAll') }}</span>
+ </b-form-checkbox>
+ </template>
+ <template #cell(checkbox)="row">
+ <b-form-checkbox
+ v-model="row.rowSelected"
+ :data-test-id="`snmpAlerts-checkbox-selectRow-${row.index}`"
+ @change="toggleSelectRow($refs.table, row.index)"
+ >
+ <span class="sr-only">{{ $t('global.table.selectItem') }}</span>
+ </b-form-checkbox>
+ </template>
+
+ <!-- table actions column -->
+ <template #cell(actions)="{ item }">
+ <table-row-action
+ v-for="(action, index) in item.actions"
+ :key="index"
+ :value="action.value"
+ :enabled="action.enabled"
+ :title="action.title"
+ :data-test-id="`snmpAlerts-button-deleteRow-${item.index}`"
+ @click-table-action="onTableRowAction($event, item)"
+ >
+ <template #icon>
+ <icon-trashcan v-if="action.value === 'delete'" />
+ </template>
+ </table-row-action>
+ </template>
+ </b-table>
+ </b-col>
+ </b-row>
+ <!-- Modals -->
+ <modal-add-destination @ok="onModalOk" />
+ </b-container>
+</template>
+
+<script>
+import IconTrashcan from '@carbon/icons-vue/es/trash-can/20';
+import ModalAddDestination from './ModalAddDestination';
+import PageTitle from '@/components/Global/PageTitle';
+import IconAdd from '@carbon/icons-vue/es/add--alt/20';
+import TableToolbar from '@/components/Global/TableToolbar';
+import TableRowAction from '@/components/Global/TableRowAction';
+import LoadingBarMixin from '@/components/Mixins/LoadingBarMixin';
+import BVToastMixin from '@/components/Mixins/BVToastMixin';
+
+import BVTableSelectableMixin, {
+ selectedRows,
+ tableHeaderCheckboxModel,
+ tableHeaderCheckboxIndeterminate,
+} from '@/components/Mixins/BVTableSelectableMixin';
+export default {
+ name: 'SnmpAlerts',
+ components: {
+ PageTitle,
+ IconAdd,
+ TableToolbar,
+ IconTrashcan,
+ ModalAddDestination,
+ TableRowAction,
+ },
+ mixins: [BVTableSelectableMixin, BVToastMixin, LoadingBarMixin],
+ beforeRouteLeave(to, from, next) {
+ this.hideLoader();
+ next();
+ },
+ data() {
+ return {
+ fields: [
+ {
+ key: 'checkbox',
+ },
+ {
+ key: 'IP',
+ label: this.$t('pageSnmpAlerts.table.ipaddress'),
+ },
+ {
+ key: 'Port',
+ label: this.$t('pageSnmpAlerts.table.port'),
+ },
+ {
+ key: 'actions',
+ label: '',
+ tdClass: 'text-right text-nowrap',
+ },
+ ],
+ tableToolbarActions: [
+ {
+ value: 'delete',
+ label: this.$t('global.action.delete'),
+ },
+ ],
+ selectedRows: selectedRows,
+ tableHeaderCheckboxModel: tableHeaderCheckboxModel,
+ tableHeaderCheckboxIndeterminate: tableHeaderCheckboxIndeterminate,
+ };
+ },
+ computed: {
+ allSnmpDetails() {
+ return this.$store.getters['snmpAlerts/allSnmpDetails'];
+ },
+ tableItems() {
+ // transform destination data to table data
+ return this.allSnmpDetails.map((subscriptions) => {
+ const [destination, dataWithProtocol, dataWithoutProtocol] = [
+ subscriptions.Destination,
+ subscriptions.Destination.split('/')[2].split(':'),
+ subscriptions.Destination.split(':'),
+ ];
+ //condition to check if destination comes with protocol or not
+ const conditionForProtocolCheck = destination.includes('://');
+ const ip = conditionForProtocolCheck
+ ? dataWithProtocol[0]
+ : dataWithoutProtocol[0];
+ const port = conditionForProtocolCheck
+ ? dataWithProtocol[1]
+ : dataWithoutProtocol[1];
+ return {
+ IP: ip,
+ Port: port,
+ id: subscriptions.Id,
+ actions: [
+ {
+ value: 'delete',
+ enabled: true,
+ title: this.$tc('pageSnmpAlerts.deleteDestination'),
+ },
+ ],
+ ...subscriptions,
+ };
+ });
+ },
+ },
+ created() {
+ this.startLoader();
+ this.$store
+ .dispatch('snmpAlerts/getSnmpDetails')
+ .finally(() => this.endLoader());
+ },
+ methods: {
+ onModalOk({ ipAddress, port }) {
+ const protocolIpAddress = 'snmp://' + ipAddress;
+ const destination = port
+ ? protocolIpAddress + ':' + port
+ : protocolIpAddress;
+ const data = {
+ Destination: destination,
+ SubscriptionType: 'SNMPTrap',
+ Protocol: 'SNMPv2c',
+ };
+ this.startLoader();
+ this.$store
+ .dispatch('snmpAlerts/addDestination', { data })
+ .then((success) => this.successToast(success))
+ .catch(({ message }) => this.errorToast(message))
+ .finally(() => this.endLoader());
+ },
+ initModalAddDestination() {
+ this.$bvModal.show('add-destination');
+ },
+ initModalDeleteDestination(destination) {
+ this.$bvModal
+ .msgBoxConfirm(
+ this.$t('pageSnmpAlerts.modal.deleteConfirmMessage', {
+ destination: destination.id,
+ }),
+ {
+ title: this.$tc('pageSnmpAlerts.modal.deleteSnmpDestinationTitle'),
+ okTitle: this.$tc('pageSnmpAlerts.deleteDestination'),
+ cancelTitle: this.$t('global.action.cancel'),
+ }
+ )
+ .then((deleteConfirmed) => {
+ if (deleteConfirmed) {
+ this.deleteDestination(destination);
+ }
+ });
+ },
+ deleteDestination({ id }) {
+ this.startLoader();
+ this.$store
+ .dispatch('snmpAlerts/deleteDestination', id)
+ .then((success) => this.successToast(success))
+ .catch(({ message }) => this.errorToast(message))
+ .finally(() => this.endLoader());
+ },
+ onBatchAction(action) {
+ if (action === 'delete') {
+ this.$bvModal
+ .msgBoxConfirm(
+ this.$tc(
+ 'pageSnmpAlerts.modal.batchDeleteConfirmMessage',
+ this.selectedRows.length
+ ),
+ {
+ title: this.$tc(
+ 'pageSnmpAlerts.modal.deleteSnmpDestinationTitle',
+ this.selectedRows.length
+ ),
+ okTitle: this.$tc(
+ 'pageSnmpAlerts.deleteDestination',
+ this.selectedRows.length
+ ),
+ cancelTitle: this.$t('global.action.cancel'),
+ }
+ )
+ .then((deleteConfirmed) => {
+ if (deleteConfirmed) {
+ this.startLoader();
+ this.$store
+ .dispatch(
+ 'snmpAlerts/deleteMultipleDestinations',
+ this.selectedRows
+ )
+ .then((messages) => {
+ messages.forEach(({ type, message }) => {
+ if (type === 'success') this.successToast(message);
+ if (type === 'error') this.errorToast(message);
+ });
+ })
+ .finally(() => this.endLoader());
+ }
+ });
+ }
+ },
+ onTableRowAction(action, row) {
+ if (action === 'delete') {
+ this.initModalDeleteDestination(row);
+ }
+ },
+ },
+};
+</script>
diff --git a/src/views/Settings/SnmpAlerts/index.js b/src/views/Settings/SnmpAlerts/index.js
new file mode 100644
index 00000000..f27ed4aa
--- /dev/null
+++ b/src/views/Settings/SnmpAlerts/index.js
@@ -0,0 +1,2 @@
+import SnmpAlerts from './SnmpAlerts.vue';
+export default SnmpAlerts;