Skip to content

Commit

Permalink
F #6233: Replace select controllers (#3119)
Browse files Browse the repository at this point in the history
Replaces majority of all select controllers with the autocomplete controller instead
  - Does not replace any select controllers under the oneprovision UI
 - Works similarly to the select controller, with the added functionality that you can filter all options by typing

Signed-off-by: Victor Hansson <vhansson@opennebula.io>
  • Loading branch information
vichansson authored Jun 19, 2024
1 parent a644578 commit 24abd57
Show file tree
Hide file tree
Showing 58 changed files with 303 additions and 156 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@
* See the License for the specific language governing permissions and *
* limitations under the License. *
* ------------------------------------------------------------------------- */
import { memo, useCallback } from 'react'
import { memo, useCallback, useEffect } from 'react'
import PropTypes from 'prop-types'

import { TextField, Chip, Autocomplete } from '@mui/material'
import { useController } from 'react-hook-form'
import { useController, useWatch, useFormContext } from 'react-hook-form'

import { ErrorHelper } from 'client/components/FormControl'
import { Translate } from 'client/components/HOC'
Expand All @@ -36,6 +36,8 @@ const AutocompleteController = memo(
readOnly = false,
optionsOnly = false,
onConditionChange,
watcher,
dependencies,
disableEnter = false,
}) => {
const {
Expand All @@ -62,9 +64,42 @@ const AutocompleteController = memo(
onConditionChange(newValueToChange ?? '')
}
},
[onChange, onConditionChange, multiple]
[onChange, onConditionChange, multiple, renderValue]
)

// Add watcher to know if the dependencies fields have changes
const watch = useWatch({
name: dependencies,
disabled: dependencies == null,
defaultValue: Array.isArray(dependencies) ? [] : undefined,
})

const filterOptions = (options, { inputValue }) =>
options?.filter((option) => {
const optionText = typeof option?.text === 'string' ? option.text : ''
const optionValue =
typeof option?.value === 'string' ? option.value : ''

const textMatch = optionText
.toLowerCase()
.includes(inputValue?.toLowerCase())
const valueMatch = optionValue
.toLowerCase()
.includes(inputValue?.toLowerCase())

return textMatch || valueMatch
})

const formContext = useFormContext()

useEffect(() => {
if (!watcher || !dependencies || !watch) return

const watcherValue = watcher(watch, { name, formContext })

watcherValue !== undefined && onChange(watcherValue)
}, [watch, watcher, dependencies])

