@kinvolk/headlamp-plugin
Version:
The needed infrastructure for building Headlamp plugins.
120 lines (119 loc) • 6.44 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
/*
* Copyright 2025 The Kubernetes Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Icon } from '@iconify/react';
import Box from '@mui/material/Box';
import Button from '@mui/material/Button';
import FormControl from '@mui/material/FormControl';
import IconButton from '@mui/material/IconButton';
import ListItemSecondaryAction from '@mui/material/ListItemSecondaryAction';
import ListItemText from '@mui/material/ListItemText';
import MenuItem from '@mui/material/MenuItem';
import Select from '@mui/material/Select';
import TextField from '@mui/material/TextField';
import { useCallback, useEffect, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useDispatch } from 'react-redux';
import { getTablesRowsPerPage, setTablesRowsPerPage } from '../../../helpers/tablesRowsPerPage';
import { defaultTableRowsPerPageOptions, setAppSettings } from '../../../redux/configSlice';
export default function NumRowsInput(props) {
const { t } = useTranslation(['frequent']);
const { defaultValue } = props;
const [isSelectOpen, setIsSelectOpen] = useState(false);
const [options, setOptions] = useState(defaultValue);
const focusedRef = useCallback((node) => {
if (node !== null) {
node.focus();
}
}, []);
const defaultRowsPerPageValue = useMemo(() => {
const val = getTablesRowsPerPage();
if (options.includes(val)) {
return val;
}
return defaultTableRowsPerPageOptions[0];
}, []);
const [selectedValue, setSelectedValue] = useState(defaultRowsPerPageValue);
const storedCustomValue = useMemo(() => {
const val = options.find(val => !defaultTableRowsPerPageOptions.includes(val));
if (!val) {
return defaultTableRowsPerPageOptions[0];
}
return val;
}, []);
const [customValue, setCustomValue] = useState(storedCustomValue);
const [errorMessage, setErrorMessage] = useState('');
const [minRows, maxRows] = [5, 1000];
const dispatch = useDispatch();
useEffect(() => {
dispatch(setAppSettings({ tableRowsPerPageOptions: options }));
}, [options]);
// Make sure we update the value in the localStorage when the user selects a new value.
useEffect(() => {
if (selectedValue !== -1) {
setTablesRowsPerPage(selectedValue);
}
}, [selectedValue]);
const handleChange = (event) => {
const val = parseInt(event.target.value);
setSelectedValue(val);
};
const handleClose = () => {
setIsSelectOpen(false);
};
const handleOpen = () => {
setIsSelectOpen(true);
};
const suggestionMsg = t('translation|Enter a value between {{ minRows }} and {{ maxRows }}.', {
minRows,
maxRows,
});
return (
// we have assigned value -1 to select custom option
selectedValue === -1 ? (_jsxs(Box, { display: "inline-flex", alignItems: "baseline", children: [_jsx(TextField, { type: 'number', value: customValue, error: !!errorMessage, placeholder: t('translation|Custom row value'), helperText: errorMessage || suggestionMsg, inputProps: { min: minRows, max: maxRows }, inputRef: focusedRef, onChange: e => {
const val = parseInt(e.target.value);
if (Number.isInteger(val)) {
if (val < 5 || val > maxRows) {
setErrorMessage(suggestionMsg);
}
else {
setErrorMessage('');
}
setCustomValue(val);
}
else {
setCustomValue(undefined);
}
} }), _jsxs(Box, { display: "inline-flex", alignItems: "center", mx: 1, children: [_jsx(Button, { variant: "contained", disabled: !!errorMessage, size: "small", onClick: () => {
if (customValue === undefined) {
return;
}
const newOptions = [...new Set([...defaultTableRowsPerPageOptions, customValue])];
newOptions.sort((a, b) => a - b);
setOptions(newOptions);
setSelectedValue(customValue);
}, children: t('translation|Apply') }), _jsx(IconButton, { "aria-label": t('translation|Delete'), onClick: () => {
setOptions(defaultTableRowsPerPageOptions);
setSelectedValue(defaultTableRowsPerPageOptions[0]);
}, size: "medium", children: _jsx(Icon, { icon: "mdi:delete" }) })] })] })) : (_jsx(FormControl, { children: _jsxs(Select, { value: selectedValue, style: { width: '100px' }, open: isSelectOpen, onClose: handleClose, onOpen: handleOpen, onChange: handleChange, renderValue: value => `${value}`, size: "small", variant: "outlined", children: [options.map(option => {
const isCustom = !defaultTableRowsPerPageOptions.includes(option);
return (_jsxs(MenuItem, { value: option, children: [_jsx(ListItemText, { primary: option }), isCustom && (_jsx(ListItemSecondaryAction, { children: _jsx(IconButton, { size: "small", "aria-label": t('translation|Delete'), onClick: () => {
setOptions(defaultTableRowsPerPageOptions);
setSelectedValue(defaultTableRowsPerPageOptions[0]);
setIsSelectOpen(false);
}, children: _jsx(Icon, { icon: "mdi:delete" }) }) }))] }, option));
}), _jsx(MenuItem, { value: -1, children: t('translation|Custom value') }, 'custom')] }) })));
}