diff --git a/ui/src/components/SCV/ScvInputIcon.vue b/ui/src/components/SCV/ScvInputIcon.vue index 85d204e33f08..50118a75f98b 100644 --- a/ui/src/components/SCV/ScvInputIcon.vue +++ b/ui/src/components/SCV/ScvInputIcon.vue @@ -2,16 +2,23 @@ + + + diff --git a/ui/src/components/SnmpConfiguration/SnmpConfigDetailsPanel.vue b/ui/src/components/SnmpConfiguration/SnmpConfigDetailsPanel.vue index ea6aa8b5d8b8..2ef3ebb73299 100644 --- a/ui/src/components/SnmpConfiguration/SnmpConfigDetailsPanel.vue +++ b/ui/src/components/SnmpConfiguration/SnmpConfigDetailsPanel.vue @@ -36,10 +36,15 @@
- + +
@@ -189,14 +193,12 @@ import { FeatherButton } from '@featherds/button' import { FeatherCheckbox } from '@featherds/checkbox' import { FeatherExpansionPanel } from '@featherds/expansion' -import MoreVert from '@featherds/icon/navigation/MoreVert' import { FeatherInput } from '@featherds/input' import { FeatherSelect, ISelectItemType } from '@featherds/select' -import { DEFAULT_SNMP_V3_SECURITY_LEVEL } from '@/lib/constants' +import { DEFAULT_MONITORING_LOCATION, DEFAULT_SNMP_V3_SECURITY_LEVEL } from '@/lib/constants' import { getDefaultSnmpBaseConfiguration, useSnmpConfigStore } from '@/stores/snmpConfigStore' import { SnmpAgentConfig, SnmpBaseConfiguration, SnmpConfigFormErrors, SnmpFieldInfo } from '@/types/snmpConfig' -import { validateDefinition } from '@/lib/snmpValidator' -import SnmpConfigMonitoringLocationsDropdown from './SnmpConfigMonitoringLocationsDropdown.vue' +import { validateDefinition, SecurityLevelSelectionOptions, SnmpAuthProtocols, SnmpPrivacyProtocols } from '@/lib/snmpValidator' import SnmpConfigPairedFieldInputs from './SnmpConfigPairedFieldInputs.vue' import ScvSearchDrawer from '../SCV/ScvSearchDrawer.vue' import { ScvSearchItem } from '@/types/scv' @@ -231,7 +233,7 @@ const errors = ref({}) // local data for form inputs const firstIpAddress = ref('') const lastIpAddress = ref('') -const selectedMonitoringLocation = ref() +const selectedMonitoringLocation = ref({ _text: DEFAULT_MONITORING_LOCATION, _value: DEFAULT_MONITORING_LOCATION }) const formConfig = reactive(getDefaultSnmpBaseConfiguration()) const scvSearchDrawerOpen = ref(false) const scvSelectedProperty = ref('') @@ -241,6 +243,15 @@ const snmpV3Expanded = ref(false) const displayAdvancedConfig = ref(false) const displaySnmpV3ContextFields = ref(false) +const monitoringLocations = computed(() => { + return store.monitoringLocations.map(loc => { + return { + _text: loc.name, + _value: loc.name + } + }) +}) + const displaySnmp2Params = computed(() => { const version = String(snmpVersion.value?._value || '') return version === 'v1' || version === 'v2c' @@ -251,7 +262,7 @@ const displaySnmp3Params = computed(() => { return version === 'v3' }) -// Field metadata for v-for rendering +// Field metadata for v-for rendering using SnmpConfigPairedFieldInputs const generalParamFields: SnmpFieldInfo[] = [ { key: 'timeout', label: 'Timeout', hint: 'Timeout in milliseconds', dataTest: 'snmp-definition-timeout', isNumeric: true }, { key: 'retry', label: 'Retries', hint: 'Number of retries', dataTest: 'snmp-definition-retry', isNumeric: true } @@ -273,11 +284,20 @@ const snmpV2Fields: SnmpFieldInfo[] = [ const snmpV3Fields: SnmpFieldInfo[] = [ { key: 'securityName', label: 'Security Name', hint: 'SNMP v3 security name', dataTest: 'snmp-definition-security-name', scvEnabled: true }, - { key: 'securityLevel', label: 'Security Level', hint: 'SNMP v3 security level', dataTest: 'snmp-definition-security-level', isNumeric: true }, + { + key: 'securityLevel', label: 'Security Level', hint: 'SNMP v3 security level', dataTest: 'snmp-definition-security-level', isNumeric: true, + isSelect: true, selectOptions: SecurityLevelSelectionOptions + }, { key: 'authPassphrase', label: 'Auth Passphrase', hint: 'Authentication passphrase', dataTest: 'snmp-definition-auth-passphrase', scvEnabled: true }, - { key: 'authProtocol', label: 'Auth Protocol', hint: 'Authentication protocol', dataTest: 'snmp-definition-auth-protocol' }, + { + key: 'authProtocol', label: 'Auth Protocol', hint: 'Authentication protocol', dataTest: 'snmp-definition-auth-protocol', + isSelect: true, selectOptions: SnmpAuthProtocols.map(protocol => ({ _text: protocol, _value: protocol })) + }, { key: 'privacyPassphrase', label: 'Privacy Passphrase', hint: 'Privacy passphrase', dataTest: 'snmp-definition-privacy-passphrase', scvEnabled: true }, - { key: 'privacyProtocol', label: 'Privacy Protocol', hint: 'Privacy protocol', dataTest: 'snmp-definition-privacy-protocol' } + { + key: 'privacyProtocol', label: 'Privacy Protocol', hint: 'Privacy protocol', dataTest: 'snmp-definition-privacy-protocol', + isSelect: true, selectOptions: SnmpPrivacyProtocols.map(protocol => ({ _text: protocol, _value: protocol })) + } ] const snmpV3ContextFields: SnmpFieldInfo[] = [ @@ -287,10 +307,6 @@ const snmpV3ContextFields: SnmpFieldInfo[] = [ { key: 'enterpriseId', label: 'Enterprise ID', hint: 'Enterprise ID', dataTest: 'snmp-definition-enterprise-id' } ] -const selectedMonitoringLocationValue = computed(() => { - return String(selectedMonitoringLocation.value?._value ?? '') -}) - const loadInitialValues = () => { const currentConfig: SnmpAgentConfig = props.config ?? getDefaultSnmpBaseConfiguration() @@ -304,8 +320,7 @@ const loadInitialValues = () => { firstIpAddress.value = props.firstIp || '' lastIpAddress.value = props.lastIp || '' - const matchedLoc = store.monitoringLocations.find(x => x.name === currentConfig.location) - selectedMonitoringLocation.value = matchedLoc ? { _text: matchedLoc.name, _value: matchedLoc.name } : undefined + selectedMonitoringLocation.value = { _text: DEFAULT_MONITORING_LOCATION, _value: DEFAULT_MONITORING_LOCATION } // Load all config fields into formConfig Object.assign(formConfig, { diff --git a/ui/src/components/SnmpConfiguration/SnmpConfigLookupPanel.vue b/ui/src/components/SnmpConfiguration/SnmpConfigLookupPanel.vue index f824f99448ea..0e265ab1dcc7 100644 --- a/ui/src/components/SnmpConfiguration/SnmpConfigLookupPanel.vue +++ b/ui/src/components/SnmpConfiguration/SnmpConfigLookupPanel.vue @@ -29,11 +29,16 @@
- -
+ + +
@@ -56,18 +61,17 @@ diff --git a/ui/src/components/SnmpConfiguration/SnmpConfigPairedFieldInputs.vue b/ui/src/components/SnmpConfiguration/SnmpConfigPairedFieldInputs.vue index 5e3d2408f869..b4b0b4058921 100644 --- a/ui/src/components/SnmpConfiguration/SnmpConfigPairedFieldInputs.vue +++ b/ui/src/components/SnmpConfiguration/SnmpConfigPairedFieldInputs.vue @@ -10,10 +10,31 @@
+ +
+
+ + +
+
+
+ +
+
+
+ - + + +
@@ -33,6 +62,7 @@ diff --git a/ui/src/components/SnmpConfiguration/SnmpConfigTabContainer.vue b/ui/src/components/SnmpConfiguration/SnmpConfigTabContainer.vue index 5e055189b905..7666f41099fa 100644 --- a/ui/src/components/SnmpConfiguration/SnmpConfigTabContainer.vue +++ b/ui/src/components/SnmpConfiguration/SnmpConfigTabContainer.vue @@ -6,8 +6,8 @@ > diff --git a/ui/src/containers/SnmpConfiguration.vue b/ui/src/containers/SnmpConfiguration.vue index 6b122b66fa00..d1c6b6ad0504 100644 --- a/ui/src/containers/SnmpConfiguration.vue +++ b/ui/src/containers/SnmpConfiguration.vue @@ -62,6 +62,7 @@ const breadcrumbs = computed(() => { const onCreateDefinition = () => { store.setDefinitionCreateEditMode(SnmpConfigEditMode.Create) + store.resetCurrentDefinition() store.setActiveTab(ActiveTabs.Definitions) } @@ -71,6 +72,7 @@ const onCreateProfile = () => { } onMounted(async () => { + store.resetState() store.fetchMonitoringLocations() store.populateSnmpConfig() scvStore.getAliases() diff --git a/ui/src/lib/snmpValidator.ts b/ui/src/lib/snmpValidator.ts index e131d2cea7c4..5bf8c1a79696 100644 --- a/ui/src/lib/snmpValidator.ts +++ b/ui/src/lib/snmpValidator.ts @@ -30,7 +30,13 @@ const MIN_PORT = 1 const MAX_PORT = 65535 const MAX_REQUEST_SIZE_MINIMUM = 484 -const SnmpAuthProtocols = [ +export const SecurityLevelSelectionOptions = [ + { _text: 'No Auth (1)', _value: String(SnmpSecurityLevel.NoAuthNoPriv) }, + { _text: 'Auth Only (2)', _value: String(SnmpSecurityLevel.AuthNoPriv) }, + { _text: 'Auth and Privacy (3)', _value: String(SnmpSecurityLevel.AuthPriv) } +] + +export const SnmpAuthProtocols = [ 'MD5', 'SHA', 'SHA-224', @@ -38,7 +44,7 @@ const SnmpAuthProtocols = [ 'SHA-512' ] -const SnmpPrivacyProtocols = [ +export const SnmpPrivacyProtocols = [ 'DES', 'AES', 'AES192', diff --git a/ui/src/stores/snmpConfigStore.ts b/ui/src/stores/snmpConfigStore.ts index 2ed1f9b24b1d..943026567020 100644 --- a/ui/src/stores/snmpConfigStore.ts +++ b/ui/src/stores/snmpConfigStore.ts @@ -199,6 +199,20 @@ export const useSnmpConfigStore = defineStore('useSnmpConfigStore', () => { currentDefinition.value = definition } + const resetCurrentDefinition = () => { + currentDefinition.value = getDefaultSnmpDefinition() + } + + const resetState = () => { + isLoading.value = false + setActiveTab(0) + resetCurrentDefinition() + setDefinitionCreateEditMode(SnmpConfigEditMode.Table) + setSnmpLookupEditMode(SnmpLookupEditMode.Lookup) + setProfileLabel('') + setSnmpProfileEditMode(SnmpConfigEditMode.Table) + } + const setProfileLabel = (label: string) => { profileLabel.value = label } @@ -260,13 +274,11 @@ export const useSnmpConfigStore = defineStore('useSnmpConfigStore', () => { } as SnmpConfigInfoDto const resp = await saveSnmpDefinition(dto) - return resp } const removeDefinition = async (ipAddress: string, location: string): Promise => { const resp = await deleteSnmpDefinition(ipAddress, location) - return resp } @@ -300,13 +312,11 @@ export const useSnmpConfigStore = defineStore('useSnmpConfigStore', () => { } as SnmpSaveProfileDto const resp = await saveSnmpProfile(dto) - return resp } const deleteProfile = async (label: string): Promise => { const resp = await deleteSnmpProfile(label) - return resp } @@ -326,6 +336,8 @@ export const useSnmpConfigStore = defineStore('useSnmpConfigStore', () => { saveDefinition, saveProfile, setActiveTab, + resetCurrentDefinition, + resetState, setCurrentDefinition, setDefinitionCreateEditMode, setProfileLabel, diff --git a/ui/src/types/snmpConfig.ts b/ui/src/types/snmpConfig.ts index 3c14381030f9..5ade2fa6c2a0 100644 --- a/ui/src/types/snmpConfig.ts +++ b/ui/src/types/snmpConfig.ts @@ -20,6 +20,8 @@ /// License. /// +import { ISelectItemType } from '@featherds/select' + export enum SnmpSecurityLevel { None = 0, NoAuthNoPriv = 1, @@ -189,11 +191,26 @@ export interface SnmpProfileFormErrors extends SnmpConfigFormErrors { label?: string filterExpression?: string } + +// Used for defining the fields for the SnmpConfigPairedFieldInputs component export interface SnmpFieldInfo { + // The key for the field, used to bind to the config object key: string + label: string hint?: string dataTest: string + + // if true, the field will display an SCV input icon scvEnabled?: boolean + + // true if the underlying value is numeric isNumeric?: boolean + + // true if the field is a select dropdown + isSelect?: boolean + + // options for the select dropdown. _text is display label, _value is the underlying value. + // _value should be a string even if isNumeric is true + selectOptions?: ISelectItemType[] }