diff options
-rw-r--r-- | modern/src/common/components/SelectField.jsx | 57 | ||||
-rw-r--r-- | modern/src/reports/components/ReportFilter.jsx | 44 | ||||
-rw-r--r-- | modern/src/settings/ComputedAttributePage.jsx | 2 | ||||
-rw-r--r-- | modern/src/settings/DevicePage.jsx | 5 | ||||
-rw-r--r-- | modern/src/settings/GeofencePage.jsx | 2 | ||||
-rw-r--r-- | modern/src/settings/GroupPage.jsx | 2 | ||||
-rw-r--r-- | modern/src/settings/NotificationPage.jsx | 5 | ||||
-rw-r--r-- | modern/src/settings/PreferencesPage.jsx | 4 | ||||
-rw-r--r-- | modern/src/settings/ServerPage.jsx | 3 | ||||
-rw-r--r-- | modern/src/settings/UserPage.jsx | 3 | ||||
-rw-r--r-- | modern/src/settings/components/BaseCommandView.jsx | 2 |
11 files changed, 67 insertions, 62 deletions
diff --git a/modern/src/common/components/SelectField.jsx b/modern/src/common/components/SelectField.jsx index 35f817a0..db8c30b0 100644 --- a/modern/src/common/components/SelectField.jsx +++ b/modern/src/common/components/SelectField.jsx @@ -1,5 +1,5 @@ import { - FormControl, InputLabel, MenuItem, Select, + FormControl, InputLabel, MenuItem, Select, Autocomplete, TextField, } from '@mui/material'; import React, { useState } from 'react'; import { useEffectAsync } from '../../reactHelper'; @@ -8,9 +8,9 @@ const SelectField = ({ label, fullWidth, multiple, - value, - emptyValue = 0, - emptyTitle = '\u00a0', + value = null, + emptyValue = null, + emptyTitle = '', onChange, endpoint, data, @@ -19,6 +19,13 @@ const SelectField = ({ }) => { const [items, setItems] = useState(data); + const getOptionLabel = (option) => { + if (typeof option !== 'object') { + option = items.find((obj) => keyGetter(obj) === option); + } + return option ? titleGetter(option) : emptyTitle; + }; + useEffectAsync(async () => { if (endpoint) { const response = await fetch(endpoint); @@ -33,20 +40,34 @@ const SelectField = ({ if (items) { return ( <FormControl fullWidth={fullWidth}> - <InputLabel>{label}</InputLabel> - <Select - label={label} - multiple={multiple} - value={value} - onChange={onChange} - > - {!multiple && emptyValue !== null && ( - <MenuItem value={emptyValue}>{emptyTitle}</MenuItem> - )} - {items.map((item) => ( - <MenuItem key={keyGetter(item)} value={keyGetter(item)}>{titleGetter(item)}</MenuItem> - ))} - </Select> + {multiple ? ( + <> + <InputLabel>{label}</InputLabel> + <Select + label={label} + multiple + value={value} + onChange={onChange} + > + {items.map((item) => ( + <MenuItem key={keyGetter(item)} value={keyGetter(item)}>{titleGetter(item)}</MenuItem> + ))} + </Select> + </> + ) : ( + <Autocomplete + size="small" + options={items} + getOptionLabel={getOptionLabel} + renderOption={(props, option) => ( + <MenuItem {...props} key={keyGetter(option)} value={keyGetter(option)}>{titleGetter(option)}</MenuItem> + )} + isOptionEqualToValue={(option, value) => keyGetter(option) === value} + value={value} + onChange={(_, value) => onChange({ target: { value: value ? keyGetter(value) : emptyValue } })} + renderInput={(params) => <TextField {...params} label={label} />} + /> + )} </FormControl> ); } diff --git a/modern/src/reports/components/ReportFilter.jsx b/modern/src/reports/components/ReportFilter.jsx index eab7d0eb..e6e08f16 100644 --- a/modern/src/reports/components/ReportFilter.jsx +++ b/modern/src/reports/components/ReportFilter.jsx @@ -92,36 +92,26 @@ const ReportFilter = ({ children, handleSubmit, handleSchedule, showOnly, ignore <div className={classes.filter}> {!ignoreDevice && ( <div className={classes.filterItem}> - <FormControl fullWidth> - <InputLabel>{t(multiDevice ? 'deviceTitle' : 'reportDevice')}</InputLabel> - <Select - label={t(multiDevice ? 'deviceTitle' : 'reportDevice')} - value={multiDevice ? deviceIds : deviceId || ''} - onChange={(e) => dispatch(multiDevice ? devicesActions.selectIds(e.target.value) : devicesActions.selectId(e.target.value))} - multiple={multiDevice} - > - {Object.values(devices).sort((a, b) => a.name.localeCompare(b.name)).map((device) => ( - <MenuItem key={device.id} value={device.id}>{device.name}</MenuItem> - ))} - </Select> - </FormControl> + <SelectField + label={t(multiDevice ? 'deviceTitle' : 'reportDevice')} + data={Object.values(devices).sort((a, b) => a.name.localeCompare(b.name))} + value={multiDevice ? deviceIds : deviceId} + onChange={(e) => dispatch(multiDevice ? devicesActions.selectIds(e.target.value) : devicesActions.selectId(e.target.value))} + multiple={multiDevice} + fullWidth + /> </div> )} {includeGroups && ( <div className={classes.filterItem}> - <FormControl fullWidth> - <InputLabel>{t('settingsGroups')}</InputLabel> - <Select - label={t('settingsGroups')} - value={groupIds} - onChange={(e) => dispatch(reportsActions.updateGroupIds(e.target.value))} - multiple - > - {Object.values(groups).sort((a, b) => a.name.localeCompare(b.name)).map((group) => ( - <MenuItem key={group.id} value={group.id}>{group.name}</MenuItem> - ))} - </Select> - </FormControl> + <SelectField + label={t('settingsGroups')} + data={Object.values(groups).sort((a, b) => a.name.localeCompare(b.name))} + value={groupIds} + onChange={(e) => dispatch(reportsActions.updateGroupIds(e.target.value))} + multiple + fullWidth + /> </div> )} {button !== 'schedule' ? ( @@ -175,7 +165,7 @@ const ReportFilter = ({ children, handleSubmit, handleSchedule, showOnly, ignore </div> <div className={classes.filterItem}> <SelectField - value={calendarId || 0} + value={calendarId} onChange={(event) => setCalendarId(Number(event.target.value))} endpoint="/api/calendars" label={t('sharedCalendar')} diff --git a/modern/src/settings/ComputedAttributePage.jsx b/modern/src/settings/ComputedAttributePage.jsx index f179a78d..1b19033c 100644 --- a/modern/src/settings/ComputedAttributePage.jsx +++ b/modern/src/settings/ComputedAttributePage.jsx @@ -147,7 +147,7 @@ const ComputedAttributePage = () => { </AccordionSummary> <AccordionDetails className={classes.details}> <SelectField - value={deviceId || 0} + value={deviceId} onChange={(e) => setDeviceId(Number(e.target.value))} endpoint="/api/devices" label={t('sharedDevice')} diff --git a/modern/src/settings/DevicePage.jsx b/modern/src/settings/DevicePage.jsx index ae8c9bf3..0feb000b 100644 --- a/modern/src/settings/DevicePage.jsx +++ b/modern/src/settings/DevicePage.jsx @@ -94,7 +94,7 @@ const DevicePage = () => { </AccordionSummary> <AccordionDetails className={classes.details}> <SelectField - value={item.groupId || 0} + value={item.groupId} onChange={(event) => setItem({ ...item, groupId: Number(event.target.value) })} endpoint="/api/groups" label={t('groupParent')} @@ -116,7 +116,6 @@ const DevicePage = () => { /> <SelectField value={item.category || 'default'} - emptyValue={null} onChange={(event) => setItem({ ...item, category: event.target.value })} data={deviceCategories.map((category) => ({ id: category, @@ -125,7 +124,7 @@ const DevicePage = () => { label={t('deviceCategory')} /> <SelectField - value={item.calendarId || 0} + value={item.calendarId} onChange={(event) => setItem({ ...item, calendarId: Number(event.target.value) })} endpoint="/api/calendars" label={t('sharedCalendar')} diff --git a/modern/src/settings/GeofencePage.jsx b/modern/src/settings/GeofencePage.jsx index 93b23c7e..c3c96ef8 100644 --- a/modern/src/settings/GeofencePage.jsx +++ b/modern/src/settings/GeofencePage.jsx @@ -67,7 +67,7 @@ const GeofencePage = () => { label={t('sharedDescription')} /> <SelectField - value={item.calendarId || 0} + value={item.calendarId} onChange={(event) => setItem({ ...item, calendarId: Number(event.target.value) })} endpoint="/api/calendars" label={t('sharedCalendar')} diff --git a/modern/src/settings/GroupPage.jsx b/modern/src/settings/GroupPage.jsx index d21d0e5a..ba1cbc76 100644 --- a/modern/src/settings/GroupPage.jsx +++ b/modern/src/settings/GroupPage.jsx @@ -72,7 +72,7 @@ const GroupPage = () => { </AccordionSummary> <AccordionDetails className={classes.details}> <SelectField - value={item.groupId || 0} + value={item.groupId} onChange={(event) => setItem({ ...item, groupId: Number(event.target.value) })} endpoint="/api/groups" label={t('groupParent')} diff --git a/modern/src/settings/NotificationPage.jsx b/modern/src/settings/NotificationPage.jsx index 978d940c..63aa9b95 100644 --- a/modern/src/settings/NotificationPage.jsx +++ b/modern/src/settings/NotificationPage.jsx @@ -65,7 +65,6 @@ const NotificationPage = () => { <AccordionDetails className={classes.details}> <SelectField value={item.type} - emptyValue={null} onChange={(e) => setItem({ ...item, type: e.target.value })} endpoint="/api/notifications/types" keyGetter={(it) => it.type} @@ -93,7 +92,7 @@ const NotificationPage = () => { /> {item.notificators?.includes('command') && ( <SelectField - value={item.commandId || 0} + value={item.commandId} onChange={(event) => setItem({ ...item, commandId: Number(event.target.value) })} endpoint="/api/commands" titleGetter={(it) => it.description} @@ -129,7 +128,7 @@ const NotificationPage = () => { </AccordionSummary> <AccordionDetails className={classes.details}> <SelectField - value={item.calendarId || 0} + value={item.calendarId} onChange={(event) => setItem({ ...item, calendarId: Number(event.target.value) })} endpoint="/api/calendars" label={t('sharedCalendar')} diff --git a/modern/src/settings/PreferencesPage.jsx b/modern/src/settings/PreferencesPage.jsx index 676bd58b..2d6df62f 100644 --- a/modern/src/settings/PreferencesPage.jsx +++ b/modern/src/settings/PreferencesPage.jsx @@ -239,7 +239,6 @@ const PreferencesPage = () => { </AccordionSummary> <AccordionDetails className={classes.details}> <SelectField - emptyValue={null} value={attributes.devicePrimary || 'name'} onChange={(e) => setAttributes({ ...attributes, devicePrimary: e.target.value })} data={deviceFields} @@ -247,8 +246,7 @@ const PreferencesPage = () => { label={t('devicePrimaryInfo')} /> <SelectField - emptyValue="" - value={attributes.deviceSecondary || ''} + value={attributes.deviceSecondary} onChange={(e) => setAttributes({ ...attributes, deviceSecondary: e.target.value })} data={deviceFields} titleGetter={(it) => t(it.name)} diff --git a/modern/src/settings/ServerPage.jsx b/modern/src/settings/ServerPage.jsx index 7a3a1bbe..0ac76334 100644 --- a/modern/src/settings/ServerPage.jsx +++ b/modern/src/settings/ServerPage.jsx @@ -172,8 +172,7 @@ const ServerPage = () => { </Select> </FormControl> <SelectField - value={item.attributes.timezone || ''} - emptyValue="" + value={item.attributes.timezone} onChange={(e) => setItem({ ...item, attributes: { ...item.attributes, timezone: e.target.value } })} endpoint="/api/server/timezones" keyGetter={(it) => it} diff --git a/modern/src/settings/UserPage.jsx b/modern/src/settings/UserPage.jsx index 4e0cab2c..6748dd31 100644 --- a/modern/src/settings/UserPage.jsx +++ b/modern/src/settings/UserPage.jsx @@ -258,8 +258,7 @@ const UserPage = () => { </Select> </FormControl> <SelectField - value={(item.attributes && item.attributes.timezone) || ''} - emptyValue="" + value={item.attributes && item.attributes.timezone} onChange={(e) => setItem({ ...item, attributes: { ...item.attributes, timezone: e.target.value } })} endpoint="/api/server/timezones" keyGetter={(it) => it} diff --git a/modern/src/settings/components/BaseCommandView.jsx b/modern/src/settings/components/BaseCommandView.jsx index acf39090..bb70c3b9 100644 --- a/modern/src/settings/components/BaseCommandView.jsx +++ b/modern/src/settings/components/BaseCommandView.jsx @@ -28,7 +28,7 @@ const BaseCommandView = ({ deviceId, item, setItem }) => { return ( <> <SelectField - value={item.type || ''} + value={item.type} onChange={(e) => setItem({ ...item, type: e.target.value, attributes: {} })} endpoint={deviceId ? `/api/commands/types?${new URLSearchParams({ deviceId }).toString()}` : '/api/commands/types'} keyGetter={(it) => it.type} |