diff --git a/src/components/AppNavigation/AppNavigationMixin.js b/src/components/AppNavigation/AppNavigationMixin.js
index edeabc52f4..ad9af89914 100644
--- a/src/components/AppNavigation/AppNavigationMixin.js
+++ b/src/components/AppNavigation/AppNavigationMixin.js
@@ -123,6 +123,11 @@ const AppNavigationMixin = {
label: this.$t('appNavigation.powerRestorePolicy'),
route: '/settings/power-restore-policy',
},
+ {
+ id: 'snmp-alerts',
+ label: this.$t('appNavigation.snmpAlerts'),
+ route: '/settings/snmp-alerts',
+ },
],
},
{
diff --git a/src/env/components/AppNavigation/ibm.js b/src/env/components/AppNavigation/ibm.js
index 32f5c9f47c..233c3f7565 100644
--- a/src/env/components/AppNavigation/ibm.js
+++ b/src/env/components/AppNavigation/ibm.js
@@ -118,6 +118,11 @@ const AppNavigationMixin = {
label: this.$t('appNavigation.powerRestorePolicy'),
route: '/settings/power-restore-policy',
},
+ {
+ id: 'snmp-alerts',
+ label: this.$t('appNavigation.snmpAlerts'),
+ route: '/settings/snmp-alerts',
+ },
],
},
{
diff --git a/src/env/router/ibm.js b/src/env/router/ibm.js
index c6ac61f79d..2eacbdca89 100644
--- a/src/env/router/ibm.js
+++ b/src/env/router/ibm.js
@@ -25,6 +25,7 @@ import SerialOverLanConsole from '@/views/Operations/SerialOverLan/SerialOverLan
import ServerPowerOperations from '@/views/Operations/ServerPowerOperations';
import Certificates from '@/views/SecurityAndAccess/Certificates';
import Power from '@/views/ResourceManagement/Power';
+import SnmpAlerts from '@/views/Settings/SnmpAlerts';
import i18n from '@/i18n';
// Custom components
@@ -206,6 +207,14 @@ const routes = [
title: i18n.t('appPageTitle.powerRestorePolicy'),
},
},
+ {
+ path: '/settings/snmp-alerts',
+ name: 'snmp-alerts',
+ component: SnmpAlerts,
+ meta: {
+ title: i18n.t('appPageTitle.snmpAlerts'),
+ },
+ },
{
path: '/resource-management/power',
name: 'power',
diff --git a/src/locales/en-US.json b/src/locales/en-US.json
index afe886dcf2..1edc03c77a 100644
--- a/src/locales/en-US.json
+++ b/src/locales/en-US.json
@@ -126,6 +126,7 @@
"serverPowerOperations": "@:appPageTitle.serverPowerOperations",
"certificates": "@:appPageTitle.certificates",
"virtualMedia": "@:appPageTitle.virtualMedia",
+ "snmpAlerts": "@:appPageTitle.snmpAlerts",
"power": "@:appPageTitle.power"
},
"appPageTitle": {
@@ -154,7 +155,8 @@
"serialOverLan": "Serial over LAN (SOL) console",
"serverPowerOperations": "Server power operations",
"certificates": "Certificates",
- "virtualMedia": "Virtual media"
+ "virtualMedia": "Virtual media",
+ "snmpAlerts":"SNMP Alerts"
},
"pageChangePassword": {
"changePassword": "Change password",
@@ -806,6 +808,32 @@
"successSaveSettings": "Successfully saved settings."
}
},
+ "pageSnmpAlerts": {
+ "addDestination": "Add destination",
+ "deleteDestination": "Delete destination | Delete destinations",
+ "pageDescription": "Set the Simple Network Management Protocol (SNMP) traps with an IP address and a port.",
+ "modal": {
+ "addSnmpDestinationTitle": "Add SNMP alert destination",
+ "batchDeleteConfirmMessage": "Are you sure you want to delete the SNMP alert destination? This action cannot be undone. | Are you sure you want to delete %{count} SNMP alert destinations? This action cannot be undone.",
+ "deleteConfirmMessage": "Are you sure you want to delete the SNMP alert destination? This action cannot be undone.",
+ "deleteSnmpDestinationTitle": "Delete SNMP alert destination | Delete SNMP alert destinations",
+ "ipaddress": "IP Address",
+ "port": "Port"
+ },
+ "table": {
+ "ipaddress": "IP Address",
+ "port": "Port"
+ },
+ "toast": {
+ "errorAddDestination":"Error in adding SNMP alert destination",
+ "errorBatchDelete": "Error in deleting SNMP alert destination. | Error in deleting SNMP alert destinations.",
+ "errorDeleteDestination": "Error deleting SNMP alert destination.",
+ "errorLoadSnmpDetails": "Error loading SNMP alert details.",
+ "successAddDestination":"Successfully added SNMP alert destination.",
+ "successBatchDelete": "Successfully deleted SNMP alert destination. | Successfully deleted %{count} SNMP alert destinations.",
+ "successDeleteDestination": "Successfully deleted SNMP alert destination."
+ }
+ },
"pageCertificates": {
"addNewCertificate": "Add new certificate",
"caCertificate": "CA Certificate",
diff --git a/src/router/routes.js b/src/router/routes.js
index b99aac5166..48c3f42c4a 100644
--- a/src/router/routes.js
+++ b/src/router/routes.js
@@ -28,6 +28,7 @@ import ServerPowerOperations from '@/views/Operations/ServerPowerOperations';
import Certificates from '@/views/SecurityAndAccess/Certificates';
import VirtualMedia from '@/views/Operations/VirtualMedia';
import Power from '@/views/ResourceManagement/Power';
+import SnmpAlerts from '@/views/Settings/SnmpAlerts';
import i18n from '@/i18n';
const routes = [
@@ -182,6 +183,14 @@ const routes = [
title: i18n.t('appPageTitle.dateTime'),
},
},
+ {
+ path: '/settings/snmp-alerts',
+ name: 'snmp-alerts',
+ component: SnmpAlerts,
+ meta: {
+ title: i18n.t('appPageTitle.snmpAlerts'),
+ },
+ },
{
path: '/operations/factory-reset',
name: 'factory-reset',
diff --git a/src/store/index.js b/src/store/index.js
index d7c1b22d03..3f9cf17904 100644
--- a/src/store/index.js
+++ b/src/store/index.js
@@ -27,7 +27,7 @@ import AssemblyStore from './modules/HardwareStatus/AssemblyStore';
import PostCodeLogsStore from './modules/Logs/PostCodeLogsStore';
import PoliciesStore from './modules/SecurityAndAccess/PoliciesStore';
import FactoryResetStore from './modules/Operations/FactoryResetStore';
-
+import SnmpAlertsStore from './modules/Settings/SnmpAlertsStore';
import WebSocketPlugin from './plugins/WebSocketPlugin';
import DateTimeStore from './modules/Settings/DateTimeStore';
import VirtualMediaStore from './modules/Operations/VirtualMediaStore';
@@ -55,6 +55,7 @@ export default new Vuex.Store({
eventLog: EventLogStore,
sensors: SensorsStore,
serverLed: ServerLedStore,
+ snmpAlerts: SnmpAlertsStore,
certificates: CertificatesStore,
system: SystemStore,
memory: MemoryStore,
diff --git a/src/store/modules/Settings/SnmpAlertsStore.js b/src/store/modules/Settings/SnmpAlertsStore.js
new file mode 100644
index 0000000000..17b91dfa36
--- /dev/null
+++ b/src/store/modules/Settings/SnmpAlertsStore.js
@@ -0,0 +1,116 @@
+import api, { getResponseCount } from '@/store/api';
+import i18n from '@/i18n';
+const SnmpAlertsStore = {
+ namespaced: true,
+ state: {
+ allSnmpDetails: [],
+ },
+ getters: {
+ allSnmpDetails(state) {
+ return state.allSnmpDetails;
+ },
+ },
+ mutations: {
+ setSnmpDetails(state, allSnmpDetails) {
+ state.allSnmpDetails = allSnmpDetails;
+ },
+ },
+ actions: {
+ async getSnmpAlertUrl() {
+ return await api
+ .get('/redfish/v1/')
+ .then((response) => api.get(response.data.EventService['@odata.id']))
+ .then((response) => api.get(response.data.Subscriptions['@odata.id']))
+ .then((response) => response.data['@odata.id'])
+ .catch((error) => console.log('Error', error));
+ },
+ async getSnmpDetails({ commit, dispatch }) {
+ const snmpAlertUrl = await dispatch('getSnmpAlertUrl');
+ return await api
+ .get(snmpAlertUrl)
+ .then((response) =>
+ response.data.Members.map((user) => user['@odata.id'])
+ )
+ .then((userIds) => api.all(userIds.map((user) => api.get(user))))
+ .then((users) => {
+ const snmpDetailsData = users.map((user) => user.data);
+ commit('setSnmpDetails', snmpDetailsData);
+ })
+ .catch((error) => {
+ console.log(error);
+ const message = i18n.t('pageSnmpAlerts.toast.errorLoadSnmpDetails');
+ throw new Error(message);
+ });
+ },
+ async deleteDestination({ dispatch }, id) {
+ const snmpAlertUrl = await dispatch('getSnmpAlertUrl');
+ return await api
+ .delete(`${snmpAlertUrl}/${id}`)
+ .then(() => dispatch('getSnmpDetails'))
+ .then(() =>
+ i18n.t('pageSnmpAlerts.toast.successDeleteDestination', {
+ id,
+ })
+ )
+ .catch((error) => {
+ console.log(error);
+ const message = i18n.t(
+ 'pageSnmpAlerts.toast.errorDeleteDestination',
+ {
+ id,
+ }
+ );
+ throw new Error(message);
+ });
+ },
+ async deleteMultipleDestinations({ dispatch }, destination) {
+ const snmpAlertUrl = await dispatch('getSnmpAlertUrl');
+ const promises = destination.map(({ id }) => {
+ return api.delete(`${snmpAlertUrl}/${id}`).catch((error) => {
+ console.log(error);
+ return error;
+ });
+ });
+ return await api
+ .all(promises)
+ .then((response) => {
+ dispatch('getSnmpDetails');
+ return response;
+ })
+ .then(
+ api.spread((...responses) => {
+ const { successCount, errorCount } = getResponseCount(responses);
+ let toastMessages = [];
+ if (successCount) {
+ const message = i18n.tc(
+ 'pageSnmpAlerts.toast.successBatchDelete',
+ successCount
+ );
+ toastMessages.push({ type: 'success', message });
+ }
+ if (errorCount) {
+ const message = i18n.tc(
+ 'pageSnmpAlerts.toast.errorBatchDelete',
+ errorCount
+ );
+ toastMessages.push({ type: 'error', message });
+ }
+ return toastMessages;
+ })
+ );
+ },
+ async addDestination({ dispatch }, { data }) {
+ const snmpAlertUrl = await dispatch('getSnmpAlertUrl');
+ return await api
+ .post(snmpAlertUrl, data)
+ .then(() => dispatch('getSnmpDetails'))
+ .then(() => i18n.t('pageSnmpAlerts.toast.successAddDestination'))
+ .catch((error) => {
+ console.log(error);
+ const message = i18n.t('pageSnmpAlerts.toast.errorAddDestination');
+ throw new Error(message);
+ });
+ },
+ },
+};
+export default SnmpAlertsStore;
diff --git a/src/views/Settings/SnmpAlerts/ModalAddDestination.vue b/src/views/Settings/SnmpAlerts/ModalAddDestination.vue
new file mode 100644
index 0000000000..1d14117809
--- /dev/null
+++ b/src/views/Settings/SnmpAlerts/ModalAddDestination.vue
@@ -0,0 +1,142 @@
+
+
+
+ {{ $t('pageSnmpAlerts.modal.addSnmpDestinationTitle') }}
+
+
+
+
+
+
+
+
+
+
+ {{ $t('global.form.fieldRequired') }}
+
+
+ {{ $t('global.form.invalidFormat') }}
+
+
+
+
+
+
+
+ {{ $t('pageSnmpAlerts.modal.port') }} -
+
+ {{ $t('global.form.optional') }}
+
+
+
+
+
+ {{
+ $t('global.form.valueMustBeBetween', {
+ min: 0,
+ max: 65535,
+ })
+ }}
+
+
+
+
+
+
+
+
+
+ {{ $t('global.action.cancel') }}
+
+
+ {{ $t('pageSnmpAlerts.addDestination') }}
+
+
+
+
+
diff --git a/src/views/Settings/SnmpAlerts/SnmpAlerts.vue b/src/views/Settings/SnmpAlerts/SnmpAlerts.vue
new file mode 100644
index 0000000000..08b3c114e1
--- /dev/null
+++ b/src/views/Settings/SnmpAlerts/SnmpAlerts.vue
@@ -0,0 +1,272 @@
+
+
+
+
+
+
+
+ {{ $t('pageSnmpAlerts.addDestination') }}
+
+
+
+
+
+
+
+
+
+
+ {{ $t('global.table.selectAll') }}
+
+
+
+
+ {{ $t('global.table.selectItem') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/Settings/SnmpAlerts/index.js b/src/views/Settings/SnmpAlerts/index.js
new file mode 100644
index 0000000000..f27ed4aa46
--- /dev/null
+++ b/src/views/Settings/SnmpAlerts/index.js
@@ -0,0 +1,2 @@
+import SnmpAlerts from './SnmpAlerts.vue';
+export default SnmpAlerts;
diff --git a/tests/unit/__snapshots__/AppNavigation.spec.js.snap b/tests/unit/__snapshots__/AppNavigation.spec.js.snap
index 37609d3992..e25f9c16ed 100644
--- a/tests/unit/__snapshots__/AppNavigation.spec.js.snap
+++ b/tests/unit/__snapshots__/AppNavigation.spec.js.snap
@@ -453,6 +453,15 @@ exports[`AppNavigation.vue should render correctly 1`] = `
appNavigation.powerRestorePolicy
+
+
+ appNavigation.snmpAlerts
+
+
@@ -1114,6 +1123,15 @@ exports[`AppNavigation.vue should render with nav-container open 1`] = `
appNavigation.powerRestorePolicy
+
+
+ appNavigation.snmpAlerts
+
+