return (
<Autocomplete
fullWidth
Expand All @@ -85,9 +120,15 @@ const AutocompleteController = memo(
}
}}
options={values}
filterOptions={filterOptions}
value={selected}
multiple={multiple}
freeSolo={!optionsOnly}
renderOption={(props, option) => (
<li {...props} data-value={option?.value ?? option?.text}>
{option?.text}
</li>
)}
renderTags={(tags, getTagProps) =>
tags.map((tag, index) => {
const labelTag =
Expand Down Expand Up @@ -168,6 +209,11 @@ AutocompleteController.propTypes = {
readOnly: PropTypes.bool,
optionsOnly: PropTypes.bool,
onConditionChange: PropTypes.func,
watcher: PropTypes.func,
dependencies: PropTypes.oneOfType([
PropTypes.string,
PropTypes.arrayOf(PropTypes.string),
]),
}

AutocompleteController.displayName = 'AutocompleteController'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@ const NAME = {
const INCREMENT_ID = ({ increments = [] }) => ({
name: 'increment_id',
label: T.IncrementId,
type: INPUT_TYPES.SELECT,
type: INPUT_TYPES.AUTOCOMPLETE,
optionsOnly: true,
values: (deps) => {
const selectedImage = deps?.[BACKUP_IMG_ID]?.[0]
let backupIncrements = [].concat(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ const PRIORITY = {
const EXECUTION = {
name: 'EXECUTION',
label: T.Execution,
type: INPUT_TYPES.SELECT,
type: INPUT_TYPES.AUTOCOMPLETE,
optionsOnly: true,
values: arrayToOptions(Object.keys(EXECUTION_OPTIONS), {
getText: (type) => type,
getValue: (type) => EXECUTION_OPTIONS[type],
Expand All @@ -68,7 +69,8 @@ const EXECUTION = {
const FS_FREEZE = {
name: 'FS_FREEZE',
label: T.FSFreeze,
type: INPUT_TYPES.SELECT,
type: INPUT_TYPES.AUTOCOMPLETE,
optionsOnly: true,
values: arrayToOptions(Object.keys(FS_FREEZE_OPTIONS), {
getText: (type) => type,
getValue: (type) => FS_FREEZE_OPTIONS[type],
Expand All @@ -80,7 +82,8 @@ const FS_FREEZE = {
const MODE = {
name: 'MODE',
label: T.Mode,
type: INPUT_TYPES.SELECT,
type: INPUT_TYPES.AUTOCOMPLETE,
optionsOnly: true,
values: arrayToOptions(Object.keys(BACKUP_MODE_OPTIONS), {
addEmpty: true,
getText: (type) => type,
Expand All @@ -93,7 +96,8 @@ const MODE = {
const INCREMENT_MODE = {
name: 'INCREMENT_MODE',
label: T.IncrementMode,
type: INPUT_TYPES.SELECT,
type: INPUT_TYPES.AUTOCOMPLETE,
optionsOnly: true,
dependOf: MODE.name,
htmlType: (mode) =>
mode !== BACKUP_MODE_OPTIONS[T.Increment] && INPUT_TYPES.HIDDEN,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,8 @@ const RESTIC_COMPRESSION = {
label: T.CompressionLevel,
tooltip: T.CompressionLevelConcept,
dependOf: '$general.STORAGE_BACKEND',
type: INPUT_TYPES.SELECT,
type: INPUT_TYPES.AUTOCOMPLETE,
optionsOnly: true,
values: () =>
arrayToOptions(['OFF', 'AUTO', 'MAX'], {
addEmpty: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ import { isVcenter, typeIsOneOf } from '../../functions'
const VCENTER_ADAPTER_TYPE = {
name: 'VCENTER_ADAPTER_TYPE',
label: T.AdapterTypeUsedByVirtualDisksVMs,
type: INPUT_TYPES.SELECT,
type: INPUT_TYPES.AUTOCOMPLETE,
optionsOnly: true,
values: () =>
arrayToOptions(Object.values(DS_VCENTER_ADAPTER_TYPE_OPTIONS), {
addEmpty: true,
Expand All @@ -45,7 +46,8 @@ const VCENTER_ADAPTER_TYPE = {
const VCENTER_DISK_TYPE = {
name: 'VCENTER_DISK_TYPE',
label: T.TypeOfDiskToBeCreated,
type: INPUT_TYPES.SELECT,
type: INPUT_TYPES.AUTOCOMPLETE,
optionsOnly: true,
values: () =>
arrayToOptions(Object.values(DS_VCENTER_DISK_TYPE_OPTIONS), {
addEmpty: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@ const NAME = {
const STORAGE_BACKEND = {
name: 'STORAGE_BACKEND',
label: T.StorageBackend,
type: INPUT_TYPES.SELECT,
type: INPUT_TYPES.AUTOCOMPLETE,
optionsOnly: true,
dependOf: TYPE.name,
values: (type) =>
arrayToOptions(getStorageBackendsFromDStype(type), {
Expand All @@ -87,7 +88,8 @@ const STORAGE_BACKEND = {
const DS_MAD = {
name: 'DS_MAD',
label: T.Datastore,
type: INPUT_TYPES.SELECT,
type: INPUT_TYPES.AUTOCOMPLETE,
optionsOnly: true,
dependOf: STORAGE_BACKEND.name,
values: arrayToOptions(Object.values(DATASTORE_OPTIONS), {
addEmpty: false,
Expand All @@ -104,7 +106,8 @@ const DS_MAD = {
const TM_MAD = {
name: 'TM_MAD',
label: T.Transfer,
type: INPUT_TYPES.SELECT,
type: INPUT_TYPES.AUTOCOMPLETE,
optionsOnly: true,
dependOf: STORAGE_BACKEND.name,
values: arrayToOptions(Object.values(TRANSFER_OPTIONS), {
addEmpty: false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@ export const DESCRIPTION = {
export const TYPE = {
name: 'TYPE',
label: T.Type,
type: INPUT_TYPES.SELECT,
type: INPUT_TYPES.AUTOCOMPLETE,
optionsOnly: true,
values: arrayToOptions(Object.values(IMAGE_TYPES_FOR_FILES), {
addEmpty: false,
getText: (type) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ const VIEW = (view, admin) => ({
const DEFAULT_VIEW = (views, admin) => ({
name: admin ? `GROUP_ADMIN_DEFAULT_VIEW` : `DEFAULT_VIEW`,
label: T['groups.views.default'],
type: INPUT_TYPES.SELECT,
type: INPUT_TYPES.AUTOCOMPLETE,
optionsOnly: true,
values: arrayToOptions(views, {
getText: (view) => (T[view.name] ? T[view.name] : view.name),
getValue: (view) => view.type,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ const htmlType = (opt) => (value) => value !== opt && INPUT_TYPES.HIDDEN
export const DEV_PREFIX = {
name: 'DEV_PREFIX',
label: T.Bus,
type: INPUT_TYPES.SELECT,
type: INPUT_TYPES.AUTOCOMPLETE,
optionsOnly: true,
values: arrayToOptions(Object.entries(BUS_TYPES), {
addEmpty: true,
getText: ([_, name]) => name,
Expand Down Expand Up @@ -100,7 +101,8 @@ export const FORMAT_FIELD = {
dependOf: `$general.${IMAGE_LOCATION_FIELD.name}`,
htmlType: htmlType(IMAGE_LOCATION_TYPES.EMPTY),
label: T.Format,
type: INPUT_TYPES.SELECT,
type: INPUT_TYPES.AUTOCOMPLETE,
optionsOnly: true,
values: arrayToOptions(Object.values(FORMAT_TYPES), {
addEmpty: true,
getText: (type) => type.toUpperCase(),
Expand Down Expand Up @@ -144,7 +146,8 @@ export const FS = {
dependOf: `$general.${IMAGE_LOCATION_FIELD.name}`,
htmlType: htmlType(IMAGE_LOCATION_TYPES.EMPTY),
label: T.Fs,
type: INPUT_TYPES.SELECT,
type: INPUT_TYPES.AUTOCOMPLETE,
optionsOnly: true,
values: () => {
const { data: sunstoneConfig = {} } = useGetSunstoneConfigQuery()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@ export const DESCRIPTION = {
export const TYPE = {
name: 'TYPE',
label: T.Type,
type: INPUT_TYPES.SELECT,
type: INPUT_TYPES.AUTOCOMPLETE,
optionsOnly: true,
values: arrayToOptions(Object.values(IMAGE_TYPES_FOR_IMAGES), {
addEmpty: false,
getText: (type) => {
Expand Down Expand Up @@ -181,7 +182,8 @@ export const SIZEUNIT = {
dependOf: IMAGE_LOCATION_FIELD.name,
htmlType: htmlType(IMAGE_LOCATION_TYPES.EMPTY, true),
label: T.SizeUnit,
type: INPUT_TYPES.SELECT,
type: INPUT_TYPES.AUTOCOMPLETE,
optionsOnly: true,
tooltip: T.SizeUnitTooltip,
values: arrayToOptions([UNITS.MB, UNITS.GB, UNITS.TB], {
addEmpty: false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ const DESCRIPTION = {
const TYPE = {
name: 'MARKET_MAD',
label: T['marketplace.form.create.general.type'],
type: INPUT_TYPES.SELECT,
type: INPUT_TYPES.AUTOCOMPLETE,
optionsOnly: true,
values: arrayToOptions(Object.keys(MARKET_TYPES), {
addEmpty: true,
getText: (key) => T[MARKET_TYPES[key].text],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ import {
export const RULE_TYPE = {
name: 'RULE_TYPE',
label: T.Traffic,
type: INPUT_TYPES.SELECT,
type: INPUT_TYPES.AUTOCOMPLETE,
optionsOnly: true,
values: arrayToOptions(Object.values(RULE_TYPE_STRING), {
addEmpty: false,
getText: (ruleType) => {
Expand All @@ -60,7 +61,8 @@ export const RULE_TYPE = {
export const PROTOCOL = {
name: 'PROTOCOL',
label: T.Protocol,
type: INPUT_TYPES.SELECT,
type: INPUT_TYPES.AUTOCOMPLETE,
optionsOnly: true,
values: arrayToOptions(Object.values(PROTOCOL_STRING), {
addEmpty: false,
getText: (protocol) => {
Expand Down Expand Up @@ -94,7 +96,8 @@ export const ICMP_TYPE = {
name: 'ICMP_TYPE',
dependOf: PROTOCOL.name,
label: T.ICMP,
type: INPUT_TYPES.SELECT,
type: INPUT_TYPES.AUTOCOMPLETE,
optionsOnly: true,
htmlType: (protocol) =>
protocol !== PROTOCOL_STRING.ICMP && INPUT_TYPES.HIDDEN,
values: arrayToOptions(Object.entries(ICMP_STRING), {
Expand All @@ -115,7 +118,8 @@ export const ICMPV6_TYPE = {
name: 'ICMPv6_TYPE',
dependOf: PROTOCOL.name,
label: T.ICMPV6,
type: INPUT_TYPES.SELECT,
type: INPUT_TYPES.AUTOCOMPLETE,
optionsOnly: true,
htmlType: (protocol) =>
protocol !== PROTOCOL_STRING.ICMPV6 && INPUT_TYPES.HIDDEN,
values: arrayToOptions(Object.entries(ICMP_V6_STRING), {
Expand All @@ -135,7 +139,8 @@ export const ICMPV6_TYPE = {
export const RANGE_TYPE = {
name: 'RANGE_TYPE',
label: T.PortRange,
type: INPUT_TYPES.SELECT,
type: INPUT_TYPES.AUTOCOMPLETE,
optionsOnly: true,
values: arrayToOptions([T.All, T.PortRange], {
addEmpty: false,
}),
Expand Down Expand Up @@ -164,7 +169,8 @@ export const RANGE = {
export const TARGET = {
name: 'TARGET',
label: T.TargetNetwork,
type: INPUT_TYPES.SELECT,
type: INPUT_TYPES.AUTOCOMPLETE,
optionsOnly: true,
values: arrayToOptions(
[T.AnyNetwork, T.ManualNetwork, T.OpennebulaVirtualNetwork],
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ const VM_SHUTDOWN_TYPES = {
const STRATEGY_TYPE = {
label: 'Strategy',
name: 'ADVANCED.DEPLOYMENT',
type: INPUT_TYPES.SELECT,
type: INPUT_TYPES.AUTOCOMPLETE,
optionsOnly: true,
values: arrayToOptions(Object.keys(STRATEGY_TYPES), {
addEmpty: false,
getText: (key) => STRATEGY_TYPES[key],
Expand All @@ -49,7 +50,8 @@ const STRATEGY_TYPE = {
const VM_SHUTDOWN_TYPE = {
label: 'VM Shutdown',
name: 'ADVANCED.VMSHUTDOWN',
type: INPUT_TYPES.SELECT,
type: INPUT_TYPES.AUTOCOMPLETE,
optionsOnly: true,
values: arrayToOptions(Object.values(VM_SHUTDOWN_TYPES), { addEmpty: false }),
validation: string()
.trim()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ const CA_TYPES = {
const CA_TYPE = {
name: 'type',
label: 'Type',
type: INPUT_TYPES.SELECT,
type: INPUT_TYPES.AUTOCOMPLETE,
optionsOnly: true,
values: arrayToOptions(Object.values(CA_TYPES), { addEmpty: false }),
defaultValueProp: CA_TYPES.text,
validation: string()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ export const NETWORK_TYPES = {
const NETWORK_TYPE = {
name: 'type',
label: 'Type',
type: INPUT_TYPES.SELECT,
type: INPUT_TYPES.AUTOCOMPLETE,
optionsOnly: true,
values: arrayToOptions(Object.values(NETWORK_TYPES), { addEmpty: false }),
validation: string()
.trim()
Expand Down Expand Up @@ -63,7 +64,8 @@ const DESCRIPTION = {
const NETWORK_SELECTION = {
name: 'network',
label: 'Network',
type: INPUT_TYPES.SELECT,
type: INPUT_TYPES.AUTOCOMPLETE,
optionsOnly: true,
values: () => {
const { data: vnets = [] } = useGetVNetworksQuery()
const networks = vnets
Expand Down
Loading

0 comments on commit 24abd57

Please sign in to comment.