diff options
author | Vitalii Lysak <v.lysak@dunice.net> | 2022-09-20 13:35:38 +0300 |
---|---|---|
committer | Vitalii Lysak <v.lysak@dunice.net> | 2022-09-20 13:35:38 +0300 |
commit | 4d04ae12f310f1bccf1270f1d3a4090b888ecf6e (patch) | |
tree | 793e75c70b133a1ddf2dbfe56134ef869ca7fc62 | |
parent | ab93e8470ddb49f4a522446dfb9c7882ff37daaf (diff) | |
parent | 37f6f72ff1ed6d4795c3f67ca2ba92367582e562 (diff) | |
download | webui-vue-4d04ae12f310f1bccf1270f1d3a4090b888ecf6e.tar.xz |
merge smtp, snmp, syslog
-rw-r--r-- | src/assets/styles/bmc/_sila/_modal.scss | 2 | ||||
-rw-r--r-- | src/env/components/AppNavigation/sila.js | 5 | ||||
-rw-r--r-- | src/env/router/sila.js | 9 | ||||
-rw-r--r-- | src/locales/en-US.json | 31 | ||||
-rw-r--r-- | src/locales/ru-RU.json | 45 | ||||
-rw-r--r-- | src/store/index.js | 6 | ||||
-rw-r--r-- | src/store/modules/Settings/SmtpStore.js | 100 | ||||
-rw-r--r-- | src/store/modules/Settings/SnmpStore.js | 73 | ||||
-rw-r--r-- | src/store/modules/Settings/SyslogStore.js | 36 | ||||
-rw-r--r-- | src/views/_sila/Overview/Overview.vue | 10 | ||||
-rw-r--r-- | src/views/_sila/Settings/TransferInfo/ModalSmtp.vue | 98 | ||||
-rw-r--r-- | src/views/_sila/Settings/TransferInfo/ModalSnmp.vue | 136 | ||||
-rw-r--r-- | src/views/_sila/Settings/TransferInfo/Smtp.vue | 414 | ||||
-rw-r--r-- | src/views/_sila/Settings/TransferInfo/Snmp.vue | 139 | ||||
-rw-r--r-- | src/views/_sila/Settings/TransferInfo/Syslog.vue | 220 | ||||
-rw-r--r-- | src/views/_sila/Settings/TransferInfo/Transfer.vue | 64 | ||||
-rw-r--r-- | src/views/_sila/Settings/TransferInfo/WarningSmnp.vue | 57 | ||||
-rw-r--r-- | src/views/_sila/Settings/TransferInfo/index.js | 2 |
18 files changed, 1447 insertions, 0 deletions
diff --git a/src/assets/styles/bmc/_sila/_modal.scss b/src/assets/styles/bmc/_sila/_modal.scss index 79f8313b..e67cb777 100644 --- a/src/assets/styles/bmc/_sila/_modal.scss +++ b/src/assets/styles/bmc/_sila/_modal.scss @@ -67,6 +67,8 @@ #modal-ssh, #modal-ipmi, +#modal-smtp, +#modal-snmp, #modal-dns, #modal-hostname, #modal-mac-address, diff --git a/src/env/components/AppNavigation/sila.js b/src/env/components/AppNavigation/sila.js index b7b1ca5a..ee3cb840 100644 --- a/src/env/components/AppNavigation/sila.js +++ b/src/env/components/AppNavigation/sila.js @@ -181,6 +181,11 @@ const AppNavigationMixin = { label: this.$t('appNavigation.powerRestorePolicy'), route: '/settings/power-restore-policy', }, + { + id: 'settings/transfer', + label: this.$t('appPageTitle.transfer'), + route: '/settings/transfer', + }, ], }, { diff --git a/src/env/router/sila.js b/src/env/router/sila.js index 9a3fbc1e..8ba9585f 100644 --- a/src/env/router/sila.js +++ b/src/env/router/sila.js @@ -36,6 +36,7 @@ import FansDynamic from '@/views/_sila/Fans/Dynamic'; import MotherboardDynamic from '@/views/_sila/Motherboard/Dynamic'; import PowerStatic from '@/views/_sila/Power/Static'; import PowerDynamic from '@/views/_sila/Power/Dynamic'; +import TransferInfo from '@/views/_sila/Settings/TransferInfo'; import i18n from '@/i18n'; @@ -280,6 +281,14 @@ const routes = [ }, }, { + path: '/settings/transfer', + name: 'transfer', + component: TransferInfo, + meta: { + title: i18n.t('appPageTitle.transfer'), + }, + }, + { path: '/resource-management/power', name: 'power', component: Power, diff --git a/src/locales/en-US.json b/src/locales/en-US.json index fc6d7bd3..4f95af69 100644 --- a/src/locales/en-US.json +++ b/src/locales/en-US.json @@ -209,6 +209,7 @@ "virtualMedia": "Virtual media", "keyClear": "Key clear", "specification": "Specification", + "transfer": "Communication settings", "pciDevices": "PCI-devices" }, "pageChangePassword": { @@ -1150,6 +1151,36 @@ "deviceClass": "Device Class" } }, + "pageTransfer": { + "title": "Setting up information transfer", + "description": "Set up SNMP, SMTP and SYSLOG", + "saveSmtpSuсcess": "Save SMTP successfully.", + "saveSmtpError": "Save SMTP error.", + "smtp": { + "smtpTitle": "Warning SMTP", + "username": "Username", + "password": "Password", + "host": "SMTP server", + "port": "SMTP port", + "authorization": "Authorization", + "sslEnabled": "SSL Support", + "testMessage": "Test message" + }, + "snmp": { + "snmpTitle": "SNMP settings", + "host": "SNMP server", + "port": "SNMP port", + "saveSubscriberSuсcess": "Subscriber added successfully", + "deleteSubscriberSuсcess": "Subscriber deleted successfully", + "saveSubscriberError": "Error adding subscriber", + "deleteSubscriberError": "Subscriber deletion error", + "delSubscriber": "Delete Subscriber" + }, + "table": { + "userName": "User name", + "value": "Value" + } + }, "countries": { "AF": "Afghanistan", "AL": "Albania", diff --git a/src/locales/ru-RU.json b/src/locales/ru-RU.json index 8bf5e8af..5188a898 100644 --- a/src/locales/ru-RU.json +++ b/src/locales/ru-RU.json @@ -209,6 +209,7 @@ "virtualMedia": "Виртуальные носители", "keyClear": "Удаление ключей", "specification": "Характеристики", + "transfer": "Настройки передачи информации", "pciDevices": "PCI-устройства" }, "pageChangePassword": { @@ -1151,6 +1152,50 @@ "deviceClass": "Класс девайса" } }, + "pageTransfer": { + "title": "Настройка передачи информации", + "description": "Настройте SNMP, SMTP и SYSLOG", + "saveSmtpSuсcess": "Настройки SMTP успешно сохранены.", + "saveSmtpError": "Ошибка сохранения настроек SMTP.", + "smtp": { + "smtpTitle": "Настройки SMTP", + "username": "Имя пользователя", + "password": "Пароль", + "email": "Email", + "host": "SMTP сервер", + "port": "SMTP порт", + "authorization": "Авторизация", + "sslEnabled": "Поддержка SSL", + "testMessage": "Тестовое сообщение", + "saveSubscriberSuсcess": "Подписчик успешно добавлен", + "deleteSubscriberSuсcess": "Подписчик успешно удален", + "saveSubscriberError": "Ошибка добавления подписчика", + "deleteSubscriberError": "Ошибка удаления подписчика", + "delSubscriber": "Удалить подписчика" + }, + "snmp": { + "snmpTitle": "Настройки SNMP", + "host": "SNMP сервер", + "port": "SNMP порт", + "saveSubscriberSuсcess": "Подписчик успешно добавлен", + "deleteSubscriberSuсcess": "Подписчик успешно удален", + "saveSubscriberError": "Ошибка добавления подписчика", + "deleteSubscriberError": "Ошибка удаления подписчика", + "delSubscriber": "Удалить подписчика" + }, + "syslog": { + "title": "Настройки SYSLOG", + "ip": "IP-адрес syslog сервера", + "port": "Syslog - порт", + "saveSettingsSuсcess": "Настройки успешно сохранены", + "saveSettingsError": "Ошибка сохранения настроек", + "status": "Статус" + }, + "table": { + "userName": "Имя пользователя", + "value": "Значение" + } + }, "countries": { "AF": "Афганистан", "AL": "Албания", diff --git a/src/store/index.js b/src/store/index.js index a4dd16ed..a9afa310 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -30,6 +30,9 @@ import PoliciesStore from './modules/SecurityAndAccess/PoliciesStore'; import FactoryResetStore from './modules/Operations/FactoryResetStore'; import KeyClearStore from './modules/Operations/KeyClearStore'; import PciStore from './modules/HardwareStatus/PciStore'; +import SmtpStore from './modules/Settings/SmtpStore'; +import SnmpStore from './modules/Settings/SnmpStore'; +import SyslogStore from './modules/Settings/SyslogStore'; import WebSocketPlugin from './plugins/WebSocketPlugin'; import DateTimeStore from './modules/Settings/DateTimeStore'; @@ -73,6 +76,9 @@ export default new Vuex.Store({ factoryReset: FactoryResetStore, keyClear: KeyClearStore, pciStore: PciStore, + smtpStore: SmtpStore, + snmpStore: SnmpStore, + syslogStore: SyslogStore, }, plugins: [WebSocketPlugin], }); diff --git a/src/store/modules/Settings/SmtpStore.js b/src/store/modules/Settings/SmtpStore.js new file mode 100644 index 00000000..195f245a --- /dev/null +++ b/src/store/modules/Settings/SmtpStore.js @@ -0,0 +1,100 @@ +import api from '@/store/api'; +import i18n from '@/i18n'; + +const SmtpStore = { + namespaced: true, + state: { + settings: {}, + subscribers: [], + }, + getters: { + settings: (state) => state.settings, + subscribers: (state) => state.subscribers, + }, + mutations: { + saveSettings: (state, data) => (state.settings = data), + setSubscribers: (state, data) => (state.subscribers = data), + }, + actions: { + async deleteSubscriber({ dispatch }, email) { + return await api + .get(`/redfish/v1/Smtp/DeleteMails&${email}`) + .then(async () => { + await dispatch('getSubscribers'); + return i18n.t('pageTransfer.smtp.deleteSubscriberSuсcess'); + }) + .catch((error) => { + console.log(error); + throw new Error(i18n.t('pageTransfer.smtp.deleteSubscriberError')); + }); + }, + + async addSubscriber({ dispatch }, payload) { + return await api + .get(`/redfish/v1/Smtp/AddMails&${payload.email}`) + .then(async () => { + await dispatch('getSubscribers'); + return i18n.t('pageTransfer.smtp.saveSubscriberSuсcess'); + }) + .catch((error) => { + console.log(error); + throw new Error(i18n.t('pageTransfer.smtp.saveSubscriberError')); + }); + }, + + async getSubscribers({ commit }) { + return await api + .get('/redfish/v1/Smtp/GetMails') + .then(({ data: { mails = [] } = {} }) => + mails.map((host) => { + return { + host, + }; + }) + ) + .then((subscribers) => commit('setSubscribers', subscribers)) + .catch((error) => { + console.log(error); + throw new Error(i18n.t('pageUserManagement.toast.errorLoadUsers')); + }); + }, + + async setSettings({ dispatch }, payload) { + let url = `/redfish/v1/Smtp/SetSettings`; + for (let key in payload) { + url += `&${key}=${payload[key]}`; + } + + return await api + .get(url) + .then(async () => { + await dispatch('getSettings'); + return i18n.t('pageTransfer.saveSmtpSuсcess'); + }) + .catch((error) => { + console.log(error); + throw new Error(i18n.t('pageTransfer.saveSmtpError')); + }); + }, + + async getSettings({ commit }) { + return await api + .get('/redfish/v1/Smtp/GetSettings') + .then(({ data = {} }) => { + commit('saveSettings', data); + }) + .catch((error) => console.log(error)); + }, + + async sendTestMessage(_, payload) { + let url = `/redfish/v1/Smtp/SendMail`; + for (let key in payload) { + url += `&${key}=${payload[key]}`; + } + + return await api.get(url); + }, + }, +}; + +export default SmtpStore; diff --git a/src/store/modules/Settings/SnmpStore.js b/src/store/modules/Settings/SnmpStore.js new file mode 100644 index 00000000..3fda494f --- /dev/null +++ b/src/store/modules/Settings/SnmpStore.js @@ -0,0 +1,73 @@ +import api from '@/store/api'; +import i18n from '@/i18n'; + +const SnmpStore = { + namespaced: true, + state: { subscribers: [] }, + getters: { subscribers: (state) => state.subscribers }, + mutations: { + setSubscribers: (state, data) => (state.subscribers = data), + }, + actions: { + async deleteSubscriber({ dispatch }, index) { + return await api + .delete(`/redfish/v1/EventService/Subscriptions/${index}`) + .then(async () => { + await dispatch('getSubscribers'); + return i18n.t('pageTransfer.snmp.deleteSubscriberSuсcess'); + }) + .catch((error) => { + console.log(error); + throw new Error(i18n.t('pageTransfer.snmp.deleteSubscriberError')); + }); + }, + async addSubscriber({ dispatch }, payload) { + return await api + .post('/redfish/v1/EventService/Subscriptions', payload) + .then(async () => { + await dispatch('getSubscribers'); + return i18n.t('pageTransfer.snmp.saveSubscriberSuсcess'); + }) + .catch((error) => { + console.log(error); + throw new Error(i18n.t('pageTransfer.snmp.saveSubscriberError')); + }); + }, + async getSubscribers({ commit }) { + return await api + .get('/redfish/v1/EventService/Subscriptions') + .then(({ data: { Members } }) => { + return Members.filter((member) => + member['@odata.id'].includes('snmp') + ); + }) + .then((members) => { + return api.all(members.map((member) => api.get(member['@odata.id']))); + }) + .then((subscribersRow) => { + return subscribersRow.map((subscriberRow) => { + return subscriberRow.data; + }); + }) + .then((data) => { + return data.map((subscriber) => { + const host = subscriber.Destination.split('/')[2].split(':')[0]; + const port = subscriber.Destination.split('/')[2].split(':')[1]; + return { + ...subscriber, + host, + port, + }; + }); + }) + .then((subscribers) => commit('setSubscribers', subscribers)) + .catch((error) => { + console.log(error); + const message = i18n.t('pageUserManagement.toast.errorLoadUsers'); + throw new Error(message); + }); + }, + }, +}; + +export default SnmpStore; diff --git a/src/store/modules/Settings/SyslogStore.js b/src/store/modules/Settings/SyslogStore.js new file mode 100644 index 00000000..f0b0eb59 --- /dev/null +++ b/src/store/modules/Settings/SyslogStore.js @@ -0,0 +1,36 @@ +import api from '@/store/api'; +import i18n from '@/i18n'; + +const SyslogStore = { + namespaced: true, + state: { settings: {} }, + getters: { settings: (state) => state.settings }, + mutations: { + saveSettings: (state, data) => (state.settings = data), + }, + actions: { + async saveSettings({ dispatch }, payload) { + return await api + .post('/redfish/v1/Syslog/Actions/Syslog.UpdateConfig', payload) + .then(async () => { + await dispatch('getSettings'); + return i18n.t('pageTransfer.syslog.saveSettingsSuсcess'); + }) + .catch((error) => { + console.log(error); + throw new Error(i18n.t('pageTransfer.syslog.saveSettingsError')); + }); + }, + + async getSettings({ commit }) { + return await api + .get('/redfish/v1/Syslog') + .then(({ data: { Configuration = {} } = {} }) => { + commit('saveSettings', Configuration); + }) + .catch((error) => console.log(error)); + }, + }, +}; + +export default SyslogStore; diff --git a/src/views/_sila/Overview/Overview.vue b/src/views/_sila/Overview/Overview.vue index 9f97fb3e..c3928789 100644 --- a/src/views/_sila/Overview/Overview.vue +++ b/src/views/_sila/Overview/Overview.vue @@ -5,6 +5,16 @@ <page-section :section-title="$t('pageOverview.systemInformation')" class="mb-1" + @overviewEventsComplete=" + () => { + console.log('как подключить веб камеру к ноутбуку'); + } + " + @overview-firmware-complete=" + () => { + console.log('как подключить веб камеру к ноутбуку'); + } + " > <b-card-group deck> <overview-server /> diff --git a/src/views/_sila/Settings/TransferInfo/ModalSmtp.vue b/src/views/_sila/Settings/TransferInfo/ModalSmtp.vue new file mode 100644 index 00000000..c3bdc493 --- /dev/null +++ b/src/views/_sila/Settings/TransferInfo/ModalSmtp.vue @@ -0,0 +1,98 @@ +<template> + <b-modal + id="modal-smtp" + ref="modal" + :title="$t('global.action.add')" + @hidden="resetForm" + > + <b-form id="form-smtp" @submit.prevent="handleSubmit"> + <b-row> + <b-col sm="6"> + <b-form-group + :label="$t('pageTransfer.smtp.email')" + label-for="smtpEmail" + > + <b-form-input + id="smtpEmail" + v-model="email" + type="text" + :state="getValidationState($v.email)" + data-test-id="smtp-input-email" + @input="$v.email.$touch()" + /> + <b-form-invalid-feedback role="alert"> + <template v-if="!$v.email.required"> + {{ $t('global.form.fieldRequired') }} + </template> + <template v-if="!$v.email.email"> + {{ $t('global.form.invalidFormat') }} + </template> + </b-form-invalid-feedback> + </b-form-group> + </b-col> + </b-row> + </b-form> + <template #modal-footer="{ cancel }"> + <b-button variant="secondary" @click="cancel()"> + {{ $t('global.action.cancel') }} + </b-button> + <b-button form="form-smtp" type="submit" variant="primary" @click="onOk"> + {{ $t('global.action.add') }} + </b-button> + </template> + </b-modal> +</template> + +<script> +import VuelidateMixin from '@/components/_sila/Mixins/VuelidateMixin.js'; +import { email, required } from 'vuelidate/lib/validators'; + +export default { + mixins: [VuelidateMixin], + data() { + return { + email: null, + }; + }, + validations() { + return { + email: { + required, + email, + }, + }; + }, + methods: { + handleSubmit() { + this.$v.$touch(); + if (this.$v.$invalid) return; + + this.$emit('ok', { + email: this.email, + }); + this.closeModal(); + }, + closeModal() { + this.$nextTick(() => { + this.$refs.modal.hide(); + }); + }, + resetForm() { + this.email = null; + this.$v.$reset(); + this.$emit('hidden'); + }, + onOk(bvModalEvt) { + // prevent modal close + bvModalEvt.preventDefault(); + this.handleSubmit(); + }, + }, +}; +</script> + +<style lang="scss" scoped> +.input-group-prepend + input { + padding-left: 70px !important; +} +</style> diff --git a/src/views/_sila/Settings/TransferInfo/ModalSnmp.vue b/src/views/_sila/Settings/TransferInfo/ModalSnmp.vue new file mode 100644 index 00000000..c54616a5 --- /dev/null +++ b/src/views/_sila/Settings/TransferInfo/ModalSnmp.vue @@ -0,0 +1,136 @@ +<template> + <b-modal + id="modal-snmp" + ref="modal" + :title="$t('global.action.add')" + @hidden="resetForm" + > + <b-form id="form-snmp" @submit.prevent="handleSubmit"> + <b-row> + <b-col sm="6"> + <b-form-group + :label="$t('pageTransfer.snmp.host')" + label-for="snmpHost" + > + <b-form-input + id="snmpHost" + v-model="host" + type="text" + :state="getValidationState($v.host)" + data-test-id="snmp-input-host" + @input="$v.host.$touch()" + /> + <b-form-invalid-feedback role="alert"> + <template v-if="!$v.host.required"> + {{ $t('global.form.fieldRequired') }} + </template> + <template v-if="!$v.host.ipAddress"> + {{ $t('global.form.invalidFormat') }} + </template> + </b-form-invalid-feedback> + </b-form-group> + </b-col> + <b-col sm="6"> + <b-form-group + :label="$t('pageTransfer.snmp.port')" + label-for="snmpPort" + > + <b-form-input + id="snmpPort" + v-model="port" + type="number" + :state="getValidationState($v.port)" + data-test-id="snmp-input-port" + @input="$v.port.$touch()" + /> + <b-form-invalid-feedback role="alert"> + <template v-if="!$v.port.required"> + {{ $t('global.form.fieldRequired') }} + </template> + <template v-if="!$v.port.pattern"> + {{ $t('global.form.invalidFormat') }} + </template> + </b-form-invalid-feedback> + </b-form-group> + </b-col> + </b-row> + </b-form> + <template #modal-footer="{ cancel }"> + <b-button variant="secondary" @click="cancel()"> + {{ $t('global.action.cancel') }} + </b-button> + <b-button form="form-snmp" type="submit" variant="primary" @click="onOk"> + {{ $t('global.action.add') }} + </b-button> + </template> + </b-modal> +</template> + +<script> +import VuelidateMixin from '@/components/_sila/Mixins/VuelidateMixin.js'; +import { helpers, ipAddress, required } from 'vuelidate/lib/validators'; +import { isoPortRegex } from '@/utilities/_sila/regexConstants'; + +export default { + mixins: [VuelidateMixin], + data() { + return { + form: { + Destination: null, + SubscriptionType: 'SNMPTrap', + Protocol: 'SNMPv2c', + Context: 'testContext', + }, + host: null, + port: null, + }; + }, + validations() { + return { + host: { + required, + ipAddress, + }, + port: { + required, + pattern: helpers.regex('pattern', isoPortRegex), + }, + }; + }, + methods: { + handleSubmit() { + this.$v.$touch(); + if (this.$v.$invalid) return; + + this.$emit('ok', { + ...this.form, + Destination: `snmp://${this.host}:${this.port}`, + }); + this.closeModal(); + }, + closeModal() { + this.$nextTick(() => { + this.$refs.modal.hide(); + }); + }, + resetForm() { + this.host = null; + this.port = null; + this.form.Destination = null; + this.$v.$reset(); + this.$emit('hidden'); + }, + onOk(bvModalEvt) { + // prevent modal close + bvModalEvt.preventDefault(); + this.handleSubmit(); + }, + }, +}; +</script> + +<style lang="scss" scoped> +.input-group-prepend + input { + padding-left: 70px !important; +} +</style> diff --git a/src/views/_sila/Settings/TransferInfo/Smtp.vue b/src/views/_sila/Settings/TransferInfo/Smtp.vue new file mode 100644 index 00000000..40a182d8 --- /dev/null +++ b/src/views/_sila/Settings/TransferInfo/Smtp.vue @@ -0,0 +1,414 @@ +<template> + <page-section :section-title="$t('pageTransfer.smtp.smtpTitle')"> + <b-row class="smtp-warning mb-5"> + <b-col xs="12" sm="12"> + <div class="switch-group"> + <label for="authenticationSwitch">{{ + $t('pageTransfer.smtp.authorization') + }}</label> + <b-form-checkbox + id="authenticationSwitch" + v-model="form.is_need_auth" + data-test-id="checkbox-authorization" + switch + :disabled="loading || isNotAdmin" + @change="onChangeAuthCheckbox($event)" + > + <span v-if="form.is_need_auth"> + {{ $t('global.status.enabled') }} + </span> + <span v-else>{{ $t('global.status.disabled') }}</span> + </b-form-checkbox> + </div> + </b-col> + <b-col xs="12" sm="6"> + <b-form-group + :label="$t('pageTransfer.smtp.username')" + label-for="smtp-name" + > + <b-form-input + id="smtp-name" + v-model="form.username" + type="text" + :state="getValidationState($v.form.username)" + :disabled="loading || isNotAdmin || !form.is_need_auth" + @input="$v.form.username.$touch()" + /> + <b-form-invalid-feedback role="alert"> + <template v-if="!$v.form.username.required"> + {{ $t('global.form.fieldRequired') }} + </template> + <template v-else-if="!$v.form.username.maxLength"> + {{ $t('global.form.lengthMustBeBetween', { min: 1, max: 16 }) }} + </template> + <template v-else-if="!$v.form.username.pattern"> + {{ $t('global.form.invalidFormat') }} + </template> + </b-form-invalid-feedback> + </b-form-group></b-col + > + <b-col xs="12" sm="6"> + <b-form-group + :label="$t('pageTransfer.smtp.password')" + label-for="smtp-password" + > + <input-password-toggle> + <b-form-input + id="smtp-password" + v-model="form.password" + type="password" + :state="getValidationState($v.form.password)" + :disabled="loading || isNotAdmin || !form.is_need_auth" + @input="$v.form.password.$touch()" + /> + <b-form-invalid-feedback role="alert"> + <template v-if="!$v.form.password.required"> + {{ $t('global.form.fieldRequired') }} + </template> + <template + v-if=" + !$v.form.password.minLength || !$v.form.password.maxLength + " + > + {{ + $t('pageUserManagement.modal.passwordMustBeBetween', { + min: 8, + max: 20, + }) + }} + </template> + </b-form-invalid-feedback> + </input-password-toggle> + </b-form-group> + </b-col> + <b-col xs="12" sm="6"> + <b-form-group + :label="$t('pageTransfer.smtp.host')" + label-for="smtp-host" + > + <b-form-input + id="smtp-host" + v-model="form.host" + :state="getValidationState($v.form.host)" + :disabled="loading || isNotAdmin" + @input="$v.form.host.$touch()" + /> + <b-form-invalid-feedback role="alert"> + <template v-if="!$v.form.host.required"> + {{ $t('global.form.fieldRequired') }} + </template> + <template v-if="!$v.form.host.ipAddress"> + {{ $t('global.form.invalidFormat') }} + </template> + </b-form-invalid-feedback> + </b-form-group> + </b-col> + <b-col xs="12" sm="6"> + <b-form-group + :label="$t('pageTransfer.smtp.port')" + label-for="smtp-port" + > + <b-form-input + id="smtp-port" + v-model="form.port" + type="number" + :state="getValidationState($v.form.port)" + :disabled="loading || isNotAdmin" + @input="$v.form.port.$touch()" + /> + <b-form-invalid-feedback role="alert"> + <template v-if="!$v.form.port.required"> + {{ $t('global.form.fieldRequired') }} + </template> + <template v-if="!$v.form.port.pattern"> + {{ $t('global.form.invalidFormat') }} + </template> + </b-form-invalid-feedback> + </b-form-group> + </b-col> + <b-col xs="12" sm="12"> + <div class="switch-group"> + <label for="sslSwitch">{{ + $t('pageTransfer.smtp.sslEnabled') + }}</label> + <b-form-checkbox + id="sslSwitch" + v-model="form.is_need_ssl" + data-test-id="checkbox-ssl" + switch + :disabled="isNotAdmin" + > + <span v-if="form.is_need_ssl"> + {{ $t('global.status.enabled') }} + </span> + <span v-else>{{ $t('global.status.disabled') }}</span> + </b-form-checkbox> + </div> + </b-col> + <b-col xs="4" class="d-flex justify-content-between align-items-start"> + <b-button + variant="secondary" + :disabled="loading || isNotAdmin" + @click="sendMail" + > + {{ $t('pageTransfer.smtp.testMessage') }} + </b-button> + + <b-button + variant="primary" + :disabled="loading || isNotAdmin" + @click="saveSmtp" + > + {{ $t('global.action.save') }} + </b-button> + </b-col> + </b-row> + <b-row> + <b-col> + <div class="text-right"> + <b-button + variant="primary" + :disabled="loading || isNotAdmin" + @click="initAddModal()" + > + <icon-add /> + {{ $t('global.action.add') }} + </b-button> + </div> + <b-table + responsive="md" + hover + :busy="loading" + :fields="fields" + :items="subscribers" + :empty-text="$t('global.table.emptyMessage')" + show-empty + > + <!-- 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" + @click-table-action="onTableAction($event, item)" + > + <template #icon> + <icon-trashcan + v-if="action.value === 'delete'" + :data-test-id="`smtp-tableRowAction-delete-${index}`" + /> + </template> + </table-row-action> + </template> + </b-table> + </b-col> + </b-row> + </page-section> +</template> + +<script> +import PageSection from '@/components/_sila/Global/PageSection'; +import BVToastMixin from '@/components/_sila/Mixins/BVToastMixin'; +import TableRowAction from '@/components/_sila/Global/TableRowAction'; +import LoadingBarMixin, { + loading, +} from '@/components/_sila/Mixins/LoadingBarMixin'; + +import IconAdd from '@carbon/icons-vue/es/add--alt/20'; +import IconTrashcan from '@carbon/icons-vue/es/trash-can/20'; +import InputPasswordToggle from '@/components/_sila/Global/InputPasswordToggle'; +import { + helpers, + ipAddress, + maxLength, + minLength, + required, + requiredIf, +} from 'vuelidate/lib/validators'; +import VuelidateMixin from '@/components/_sila/Mixins/VuelidateMixin.js'; +import { isoPortRegex } from '@/utilities/_sila/regexConstants'; + +export default { + name: 'Smtp', + components: { + IconAdd, + IconTrashcan, + PageSection, + TableRowAction, + InputPasswordToggle, + }, + mixins: [BVToastMixin, LoadingBarMixin, VuelidateMixin], + + data() { + return { + loading, + form: { + username: '', + password: '', + host: '', + port: '', + is_need_auth: false, + is_need_ssl: false, + }, + fields: [ + { + key: 'host', + label: this.$t('pageTransfer.table.userName'), + }, + { key: 'actions', label: '', tdClass: 'text-right' }, + ], + }; + }, + computed: { + settings() { + return this.$store.getters['smtpStore/settings']; + }, + subscribers() { + return this.$store.getters['smtpStore/subscribers'].map((subscriber) => { + return { + ...subscriber, + actions: [ + { + value: 'delete', + title: this.$t('pageTransfer.smtp.delSubscriber'), + }, + ], + }; + }); + }, + isNotAdmin() { + return ( + this.$store.getters['authentication/role'] === 'ReadOnly' || + this.$store.getters['authentication/role'] === 'Operator' + ); + }, + }, + watch: { + settings() { + this.setForm(); + }, + }, + created() { + this.startLoader(); + Promise.all([ + this.$store.dispatch('smtpStore/getSettings'), + this.$store.dispatch('smtpStore/getSubscribers'), + ]).finally(() => { + this.setForm(); + this.endLoader(); + }); + }, + validations() { + return { + form: { + username: { + required: requiredIf(function () { + return this.form.is_need_auth; + }), + maxLength: maxLength(16), + pattern: helpers.regex('pattern', /^([a-zA-Z_][a-zA-Z0-9_]*)/), + }, + password: { + required: requiredIf(function () { + return this.form.is_need_auth; + }), + minLength: minLength(8), + maxLength: maxLength(20), + }, + host: { + required, + ipAddress, + }, + port: { + required, + pattern: helpers.regex('pattern', isoPortRegex), + }, + }, + }; + }, + methods: { + onChangeAuthCheckbox($event) { + if (!$event) { + this.resetAuthForm(); + } + }, + onTableAction($event, { host }) { + if ($event === 'delete') { + this.deleteSubscriber(host); + } + }, + deleteSubscriber(host) { + this.startLoader(); + this.$store + .dispatch('smtpStore/deleteSubscriber', host) + .then((success) => this.successToast(success)) + .catch(({ message }) => this.errorToast(message)) + .finally(() => this.endLoader()); + }, + initAddModal() { + this.$bvModal.show('modal-smtp'); + }, + saveSmtp() { + this.$v.$touch(); + if (this.$v.$invalid) return; + + this.startLoader(); + if (!this.form.is_need_auth) { + // eslint-disable-next-line no-unused-vars + const { username, password, ...formWithoutCredits } = this.form; + this.form = formWithoutCredits; + } + + this.$store + .dispatch('smtpStore/setSettings', this.form) + .then((message) => this.successToast(message)) + .catch(({ message }) => this.errorToast(message)) + .finally(() => this.endLoader()); + }, + sendMail() { + this.$store + .dispatch('smtpStore/sendTestMessage', { + from: 'ex@mail.ru', + to: 'v.lysak@dunice.net', + subject: 'qwerty', + text: 'lol', + }) + .then((message) => this.successToast(message)) + .catch(({ message }) => this.errorToast(message)); + }, + setForm() { + if (!this.settings) { + return; + } + + this.form.username = this.settings.username; + this.form.password = this.settings.password; + this.form.host = this.settings.host; + this.form.port = this.settings.port; + this.form.is_need_auth = this.settings.is_need_auth; + this.form.is_need_ssl = this.settings.is_need_ssl; + }, + resetAuthForm() { + this.form.username = null; + this.form.password = null; + }, + }, +}; +</script> + +<style lang="scss" scoped> +.switch-group { + margin-bottom: 1.5rem; +} +.smtp-warning { + width: 50%; + @media (max-width: 1200px) { + width: 75%; + } + @media (max-width: 576px) { + width: 100%; + } +} +</style> diff --git a/src/views/_sila/Settings/TransferInfo/Snmp.vue b/src/views/_sila/Settings/TransferInfo/Snmp.vue new file mode 100644 index 00000000..ef9e18ac --- /dev/null +++ b/src/views/_sila/Settings/TransferInfo/Snmp.vue @@ -0,0 +1,139 @@ +<template> + <page-section :section-title="$t('pageTransfer.snmp.snmpTitle')"> + <b-row> + <b-col> + <div class="text-right"> + <b-button + variant="primary" + :disabled="loading || isNotAdmin" + @click="initAddModal()" + > + <icon-add /> + {{ $t('global.action.add') }} + </b-button> + </div> + <b-table + responsive="md" + hover + :busy="loading" + :fields="fields" + :items="subscribers" + :empty-text="$t('global.table.emptyMessage')" + show-empty + > + <!-- 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" + @click-table-action="onTableAction($event, item)" + > + <template #icon> + <icon-trashcan + v-if="action.value === 'delete'" + :data-test-id="`snmp-tableRowAction-delete-${index}`" + /> + </template> + </table-row-action> + </template> + </b-table> + </b-col> + </b-row> + </page-section> +</template> + +<script> +import PageSection from '@/components/_sila/Global/PageSection'; +import BVToastMixin from '@/components/_sila/Mixins/BVToastMixin'; +import TableRowAction from '@/components/_sila/Global/TableRowAction'; +import LoadingBarMixin, { + loading, +} from '@/components/_sila/Mixins/LoadingBarMixin'; + +import IconAdd from '@carbon/icons-vue/es/add--alt/20'; +import IconTrashcan from '@carbon/icons-vue/es/trash-can/20'; + +export default { + name: 'Snmp', + components: { + IconAdd, + IconTrashcan, + PageSection, + TableRowAction, + }, + mixins: [BVToastMixin, LoadingBarMixin], + + data() { + return { + loading, + actions: [ + { + value: 'delete', + title: this.$t('global.action.delete'), + }, + ], + fields: [ + { + key: 'host', + label: this.$t('pageTransfer.snmp.host'), + }, + { + key: 'port', + label: this.$t('pageTransfer.snmp.port'), + }, + { key: 'actions', label: '', tdClass: 'text-right' }, + ], + }; + }, + computed: { + subscribers() { + return this.$store.getters['snmpStore/subscribers'].map((subscriber) => { + return { + ...subscriber, + actions: [ + { + value: 'delete', + title: this.$t('pageTransfer.snmp.delSubscriber'), + }, + ], + }; + }); + }, + isNotAdmin() { + return ( + this.$store.getters['authentication/role'] === 'ReadOnly' || + this.$store.getters['authentication/role'] === 'Operator' + ); + }, + }, + + created() { + this.startLoader(); + this.$store.dispatch('snmpStore/getSubscribers').finally(() => { + this.endLoader(); + }); + }, + + methods: { + onTableAction($event, { Id }) { + if ($event === 'delete') { + this.deleteSubscriber(Id); + } + }, + deleteSubscriber(index) { + this.startLoader(); + this.$store + .dispatch('snmpStore/deleteSubscriber', index) + .then((success) => this.successToast(success)) + .catch(({ message }) => this.errorToast(message)) + .finally(() => this.endLoader()); + }, + initAddModal() { + this.$bvModal.show('modal-snmp'); + }, + }, +}; +</script> diff --git a/src/views/_sila/Settings/TransferInfo/Syslog.vue b/src/views/_sila/Settings/TransferInfo/Syslog.vue new file mode 100644 index 00000000..07884de5 --- /dev/null +++ b/src/views/_sila/Settings/TransferInfo/Syslog.vue @@ -0,0 +1,220 @@ +<template> + <page-section :section-title="$t('pageTransfer.syslog.title')"> + <b-row class="mt-4 justify-content-end syslog-warning"> + <b-col xs="12" sm="12"> + <div class="switch-group"> + <label for="statusSwitch">{{ + $t('pageTransfer.syslog.status') + }}</label> + <b-form-checkbox + id="statusSwitch" + v-model="syslogStatus" + data-test-id="checkbox-status" + switch + :disabled="loading || isNotAdmin" + @change="onChangeStatusCheckbox($event)" + > + <span v-if="syslogStatus"> + {{ $t('global.status.enabled') }} + </span> + <span v-else>{{ $t('global.status.disabled') }}</span> + </b-form-checkbox> + </div> + </b-col> + <b-col xs="12" sm="6"> + <b-form-group + :label="$t('pageTransfer.syslog.ip')" + label-for="syslog-ip" + > + <b-form-input + id="syslog-ip" + v-model="form.Address" + :state="getValidationState($v.form.Address)" + :disabled="!syslogStatus || loading || isNotAdmin" + @input="$v.form.Address.$touch()" + /> + <b-form-invalid-feedback role="alert"> + <template v-if="!$v.form.Address.required"> + {{ $t('global.form.fieldRequired') }} + </template> + <template v-if="!$v.form.Address.ipAddress"> + {{ $t('global.form.invalidFormat') }} + </template> + </b-form-invalid-feedback> + </b-form-group> + </b-col> + <b-col xs="12" sm="6"> + <b-form-group + :label="$t('pageTransfer.syslog.port')" + label-for="syslog-port" + > + <b-form-input + id="syslog-port" + v-model="form.Port" + type="number" + :state="getValidationState($v.form.Port)" + :disabled="!syslogStatus || loading || isNotAdmin" + @input="$v.form.Address.$touch()" + /> + <b-form-invalid-feedback role="alert"> + <template v-if="!$v.form.Port.required"> + {{ $t('global.form.fieldRequired') }} + </template> + <template v-if="!$v.form.Port.pattern"> + {{ $t('global.form.invalidFormat') }} + </template> + </b-form-invalid-feedback> + </b-form-group> + </b-col> + <b-col xs="4" class="d-flex justify-content-end align-items-start"> + <b-button + variant="primary" + :disabled="loading || isNotAdmin" + @click="saveSyslog" + > + {{ $t('global.action.save') }} + </b-button> + </b-col> + </b-row> + </page-section> +</template> + +<script> +import PageSection from '@/components/_sila/Global/PageSection'; +import BVToastMixin from '@/components/_sila/Mixins/BVToastMixin'; +import LoadingBarMixin, { + loading, +} from '@/components/_sila/Mixins/LoadingBarMixin'; + +import { helpers, ipAddress, requiredIf } from 'vuelidate/lib/validators'; +import VuelidateMixin from '@/components/_sila/Mixins/VuelidateMixin.js'; +import { isoPortRegex } from '@/utilities/_sila/regexConstants'; + +export default { + name: 'Syslog', + components: { + PageSection, + }, + mixins: [BVToastMixin, LoadingBarMixin, VuelidateMixin], + + data() { + return { + loading, + syslogStatus: false, + form: { + Address: null, + Port: null, + }, + }; + }, + computed: { + settings() { + return this.$store.getters['syslogStore/settings']; + }, + isNotAdmin() { + return ( + this.$store.getters['authentication/role'] === 'ReadOnly' || + this.$store.getters['authentication/role'] === 'Operator' + ); + }, + }, + + watch: { + settings() { + this.setForm(); + }, + }, + + created() { + this.startLoader(); + this.$store.dispatch('syslogStore/getSettings').finally(() => { + this.setForm(); + this.endLoader(); + }); + }, + + validations() { + return { + form: { + Address: { + required: requiredIf(function () { + return this.syslogStatus; + }), + ipAddress, + }, + Port: { + required: requiredIf(function () { + return this.syslogStatus; + }), + pattern: helpers.regex('pattern', isoPortRegex), + }, + }, + }; + }, + + methods: { + onChangeStatusCheckbox($event) { + if (!$event) { + this.resetForm(); + } + }, + saveSyslog() { + this.$v.$touch(); + if (this.$v.$invalid) return; + + this.startLoader(); + if (!this.syslogStatus) { + this.form = { + Address: '', + Port: 0, + }; + } + + this.form.Port = +this.form.Port; + this.$store + .dispatch('syslogStore/saveSettings', this.form) + .then((success) => this.successToast(success)) + .catch(({ message }) => this.errorToast(message)) + .finally(() => this.endLoader()); + }, + + setForm() { + if (!this.settings) { + return; + } + + const isOff = !this.settings.Address && this.settings.Port === 0; + + if (isOff) { + this.syslogStatus = false; + this.form.Address = null; + this.form.Port = null; + } else { + this.syslogStatus = true; + this.form.Address = this.settings.Address; + this.form.Port = this.settings.Port; + } + }, + + resetForm() { + this.form.Address = null; + this.form.Port = null; + }, + }, +}; +</script> + +<style lang="scss" scoped> +.switch-group { + margin-bottom: 1.5rem; +} +.syslog-warning { + width: 50%; + @media (max-width: 1200px) { + width: 75%; + } + @media (max-width: 576px) { + width: 100%; + } +} +</style> diff --git a/src/views/_sila/Settings/TransferInfo/Transfer.vue b/src/views/_sila/Settings/TransferInfo/Transfer.vue new file mode 100644 index 00000000..4b70778b --- /dev/null +++ b/src/views/_sila/Settings/TransferInfo/Transfer.vue @@ -0,0 +1,64 @@ +<template> + <b-container fluid="xl"> + <page-title :description="$t('pageTransfer.description')" /> + <snmp /> + <hr /> + <smtp /> + <hr /> + <syslog /> + <hr /> + <modal-snmp @ok="saveSnmp" /> + <modal-smtp @ok="saveSmtp" /> + </b-container> +</template> + +<script> +import BVToastMixin from '@/components/_sila/Mixins/BVToastMixin'; +import LoadingBarMixin, { + loading, +} from '@/components/_sila/Mixins/LoadingBarMixin'; + +import PageTitle from '@/components/_sila/Global/PageTitle'; +import Snmp from './Snmp'; +import Smtp from './Smtp'; +import ModalSnmp from './ModalSnmp.vue'; +import ModalSmtp from './ModalSmtp.vue'; +import Syslog from './Syslog'; + +export default { + name: 'PowerRestorePolicy', + components: { + PageTitle, + Snmp, + ModalSnmp, + Smtp, + ModalSmtp, + Syslog, + }, + mixins: [BVToastMixin, LoadingBarMixin], + data() { + return { + loading, + }; + }, + methods: { + saveSnmp(modalFormData) { + this.startLoader(); + this.$store + .dispatch('snmpStore/addSubscriber', modalFormData) + .then((message) => this.successToast(message)) + .catch(({ message }) => this.errorToast(message)) + .finally(() => this.endLoader()); + }, + + saveSmtp(modalFormData) { + this.startLoader(); + this.$store + .dispatch('smtpStore/addSubscriber', modalFormData) + .then((message) => this.successToast(message)) + .catch(({ message }) => this.errorToast(message)) + .finally(() => this.endLoader()); + }, + }, +}; +</script> diff --git a/src/views/_sila/Settings/TransferInfo/WarningSmnp.vue b/src/views/_sila/Settings/TransferInfo/WarningSmnp.vue new file mode 100644 index 00000000..df97d1a1 --- /dev/null +++ b/src/views/_sila/Settings/TransferInfo/WarningSmnp.vue @@ -0,0 +1,57 @@ +<template> + <page-section section-title="Предупреждения SNmP"> + <b-row> + <b-col> + <b-table + hover + responsive="md" + show-empty + :items="items" + :fields="fields" + :empty-text="$t('global.table.emptyMessage')" + > + </b-table> + </b-col> + </b-row> + <b-row> + <b-col class="d-flex justify-content-end flex-wrap"> + <b-button variant="secondary" class="mr-3 mb-3"> + {{ 'Тестовое сообщение' }} + </b-button> + <b-button variant="primary" class="mb-3"> + {{ $t('global.action.save') }} + </b-button> + </b-col> + </b-row> + </page-section> +</template> + +<script> +import PageSection from '@/components/_sila/Global/PageSection'; + +export default { + name: 'WarningSmnp', + components: { + PageSection, + }, + + data() { + return { + fields: [ + { + key: 'id', + label: 'Тип предупреждения', + formatter: this.dataFormatter, + }, + { + key: 'health', + label: 'Значение', + formatter: this.dataFormatter, + tdClass: 'text-nowrap', + }, + ], + }; + }, + computed: {}, +}; +</script> diff --git a/src/views/_sila/Settings/TransferInfo/index.js b/src/views/_sila/Settings/TransferInfo/index.js new file mode 100644 index 00000000..50508f66 --- /dev/null +++ b/src/views/_sila/Settings/TransferInfo/index.js @@ -0,0 +1,2 @@ +import Transfer from './Transfer.vue'; +export default Transfer; |