diff --git a/package-lock.json b/package-lock.json index b68d049..7b80cea 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "wlan-cloud-owprov-ui", - "version": "2.11.0(29)", + "version": "2.11.0(37)", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "wlan-cloud-owprov-ui", - "version": "2.11.0(29)", + "version": "2.11.0(37)", "license": "ISC", "dependencies": { "@chakra-ui/anatomy": "^2.1.1", diff --git a/package.json b/package.json index 3a70936..cefbaba 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wlan-cloud-owprov-ui", - "version": "2.11.0(29)", + "version": "2.11.0(37)", "description": "", "main": "index.tsx", "scripts": { diff --git a/src/pages/ConfigurationPage/ConfigurationCard/ConfigurationSectionsCard/InterfaceSection/SingleInterface/SsidList/AdvancedSettings.tsx b/src/pages/ConfigurationPage/ConfigurationCard/ConfigurationSectionsCard/InterfaceSection/SingleInterface/SsidList/AdvancedSettings.tsx index f50f831..3a9b983 100644 --- a/src/pages/ConfigurationPage/ConfigurationCard/ConfigurationSectionsCard/InterfaceSection/SingleInterface/SsidList/AdvancedSettings.tsx +++ b/src/pages/ConfigurationPage/ConfigurationCard/ConfigurationSectionsCard/InterfaceSection/SingleInterface/SsidList/AdvancedSettings.tsx @@ -165,6 +165,13 @@ const AdvancedSettings: React.FC<{ editing: boolean; namePrefix: string }> = ({ isDisabled={!editing} emptyIsUndefined /> + {!NO_MULTI_PROTOS.includes(proto as string) && ( { radius: INTERFACE_SSID_RADIUS_SCHEMA(t), 'pass-point': INTERFACE_SSID_PASS_POINT_SCHEMA(t), 'dtim-period': number().moreThan(0).lessThan(256).integer().default(2), + 'tip-information-element': bool().default(true), }); return useDefault ? shape : shape.nullable().default(undefined); diff --git a/src/pages/ConfigurationPage/ConfigurationCard/ConfigurationSectionsCard/ServicesSection/DhcpRelay.tsx b/src/pages/ConfigurationPage/ConfigurationCard/ConfigurationSectionsCard/ServicesSection/DhcpRelay.tsx new file mode 100644 index 0000000..f9da4cb --- /dev/null +++ b/src/pages/ConfigurationPage/ConfigurationCard/ConfigurationSectionsCard/ServicesSection/DhcpRelay.tsx @@ -0,0 +1,178 @@ +import * as React from 'react'; +import { Box, Flex, Heading, SimpleGrid } from '@chakra-ui/react'; +import { SERVICES_DHCP_RELAY_VLAN_SCHEMA } from './servicesConstants'; +import Card from 'components/Card'; +import CardBody from 'components/Card/CardBody'; +import CardHeader from 'components/Card/CardHeader'; +import MultiSelectField from 'components/FormFields/MultiSelectField'; +import NumberField from 'components/FormFields/NumberField'; +import ObjectArrayFieldModal from 'components/FormFields/ObjectArrayFieldModal'; +import SelectField from 'components/FormFields/SelectField'; +import StringField from 'components/FormFields/StringField'; + +type Props = { + isEditing: boolean; +}; + +const selectPortsOptions = [ + { + value: '*', + label: 'All', + }, + { + value: 'WAN*', + label: 'WAN*', + }, + { + value: 'LAN*', + label: 'LAN*', + }, + { + value: 'LAN1', + label: 'LAN1', + }, + { + value: 'LAN2', + label: 'LAN2', + }, + { + value: 'LAN3', + label: 'LAN3', + }, + { + value: 'LAN4', + label: 'LAN4', + }, + { + value: 'LAN5', + label: 'LAN5', + }, + { + value: 'LAN6', + label: 'LAN6', + }, + { + value: 'LAN7', + label: 'LAN7', + }, + { + value: 'LAN8', + label: 'LAN8', + }, + { + value: 'LAN9', + label: 'LAN9', + }, + { + value: 'LAN10', + label: 'LAN10', + }, + { + value: 'LAN11', + label: 'LAN11', + }, + { + value: 'LAN12', + label: 'LAN12', + }, +]; + +const DhcpRelay = ({ isEditing }: Props) => { + const columns = React.useMemo( + () => [ + { + id: 'vlan', + Header: 'Vlan ID', + Footer: '', + accessor: 'vlan', + customWidth: '40px', + }, + { + id: 'circuit-id-format', + Header: 'Circuit ID Format', + Footer: '', + accessor: 'circuit-id-format', + }, + { + id: 'remote-id-format', + Header: 'Remote ID Format', + Footer: '', + accessor: 'remote-id-format', + }, + { + id: 'relay-server', + Header: 'Relay Server', + Footer: '', + accessor: 'relay-server', + }, + ], + [], + ); + + return ( + + + + DHCP Relay + + + + + + + + + + + + + + + + + + + + } + columns={columns} + schema={SERVICES_DHCP_RELAY_VLAN_SCHEMA} + isDisabled={!isEditing} + isRequired + /> + + + + ); +}; + +export default DhcpRelay; diff --git a/src/pages/ConfigurationPage/ConfigurationCard/ConfigurationSectionsCard/ServicesSection/index.jsx b/src/pages/ConfigurationPage/ConfigurationCard/ConfigurationSectionsCard/ServicesSection/index.jsx index a4ac817..be20938 100644 --- a/src/pages/ConfigurationPage/ConfigurationCard/ConfigurationSectionsCard/ServicesSection/index.jsx +++ b/src/pages/ConfigurationPage/ConfigurationCard/ConfigurationSectionsCard/ServicesSection/index.jsx @@ -11,6 +11,7 @@ import SubSectionPicker from '../common/SubSectionPicker'; import AirtimePolicies from './AirtimePolicies'; import Captive from './Captive'; import DataPlane from './DataPlane'; +import DhcpRelay from './DhcpRelay'; import FacebookWifi from './FacebookWifi'; import Gps from './Gps'; import Http from './Http'; @@ -125,6 +126,7 @@ const ServicesSection = ({ editing, setSection, sectionInformation, removeSub }) 'airtime-policies', 'captive', 'data-plane', + 'dhcp-relay', 'facebook-wifi', 'gps', 'http', @@ -149,6 +151,7 @@ const ServicesSection = ({ editing, setSection, sectionInformation, removeSub }) {isSubSectionActive('airtime-policies') && } {isSubSectionActive('captive') && } {isSubSectionActive('data-plane') && } + {isSubSectionActive('dhcp-relay') && } {isSubSectionActive('facebook-wifi') && } {isSubSectionActive('gps') && } {isSubSectionActive('http') && } diff --git a/src/pages/ConfigurationPage/ConfigurationCard/ConfigurationSectionsCard/ServicesSection/servicesConstants.js b/src/pages/ConfigurationPage/ConfigurationCard/ConfigurationSectionsCard/ServicesSection/servicesConstants.js index b52b391..f36159d 100644 --- a/src/pages/ConfigurationPage/ConfigurationCard/ConfigurationSectionsCard/ServicesSection/servicesConstants.js +++ b/src/pages/ConfigurationPage/ConfigurationCard/ConfigurationSectionsCard/ServicesSection/servicesConstants.js @@ -1,6 +1,26 @@ import { object, number, string, array, bool } from 'yup'; import { testFqdnHostname, testIpv4, testLength, testUcMac } from 'constants/formTests'; +export const SERVICES_DHCP_RELAY_VLAN_SCHEMA = (t, useDefault = false) => { + const shape = object().shape({ + vlan: number().required(t('form.required')).moreThan(-1).lessThan(4097).integer().default(1), + 'relay-server': string().required(t('form.required')).default(''), + 'circuit-id-format': string().required(t('form.required')).default('vlan-id'), + 'remote-id-format': string().required(t('form.required')).default('ap-mac'), + }); + + return useDefault ? shape : shape.nullable().default(undefined); +}; + +export const SERVICES_DHCP_RELAY_SCHEMA = (t, useDefault = false) => { + const shape = object().shape({ + 'select-ports': array().of(string()).min(1, t('form.required')).default([]), + vlans: array().of(SERVICES_DHCP_RELAY_VLAN_SCHEMA(t, useDefault)).default([]), + }); + + return useDefault ? shape : shape.nullable().default(undefined); +}; + export const SERVICES_CAPTIVE_SCHEMA = (t, useDefault = false) => { const shape = object() .shape({ @@ -428,6 +448,7 @@ export const SERVICES_SCHEMA = (t, useDefault = false) => ieee8021x: SERVICES_IEEE8021X_SCHEMA(t, useDefault), captive: SERVICES_CAPTIVE_SCHEMA(t, useDefault), gps: SERVICES_GPS_SCHEMA(t, useDefault), + 'dhcp-relay': SERVICES_DHCP_RELAY_SCHEMA(t, useDefault), }), }); @@ -471,6 +492,8 @@ export const getSubSectionDefaults = (t, sub) => { return SERVICES_CAPTIVE_SCHEMA(t, true).cast(); case 'gps': return SERVICES_GPS_SCHEMA(t, true).cast(); + case 'dhcp-relay': + return SERVICES_DHCP_RELAY_SCHEMA(t, true).cast(); default: return null; } diff --git a/src/pages/ConfigurationPage/ConfigurationCard/ConfigurationSectionsCard/UnitSection/BeaconAdvertisement.tsx b/src/pages/ConfigurationPage/ConfigurationCard/ConfigurationSectionsCard/UnitSection/BeaconAdvertisement.tsx new file mode 100644 index 0000000..1ecb193 --- /dev/null +++ b/src/pages/ConfigurationPage/ConfigurationCard/ConfigurationSectionsCard/UnitSection/BeaconAdvertisement.tsx @@ -0,0 +1,62 @@ +import * as React from 'react'; +import { Box, Flex, Heading, Switch } from '@chakra-ui/react'; +import NumberField from 'components/FormFields/NumberField'; +import ToggleField from 'components/FormFields/ToggleField'; +import useFastField from 'hooks/useFastField'; + +type Props = { + isEditing: boolean; +}; + +const BeaconAdvertisement = ({ isEditing }: Props) => { + const field = useFastField({ name: 'configuration.beacon-advertisement' }); + + const isActive = !!field.value; + + const onOpen = React.useCallback(() => { + field.onChange({ + 'device-name': true, + 'device-serial': true, + 'network-id': 0, + }); + }, []); + + const onClose = React.useCallback(() => { + field.onChange(undefined); + }, []); + + return ( + + + Beacon Advertisement + + + {isActive ? ( + + + + + + + + + + ) : null} + + ); +}; + +export default BeaconAdvertisement; diff --git a/src/pages/ConfigurationPage/ConfigurationCard/ConfigurationSectionsCard/UnitSection/Unit.jsx b/src/pages/ConfigurationPage/ConfigurationCard/ConfigurationSectionsCard/UnitSection/Unit.jsx index 9533376..8e161c8 100644 --- a/src/pages/ConfigurationPage/ConfigurationCard/ConfigurationSectionsCard/UnitSection/Unit.jsx +++ b/src/pages/ConfigurationPage/ConfigurationCard/ConfigurationSectionsCard/UnitSection/Unit.jsx @@ -1,7 +1,8 @@ import React from 'react'; -import { Heading, SimpleGrid } from '@chakra-ui/react'; +import { Box, Heading, SimpleGrid } from '@chakra-ui/react'; import PropTypes from 'prop-types'; import { useTranslation } from 'react-i18next'; +import BeaconAdvertisement from './BeaconAdvertisement'; import Card from 'components/Card'; import CardBody from 'components/Card/CardBody'; import CardHeader from 'components/Card/CardHeader'; @@ -23,144 +24,147 @@ const Unit = ({ editing }) => { {t('configurations.unit')} - - - - - - - - - + + + + + + + + + + + + ); diff --git a/src/pages/ConfigurationPage/ConfigurationCard/ConfigurationSectionsCard/UnitSection/unitConstants.js b/src/pages/ConfigurationPage/ConfigurationCard/ConfigurationSectionsCard/UnitSection/unitConstants.js index 25f28a2..3fc8314 100644 --- a/src/pages/ConfigurationPage/ConfigurationCard/ConfigurationSectionsCard/UnitSection/unitConstants.js +++ b/src/pages/ConfigurationPage/ConfigurationCard/ConfigurationSectionsCard/UnitSection/unitConstants.js @@ -13,6 +13,12 @@ export const DEFAULT_UNIT = { }, }; +export const UNIT_BEACON_ADVERTISEMENT_SCHEMA = (t) => + object().shape({ + 'device-name': string().required(t('form.required')).default(''), + 'device-serial': string().required(t('form.required')).default(''), + 'network-id': number().required(t('form.required')).min(0).lessThan(65535).default(1024), + }); export const UNIT_SCHEMA = (t) => object().shape({ name: string().required(t('form.required')).default('Unit'), @@ -27,5 +33,6 @@ export const UNIT_SCHEMA = (t) => timezone: string().default(undefined), 'leds-active': bool().default(true), 'random-password': bool().default(false), + 'beacon-advertisement': UNIT_BEACON_ADVERTISEMENT_SCHEMA(t).default(undefined), }), });