Skip to content

Commit

Permalink
F #3951: Fix switcher component (#175)
Browse files Browse the repository at this point in the history
* Fix switcher component
* Fix header styles
* Add popover component in header
  • Loading branch information
Sergio Betanzos authored and rsmontero committed Sep 2, 2020
1 parent ef47322 commit 288b750
Show file tree
Hide file tree
Showing 20 changed files with 420 additions and 268 deletions.
14 changes: 12 additions & 2 deletions src/fireedge/src/public/components/FormControl/ErrorHelper.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React from 'react';
import { string } from 'prop-types';

import {
Box,
Expand Down Expand Up @@ -26,12 +27,13 @@ const useStyles = makeStyles(theme => {
},
text: {
...theme.typography.body1,
paddingLeft: theme.spacing(1)
paddingLeft: theme.spacing(1),
overflowWrap: 'anywhere'
}
};
});

const ErrorHelper = ({ label = 'Error', ...rest }) => {
const ErrorHelper = ({ label, ...rest }) => {
const classes = useStyles();

return (
Expand All @@ -44,4 +46,12 @@ const ErrorHelper = ({ label = 'Error', ...rest }) => {
);
};

ErrorHelper.propTypes = {
label: string
};

ErrorHelper.defaultProps = {
label: 'Error'
};

export default ErrorHelper;
19 changes: 7 additions & 12 deletions src/fireedge/src/public/components/FormControl/GroupSelect.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,16 @@
/* -------------------------------------------------------------------------- */

import React from 'react';
import { func } from 'prop-types';

import { MenuItem, TextField } from '@material-ui/core';
import { FilterVintage } from '@material-ui/icons';

import useAuth from 'client/hooks/useAuth';
import useOpennebula from 'client/hooks/useOpennebula';
import { Translate } from 'client/components/HOC';
import { Tr } from 'client/components/HOC';
import { FILTER_POOL } from 'client/constants';

const GroupSelect = ({ handleChange }) => {
const GroupSelect = props => {
const { filterPool, authUser } = useAuth();
const { groups } = useOpennebula();

Expand Down Expand Up @@ -53,25 +52,21 @@ const GroupSelect = ({ handleChange }) => {
<TextField
select
fullWidth
onChange={handleChange}
defaultValue={defaultValue}
variant="outlined"
inputProps={{ 'data-cy': 'select-group' }}
label={<Translate word="Select a group" />}
label={Tr('Select a group')}
FormHelperTextProps={{ 'data-cy': 'select-group-error' }}
{...props}
>
<MenuItem value={FILTER_POOL.ALL_RESOURCES}>{`Show all`}</MenuItem>
<MenuItem value={FILTER_POOL.ALL_RESOURCES}>{Tr('Show all')}</MenuItem>
{orderGroups}
</TextField>
);
};

GroupSelect.propTypes = {
handleChange: func
};
GroupSelect.propTypes = {};

GroupSelect.defaultProps = {
handleChange: () => undefined
};
GroupSelect.defaultProps = {};

export default GroupSelect;
35 changes: 0 additions & 35 deletions src/fireedge/src/public/components/Header/FilterPoolSelect.js

This file was deleted.

80 changes: 80 additions & 0 deletions src/fireedge/src/public/components/Header/Group.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import React from 'react';

import { Button } from '@material-ui/core';
import FilterIcon from '@material-ui/icons/FilterDrama';
import SelectedIcon from '@material-ui/icons/FilterVintage';

import useAuth from 'client/hooks/useAuth';
import useOpennebula from 'client/hooks/useOpennebula';
import Search from 'client/components/Search';

import { FILTER_POOL } from 'client/constants';
import HeaderPopover from 'client/components/Header/Popover';
import headerStyles from 'client/components/Header/styles';

const { ALL_RESOURCES, PRIMARY_GROUP_RESOURCES } = FILTER_POOL;

const Group = () => {
const classes = headerStyles();
const { authUser, filterPool, setPrimaryGroup } = useAuth();
const { groups } = useOpennebula();

const handleChangeGroup = group => {
group && setPrimaryGroup({ group });
};

const filterSearch = ({ NAME }, search) =>
NAME?.toLowerCase().includes(search);

const renderResult = ({ ID, NAME }, handleClose) => {
const isSelected =
(filterPool === ALL_RESOURCES && ALL_RESOURCES === ID) ||
(filterPool === PRIMARY_GROUP_RESOURCES && authUser?.GID === ID);

return (
<Button
key={`term-${ID}`}
fullWidth
className={classes.groupButton}
onClick={() => {
handleChangeGroup(ID);
handleClose();
}}
>
{NAME}
{isSelected && <SelectedIcon className={classes.groupSelectedIcon} />}
</Button>
);
};

const sortMainGroupFirst = groups
?.concat({ ID: ALL_RESOURCES, NAME: 'Show All' })
?.sort((a, b) => {
if (a.ID === authUser?.GUID) {
return -1;
} else if (b.ID === authUser?.GUID) {
return 1;
}
return 0;
});

return (
<HeaderPopover
id="group-list"
icon={<FilterIcon />}
IconProps={{ 'data-cy': 'header-group-button' }}
headerTitle="Switch group"
>
{({ handleClose }) => (
<Search
list={sortMainGroupFirst}
maxResults={5}
filterSearch={filterSearch}
renderResult={group => renderResult(group, handleClose)}
/>
)}
</HeaderPopover>
);
};

export default Group;
124 changes: 124 additions & 0 deletions src/fireedge/src/public/components/Header/Popover.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import React, { useState } from 'react';
import PropTypes from 'prop-types';

import {
Box,
IconButton,
useMediaQuery,
Popover,
Typography,
Button
} from '@material-ui/core';
import CloseIcon from '@material-ui/icons/Close';

import { Tr } from 'client/components/HOC';

import headerStyles from 'client/components/Header/styles';
import clsx from 'clsx';

const typeButton = {
button: Button,
iconButton: IconButton
};

const HeaderPopover = ({
id,
icon,
buttonLabel,
IconProps,
headerTitle,
disablePadding,
children
}) => {
const classes = headerStyles();
const isMobile = useMediaQuery(theme => theme.breakpoints.only('xs'));

const [anchorEl, setAnchorEl] = useState(null);

const handleOpen = event => setAnchorEl(event.currentTarget);
const handleClose = () => setAnchorEl(null);

const open = Boolean(anchorEl);
const anchorId = open ? id : undefined;

const ButtonComponent = React.useMemo(
() => (buttonLabel ? typeButton.button : typeButton.iconButton),
[buttonLabel]
);

return (
<>
<ButtonComponent
color="inherit"
aria-controls={anchorId}
aria-describedby={anchorId}
aria-haspopup="true"
onClick={handleOpen}
{...IconProps}
>
{icon}
{buttonLabel && (
<span className={classes.buttonLabel}>{buttonLabel}</span>
)}
</ButtonComponent>
<Popover
BackdropProps={{ invisible: !isMobile }}
PaperProps={{
className: clsx(classes.paper, {
[classes.padding]: !disablePadding
})
}}
id={anchorId}
open={open}
anchorEl={anchorEl}
onClose={handleClose}
anchorOrigin={{
vertical: 'bottom',
horizontal: 'right'
}}
transformOrigin={{
vertical: 'top',
horizontal: 'right'
}}
>
{(headerTitle || isMobile) && (
<Box className={classes.header}>
{headerTitle && (
<Typography className={classes.title} variant="body1">
{Tr(headerTitle)}
</Typography>
)}
{isMobile && (
<IconButton onClick={handleClose}>
<CloseIcon />
</IconButton>
)}
</Box>
)}
{children({ handleClose })}
</Popover>
</>
);
};

HeaderPopover.propTypes = {
id: PropTypes.string,
icon: PropTypes.node,
buttonLabel: PropTypes.string,
IconProps: PropTypes.objectOf(PropTypes.object),
headerTitle: PropTypes.string,
disablePadding: PropTypes.bool,
children: PropTypes.func
};

HeaderPopover.defaultProps = {
id: 'id-popover',
icon: null,
buttonLabel: undefined,
IconProps: {},
headerTitle: null,
disablePadding: false,
children: () => undefined
};

export default HeaderPopover;
Loading

0 comments on commit 288b750

Please sign in to comment.