New file |
| | |
| | | import React, { useState, useEffect } from 'react'; |
| | | import { |
| | | Select, |
| | | MenuItem, |
| | | Autocomplete, |
| | | TextField, |
| | | InputAdornment, |
| | | IconButton, |
| | | useTheme, |
| | | } from '@mui/material'; |
| | | import { useTranslate } from 'react-admin'; |
| | | import CloseIcon from '@mui/icons-material/Close'; |
| | | import { MAP_MODE, DEVICE_TYPE } from "../constants"; |
| | | import * as Tool from "../tool"; |
| | | |
| | | const renderTitle = (title, uuid) => ( |
| | | <> |
| | | <span style={{ fontWeight: 'bold' }}>{title}</span> |
| | | <span style={{ float: 'right', opacity: 0.3 }}>{uuid}</span> |
| | | </> |
| | | ); |
| | | |
| | | const deviceTypeSelectOptionsFn = (translate) => { |
| | | const deviceTypes = [ |
| | | { |
| | | key: DEVICE_TYPE.SHELF, |
| | | id: 'page.map.devices.shelf', |
| | | }, |
| | | { |
| | | key: DEVICE_TYPE.STATION, |
| | | id: 'page.map.devices.station', |
| | | }, |
| | | { |
| | | key: DEVICE_TYPE.AGV, |
| | | id: 'page.map.devices.agv', |
| | | }, |
| | | { |
| | | key: DEVICE_TYPE.POINT, |
| | | id: 'page.map.devices.point', |
| | | }, |
| | | // Add other sensor types if needed |
| | | ]; |
| | | |
| | | return deviceTypes.map(({ key, id }) => ({ |
| | | value: key, |
| | | label: translate(id), |
| | | })); |
| | | }; |
| | | |
| | | const getAllDeviceList = (curDeviceType) => { |
| | | const children = Tool.getMapContainer()?.children || []; |
| | | return children.reduce((list, child) => { |
| | | if (child?.data) { |
| | | const { data } = child; |
| | | if (data.type === curDeviceType && data.no) { |
| | | list.push({ |
| | | value: data.no, |
| | | label: renderTitle(data.no, data.uuid), |
| | | }); |
| | | } |
| | | } |
| | | return list; |
| | | }, []); |
| | | }; |
| | | |
| | | const MapSearch = (props) => { |
| | | const { |
| | | setCurSprite, |
| | | setSpriteSettings, |
| | | mode, |
| | | setMode, |
| | | } = props; |
| | | |
| | | const theme = useTheme(); |
| | | const themeMode = theme.palette.mode; |
| | | const translate = useTranslate(); |
| | | |
| | | // type |
| | | const deviceTypeOptions = deviceTypeSelectOptionsFn(translate); |
| | | const [curDeviceType, setCurDeviceType] = useState( |
| | | deviceTypeOptions[0]?.value || '' |
| | | ); |
| | | // list |
| | | const [deviceList, setDeviceList] = useState([]); |
| | | const [filterDeviceList, setFilterDeviceList] = useState([]); |
| | | const [inputValue, setInputValue] = useState(''); |
| | | const [selectedOption, setSelectedOption] = useState(null); |
| | | |
| | | const resetSearch = () => { |
| | | const deviceListAll = getAllDeviceList(curDeviceType); |
| | | setDeviceList(deviceListAll); |
| | | setFilterDeviceList(deviceListAll); |
| | | setInputValue(''); |
| | | setSelectedOption(null); |
| | | }; |
| | | |
| | | useEffect(() => { |
| | | if (!Tool.getMapContainer()) return; |
| | | setTimeout(() => { |
| | | resetSearch(); |
| | | }, 200); |
| | | }, [curDeviceType, props.curZone]); |
| | | |
| | | useEffect(() => { |
| | | if (!Tool.getMapContainer()) return; |
| | | if (inputValue !== '' && deviceList.length > 0) { |
| | | setFilterDeviceList( |
| | | deviceList.filter((item) => item.value.includes(inputValue)) |
| | | ); |
| | | } else { |
| | | setFilterDeviceList(deviceList); |
| | | } |
| | | }, [inputValue]); |
| | | |
| | | const onSecondSelect = (option) => { |
| | | if (!option) return; |
| | | const uuid = option.label.props.children[1]?.props?.children; |
| | | const selectSprite = Tool.findSpriteByUuid(uuid); |
| | | if (selectSprite) { |
| | | Tool.focusSprite(selectSprite); |
| | | } |
| | | switch (mode) { |
| | | case MAP_MODE.OBSERVER_MODE: |
| | | setCurSprite(selectSprite); |
| | | break; |
| | | case MAP_MODE.MOVABLE_MODE: |
| | | setMode(MAP_MODE.SETTINGS_MODE); |
| | | setTimeout(() => { |
| | | setSpriteSettings(selectSprite); |
| | | }, 200); |
| | | break; |
| | | case MAP_MODE.SETTINGS_MODE: |
| | | setSpriteSettings(selectSprite); |
| | | break; |
| | | default: |
| | | break; |
| | | } |
| | | }; |
| | | |
| | | return ( |
| | | <> |
| | | <Select |
| | | className="map-header-select" |
| | | variant="filled" |
| | | style={{ width: 160, marginRight: 8 }} |
| | | size="medium" |
| | | value={curDeviceType} |
| | | onChange={(event) => setCurDeviceType(event.target.value)} |
| | | > |
| | | {deviceTypeOptions.map((option) => ( |
| | | <MenuItem key={option.value} value={option.value}> |
| | | <span style={{ fontWeight: 'bold' }}>{option.label}</span> |
| | | </MenuItem> |
| | | ))} |
| | | </Select> |
| | | <Autocomplete |
| | | className="map-header-select" |
| | | style={{ width: 360 }} |
| | | size="medium" |
| | | options={filterDeviceList} |
| | | getOptionLabel={(option) => option.value} |
| | | renderOption={(props, option) => ( |
| | | <li {...props}>{option.label}</li> |
| | | )} |
| | | renderInput={(params) => ( |
| | | <TextField |
| | | {...params} |
| | | variant="filled" |
| | | placeholder={translate('common.msg.placeholder')} |
| | | InputProps={{ |
| | | ...params.InputProps, |
| | | endAdornment: ( |
| | | <> |
| | | {params.InputProps.endAdornment} |
| | | {inputValue && ( |
| | | <InputAdornment position="end"> |
| | | <IconButton |
| | | onClick={() => { |
| | | setInputValue(''); |
| | | setSelectedOption(null); |
| | | }} |
| | | > |
| | | <CloseIcon /> |
| | | </IconButton> |
| | | </InputAdornment> |
| | | )} |
| | | </> |
| | | ), |
| | | }} |
| | | /> |
| | | )} |
| | | value={selectedOption} |
| | | onChange={(event, newValue) => { |
| | | setSelectedOption(newValue); |
| | | onSecondSelect(newValue); |
| | | }} |
| | | inputValue={inputValue} |
| | | onInputChange={(event, newInputValue) => { |
| | | setInputValue(newInputValue); |
| | | }} |
| | | /> |
| | | </> |
| | | ); |
| | | }; |
| | | |
| | | export default MapSearch; |