@material-ui/core#Collapse JavaScript Examples
The following examples show how to use
@material-ui/core#Collapse.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: LanguageSelector.js From covid-trials-dashboard with MIT License | 6 votes |
LanguageSelector = ({ languages, onSelect }) => {
const { t } = useTranslation('languages')
const [open, setOpen] = useState(false)
const classes = useStyles()
console.log({ languages })
return (
<>
<ListItem button onClick={() => setOpen(!open)}>
<ListItemIcon>
<LanguageOutlined />
</ListItemIcon>
<ListItemText primary={t('selectorTitle')} />
{open ? <ExpandLess /> : <ExpandMore />}
</ListItem>
<Collapse in={open} timeout={300} unmountOnExit>
<List component='div' disablePadding>
{languages.map(lan => (
<ListItem
key={lan}
button
className={classes.nested}
onClick={() => onSelect(lan)}
>
<ListItemText primary={t(lan)} />
</ListItem>
))}
</List>
</Collapse>
</>
)
}
Example #2
Source File: sidebar-item.js From horondi_client_fe with MIT License | 6 votes |
SideBarItem = ({ category, handlerItem, models, translationsKey, mainItemStyles }) => {
const { sort, page, countPerPage, categoryFilter, modelsFilter, defaultPage } = URL_QUERIES_NAME;
const { t } = useTranslation();
const styles = useStyles();
const [isListOpen, setIsListOpen] = useState(false);
const handleClick = () => {
setIsListOpen((prevValue) => setIsListOpen(!prevValue));
};
const countPerPageValue = ITEMS_PER_PAGE[0].value;
return (
<>
<li className={mainItemStyles}>
<ListItemText button='true' onClick={handleClick} primary={t(`${translationsKey}.name`)} />
{isListOpen ? <RemoveIcon onClick={handleClick} /> : <AddIcon onClick={handleClick} />}
</li>
<Collapse in={isListOpen} timeout='auto' unmountOnExit>
<List className={styles.list}>
{models.map((model) => (
<ListItem button className={styles.nested} key={model._id} onClick={handlerItem}>
<Link
to={`/catalog/products?${page}=${defaultPage}&${sort}=${POPULARITY}&${countPerPage}=${countPerPageValue}&${categoryFilter}=${category}&${modelsFilter}=${model._id}`}
>
<ListItemText primary={t(`${model.translationsKey}.name`)} />
</Link>
</ListItem>
))}
</List>
</Collapse>
<div className={styles.itemHighlighting} />
</>
);
}
Example #3
Source File: ListDropdown.js From mui-storyblok with MIT License | 6 votes |
ListDropdown = ({
rootClass,
listExpansion,
content,
dataBlokC,
dataBlokUid,
storyblokClass,
}) => {
const styles = StoryBlok.arrayToMuiStyles(rootClass);
const [open, setOpen] = useState(false);
const handleClick = () => {
setOpen(!open);
};
return (
<MuiList
className={`${styles.root} ${storyblokClass}`}
data-blok-c={dataBlokC}
data-blok-uid={dataBlokUid}
>
<ListExpansion {...listExpansion[0]} handleClick={handleClick} open={open} />
<Collapse in={open} timeout="auto" unmountOnExit>
{content.map((component, key) => renderComponents({ List }, component, key))}
</Collapse>
</MuiList>
);
}
Example #4
Source File: CollapsibleMenuItem.js From generator-webapp-rocket with MIT License | 6 votes |
CollapsibleMenuItem = ({ menu, ...rest }) => {
const [open, setOpen] = useState(false)
const toggleSubMenu = useCallback(() => setOpen(current => !current), [])
return (
<>
<MenuItem menu={menu} subMenuOpen={open} onToggleSubMenu={toggleSubMenu} {...rest} />
<Collapse in={open} timeout="auto" unmountOnExit>
<List disablePadding>
{menu?.children?.map((subMenu, key) => (
<MenuItem key={key} menu={subMenu} isSubMenuItem={true} {...rest} />
))}
</List>
</Collapse>
</>
)
}
Example #5
Source File: Filter.jsx From covid-trials-dashboard with MIT License | 6 votes |
Filter = ({ name, options, selected, onSelect }) => {
const [open, setOpen] = useState(false)
const classes = useStyles()
const handleClick = useCallback(() => setOpen(!open), [open])
return (
<>
<ListItem button onClick={handleClick}>
<ListItemText primary={name} />
{open ? <ExpandLess /> : <ExpandMore />}
</ListItem>
<Collapse in={open} timeout={300} unmountOnExit>
<List component='div' disablePadding>
{options.map(opt => (
<ListItem
key={opt}
button
className={classes.nested}
onClick={() => onSelect(opt)}
>
<ListItemIcon>
<Checkbox
edge='start'
checked={selected.includes(opt)}
tabIndex={-1}
/>
</ListItemIcon>
<ListItemText primary={opt} />
</ListItem>
))}
</List>
</Collapse>
</>
)
}
Example #6
Source File: TagList.js From ra-data-django-rest-framework with MIT License | 6 votes |
SubTree = ({ level, root, getChildNodes, openChildren, toggleNode }) => {
const childNodes = getChildNodes(root);
const hasChildren = childNodes.length > 0;
const open = openChildren.includes(root.id);
return (
<Fragment>
<ListItem
button={hasChildren}
onClick={() => hasChildren && toggleNode(root)}
style={{ paddingLeft: level * 16 }}
>
{hasChildren && open && <ExpandLess />}
{hasChildren && !open && <ExpandMore />}
{!hasChildren && <div style={{ width: 24 }}> </div>}
<ListItemText primary={root.name} />
<ListItemSecondaryAction>
<EditButton record={root} basePath="/tags" />
</ListItemSecondaryAction>
</ListItem>
<Collapse in={open} timeout="auto" unmountOnExit>
<MuiList component="div" disablePadding>
{childNodes.map(node => (
<SubTree
key={node.id}
root={node}
getChildNodes={getChildNodes}
openChildren={openChildren}
toggleNode={toggleNode}
level={level + 1}
/>
))}
</MuiList>
</Collapse>
</Fragment>
);
}
Example #7
Source File: AlertMessage.js From medha-STPC with GNU Affero General Public License v3.0 | 6 votes |
AlertMessage = props => {
let alertTitle = props.alertTitle;
return (
<Collapse in={props.openAlert}>
<Alert
variant={props.variant}
severity={alertTitle}
action={
<IconButton
aria-label={props.arialabel}
color={props.color}
size={props.size}
onClick={props.onClick}
>
<CloseIcon fontSize="inherit" />
</IconButton>
}
>
{props.children}
</Alert>
</Collapse>
);
}
Example #8
Source File: Disruption.js From warsinhk with MIT License | 5 votes |
Disruption = props => {
const { node, onCategoryClick } = props
const { i18n, t } = useTranslation()
const [expanded, setExpanded] = React.useState(false)
const handleExpandClick = () => {
setExpanded(!expanded)
}
const sourceUrl = withLanguage(i18n, node, "source_url")
const hasDescription = props.children && props.children.length > 0
const ExpandIcon = expanded ? InvertedExpandMoreIcon : ExpandMoreIcon
return (
<DisruptionCard>
<DisruptionCardHeader title={withLanguage(i18n, node, "name")} />
<DisruptionCardContent>
<Box alignItems="flex-start">
<Row>
<Chip
label={withLanguage(i18n, node, "category")}
size="small"
variant="outlined"
onClick={() =>
onCategoryClick(withLanguage(i18n, node, "category"))
}
/>
</Row>
<Row>
<DisruptionDetail variant="body1">
{withLanguage(i18n, node, "detail")}
</DisruptionDetail>
</Row>
<Row>
{t("disruption.status")}:{" "}
{withLanguage(i18n, node, "status") || "-"}
</Row>
<Row>
{t("disruption.to")}: {withLanguage(i18n, node, "to") || "-"}
</Row>
</Box>
</DisruptionCardContent>
<>
<DisruptionCardActions disableSpacing>
<DisruptionAction>
{sourceUrl && (
<Row>
<Typography variant="caption">
<Link component={Link} href={sourceUrl} target="_blank">
{t("disruption.source")}
</Link>
</Typography>
</Row>
)}
<Row>
<Typography variant="caption">
{t("disruption.last_updated", { date: node.last_update })}
</Typography>
</Row>
</DisruptionAction>
{hasDescription && (
<IconButton onClick={handleExpandClick} aria-expanded={expanded}>
<ExpandIcon />
</IconButton>
)}
</DisruptionCardActions>
{hasDescription && (
<Collapse in={expanded} timeout="auto" unmountOnExit>
<DisruptionCardContent>
{hasDescription && (
<Box alignItems="flex-start">{props.children}</Box>
)}
</DisruptionCardContent>
</Collapse>
)}
</>
</DisruptionCard>
)
}
Example #9
Source File: Comments.jsx From archeage-tools with The Unlicense | 5 votes |
render() {
const { postId } = this.props;
const { comments, commentCount, newComment, sortAsc } = this.state;
return (
<div className="section" id="comments">
<AppBar position="static">
<Toolbar variant="dense">
<Typography variant="h6" className="title-text">
Comments ({commentCount})
</Typography>
<Tooltip title={`Show ${sortAsc ? 'Newest' : 'Oldest'} First`}>
<IconButton color="inherit" onClick={this.setSortAsc(!sortAsc)}>
<SortIcon />
</IconButton>
</Tooltip>
<IfPerm permission="comment.create">
<Tooltip title="Write Comment">
<IconButton color="inherit" onClick={this.handleNewComment}>
<CreateIcon />
</IconButton>
</Tooltip>
</IfPerm>
</Toolbar>
</AppBar>
<Paper className="body-container space-children comments-container">
<Collapse in={newComment} unmountOnExit>
<EditComment
postId={postId}
depth={2}
onCancel={this.cancelNewComment}
onUpdateComments={this.updateComments}
/>
</Collapse>
{comments && comments.map(comment => (
<Comment
{...comment}
onUpdateComments={this.updateComments}
key={`comment-${comment.id}`}
depth={2}
sortAsc={sortAsc}
/>))}
{(!comments || comments.length === 0) &&
<Typography align="center">
There are no comments on this topic.
</Typography>}
</Paper>
</div>
);
}
Example #10
Source File: SidePanelItem.jsx From simplQ-frontend with GNU General Public License v3.0 | 5 votes |
SidePanelItem = ({
title,
description,
Icon,
expandable = false,
onClick,
children,
tourTag = '',
style = 'side-panel-item',
}) => {
const [open, setOpen] = useState(false);
const onClickHandler = () => {
if (expandable) {
setOpen(!open);
}
if (onClick) {
onClick();
}
};
return (
<div className={styles[style]}>
<div
reactour-selector={tourTag}
className={styles['header']}
tabIndex={0}
role="button"
onKeyDown={onClickHandler}
onClick={onClickHandler}
>
<Icon className={styles['icon']} fontSize="large" />
<div>
<h2>{title}</h2>
<p className={styles['description']}>{description}</p>
</div>
{expandable && <ExpandButton isOpen={open} />}
</div>
{expandable && (
<Collapse timeout="auto" in={open}>
{children}
</Collapse>
)}
</div>
);
}
Example #11
Source File: index.js From iiitt with MIT License | 5 votes |
export default function Faq(props) {
const { question, answer, questionNumber } = props;
const classes = createStyles(props);
const [expanded, setExpanded] = React.useState(false);
const toggleFaq = () => {
setExpanded(!expanded);
};
return (
<>
<Card className={classes.root}>
<CardContent
onClick={toggleFaq}
aria-expanded={expanded}
aria-label="Show answer"
>
<IconButton
onClick={toggleFaq}
aria-expanded={expanded}
aria-label="Show answer"
>
<KeyboardArrowRightIcon />
</IconButton>
{question}
</CardContent>
<Collapse
in={expanded}
timeout="auto"
unmountOnExit
className={classes.answer}
>
<CardContent className={classes.text}>
{answer}
{questionNumber === 11 ? <Link style={{display: 'inline'}} to='/contactus'>location page for more information.</Link> : null}
</CardContent>
</Collapse>
</Card>
</>
);
}
Example #12
Source File: ToolbarExtension.js From eSim-Cloud with GNU General Public License v3.0 | 5 votes |
function LibraryRow ({ library }) {
const dispatch = useDispatch()
const [open, setopen] = React.useState(false)
const classes = useStyles()
const components = useSelector(state => state.schematicEditorReducer.components)
const handleAppply = (lib) => {
dispatch(fetchLibrary(lib.id))
}
const handleUnapply = (lib) => {
dispatch(removeLibrary(lib.id))
}
const handleOpen = () => {
if (components[library.id].length === 0) { dispatch(fetchComponents(library.id)) }
setopen(!open)
}
return (
<Paper style={{ marginBottom: '.5rem' }}>
<ListSubheader>
<ListItem onClick={handleOpen} >
{open ? <ExpandLess /> : <ExpandMore />}
<ListItemText primary={library.library_name.slice(0, -4)} />
<ListItemSecondaryAction>
{(!library.default && !library.additional) &&
<Button variant="contained" size="small"
style={{ backgroundColor: '#ff1744', color: '#ffffff', margin: '.5rem' }}
onClick={() => { dispatch(deleteLibrary(library.id)) }} hidden={library.default || library.additional} >
Delete
</Button>
}
{library.active
? <Button variant="contained" size="small" color="secondary"
onClick={() => { handleUnapply(library) }} style={{ margin: '.5rem' }}>
Remove
</Button>
: <Button variant="contained" size="small" color="primary"
onClick={() => { handleAppply(library) }} style={{ margin: '.5rem' }}>
Use
</Button>
}
</ListItemSecondaryAction>
</ListItem>
</ListSubheader>
{(components[library.id]) &&
<Collapse in={open} timeout="auto" unmountOnExit>
<List component="div" style={{ paddingLeft: '1rem', paddingRight: '1rem' }}>
{components[library.id].map(component => {
return (
<ListItem alignItems='center' key={component.id} dense className={classes.nested}>
<ListItemText primary={component.name} secondary={component.description} />
</ListItem>
)
})}
</List>
</Collapse>
}
</Paper>
)
}
Example #13
Source File: SystemStatus.jsx From Edlib with GNU General Public License v3.0 | 5 votes |
SystemStatus = ({ name, loading, error, data }) => {
const [isExpanded, setIsExpanded] = React.useState(false);
if (loading) {
return (
<Paper>
<h2>{name}</h2>
</Paper>
);
}
if (error) {
return (
<Paper>
<Box display="flex" justifyContent="space-between">
<div>{name}</div>
<div>
<i className="fa fa-caret-down" />
</div>
</Box>
<Collapse in={isExpanded} timeout="auto">
<Typography>
Could not get service status. This might be because the
service is not set up properly or that you have no
internet connection.
</Typography>
</Collapse>
</Paper>
);
}
return (
<Paper>
<Box
display="flex"
justifyContent="space-between"
bgcolor={data.color + '.main'}
onClick={() => setIsExpanded(!isExpanded)}
>
<div>{name}</div>
<div>
<i className="fa fa-caret-down" />
</div>
</Box>
<Collapse in={isExpanded}>
<Table>
<TableHead>
<tr>
<th width={35} />
<th>Subservice name</th>
<th>Status</th>
<th>Parameters</th>
</tr>
</TableHead>
<TableBody>
{data.systems.map((s, index) => (
<TableRow key={index}>
<TableCell className={'bg-' + s.color} />
<TableCell>{s.name}</TableCell>
<TableCell>{s.statusMessage}</TableCell>
<TableCell>
{s.parameters &&
Object.entries(s.parameters).map(
([key, value]) => (
<div>
<strong>{key}: </strong>
{value}
</div>
)
)}
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</Collapse>
</Paper>
);
}
Example #14
Source File: CheckboxFacet.js From azure-search-react-template with MIT License | 5 votes |
export default function CheckboxFacet(props) {
let [isExpanded, setIsExpanded] = useState(false);
const checkboxes = props.values.map(facetValue => {
let isSelected = props.selectedFacets.some(facet => facet.value === facetValue.value);
return (
<FacetValueListItem dense disableGutters id={facetValue.value}>
<Checkbox
edge="start"
disableRipple
checked={isSelected}
onClick= {
isSelected ?
() => props.removeFilter({field: props.name, value: facetValue.value}) :
() => props.addFilter(props.name, facetValue.value)
}
/>
<ListItemText primary={facetValue.value + " (" + facetValue.count + ")"}/>
</FacetValueListItem>
);
});
return (
<div>
<FacetListItem disableRipple={true} button onClick={() => setIsExpanded(!isExpanded)}>
<ListItemText
primary={props.mapFacetName(props.name)}
/>
{isExpanded ? <ExpandLess /> : <ExpandMore />}
</FacetListItem>
<Collapse in={isExpanded} component="div">
<FacetValuesList>
{checkboxes}
</FacetValuesList>
</Collapse>
</div>
);
}
Example #15
Source File: CheckoutItem.jsx From resilience-app with GNU General Public License v3.0 | 5 votes |
export default function CheckoutItem({ cost, description, name, onChange, quantity }) {
const classes = useStyles();
const [open, setOpen] = useState(false);
const [width, setWidth] = useState(0);
const ref = useCallback((node) => node && setWidth(node.offsetWidth), []);
const crop = width / CHAR_WIDTH;
const formatedDescription =
description.length > crop ? description.slice(0, crop) + "..." : description;
return (
<>
<Divider />
<ListItem className={classes.listItem}>
{onChange ? (
<Select
className={classes.select}
native
variant="outlined"
value={quantity}
onChange={onChange}
inputProps={{
name: "quantity",
id: "quantity",
}}
>
{[...Array(MAX_ORDER + 1)].map((e, i) => (
<option value={i} key={i}>
{i}
</option>
))}
</Select>
) : (
<Typography className={classes.quantity} variant="h4">
{quantity}
</Typography>
)}
<RootRef rootRef={ref}>
<Box onClick={() => setOpen(!open)} flex={1} display="flex" flexDirection="column">
<Typography variant="h4" color="textPrimary">
{name}
</Typography>
{!open && formatedDescription}
<Collapse in={open} timeout={0}>
{description}
</Collapse>
<Expand open={open} />
</Box>
</RootRef>
<ListItemText className={classes.cost}>
<Typography variant={onChange ? "h4" : "body1"} color="textPrimary">
${parseFloat(cost).toFixed(2)}
</Typography>
</ListItemText>
</ListItem>
</>
);
}
Example #16
Source File: ConnectionsList.js From spl-token-wallet with Apache License 2.0 | 5 votes |
function ConnectionsListItem({ origin, connectedWallet }) {
const classes = useStyles();
const [open, setOpen] = useState(false);
// TODO better way to get high res icon?
const appleIconUrl = origin + '/apple-touch-icon.png';
const faviconUrl = origin + '/favicon.ico';
const [iconUrl, setIconUrl] = useState(appleIconUrl);
const { accounts } = useWalletSelector();
// TODO better way to do this
const account = accounts.find(
(account) => account.address.toBase58() === connectedWallet.publicKey,
);
const setAutoApprove = (autoApprove) => {
chrome.storage.local.get('connectedWallets', (result) => {
result.connectedWallets[origin].autoApprove = autoApprove;
chrome.storage.local.set({ connectedWallets: result.connectedWallets });
});
};
const disconnectWallet = () => {
chrome.storage.local.get('connectedWallets', (result) => {
delete result.connectedWallets[origin];
chrome.storage.local.set({ connectedWallets: result.connectedWallets });
});
};
return (
<>
<ListItem button onClick={() => setOpen((open) => !open)}>
<ListItemIcon>
<div className={classes.listItemIcon}>
<img
src={iconUrl}
onError={() => setIconUrl(faviconUrl)}
className={classes.listItemImage}
alt=""
/>
</div>
</ListItemIcon>
<div style={{ display: 'flex', flex: 1 }}>
<ListItemText primary={origin} secondary={account.name} />
</div>
{open ? <ExpandLess /> : <ExpandMore />}
</ListItem>
<Collapse in={open} timeout="auto" unmountOnExit>
<div class={classes.itemDetails}>
<div class={classes.buttonContainer}>
<Button
variant={connectedWallet.autoApprove ? 'contained' : 'outlined'}
color="primary"
size="small"
startIcon={<DoneAll />}
onClick={() => setAutoApprove(!connectedWallet.autoApprove)}
>
{connectedWallet.autoApprove ? 'Auto-Approved' : 'Auto-Approve'}
</Button>
<Button
variant="outlined"
color="secondary"
size="small"
startIcon={<DeleteIcon />}
onClick={disconnectWallet}
>
Disconnect
</Button>
</div>
</div>
</Collapse>
</>
);
}
Example #17
Source File: SidebarLink.js From react-code-splitting-2021-04-26 with MIT License | 4 votes |
export default function SidebarLink({
link,
icon,
label,
children,
location,
isSidebarOpened,
nested,
type,
}) {
var classes = useStyles();
// local
var [isOpen, setIsOpen] = useState(false);
var isLinkActive =
link &&
(location.pathname === link || location.pathname.indexOf(link) !== -1);
if (type === "title")
return (
<Typography
className={classnames(classes.linkText, classes.sectionTitle, {
[classes.linkTextHidden]: !isSidebarOpened,
})}
>
{label}
</Typography>
);
if (type === "divider") return <Divider className={classes.divider} />;
if (link && link.includes('http')) {
return (
<ListItem
button
className={classes.link}
classes={{
root: classnames(classes.linkRoot, {
[classes.linkActive]: isLinkActive && !nested,
[classes.linkNested]: nested,
}),
}}
disableRipple
>
<a className={classes.externalLink} href={link}>
<ListItemIcon
className={classnames(classes.linkIcon, {
[classes.linkIconActive]: isLinkActive,
})}
>
{nested ? <Dot color={isLinkActive && "primary"} /> : icon}
</ListItemIcon>
<ListItemText
classes={{
primary: classnames(classes.linkText, {
[classes.linkTextActive]: isLinkActive,
[classes.linkTextHidden]: !isSidebarOpened,
}),
}}
primary={label}
/>
</a>
</ListItem>
)
}
if (!children)
return (
<ListItem
button
component={link && Link}
to={link}
className={classes.link}
classes={{
root: classnames(classes.linkRoot, {
[classes.linkActive]: isLinkActive && !nested,
[classes.linkNested]: nested,
}),
}}
disableRipple
>
<ListItemIcon
className={classnames(classes.linkIcon, {
[classes.linkIconActive]: isLinkActive,
})}
>
{nested ? <Dot color={isLinkActive && "primary"} /> : icon}
</ListItemIcon>
<ListItemText
classes={{
primary: classnames(classes.linkText, {
[classes.linkTextActive]: isLinkActive,
[classes.linkTextHidden]: !isSidebarOpened,
}),
}}
primary={label}
/>
</ListItem>
);
return (
<>
<ListItem
button
component={link && Link}
onClick={toggleCollapse}
className={classes.link}
to={link}
disableRipple
>
<ListItemIcon
className={classnames(classes.linkIcon, {
[classes.linkIconActive]: isLinkActive,
})}
>
{icon ? icon : <InboxIcon />}
</ListItemIcon>
<ListItemText
classes={{
primary: classnames(classes.linkText, {
[classes.linkTextActive]: isLinkActive,
[classes.linkTextHidden]: !isSidebarOpened,
}),
}}
primary={label}
/>
</ListItem>
{children && (
<Collapse
in={isOpen && isSidebarOpened}
timeout="auto"
unmountOnExit
className={classes.nestedList}
>
<List component="div" disablePadding>
{children.map(childrenLink => (
<SidebarLink
key={childrenLink && childrenLink.link}
location={location}
isSidebarOpened={isSidebarOpened}
classes={classes}
nested
{...childrenLink}
/>
))}
</List>
</Collapse>
)}
</>
);
// ###########################################################
function toggleCollapse(e) {
if (isSidebarOpened) {
e.preventDefault();
setIsOpen(!isOpen);
}
}
}
Example #18
Source File: EventFeedback.js From medha-STPC with GNU Affero General Public License v3.0 | 4 votes |
EventFeedback = props => {
const [open, setOpen] = React.useState(true);
const history = useHistory();
const classes = useStyles();
const [setSelectedRows] = useState([]);
const { setLoaderStatus } = useContext(LoaderContext);
const [formState, setFormState] = useState({
dataToShow: [],
tempData: [],
events: [],
greenButtonChecker: true,
/** Filters */
eventFilterData: [],
selectedRowFilter: true,
filterDataParameters: {},
isClearResetFilter: false,
isFilterSearch: false,
startDate: null,
endDate: null,
texttvalue: "",
toggleCleared: false,
isEventCleared: "",
/** Pagination and sortinig data */
resetPagination: false,
isDataLoading: false,
pageSize: "",
totalRows: "",
page: "",
pageCount: "",
sortAscending: true,
errors: {}
});
/** Special feedbackState state variable to set parameters for feedback */
const [feedbackState, setFeedbackState] = useState({
/** Feedback */
/** showModalFeedback is used to enable the popup of modal for view/add/edit feedback.*/
showModalFeedback: false,
EventTitle: null,
eventId: null,
/** feedBackGiven , fromFeedBackModal this two flags are used to set the success and error messages*/
feedBackGiven: false,
fromFeedBackModal: false,
successErrorMessage: "",
/** showErrorModalFeedback this flag sets the error feedback modal ehich is used to dispaly the popup for error */
showErrorModalFeedback: false,
/** errorMessage is used to display what error needs to be shown for popup */
errorHeading: "",
errorMessage: "",
ratings: [],
/** showAddEditModalFeedback this flags enables the add/edit feedback modal. */
showAddEditModalFeedback: false,
/** Below three flags are used to identify whether to give, edit or to view feedback. */
isGiveFeedback: false,
isEditFeedback: false,
isViewFeedback: false,
/** This has the question set for adding feedback and also for editing feedback with answers also (for editing) */
entityQuestionSet: [],
/** questionSetId is while adding/editng */
questionSetId: null,
/** feedbackSetId is used while editing to identify where to store data against which feedback. */
feedbackSetId: null,
dataFor: "",
result: {}
});
useEffect(() => {
if (auth.getUserInfo() !== null) {
getEventData(10, 1);
} else {
auth.clearAppStorage();
history.push({
pathname: routeConstants.SIGN_IN_URL
});
}
}, []);
const getEventData = async (pageSize, page, paramsForEvents = null) => {
if (
paramsForEvents !== null &&
!formUtilities.checkEmpty(paramsForEvents)
) {
let defaultParams = {};
if (paramsForEvents.hasOwnProperty(SORT_FIELD_KEY)) {
defaultParams = {
page: page,
pageSize: pageSize
};
} else {
defaultParams = {
page: page,
pageSize: pageSize,
[SORT_FIELD_KEY]: "title:asc"
};
}
Object.keys(paramsForEvents).map(key => {
defaultParams[key] = paramsForEvents[key];
});
paramsForEvents = defaultParams;
} else {
paramsForEvents = {
page: page,
pageSize: pageSize,
[SORT_FIELD_KEY]: "title:asc"
};
}
setFormState(formState => ({
...formState,
isDataLoading: true
}));
if (auth.getUserInfo().role !== null) {
if (
auth.getUserInfo().role.name === roleConstants.RPCADMIN ||
(auth.getUserInfo().role.name === roleConstants.COLLEGEADMIN &&
auth.getUserInfo().studentInfo.organization.contact.id ===
auth.getUserInfo().rpc.main_college)
) {
const EVENTS_FOR_RPC_ADMIN =
strapiConstants.STRAPI_DB_URL +
strapiConstants.STRAPI_CONTACTS +
"/" +
auth.getUserInfo().rpc.id +
"/get-rpc-events";
await serviceProviders
.serviceProviderForGetRequest(EVENTS_FOR_RPC_ADMIN, paramsForEvents)
.then(res => {
formState.dataToShow = [];
formState.tempData = [];
let eventData = [];
eventData = convertEventData(res.data.result);
setFormState(formState => ({
...formState,
events: res.data.result,
pageSize: res.data.pageSize,
totalRows: res.data.rowCount,
page: res.data.page,
pageCount: res.data.pageCount,
dataToShow: eventData,
tempData: eventData,
isDataLoading: false
}));
})
.catch(error => {
console.log("error", error);
});
} else if (auth.getUserInfo().role.name === roleConstants.ZONALADMIN) {
const EVENTS_FOR_ZONAL_ADMIN =
strapiConstants.STRAPI_DB_URL +
strapiConstants.STRAPI_CONTACTS +
"/" +
auth.getUserInfo().zone.id +
"/get-zone-events";
await serviceProviders
.serviceProviderForGetRequest(EVENTS_FOR_ZONAL_ADMIN, paramsForEvents)
.then(res => {
formState.dataToShow = [];
formState.tempData = [];
let eventData = [];
eventData = convertEventData(res.data.result);
setFormState(formState => ({
...formState,
events: res.data.result,
pageSize: res.data.pageSize,
totalRows: res.data.rowCount,
page: res.data.page,
pageCount: res.data.pageCount,
dataToShow: eventData,
tempData: eventData,
isDataLoading: false
}));
})
.catch(error => {
console.log("error", error);
});
}
} else {
auth.clearAppStorage();
history.push({
pathname: routeConstants.SIGN_IN_URL
});
}
};
const convertEventData = data => {
let x = [];
if (data.length > 0) {
for (let i in data) {
var eventIndividualData = {};
let startDate = new Date(data[i]["start_date_time"]);
let endDate = new Date(data[i]["end_date_time"]);
eventIndividualData["id"] = data[i]["id"];
eventIndividualData["title"] = data[i]["title"] ? data[i]["title"] : "";
eventIndividualData["start_date_time"] = startDate.toDateString();
eventIndividualData["end_date_time"] = endDate.toDateString();
/** Several feedback flags are taken form the response itself */
/** can a college admin add/edit/cannot give feedback */
/** */
eventIndividualData["question_set"] = data[i]["question_set"]
? true
: false;
eventIndividualData["giveFeedback"] = false;
eventIndividualData["editFeedback"] = false;
eventIndividualData["cannotGiveFeedback"] = false;
eventIndividualData["feedbackId"] = data[i]["feedbackSetId"];
if (
auth.getUserInfo().role.name === roleConstants.RPCADMIN ||
(auth.getUserInfo().role.name === roleConstants.COLLEGEADMIN &&
auth.getUserInfo().studentInfo.organization.contact.id ===
auth.getUserInfo().rpc.main_college)
) {
/** Can college admin view feedback */
eventIndividualData["isFeedbackFromCollegePresent"] =
data[i]["isFeedbackFromCollegePresent"];
if (data[i]["question_set"] && !data[i]["isFeedbackProvidedbyRPC"]) {
eventIndividualData["giveFeedback"] = true;
} else if (
data[i]["question_set"] &&
data[i]["isFeedbackProvidedbyRPC"]
) {
eventIndividualData["editFeedback"] = true;
} else if (!data[i]["question_set"]) {
eventIndividualData["cannotGiveFeedback"] = true;
} else {
eventIndividualData["cannotGiveFeedback"] = true;
}
} else {
if (data[i]["question_set"] && !data[i]["isFeedbackProvidedbyZone"]) {
eventIndividualData["giveFeedback"] = true;
} else if (
data[i]["question_set"] &&
data[i]["isFeedbackProvidedbyZone"]
) {
eventIndividualData["editFeedback"] = true;
} else if (!data[i]["question_set"]) {
eventIndividualData["cannotGiveFeedback"] = true;
} else {
eventIndividualData["cannotGiveFeedback"] = true;
}
}
x.push(eventIndividualData);
}
return x;
}
};
/** Pagination */
const handlePerRowsChange = async (perPage, page) => {
/** If we change the now of rows per page with filters supplied then the filter should by default be applied*/
if (formUtilities.checkEmpty(formState.filterDataParameters)) {
await getEventData(perPage, page);
} else {
if (formState.isFilterSearch) {
await searchFilter(perPage, page);
} else {
await getEventData(perPage, page, formState.filterDataParameters);
}
}
};
const handlePageChange = async page => {
if (formUtilities.checkEmpty(formState.filterDataParameters)) {
await getEventData(formState.pageSize, page);
} else {
if (formState.isFilterSearch) {
await searchFilter(formState.pageSize, page);
} else {
await getEventData(
formState.pageSize,
page,
formState.filterDataParameters
);
}
}
};
const handleRowSelected = useCallback(state => {
if (state.selectedCount >= 1) {
setFormState(formState => ({
...formState,
selectedRowFilter: false,
toggleCleared: false
}));
} else {
setFormState(formState => ({
...formState,
selectedRowFilter: true
}));
}
setSelectedRows(state.selectedRows);
}, []);
const selectedRowCleared = data => {
formState.toggleCleared = data;
setTimeout(() => {
setFormState(formState => ({
...formState,
toggleCleared: false
}));
}, 2000);
};
/** For Adding feedback */
const viewFeedback = async cell => {
setLoaderStatus(true);
let result = {};
if (
auth.getUserInfo().role.name === roleConstants.RPCADMIN ||
(auth.getUserInfo().role.name === roleConstants.COLLEGEADMIN &&
auth.getUserInfo().studentInfo.organization.contact.id ===
auth.getUserInfo().rpc.main_college)
) {
result = {
[roleConstants.COLLEGEADMIN]: null
};
}
const QUESTION_SET_URL =
strapiConstants.STRAPI_DB_URL +
strapiConstants.STRAPI_EVENTS +
"/" +
cell.id +
"/" +
strapiConstants.STRAPI_RPC +
"/" +
auth.getUserInfo().rpc.id +
"/getCollegeFeedbackForRPC";
await serviceProviders
.serviceProviderForGetRequest(QUESTION_SET_URL)
.then(res => {
result[roleConstants.COLLEGEADMIN] = res.data.result;
setLoaderStatus(false);
})
.catch(error => {
result[roleConstants.COLLEGEADMIN] = [];
setLoaderStatus(false);
});
setFeedbackState(feedbackState => ({
...feedbackState,
isViewFeedback: true,
isEditFeedback: false,
isGiveFeedback: false,
showModalFeedback: true,
EventTitle: cell.title,
eventId: cell.id,
feedBackGiven: false,
fromFeedBackModal: false,
successErrorMessage: "",
result: result,
showErrorModalFeedback: false
}));
};
/** For Viewing feedback for Zonal Admin feedback */
const viewCollegeFeedback = async cell => {
setLoaderStatus(true);
const COLLEGE_FEEDBACK =
strapiConstants.STRAPI_DB_URL +
strapiConstants.STRAPI_EVENTS +
"/" +
cell.id +
"/getFeedbackForZone/" +
auth.getUserInfo().zone.id +
"/DataFor/college/FeedbackType/rating";
const ZONE_FEEDBACK =
strapiConstants.STRAPI_DB_URL +
strapiConstants.STRAPI_EVENTS +
"/" +
cell.id +
"/getFeedbackForZone/" +
auth.getUserInfo().zone.id +
"/DataFor/rpc/FeedbackType/rating";
let result = {};
if (auth.getUserInfo().role.name === roleConstants.ZONALADMIN) {
result = {
[roleConstants.RPCADMIN]: null,
[roleConstants.COLLEGEADMIN]: null
};
}
await serviceProviders
.serviceProviderForGetRequest(COLLEGE_FEEDBACK)
.then(res => {
result[roleConstants.COLLEGEADMIN] = res.data.result;
})
.catch(error => {
result[roleConstants.COLLEGEADMIN] = [];
});
await serviceProviders
.serviceProviderForGetRequest(ZONE_FEEDBACK)
.then(res => {
setLoaderStatus(false);
result[roleConstants.RPCADMIN] = res.data.result;
})
.catch(error => {
setLoaderStatus(false);
result[roleConstants.RPCADMIN] = [];
});
setFeedbackState(feedbackState => ({
...feedbackState,
isViewFeedback: true,
isEditFeedback: false,
isGiveFeedback: false,
showModalFeedback: true,
EventTitle: cell.title,
eventId: cell.id,
feedBackGiven: false,
fromFeedBackModal: false,
successErrorMessage: "",
result: result,
showErrorModalFeedback: false,
dataFor: "college"
}));
};
/** Give feedback */
const giveFeedback = async event => {
setLoaderStatus(true);
const QUESTION_SET_URL =
strapiConstants.STRAPI_DB_URL +
strapiConstants.STRAPI_EVENTS +
"/" +
event.id +
"/" +
strapiConstants.STRAPI_QUESTION_SET;
await serviceProviders
.serviceProviderForGetRequest(QUESTION_SET_URL)
.then(res => {
setFeedbackState(feedbackState => ({
...feedbackState,
showModalFeedback: true,
EventTitle: event.title,
eventId: event.id,
isGiveFeedback: true,
isEditFeedback: false,
isViewFeedback: false,
showErrorModalFeedback: false,
entityQuestionSet: res.data.result.questions,
questionSetId: res.data.result.id,
feedBackGiven: false,
fromFeedBackModal: false,
successErrorMessage: ""
}));
setLoaderStatus(false);
})
.catch(error => {
setFeedbackState(feedbackState => ({
...feedbackState,
showModalFeedback: false,
showErrorModalFeedback: true,
EventTitle: event.title,
isEditFeedback: false,
isGiveFeedback: false,
isViewFeedback: false,
feedBackGiven: false,
fromFeedBackModal: false,
successErrorMessage: "",
errorHeading: "Add Feedback",
errorMessage: "Cannot add feedback"
}));
setLoaderStatus(false);
console.log("error giving feedback");
});
};
/** ------ */
/** Edit feedback */
const editFeedback = async event => {
setLoaderStatus(true);
let FEEDBACK_SET_URL = "";
if (auth.getUserInfo().role.name === roleConstants.COLLEGEADMIN) {
FEEDBACK_SET_URL =
strapiConstants.STRAPI_DB_URL +
strapiConstants.STRAPI_FEEDBACK_SETS +
"/role/" +
auth.getUserInfo().rpcAdminRole.id;
} else {
FEEDBACK_SET_URL =
strapiConstants.STRAPI_DB_URL + strapiConstants.STRAPI_FEEDBACK_SETS;
}
await serviceProviders
.serviceProviderForGetOneRequest(FEEDBACK_SET_URL, event.feedbackId)
.then(res => {
setFeedbackState(feedbackState => ({
...feedbackState,
EventTitle: event.eventName,
eventId: event.id,
isGiveFeedback: false,
isEditFeedback: true,
isViewFeedback: false,
showModalFeedback: true,
showErrorModalFeedback: false,
feedbackSetId: event.feedbackId,
questionSetId: res.data.result.question_set.id,
entityQuestionSet: res.data.result.questions,
feedBackGiven: false,
fromFeedBackModal: false,
successErrorMessage: ""
}));
setLoaderStatus(false);
})
.catch(error => {
setFeedbackState(feedbackState => ({
...feedbackState,
showModalFeedback: false,
showErrorModalFeedback: true,
EventTitle: event.eventName,
isGiveFeedback: false,
isEditFeedback: false,
isViewFeedback: false,
feedBackGiven: false,
fromFeedBackModal: false,
successErrorMessage: "",
errorHeading: "Edit Feedback",
errorMessage: "Cannot edit feedback"
}));
setLoaderStatus(false);
console.log("error giving feedback");
});
};
/** ---------------------------------------------------- */
/** Used for restoring data */
const restoreData = () => {
getEventData(formState.pageSize, 1);
};
/** Filter methods and functions */
/** This restores all the data when we clear the filters*/
const clearFilter = () => {
selectedRowCleared(true);
setFormState(formState => ({
...formState,
isFilterSearch: false,
/** Clear all filters */
filterDataParameters: {},
/** Turns on the spinner */
isClearResetFilter: true,
isDataLoading: true,
texttvalue: "",
startDate: null,
endDate: null,
eventFilterData: [],
errors: {}
}));
restoreData();
};
/** Handle Start Date filter change */
const handleStartDateChange = (START_DATE_FILTER, event) => {
let startDate = moment(event).format("YYYY-MM-DDT00:00:00.000Z");
if (startDate === "Invalid date") {
startDate = null;
delete formState.filterDataParameters[START_DATE_FILTER];
} else {
formState.filterDataParameters[START_DATE_FILTER] = new Date(
startDate
).toISOString();
if (
formState.filterDataParameters.hasOwnProperty(END_DATE_FILTER) &&
formState.filterDataParameters[START_DATE_FILTER] >
formState.filterDataParameters[END_DATE_FILTER]
) {
formState.errors["dateFrom"] = [
"Start date cannot be greater than end date"
];
} else {
delete formState.errors["dateTo"];
delete formState.errors["dateFrom"];
}
}
setFormState(formState => ({
...formState,
startDate: event
}));
};
/** Handle End Date filter change */
const handleEndDateChange = (END_DATE_FILTER, event) => {
let endDate = moment(event)
.add(1, "days")
.format("YYYY-MM-DDT00:00:00.000Z");
if (endDate === "Invalid date") {
endDate = null;
delete formState.filterDataParameters[END_DATE_FILTER];
} else {
formState.filterDataParameters[END_DATE_FILTER] = new Date(
endDate
).toISOString();
if (
formState.filterDataParameters.hasOwnProperty(START_DATE_FILTER) &&
formState.filterDataParameters[END_DATE_FILTER] <
formState.filterDataParameters[START_DATE_FILTER]
) {
formState.errors["dateTo"] = [
"End date cannot be less than start date"
];
} else {
delete formState.errors["dateFrom"];
delete formState.errors["dateTo"];
}
}
setFormState(formState => ({
...formState,
endDate: event
}));
};
const checkEmpty = obj => {
return !Object.keys(obj).length ? true : false;
};
const handleFilterChangeForEventField = event => {
setFormState(formState => ({
...formState,
filterDataParameters: {
...formState.filterDataParameters,
[EVENT_FILTER]: event.target.value
}
}));
event.persist();
};
/** Search filter is called when we select filters and click on search button */
const searchFilter = async (perPage = formState.pageSize, page = 1) => {
if (!formUtilities.checkEmpty(formState.filterDataParameters)) {
formState.isFilterSearch = true;
await getEventData(perPage, page, formState.filterDataParameters);
} else {
await getEventData(perPage, page);
}
};
const handleSort = (
column,
sortDirection,
perPage = formState.pageSize,
page = 1
) => {
formState.filterDataParameters[SORT_FIELD_KEY] =
column.selector + ":" + sortDirection;
getEventData(perPage, page, formState.filterDataParameters);
};
const hasError = field => (formState.errors[field] ? true : false);
/**Handle Closed model */
const handleCloseFeedBackModal = (
status,
message,
isModalClosedWithoutGivingFeedbach
) => {
if (isModalClosedWithoutGivingFeedbach) {
setFeedbackState(feedbackState => ({
...feedbackState,
showAddEditModalFeedback: false,
isGiveFeedback: false,
isEditFeedback: false,
isViewFeedback: false,
showModalFeedback: false,
EventTitle: null,
eventId: null,
feedBackGiven: false,
fromFeedBackModal: false,
successErrorMessage: ""
}));
} else {
if (status) {
setOpen(true);
setFeedbackState(feedbackState => ({
...feedbackState,
showAddEditModalFeedback: false,
isGiveFeedback: false,
isEditFeedback: false,
isViewFeedback: false,
showModalFeedback: false,
EventTitle: null,
eventId: null,
feedBackGiven: true,
fromFeedBackModal: true,
successErrorMessage: message
}));
getEventData(
formState.pageSize,
formState.page,
formState.filterDataParameters
);
} else {
setFeedbackState(feedbackState => ({
...feedbackState,
showAddEditModalFeedback: false,
isGiveFeedback: false,
isEditFeedback: false,
isViewFeedback: false,
showModalFeedback: false,
EventTitle: null,
eventId: null,
feedBackGiven: false,
fromFeedBackModal: true,
successErrorMessage: message
}));
}
}
};
const handleCloseModal = () => {
setFeedbackState(feedbackState => ({
...feedbackState,
showModalFeedback: false,
showErrorModalFeedback: false,
showAddEditModalFeedback: false,
isGiveFeedback: false,
isEditFeedback: false,
isViewFeedback: false,
feedBackGiven: false,
fromFeedBackModal: false,
dataFor: ""
}));
};
/** Table Data */
const column = [
{
name: "Name",
sortable: true,
selector: "title",
cell: row => <ToolTipComponent data={row.title} />
},
{
name: "Start Date",
sortable: true,
selector: "start_date_time",
cell: row => <ToolTipComponent data={row.start_date_time} />
},
{
name: "End Date",
sortable: true,
selector: "end_date_time",
cell: row => <ToolTipComponent data={row.end_date_time} />
},
{
name: "Actions",
cell: cell => (
<div className={classes.DisplayFlex}>
{/** For RPC */}
{auth.getUserInfo().role.name === roleConstants.RPCADMIN ||
(auth.getUserInfo().role.name === roleConstants.COLLEGEADMIN &&
auth.getUserInfo().studentInfo.organization.contact.id ===
auth.getUserInfo().rpc.main_college) ? (
cell.isFeedbackFromCollegePresent ? (
<div className={classes.PaddingActionButton}>
<FeedBack
message={"View college feedback"}
id={cell.id}
isViewFeedback={true}
value={cell.title}
onClick={() => viewFeedback(cell)}
/>
</div>
) : !cell.question_set ? (
<div className={classes.PaddingActionButton}>
<FeedBack
feedbackNotAvailable={true}
message={"No question set with this event"}
id={cell.id}
isViewFeedback={true}
value={cell.title}
onClick={() => {}}
/>
</div>
) : (
<div className={classes.PaddingActionButton}>
<FeedBack
feedbackNotAvailable={true}
message={"No college feedback available"}
id={cell.id}
isViewFeedback={true}
value={cell.title}
onClick={() => {}}
/>
</div>
)
) : null}
{/** For Zone */}
{auth.getUserInfo().role.name === roleConstants.ZONALADMIN ? (
<React.Fragment>
<div className={classes.PaddingActionButton}>
<FeedBack
message={"View feedback"}
id={cell.id}
isViewFeedback={true}
value={cell.title}
onClick={() => viewCollegeFeedback(cell)}
/>
</div>
</React.Fragment>
) : null}
{auth.getUserInfo().role.name === roleConstants.RPCADMIN ||
auth.getUserInfo().role.name === roleConstants.ZONALADMIN ||
(auth.getUserInfo().role.name === roleConstants.COLLEGEADMIN &&
auth.getUserInfo().studentInfo.organization.contact.id ===
auth.getUserInfo().rpc.main_college) ? (
cell.giveFeedback ? (
<div className={classes.PaddingActionButton}>
<FeedBack
isGiveFeedback={true}
isEditFeedback={false}
cannotGiveFeedback={false}
id={cell.id}
value={cell.title}
onClick={() => giveFeedback(cell)}
/>
</div>
) : cell.editFeedback ? (
<div className={classes.PaddingActionButton}>
<FeedBack
isGiveFeedback={false}
isEditFeedback={true}
cannotGiveFeedback={false}
id={cell.id}
value={cell.title}
onClick={() => editFeedback(cell)}
/>
</div>
) : cell.cannotGiveFeedback ? (
<div className={classes.PaddingActionButton}>
<FeedBack
isGiveFeedback={false}
isEditFeedback={false}
cannotGiveFeedback={true}
isdisabled={true}
id={cell.id}
value={cell.title}
onClick={() => {}}
/>
</div>
) : null
) : null}
</div>
),
width: "20%",
cellStyle: {
width: "auto",
maxWidth: "auto"
}
}
];
return (
<Grid>
<Grid item xs={12} className={classes.title}>
<Typography variant="h4" gutterBottom>
Event Feedback
</Typography>
</Grid>
<Grid item xs={12} className={classes.formgrid}>
{feedbackState.fromFeedBackModal && feedbackState.feedBackGiven ? (
<Collapse in={open}>
<Alert
severity="success"
action={
<IconButton
aria-label="close"
color="inherit"
size="small"
onClick={() => {
setOpen(false);
}}
>
<CloseIcon fontSize="inherit" />
</IconButton>
}
>
{feedbackState.successErrorMessage}
</Alert>
</Collapse>
) : null}
{feedbackState.fromFeedBackModal && !feedbackState.feedBackGiven ? (
<Collapse in={open}>
<Alert
severity="error"
action={
<IconButton
aria-label="close"
color="inherit"
size="small"
onClick={() => {
setOpen(false);
}}
>
<CloseIcon fontSize="inherit" />
</IconButton>
}
>
{feedbackState.successErrorMessage}
</Alert>
</Collapse>
) : null}
<Card>
<CardContent className={classes.Cardtheming}>
<Grid className={classes.filterOptions} container spacing={1}>
<Grid item>
<TextField
label="Name"
margin="normal"
variant="outlined"
value={formState.filterDataParameters[EVENT_FILTER] || ""}
placeholder="Name"
className={classes.autoCompleteField}
onChange={handleFilterChangeForEventField}
/>
</Grid>
<Grid item className={classes.paddingDate}>
<InlineDatePicker
id="startDate"
label="Start Date"
placeholder="Start Date"
value={formState.startDate}
name={START_DATE_FILTER}
onChange={event =>
handleStartDateChange(START_DATE_FILTER, event)
}
error={hasError("dateFrom")}
helperText={
hasError("dateFrom")
? formState.errors["dateFrom"].map(error => {
return error + " ";
})
: null
}
/>
</Grid>
<Grid item className={classes.paddingDate}>
<InlineDatePicker
id="endDate"
label="End Date"
placeholder="End Date"
value={formState.endDate}
name={END_DATE_FILTER}
onChange={event =>
handleEndDateChange(END_DATE_FILTER, event)
}
error={hasError("dateTo")}
helperText={
hasError("dateTo")
? formState.errors["dateTo"].map(error => {
return error + " ";
})
: null
}
/>
</Grid>
<Grid item className={classes.filterButtonsMargin}>
<YellowButton
variant="contained"
color="primary"
disableElevation
disabled={checkEmpty(formState.errors) ? false : true}
onClick={event => {
event.persist();
searchFilter();
}}
>
Search
</YellowButton>
</Grid>
<Grid item className={classes.filterButtonsMargin}>
<GrayButton
variant="contained"
color="primary"
onClick={clearFilter}
disableElevation
>
Reset
</GrayButton>
</Grid>
</Grid>
</CardContent>
</Card>
<Card className={classes.tabledata} variant="outlined">
{formState.dataToShow ? (
formState.dataToShow.length ? (
<Table
data={formState.dataToShow}
column={column}
defaultSortField="title"
defaultSortAsc={formState.sortAscending}
paginationResetDefaultPage={formState.resetPagination}
onSelectedRowsChange={handleRowSelected}
onSort={handleSort}
sortServer={true}
paginationDefaultPage={formState.page}
paginationPerPage={formState.pageSize}
progressPending={formState.isDataLoading}
paginationTotalRows={formState.totalRows}
paginationRowsPerPageOptions={[10, 20, 50]}
onChangeRowsPerPage={handlePerRowsChange}
onChangePage={handlePageChange}
clearSelectedRows={formState.toggleCleared}
/>
) : (
<Spinner />
)
) : (
<div className={classes.noDataMargin}>No data to show</div>
)}
{/** Feedback modal calling */}
{feedbackState.isViewFeedback ? (
<ViewFeedBack
showModal={feedbackState.showModalFeedback}
modalClose={handleCloseModal}
Title={feedbackState.EventTitle}
id={feedbackState.eventId}
fromEvent={true}
fromActivity={false}
fromRPC={
auth.getUserInfo().role.name === roleConstants.RPCADMIN ||
(auth.getUserInfo().role.name === roleConstants.COLLEGEADMIN &&
auth.getUserInfo().studentInfo.organization.contact.id ===
auth.getUserInfo().rpc.main_college)
? true
: false
}
fromZone={
auth.getUserInfo().role.name === roleConstants.ZONALADMIN
? true
: false
}
result={feedbackState.result}
dataFor={feedbackState.dataFor}
dataToShow={feedbackState.ratings}
/>
) : null}
{feedbackState.isGiveFeedback ? (
<AddEditFeedBack
isAddFeedback={true}
showModal={feedbackState.showModalFeedback}
modalClose={handleCloseFeedBackModal}
Title={feedbackState.EventTitle}
id={feedbackState.eventId}
entityQuestionSet={feedbackState.entityQuestionSet}
questionSetId={feedbackState.questionSetId}
fromEvent={true}
fromActivity={false}
formMainCollege={
auth.getUserInfo().role.name === roleConstants.COLLEGEADMIN &&
auth.getUserInfo().studentInfo.organization.contact.id ===
auth.getUserInfo().rpc.main_college
? true
: false
}
/>
) : feedbackState.isEditFeedback ? (
<AddEditFeedBack
isEditFeedback={true}
showModal={feedbackState.showModalFeedback}
modalClose={handleCloseFeedBackModal}
Title={feedbackState.EventTitle}
id={feedbackState.eventId}
entityQuestionSet={feedbackState.entityQuestionSet}
questionSetId={feedbackState.questionSetId}
feedbackSetId={feedbackState.feedbackSetId}
fromEvent={true}
fromActivity={false}
formMainCollege={
auth.getUserInfo().role.name === roleConstants.COLLEGEADMIN &&
auth.getUserInfo().studentInfo.organization.contact.id ===
auth.getUserInfo().rpc.main_college
? true
: false
}
/>
) : null}
{!feedbackState.isGiveFeedback &&
!feedbackState.isEditFeedback &&
!feedbackState.showModalFeedback &&
feedbackState.showErrorModalFeedback ? (
<NoFeedback
showModal={feedbackState.showErrorModalFeedback}
modalClose={handleCloseModal}
Title={feedbackState.EventTitle}
errorHeading={"View Feedback"}
errorMessage={feedbackState.errorMessage}
/>
) : null}
</Card>
</Grid>
</Grid>
);
}
Example #19
Source File: index.js From yasn with MIT License | 4 votes |
export default function PostCard(props) {
const classes = useStyles();
const [expanded, setExpanded] = useState(false);
const [selected, setSelected] = useState(false);
const [likeCount, setLikeCount] = useState(props.likes.likers.length);
const comments = props.comments;
const handleExpandClick = () => {
setExpanded(!expanded);
};
useEffect(() => {
if (cookies.get('userDetails')) {
name = cookies.get('userDetails').name;
userId = cookies.get('userDetails')._id;
username = cookies.get('userDetails').username;
}
if (props.likes.likers.find((e) => e === userId)) setSelected(true);
}, []);
const handleLike = (selected) => {
let liked = !selected;
axios
.post(
`${ConnectServerUrl}/handlelike?` +
queryString.stringify({ _id: props._id, email, googleToken }),
{
currentUserId: cookies.get('userDetails')._id,
email,
liked,
//liked is true if user like , false if unliked ;
}
)
.then((res) => console.log(res))
.catch((err) => console.log(err));
};
return (
<Card className={classes.root + " card"}>
<CardHeader
avatar={
<Link to={`/user/${props.creator.username}`}>
<Avatar aria-label="recipe" className={classes.avatar}>
{props.creator
? props.creator.name
? props.creator.name[0]
: // + props.creator.name.split(" ")[1][0]
props.Name[0]
: // + props.Name.split(" ")[1][0]
props.Name
? props.Name
: 'X'}
</Avatar>
</Link>
}
action={
<IconButton aria-label="settings">
<MoreVertIcon />
</IconButton>
}
title={props.title}
subheader={
<Moment format="MMM D, YYYY" withTitle>
{props.date}
</Moment>
}
/>
{props.imageUrl ? (
<>
<CardMedia
className={classes.media}
image={
`https://res.cloudinary.com/${CloudName}/image/upload/c_crop,g_custom/v1/` +
props.imageUrl
}
title="AcadVault"
/>
</>
) : (
<>
<video width="300" height="200" controls>
<source
type="video/mp4"
data-reactid=".0.1.0.0.0"
src={
`https://res.cloudinary.com/${CloudName}/video/upload/q_auto/v1588194153/` +
props.videoUrl
}
></source>
</video>
</>
)}
<CardContent>
<Typography
className="desc"
variant="body2"
color="textSecondary"
component="p"
>
<Linkify properties={{ target: '_blank' }}>
{props.description ? props.description : ''}
</Linkify>
</Typography>
</CardContent>
<CardActions disableSpacing>
<Box alignItems="center" display={'flex'}>
<IconButton
style= {{paddingRight:0}}
onClick={() => {
handleLike(selected);
selected
? setLikeCount(likeCount - 1)
: setLikeCount(likeCount + 1);
setSelected(!selected);
}}
>
{selected ? (
<FavoriteIcon color="secondary" />
) : (
<FavoriteIcon />
)}
</IconButton>
<Box l={3} p={1} b={4}>
<Typography style={{ fontSize: '1.15rem' }}>
{likeCount}
</Typography>
</Box>
<Box display={'flex'}>
<IconButton aria-label="share">
<CommentIcon />
</IconButton>
<Typography style={{ fontSize: '1.15rem', marginTop: '.5rem' }}>
{' '}
{props.comments.length}
</Typography>
</Box>
</Box>
<IconButton
className={clsx(classes.expand, {
[classes.expandOpen]: expanded,
})}
onClick={handleExpandClick}
aria-expanded={expanded}
aria-label="show more"
>
<ExpandMoreIcon />
</IconButton>
</CardActions>
<Collapse in={expanded} timeout="auto" unmountOnExit>
<Divider/>
<CardContent>
<Typography variant="h6" className={classes.title}>
Comments
</Typography>
<AddComment
name={name}
postId={props._id}
userId={userId}
username={username}
/>
{comments
? comments.map((comment) => (
<Comment
{...comment}
key={comment.date}
// onClick={handleComments}
/>
))
: null}
</CardContent>
</Collapse>
</Card>
);
}
Example #20
Source File: SurveyPageView.jsx From defizap-frontend with GNU General Public License v2.0 | 4 votes |
SurveyPageView = props => {
const {
onAnswer,
surveyList,
reDoSurvey,
isLoading,
surveyComplete,
submitResults,
recommendedZaps,
activeStep,
moveToStep,
answers,
isResultsDisabled,
stats
} = props;
const getZap = () => {
return (
<>
<br /> <br />
<h4>
You might find these Zaps useful: <br />
</h4>
<Row className="justify-content-center">
{recommendedZaps.map(zap => {
if (stats)
stats.forEach(stat => {
if (zaps[zap].name === stat.name) zaps[zap].stats = stat;
});
return <Zap key={zaps[zap].name} {...zaps[zap]} />;
})}
</Row>
<br />
<Row className="justify-content-center pb-3">
<Button
variant="info"
target="_blank"
size="lg"
href="https://defizap.typeform.com/to/UZSZg5"
type="link"
className="m-3"
block
onClick={() =>
registerEvent({
category: GENERATE_ZAP,
action: SURVEY_PAGE
})
}
>
Don't see your Zap? Submit a request and we will create one!
</Button>
</Row>
<Row>
<h5 style={{ fontSize: 15 }} className="mx-3">
DISCLOSURE:
<p>
Please note that DeFiZap is an experimental project. DeFiZap is
not providing any investment advisory or recommendation service.
By using DeFiZap or its services, you agree that you are using the
Services at your own risk and that you will not and do not hold
DeFiZap or its team members liable should the services not perform
as per your expectation.
</p>
<p>
DeFiZap is not a licensed financial advisor under any law. Please
consult your own independent investment advisor before making any
investment decisions.
</p>
</h5>
</Row>
</>
);
};
const generateResult = () => {
return (
<>
<Button
variant="outline-primary"
onClick={reDoSurvey}
className="mx-1 my-3 px-1"
size="lg"
>
Start Over
</Button>
<Button
disabled={isResultsDisabled}
variant="primary"
onClick={submitResults}
className="mx-3 my-3 px-3"
size="lg"
>
Get Results
</Button>
{isLoading ? (
<>
<Spinner animation="grow" />
<Spinner animation="grow" />
</>
) : null}
</>
);
};
const surveySteps = () => {
return (
<Collapse in={!surveyComplete}>
<Stepper
activeStep={activeStep}
nonLinear
orientation="vertical"
style={{ backgroundColor: 'inherit' }}
>
{surveyList.map(question => {
return (
<Step
key={question.questionNumber}
completed={!isEmpty(answers[question.questionNumber])}
>
<StepLabel onClick={() => moveToStep(question.questionNumber)}>
<h5>{question.question}</h5>
<p className="text-monospace text-uppercase">
{answers[question.questionNumber]}
</p>
</StepLabel>
<StepContent>
{question.options.map(option => {
return (
<Button
key={option.value}
variant="outline-primary"
size="auto"
onClick={() => onAnswer(option.key)}
className="shadow"
block
>
{option.value}
</Button>
);
})}
</StepContent>
</Step>
);
})}
</Stepper>
</Collapse>
);
};
return (
<Container>
<NavigationBar />
<h4>
Answer a few multiple choice questions to see which Zap might fit your
needs
</h4>
{surveySteps()}
{activeStep === 4 ? generateResult() : null}
{surveyComplete ? getZap() : null}
</Container>
);
}
Example #21
Source File: Comment.jsx From archeage-tools with The Unlicense | 4 votes |
render() {
const {
id,
postId,
body,
author,
createDate,
editDate,
replies,
deleted,
depth,
onUpdateComments,
sortAsc,
} = this.props;
const { collapsed, reply, edit, deleteOpen } = this.state;
const isEdited = (editDate && editDate !== createDate) && !deleted;
return (
<div className="paper-border no-border comment-box">
<div className="collapsible-left">
<Avatar user={author} size={0.875} />
<Tooltip title={collapsed ? 'Expand' : 'Collapse'} placement="top">
<div className="collapse sm" onClick={this.setCollapsed(!collapsed)} />
</Tooltip>
</div>
<div className="collapsible-right">
<div>
<Username user={author} />
<Tooltip title={new Date(createDate).toLocaleString(navigator.language || 'en-US')}>
<Typography variant="caption" className="time">
{moment(createDate).fromNow()}
</Typography>
</Tooltip>
{isEdited &&
<Tooltip title={new Date(editDate).toLocaleString(navigator.language || 'en-US')}>
<Typography variant="caption" className="time edited">
(edited {moment(editDate).fromNow()})
</Typography>
</Tooltip>}
</div>
<Collapse in={!collapsed}>
{!edit
? <Viewer value={body} />
: <EditComment
{...this.props}
onCancel={this.setEdit(false)}
/>}
{!deleted &&
<div className="small-buttons">
<IfPerm permission="comment.create">
<Button
startIcon={<ReplyIcon />}
onClick={this.setReply(true)}
>
Reply
</Button>
</IfPerm>
<IfPerm permission="comment.edit" orUserIs={author}>
<Button
startIcon={<EditIcon />}
onClick={this.setEdit(true)}
>
Edit
</Button>
</IfPerm>
<IfPerm permission="comment.delete" orUserIs={author}>
<Button
startIcon={<DeleteIcon />}
onClick={this.setDelete(true)}
>
Delete
</Button>
</IfPerm>
</div>}
<Collapse in={reply} unmountOnExit>
<EditComment
postId={postId}
onUpdateComments={onUpdateComments}
onCancel={this.setReply(false)}
depth={depth + 1}
replyUser={author}
reply={id}
/>
</Collapse>
{replies && replies.sort(sortBy('createDate', sortAsc)).map(reply => (
<ConnectedComment
{...reply}
onUpdateComments={onUpdateComments}
key={`comment-${reply.id}`}
depth={depth + 1}
sortAsc={sortAsc}
/>
))}
</Collapse>
</div>
<Dialog
open={deleteOpen}
onClose={this.setDelete(false)}
>
<AppBar position="static">
<Toolbar variant="dense">
<Typography variant="subtitle1" className="title-text">Delete Comment</Typography>
<Tooltip title="Close">
<IconButton onClick={this.setDelete(false)}>
<CloseIcon />
</IconButton>
</Tooltip>
</Toolbar>
</AppBar>
<DialogContent style={{ minHeight: 92 }}>
<blockquote><Viewer value={body} /></blockquote>
<Typography>Are you sure you want to delete this comment?</Typography>
</DialogContent>
<DialogActions>
<Button onClick={this.setDelete(false)}>Cancel</Button>
<Button color="primary" onClick={this.handleDelete}>Delete</Button>
</DialogActions>
</Dialog>
</div>
);
}
Example #22
Source File: NavSection.js From course-manager with MIT License | 4 votes |
function NavItem({ item, active }) {
const theme = useTheme();
const isActiveRoot = active(item.path);
const { title, path, icon, info, children } = item;
const [open, setOpen] = useState(isActiveRoot);
const handleOpen = () => {
setOpen((prev) => !prev);
};
const activeRootStyle = {
color: 'primary.main',
fontWeight: 'fontWeightMedium',
bgcolor: alpha(theme.palette.primary.main, theme.palette.action.selectedOpacity),
'&:before': { display: 'block' }
};
const activeSubStyle = {
color: 'text.primary',
fontWeight: 'fontWeightMedium'
};
if (children) {
return (
<>
<ListItemStyle
onClick={handleOpen}
sx={{
...(isActiveRoot && activeRootStyle)
}}
>
<ListItemIconStyle>{icon && icon}</ListItemIconStyle>
<ListItemText disableTypography primary={title} />
{info && info}
<Box
component={Icon}
icon={open ? arrowIosDownwardFill : arrowIosForwardFill}
sx={{ width: 16, height: 16, ml: 1 }}
/>
</ListItemStyle>
<Collapse in={open} timeout="auto" unmountOnExit>
<List component="div" disablePadding>
{children.map((item) => {
const { title, path } = item;
const isActiveSub = active(path);
return (
<ListItemStyle
key={title}
component={RouterLink}
to={path}
sx={{
...(isActiveSub && activeSubStyle)
}}
>
<ListItemIconStyle>
<Box
component="span"
sx={{
width: 4,
height: 4,
display: 'flex',
borderRadius: '50%',
alignItems: 'center',
justifyContent: 'center',
bgcolor: 'text.disabled',
transition: (theme) => theme.transitions.create('transform'),
...(isActiveSub && {
transform: 'scale(2)',
bgcolor: 'primary.main'
})
}}
/>
</ListItemIconStyle>
<ListItemText disableTypography primary={title} />
</ListItemStyle>
);
})}
</List>
</Collapse>
</>
);
}
return (
<ListItemStyle
component={RouterLink}
to={path}
sx={{
...(isActiveRoot && activeRootStyle)
}}
>
<ListItemIconStyle>{icon && icon}</ListItemIconStyle>
<ListItemText disableTypography primary={title} />
{info && info}
</ListItemStyle>
);
}
Example #23
Source File: verticalCollapse.js From x-admin-device-donation with MIT License | 4 votes |
function VerticalCollapse({ activePath, ...props }) {
const [open, setOpen] = useState(() =>
needsToBeOpened(window.location, props.item)
);
const { item, nestedLevel, publicity } = props;
const classes = useStyles({
itemPadding: nestedLevel > 0 ? 40 + nestedLevel * 16 : 24,
});
useEffect(() => {
if (needsToBeOpened(window.location, item)) {
setOpen(true);
}
}, [item]);
function handleClick() {
setOpen(!open);
}
return (
<ul className={clsx(classes.root, open && "open")}>
<ListItem
button
disableRipple
style={{ color: "white", paddingTop: "0px", paddingBottom: "0px" }}
className={clsx(classes.item, "list-item")}
onClick={handleClick}
component="li"
to={`/${item.name}`}
role="button"
>
{/* {item.icon && createElement(CustomIcons[item.icon])} */}
<ListItemText
style={{ paddingLeft: "16px" }}
primary={item.name}
classes={{ primary: "text-14" }}
/>
<IconButton
disableRipple
style={{ color: "white" }}
className="w-40 h-40 p-0 focus:bg-transparent hover:bg-transparent"
onClick={(ev) => ev.preventDefault()}
>
{createElement(!open ? KeyboardArrowDownIcon : KeyboardArrowUpIcon)}
</IconButton>
</ListItem>
{item.children && (
<Collapse
in={open}
className="collapse-children"
style={{ marginLeft: "16px" }}
>
{item.children.map((i, index) => {
if (i.children) {
return (
<VerticalCollapse
key={index}
activePath={activePath}
item={i}
publicity={publicity}
nestedLevel={props.nestedLevel + 1}
permissions={permissions}
/>
);
}
return (
<VerticalItem
activePath={activePath}
key={index}
item={i}
nestedLevel={props.nestedLevel + 1}
/>
);
})}
</Collapse>
)}
</ul>
);
}
Example #24
Source File: Sidebar.jsx From Edlib with GNU General Public License v3.0 | 4 votes |
Sidebar = () => {
const classes = useStyles();
const history = useHistory();
const location = useLocation();
const [currentlyExpandedName, setCurrentlyExpandedName] =
React.useState(null);
React.useEffect(() => {
setCurrentlyExpandedName(null);
}, [location]);
const links = [
{ name: 'Dashboard', to: '/dashboard', icon: <Dashboard /> },
{ name: 'Content Author', to: '/content-author', icon: <Settings /> },
{
name: 'Settings',
to: '/settings',
icon: <Settings />,
subLinks: [
{
name: 'External applications',
to: '/external-applications',
},
],
},
{
name: 'Monitoring',
to: '/monitoring',
icon: <LocalOffer />,
subLinks: [{ name: 'Status of services', to: '/system-status' }],
},
{
name: 'Jobs',
to: '/jobs',
icon: <LocalOffer />,
subLinks: [
{ name: 'Resources', to: '/resources' },
{ name: 'Auth migration', to: '/auth-migration' },
],
},
{
name: 'Analytics',
to: '/analytics',
icon: <Assessment />,
subLinks: [{ name: 'Dashboard', to: '/dashboard' }],
},
];
return (
<List dense>
{links.map(({ name, icon, to, subLinks }) => {
const isInPath = !!matchPath(location.pathname, {
path: to,
strict: false,
});
const isExpanded = isInPath || currentlyExpandedName === name;
if (subLinks) {
return (
<React.Fragment key={name}>
<ListItem
button
selected={isInPath}
onClick={() => {
setCurrentlyExpandedName(
currentlyExpandedName === name
? null
: name
);
}}
>
{icon && <ListItemIcon>{icon}</ListItemIcon>}
<ListItemText
primary={name}
primaryTypographyProps={{
className: classes.parentItem,
}}
inset={!icon}
/>
{isExpanded ? <ExpandLess /> : <ExpandMore />}
</ListItem>
<Collapse
in={isExpanded}
timeout="auto"
unmountOnExit
>
<List component="div" disablePadding dense>
{subLinks.map((subLink) => {
const subTo = to + subLink.to;
const isInSubPath = !!matchPath(
location.pathname,
{
path: subTo,
strict: false,
}
);
return (
<ListItem
key={subLink.name}
button
onClick={() =>
history.push(subTo)
}
selected={isInSubPath}
>
<ListItemText
primary={subLink.name}
inset
/>
</ListItem>
);
})}
</List>
</Collapse>
</React.Fragment>
);
}
return (
<ListItem
key={name}
button
selected={isInPath}
onClick={() => history.push(to)}
>
{icon && <ListItemIcon>{icon}</ListItemIcon>}
<ListItemText
primary={name}
primaryTypographyProps={{
className: classes.parentItem,
}}
inset={!icon}
/>
</ListItem>
);
})}
</List>
);
}
Example #25
Source File: ComponentSidebar.js From eSim-Cloud with GNU General Public License v3.0 | 4 votes |
export default function ComponentSidebar ({ compRef, ltiSimResult, setLtiSimResult }) {
const classes = useStyles()
const libraries = useSelector(state => state.schematicEditorReducer.libraries)
const collapse = useSelector(state => state.schematicEditorReducer.collapse)
const components = useSelector(state => state.schematicEditorReducer.components)
const isSimulate = useSelector(state => state.schematicEditorReducer.isSimulate)
const auth = useSelector(state => state.authReducer)
const dispatch = useDispatch()
const [isSearchedResultsEmpty, setIssearchedResultsEmpty] = useState(false)
const [searchText, setSearchText] = useState('')
const [loading, setLoading] = useState(false)
const [favourite, setFavourite] = useState(null)
const [favOpen, setFavOpen] = useState(false)
const [searchedComponentList, setSearchedComponents] = useState([])
const [searchOption, setSearchOption] = useState('NAME')
const [uploaded, setuploaded] = useState(false)
const [def, setdef] = useState(false)
const [additional, setadditional] = useState(false)
// const searchedComponentList = React.useRef([])
const timeoutId = React.useRef()
const handleSearchOptionType = (evt) => {
setSearchedComponents([])
setSearchOption(evt.target.value)
}
const handleSearchText = (evt) => {
// tempSearchTxt = evt.target.value
if (searchText.length === 0) {
setSearchedComponents([])
}
setSearchText(evt.target.value)
setSearchedComponents([])
// mimic the value so we can access the latest value in our API call.
// call api from here. and set the result to searchedComponentList.
}
React.useEffect(() => {
if (auth.isAuthenticated) {
const token = localStorage.getItem('esim_token')
const config = {
headers: {
'Content-Type': 'application/json'
}
}
if (token) {
config.headers.Authorization = `Token ${token}`
}
api
.get('favouritecomponents', config)
.then((resp) => {
setFavourite(resp.data.component)
})
.catch((err) => {
console.log(err)
})
}
}, [auth])
React.useEffect(() => {
// if the user keeps typing, stop the API call!
clearTimeout(timeoutId.current)
// don't make an API call with no data
if (!searchText.trim()) return
// capture the timeoutId so we can
// stop the call if the user keeps typing
timeoutId.current = setTimeout(() => {
// call api here
setLoading(true)
let config = {}
const token = localStorage.getItem('esim_token')
if (token && token !== undefined) {
config = {
headers: {
Authorization: `Token ${token}`
}
}
}
api.get(`components/?${searchOptions[searchOption]}=${searchText}`, config)
.then(
(res) => {
if (res.data.length === 0) {
setIssearchedResultsEmpty(true)
} else {
setIssearchedResultsEmpty(false)
setSearchedComponents([...res.data])
}
}
)
.catch((err) => { console.error(err) })
setLoading(false)
}, 800)
}, [searchText, searchOption])
const handleCollapse = (id) => {
// Fetches Components for given library if not already fetched
if (collapse[id] === false && components[id].length === 0) {
dispatch(fetchComponents(id))
}
// Updates state of collapse to show/hide dropdown
dispatch(toggleCollapse(id))
}
// For Fetching Libraries
useEffect(() => {
dispatch(fetchLibraries())
}, [dispatch])
useEffect(() => {
if (libraries.filter((ob) => { return ob.default === true }).length !== 0) { setdef(true) } else { setdef(false) }
if (libraries.filter((ob) => { return ob.additional === true }).length !== 0) { setadditional(true) } else { setadditional(false) }
if (libraries.filter((ob) => { return (!ob.additional && !ob.default) }).length !== 0) { setuploaded(true) } else { setuploaded(false) }
}, [libraries])
// Used to chunk array
const chunk = (array, size) => {
return array.reduce((chunks, item, i) => {
if (i % size === 0) {
chunks.push([item])
} else {
chunks[chunks.length - 1].push(item)
}
return chunks
}, [])
}
const libraryDropDown = (library) => {
return (
<div key={library.id}>
<ListItem onClick={(e, id = library.id) => handleCollapse(id)} button divider>
<span className={classes.head}>{library.library_name.slice(0, -4)}</span>
{collapse[library.id] ? <ExpandLess /> : <ExpandMore />}
</ListItem>
<Collapse in={collapse[library.id]} timeout={'auto'} unmountOnExit mountOnEnter exit={false}>
<List component="div" disablePadding dense >
{/* Chunked Components of Library */}
{chunk(components[library.id], COMPONENTS_PER_ROW).map((componentChunk) => {
return (
<ListItem key={componentChunk[0].svg_path} divider>
{componentChunk.map((component) => {
return (
<ListItemIcon key={component.full_name}>
<SideComp component={component} setFavourite={setFavourite} favourite={favourite} />
</ListItemIcon>
)
})}
</ListItem>
)
})}
</List>
</Collapse>
</div>
)
}
const handleFavOpen = () => {
setFavOpen(!favOpen)
}
return (
<>
<Hidden smDown>
<div className={classes.toolbar} />
</Hidden>
<div style={isSimulate ? { display: 'none' } : {}}>
{/* Display List of categorized components */}
<List>
<ListItem button>
<h2 style={{ margin: '5px' }}>Components List</h2>
</ListItem>
<ListItem>
<TextField
id="standard-number"
placeholder="Search Component"
variant="outlined"
size="small"
value={searchText}
onChange={handleSearchText}
InputProps={{
startAdornment: (
<InputAdornment position="start">
<SearchIcon />
</InputAdornment>
)
}}
/>
</ListItem>
<ListItem divider>
<TextField
style={{ width: '100%' }}
id="searchType"
size='small'
variant="outlined"
select
label="Search By"
value={searchOption}
onChange={handleSearchOptionType}
SelectProps={{
native: true
}}
>
{
searchOptionsList.map((value, i) => {
return (<option key={i} value={value}>
{value}
</option>)
})
}
</TextField>
</ListItem>
<div style={{ maxHeight: '70vh', overflowY: 'auto', overflowX: 'hidden' }} >
{searchText.length !== 0 && searchedComponentList.length !== 0 &&
searchedComponentList.map((component, i) => {
return (<ListItemIcon key={i}>
<SideComp component={component} />
</ListItemIcon>)
}
)
}
<ListItem>
<Loader
type="TailSpin"
color="#F44336"
height={100}
width={100}
visible={loading}
/>
</ListItem>
{!loading && searchText.length !== 0 && isSearchedResultsEmpty &&
<span style={{ margin: '20px' }}>No Components Found</span>
}
{/* Collapsing List Mapped by Libraries fetched by the API */}
{favourite && favourite.length > 0 &&
<>
<ListItem button onClick={handleFavOpen} divider>
<span className={classes.head}>Favourite Components</span>
<div>
{favOpen ? <ExpandLess /> : <ExpandMore />}
</div>
</ListItem>
<Collapse in={favOpen} timeout="auto" unmountOnExit>
<List component="div" disablePadding>
<ListItem>
<div style={{ marginLeft: '-30px' }}>
{chunk(favourite, 3).map((componentChunk) => {
return (
<div key={componentChunk[0].svg_path}>
<ListItem key={componentChunk[0].svg_path} divider>
{
componentChunk.map((component) => {
return (
<ListItemIcon key={component.full_name}>
<SideComp isFavourite={true} favourite={favourite} setFavourite={setFavourite} component={component} />
</ListItemIcon>
)
}
)
}
</ListItem>
</div>
)
})}
</div>
</ListItem>
</List>
</Collapse>
</>
}
{searchText.length === 0 &&
<>
<div style={!def ? { display: 'none' } : {}}>
<Divider />
<ListItem dense divider style={{ backgroundColor: '#e8e8e8' }}>
<span>DEFAULT</span>
</ListItem>
<Divider />
{ libraries.sort(function (a, b) {
const textA = a.library_name.toUpperCase()
const textB = b.library_name.toUpperCase()
return (textA < textB) ? -1 : (textA > textB) ? 1 : 0
}).filter((library) => {
if (library.default) { return 1 }
return 0
}).map(
(library) => {
return (libraryDropDown(library))
}
)}
</div>
<div style={!additional ? { display: 'none' } : {}}>
<ListItem dense divider style={{ backgroundColor: '#e8e8e8' }}>
<span className={classes.head}>ADDITIONAL</span>
</ListItem>
{ libraries.sort(function (a, b) {
const textA = a.library_name.toUpperCase()
const textB = b.library_name.toUpperCase()
return (textA < textB) ? -1 : (textA > textB) ? 1 : 0
}).filter((library) => {
if (library.additional) { return 1 }
return 0
}).map(
(library) => {
return (libraryDropDown(library))
}
)}
</div>
<div style={!uploaded ? { display: 'none' } : {}}>
<ListItem dense divider style={{ backgroundColor: '#e8e8e8' }}>
<span className={classes.head}>UPLOADED</span>
</ListItem>
{ libraries.sort(function (a, b) {
const textA = a.library_name.toUpperCase()
const textB = b.library_name.toUpperCase()
return (textA < textB) ? -1 : (textA > textB) ? 1 : 0
}).filter((library) => {
if (!library.default && !library.additional) { return 1 }
return 0
}).map(
(library) => {
return (libraryDropDown(library))
}
)}
</div>
</>
}
</div>
</List>
</div>
<div style={isSimulate ? {} : { display: 'none' }}>
{/* Display simulation modes parameters on left side pane */}
<List>
<ListItem button divider>
<h2 style={{ margin: '5px auto 5px 5px' }}>Simulation Modes</h2>
<Tooltip title="close">
<IconButton color="inherit" className={classes.tools} size="small" onClick={() => { dispatch(toggleSimulate()) }}>
<CloseIcon fontSize="small" />
</IconButton>
</Tooltip>
</ListItem>
<SimulationProperties ltiSimResult={ltiSimResult} setLtiSimResult={setLtiSimResult} />
</List>
</div>
</>
)
}
Example #26
Source File: ViewActivityBatches.js From medha-STPC with GNU Affero General Public License v3.0 | 4 votes |
ViewActivityBatches = props => {
const [open, setOpen] = React.useState(true);
const classes = useStyles();
let history = useHistory();
const [formState, setFormState] = useState({
dataToShow: [],
batches: [],
batchesFilter: [],
filterDataParameters: {},
isFilterSearch: false,
/** This is when we return from edit page */
isDataEdited: props["location"]["fromEditActivityBatch"]
? props["location"]["isDataEdited"]
: false,
editedData: props["location"]["fromEditActivityBatch"]
? props["location"]["editedData"]
: {},
fromEditActivityBatch: props["location"]["fromEditActivityBatch"]
? props["location"]["fromEditActivityBatch"]
: false,
/** This is when we return from add page */
isDataAdded: props["location"]["fromAddActivityBatch"]
? props["location"]["isDataAdded"]
: false,
addedData: props["location"]["fromAddActivityBatch"]
? props["location"]["addedData"]
: {},
fromAddActivityBatch: props["location"]["fromAddActivityBatch"]
? props["location"]["fromAddActivityBatch"]
: false,
/** This is for delete */
isDataDeleted: false,
dataToEdit: {},
dataToDelete: {},
showModalDelete: false,
/** Pagination and sortinig data */
isDataLoading: false,
pageSize: "",
totalRows: "",
page: "",
pageCount: "",
sortAscending: true,
isActivityExist: true
});
const { activity } = props.match.params;
const [activityDetails, setActivityDetails] = useState(null);
const ACTIVITY_URL =
strapiConstants.STRAPI_DB_URL +
strapiConstants.STRAPI_ACTIVITY +
`/${activity}`;
const ACTIVITY_BATCH_URL =
strapiConstants.STRAPI_DB_URL +
strapiConstants.STRAPI_INDIVIDUAL_ACTIVITY +
`/${activity}/` +
strapiConstants.STRAPI_ACTIVITIES_BATCHES_URL;
useEffect(() => {
serviceProviders
.serviceProviderForGetRequest(ACTIVITY_URL)
.then(({ data }) => {
if (data.result == null) {
history.push("/404");
} else {
setActivityDetails(data.result);
}
})
.catch(() => {
history.push("/404");
});
}, []);
useEffect(() => {
serviceProviders
.serviceProviderForGetRequest(ACTIVITY_BATCH_URL)
.then(res => {
setFormState(formState => ({
...formState,
batchesFilter: res.data.result
}));
})
.catch(error => {
console.log("error", error);
});
getActivityBatches(10, 1);
}, []);
const [alert, setAlert] = useState({
isOpen: false,
message: "",
severity: ""
});
/** This seperate function is used to get the Activity Batches data*/
const getActivityBatches = async (pageSize, page, params = null) => {
if (params !== null && !formUtilities.checkEmpty(params)) {
let defaultParams = {
page: page,
pageSize: pageSize
};
Object.keys(params).map(key => {
return (defaultParams[key] = params[key]);
});
params = defaultParams;
} else {
params = {
page: page,
pageSize: pageSize
};
}
setFormState(formState => ({
...formState,
isDataLoading: true
}));
await serviceProviders
.serviceProviderForGetRequest(ACTIVITY_BATCH_URL, params)
.then(res => {
formState.dataToShow = [];
setFormState(formState => ({
...formState,
batches: res.data.result,
dataToShow: res.data.result,
pageSize: res.data.pageSize,
totalRows: res.data.rowCount,
page: res.data.page,
pageCount: res.data.pageCount,
isDataLoading: false
}));
})
.catch(error => {
console.log("error", error);
});
};
/** Pagination */
const handlePerRowsChange = async (perPage, page) => {
/** If we change the now of rows per page with filters supplied then the filter should by default be applied*/
if (formUtilities.checkEmpty(formState.filterDataParameters)) {
await getActivityBatches(perPage, page);
} else {
if (formState.isFilterSearch) {
await searchFilter(perPage, page);
} else {
await getActivityBatches(perPage, page);
}
}
};
const handlePageChange = async page => {
if (formUtilities.checkEmpty(formState.filterDataParameters)) {
await getActivityBatches(formState.pageSize, page);
} else {
if (formState.isFilterSearch) {
await searchFilter(formState.pageSize, page);
} else {
await getActivityBatches(formState.pageSize, page);
}
}
};
/** Search filter is called when we select filters and click on search button */
const searchFilter = async (perPage = formState.pageSize, page = 1) => {
if (!formUtilities.checkEmpty(formState.filterDataParameters)) {
formState.isFilterSearch = true;
await getActivityBatches(perPage, page, formState.filterDataParameters);
}
};
const clearFilter = () => {
setFormState(formState => ({
...formState,
isFilterSearch: false,
/** Clear all filters */
filterDataParameters: {},
/** Turns on the spinner */
isDataLoading: true
}));
/**Need to confirm this thing for resetting the data */
restoreData();
};
const restoreData = () => {
getActivityBatches(formState.pageSize, 1);
};
/**
* Redirect to Activity batch UI for given activity
*/
const handleEditActivityBatch = activityBatch => {
const url = `/edit-activity-batch/${activity}`;
history.push({
pathname: url,
editActivityBatch: true,
dataForEdit: activityBatch
});
};
const handleCloseDeleteModal = () => {
/** This restores all the data when we close the modal */
setFormState(formState => ({
...formState,
isDataDeleted: false,
showModalDelete: false
}));
if (formState.isDataDeleted) {
getActivityBatches(formState.pageSize, formState.page);
} else {
}
};
const isDeleteCellCompleted = (status, activityBatch) => {
formState.isDataDeleted = status;
if (status === true) {
setAlert(() => ({
isOpen: true,
message: `Activity Batch ${activityBatch.name} Deleted Successfully`,
severity: "success"
}));
} else if (status === false) {
setAlert(() => ({
isOpen: true,
message: activityBatch.response.data.message,
severity: "error"
}));
}
};
const handleDeleteActivityBatch = activityBatch => {
setFormState(formState => ({
...formState,
dataToDelete: { ...activityBatch },
showModalDelete: true
}));
};
// const handleDeleteActivityBatch = activityBatch => {
// const url =
// strapiConstants.STRAPI_DB_URL + strapiConstants.STRAPI_ACTIVITY_BATCH_URL;
// const activityBatchId = activityBatch.id;
// serviceProviders
// .serviceProviderForDeleteRequest(url, activityBatchId)
// .then(() => {
// setAlert(() => ({
// isOpen: true,
// message: `Batch ${activityBatch.name} deleted successfully`,
// severity: "success"
// }));
// getActivityBatches(10, 1);
// })
// .catch(({ response }) => {
// setAlert(() => ({
// isOpen: true,
// message: response.data.message,
// severity: "error"
// }));
// });
// };
const handleFilterChange = event => {
setFormState(formState => ({
...formState,
filterDataParameters: {
...formState.filterDataParameters,
[ACTIVITY_BATCH_FILTER]: event.target.value
}
}));
event.persist();
};
/** Columns to show in table */
const column = [
{ name: "Batch", sortable: true, selector: "name" },
{ name: "Activity", sortable: true, selector: "activity.title" },
{
cell: cell => (
<div className={classes.DisplayFlex}>
<div className={classes.PaddingFirstActionButton}>
<EditGridIcon
id={cell.id}
value={cell.name}
onClick={() => {
handleEditActivityBatch(cell);
}}
title="Manage Batch"
/>
</div>
<div className={classes.PaddingActionButton}>
<DeleteGridIcon
id={cell.id}
value={cell.title}
onClick={() => handleDeleteActivityBatch(cell)}
/>
</div>
</div>
),
button: true,
conditionalCellStyles: [],
width: "200px"
}
];
const handleAddActivityClick = () => {
const addActivityBatchURL = `/add-activity-batch/${activity}`;
history.push({
pathname: addActivityBatchURL,
editActivityBatch: false,
dataForEdit: null
});
};
const breadcrumbs = [
{ title: "Activity", href: "/manage-activity" },
{
title: `${activityDetails ? activityDetails.title : ""} Batches`,
href: "/"
}
];
const AlertAPIResponseMessage = () => {
return (
<Collapse in={alert.isOpen}>
<Alert
severity={alert.severity || "warning"}
action={
<IconButton
aria-label="close"
color="inherit"
size="small"
onClick={() => {
setAlert(() => ({ isOpen: false }));
}}
>
<CloseIcon fontSize="inherit" />
</IconButton>
}
>
{alert.message}
</Alert>
</Collapse>
);
};
return (
<Grid>
<div className={classes.breadCrumbs}>
{activityDetails ? <Breadcrumbs list={breadcrumbs} /> : null}
</div>
<Grid
container
spacing={3}
justify="space-between"
className={classes.title}
>
<Grid item>
<Typography variant="h4" gutterBottom>
{`${activityDetails ? activityDetails.title : ""} batches`}
</Typography>
</Grid>
<Grid item>
<GreenButton
variant="contained"
color="primary"
onClick={handleAddActivityClick}
disableElevation
to={`/add-activity-batch/${activity}`}
startIcon={<AddCircleOutlineOutlinedIcon />}
>
{genericConstants.ADD_ACTIVITY_BATCHES}
</GreenButton>
</Grid>
</Grid>
<Grid item xs={12} className={classes.formgrid}>
{/** Error/Success messages to be shown for edit */}
{formState.fromEditActivityBatch && formState.isDataEdited ? (
<Collapse in={open}>
<Alert
severity="success"
action={
<IconButton
aria-label="close"
color="inherit"
size="small"
onClick={() => {
setOpen(false);
}}
>
<CloseIcon fontSize="inherit" />
</IconButton>
}
>
Batch
{formState.editedData ? ` ${formState.editedData.name} ` : " "}
has been updated successfully.
</Alert>
</Collapse>
) : null}
{formState.fromEditActivityBatch && !formState.isDataEdited ? (
<Collapse in={open}>
<Alert
severity="error"
action={
<IconButton
aria-label="close"
color="inherit"
size="small"
onClick={() => {
setOpen(false);
}}
>
<CloseIcon fontSize="inherit" />
</IconButton>
}
>
An error has occured while updating activity batch. Kindly, try
again.
</Alert>
</Collapse>
) : null}
{/** Error/Success messages to be shown for add */}
{formState.fromAddActivityBatch && formState.isDataAdded ? (
<Collapse in={open}>
<Alert
severity="success"
action={
<IconButton
aria-label="close"
color="inherit"
size="small"
onClick={() => {
setOpen(false);
}}
>
<CloseIcon fontSize="inherit" />
</IconButton>
}
>
Batch {formState.addedData ? `${formState.addedData.name} ` : " "}
has been added successfully.
</Alert>
</Collapse>
) : null}
{formState.fromAddActivityBatch && !formState.isDataAdded ? (
<Collapse in={open}>
<Alert
severity="error"
action={
<IconButton
aria-label="close"
color="inherit"
size="small"
onClick={() => {
setOpen(false);
}}
>
<CloseIcon fontSize="inherit" />
</IconButton>
}
>
An error has occured while adding activity batch. Kindly, try
again.
</Alert>
</Collapse>
) : null}
{/* If there is error from any api show here */}
<AlertAPIResponseMessage />
<Card className={styles.filterButton}>
<CardContent className={classes.Cardtheming}>
<Grid className={classes.filterOptions} container spacing={1}>
<Grid item>
<TextField
label="Batch Name"
placeholder="Batch Name"
variant="outlined"
value={
formState.filterDataParameters[ACTIVITY_BATCH_FILTER] || ""
}
name={ACTIVITY_BATCH_FILTER}
className={classes.autoCompleteField}
onChange={handleFilterChange}
/>
</Grid>
<Grid item className={classes.filterButtonsMargin}>
<YellowButton
variant="contained"
color="primary"
disableElevation
onClick={event => {
event.persist();
searchFilter();
}}
>
{genericConstants.SEARCH_BUTTON_TEXT}
</YellowButton>
</Grid>
<Grid item className={classes.filterButtonsMargin}>
<GrayButton
variant="contained"
color="primary"
onClick={clearFilter}
disableElevation
>
{genericConstants.RESET_BUTTON_TEXT}
</GrayButton>
</Grid>
</Grid>
</CardContent>
</Card>
<Table
data={formState.dataToShow}
column={column}
defaultSortField="name"
defaultSortAsc={formState.sortAscending}
progressPending={formState.isDataLoading}
paginationTotalRows={formState.totalRows}
paginationRowsPerPageOptions={[10, 20, 50]}
onChangeRowsPerPage={handlePerRowsChange}
onChangePage={handlePageChange}
noDataComponent="No Activity Batch details found"
/>
</Grid>
<DeleteActivityBatch
showModal={formState.showModalDelete}
closeModal={handleCloseDeleteModal}
activityBatch={formState.dataToDelete}
deleteEvent={isDeleteCellCompleted}
/>
</Grid>
);
}
Example #27
Source File: nav-menu.js From horondi_admin with MIT License | 4 votes |
NavMenu = ({ width }) => {
const classes = useStyles();
const dispatch = useDispatch();
const [navbarTab, setNavbarTab] = useState({
clientTab: false,
catalogTab: false,
certificatesTab: false,
constructorTab: false,
staticTab: false,
materialsTab: false,
promoTab: false
});
const staticArray = {
clientTab: false,
catalogTab: false,
certificatesTab: false,
constructorTab: false,
staticTab: false,
materialsTab: false,
promoTab: false
};
const { sideMenuStatus, pendingQuestionsCount } = useSelector(
({ Theme, EmailQuestions }) => ({
sideMenuStatus: Theme.sideMenuStatus,
pendingQuestionsCount: EmailQuestions.pendingCount
})
);
const returnedList = (pathTitle, pathTo, PathIcon, nested) => (
<ListItem
onClick={() => {
dispatch(setSideMenuStatus(!sideMenuStatus));
dispatch(resetPagination());
if (!nested) {
setNavbarTab({
...staticArray
});
}
}}
button
key={pathTitle}
component={NavLink}
to={pathTo}
className={pathTitle === 'Слайдер' ? classes.sliderTab : nested || null}
activeClassName={classes.selectedCategory}
isActive={(props) => (props ? props.url === pathTo : null)}
>
<ListItemIcon>
<PathIcon />
</ListItemIcon>
<ListItemText primary={pathTitle} />
{pathTitle === titles.emailQuestionsTitles.mainPageTitle && (
<Badge badgeContent={pendingQuestionsCount} color='error' />
)}
</ListItem>
);
const menuItems = config.menuCategories.map((category) =>
returnedList(category[0], category[1], category[2])
);
const materialMenuItems = config.materialMenuCategories.map((category) =>
returnedList(...category, classes.nested)
);
const clientMenuItems = config.clientMenuCategories.map((category) =>
returnedList(category[0], category[1], category[2], classes.nested)
);
const catalogMenuItems = config.catalogMenuCategories.map((category) =>
returnedList(category[0], category[1], category[2], classes.nested)
);
const promoMenuItems = config.promoMenuCategories.map((category) =>
returnedList(...category, classes.nested)
);
const staticPagesMenuItems = config.staticPagesCategories.map((category) =>
returnedList(category[0], category[1], category[2], classes.nested)
);
const constructorPagesMenuItems = config.constructorMenuCategories.map(
(category) =>
returnedList(category[0], category[1], category[2], classes.nested)
);
const certificatesMenuItems = config.certificatesMenuCategories.map(
(category) =>
returnedList(category[0], category[1], category[2], classes.nested)
);
const parentMenuTabsProperties = [
[
() =>
setNavbarTab({
...staticArray,
clientTab: !navbarTab.clientTab
}),
navbarTab.clientTab,
clientMenuItems,
MENU_TABS.CLIENTS,
AccessibilityNewIcon
],
[
() =>
setNavbarTab({
...staticArray,
catalogTab: !navbarTab.catalogTab
}),
navbarTab.catalogTab,
catalogMenuItems,
MENU_TABS.CATALOG,
ImportContactsIcon
],
[
() =>
setNavbarTab({
...staticArray,
certificatesTab: !navbarTab.certificatesTab
}),
navbarTab.certificatesTab,
certificatesMenuItems,
MENU_TABS.CERTIFICATES,
TuneIcon
],
[
() =>
setNavbarTab({
...staticArray,
promoTab: !navbarTab.promoTab
}),
navbarTab.promoTab,
promoMenuItems,
MENU_TABS.PROMOCODE,
PromoIcon
],
[
() =>
setNavbarTab({
...staticArray,
constructorTab: !navbarTab.constructorTab
}),
navbarTab.constructorTab,
constructorPagesMenuItems,
MENU_TABS.CONSTRUCTOR,
AccessibilityNewIcon
],
[
() =>
setNavbarTab({
...staticArray,
materialsTab: !navbarTab.materialsTab
}),
navbarTab.materialsTab,
materialMenuItems,
MENU_TABS.MATERIALS,
ExtensionIcon
],
[
() =>
setNavbarTab({
...staticArray,
staticTab: !navbarTab.staticTab
}),
navbarTab.staticTab,
staticPagesMenuItems,
MENU_TABS.STATIC_PAGES,
LayersIcon
]
];
const parentMenuItems = parentMenuTabsProperties.map((category) => {
const handleClick = category[0];
const stateMenu = category[1];
const subList = category[2];
const primary = category[3];
const ItemIcon = category[4];
return (
<Fragment key={category.toString()}>
<ListItem button onClick={handleClick}>
<ListItemIcon>
<ItemIcon />
</ListItemIcon>
<ListItemText primary={primary} />
{stateMenu ? <ExpandLess /> : <ExpandMore />}
</ListItem>
<Collapse in={stateMenu} timeout='auto' unmountOnExit>
<List>{subList}</List>
</Collapse>
</Fragment>
);
});
const handleDrawerToggle = () => {
dispatch(setSideMenuStatus(!sideMenuStatus));
};
const checkWidth = () =>
TEMPORARY_WIDTHS.find((element) => element === width);
const drawerVariant = checkWidth() ? DRAWER_TEMPORARY : DRAWER_PERMANENT;
return (
<Drawer
id='menuDrawer'
className={classes.drawer}
variant={drawerVariant}
open={sideMenuStatus}
onClose={handleDrawerToggle}
classes={{
paper: classes.drawerPaper
}}
>
<div className={classes.toolbar} />
<Divider />
<List>
{menuItems}
{parentMenuItems}
</List>
<Divider />
</Drawer>
);
}
Example #28
Source File: Map.js From pwa with MIT License | 4 votes |
function Map() {
// FIXME you are using leaflet but you haven't imported it in this component because you have put it in index.html
// try to use react leaflet and help encapsulation components (and Separation of concerns)
const [chosenMap, setChosenMap] = useState(null);
const [map, setMap] = useState(null);
const [data, setData] = useState([]);
const [label, setLabel] = useState([]);
const [zoom, setZoom] = useState(0);
const [anchorEl, setAnchorEl] = useState(null);
const [isDataFetching, setIsDataFetching] = useState(false);
const [isDataProcessing, setisDataProcessing] = useState(false);
const [vpnAlert, setVpnAlert] = useState(true);
const {user, token} = useSelector((state) => state.MyActivities);
const {
isMapFetching,
isPrivateMapFetching,
mapList,
serverError,
} = useSelector((state) => state.Map);
const dispatch = useDispatch();
const drawPolygon = useCallback(
(color, polygons) => {
if (map && polygons) {
for (let polygon of polygons) {
let tooltip = null;
let width = null;
if (isNaN(polygon[polygon.length - 1][0])) {
tooltip = polygon[polygon.length - 1][0];
width = polygon[polygon.length - 1][1];
polygon = polygon.slice(0, polygon.length - 1);
}
window.L.polygon([polygon], {
fillColor: `#${(Number(color) % 0x1000000).toString(16)}`,
fill: true,
stroke: false,
fillOpacity: Number(color) / 0x1000000 / 255.0,
}).on('click', function (e) {
showTooltip(tooltip, width, e)
}).addTo(map);
}
}
},
[map]
);
var popup = map && window.L.popup();
function showTooltip(tooltip, width, e) {
if (tooltip !== null) {
let url = `${process.env.REACT_APP_MAP_IMAGE_CDN}${tooltip}`;
popup
.setLatLng(e.latlng)
.setContent("<div>" +
"<img style=\"max-width: 1000px; width: " + width + "px;\" alt=\"stats\" src=" + url + " /> </div>")
.openOn(map);
}
}
const clearPolygon = useCallback(() => {
if (map) {
d3.selectAll('.leaflet-interactive').remove();
}
}, [map]);
const clearLabel = useCallback(() => {
if (map) {
d3.selectAll('.leaflet-tooltip').remove();
}
}, [map]);
const getData = (url, result, cached = false) => {
setIsDataFetching(false);
if (!result) return undefined;
// Add to cache if map does not exist
!cached &&
db.set({
data: result,
fileName: url,
mapName: chosenMap.id,
});
setisDataProcessing(true);
const line = result;
const lineNumber = line.length;
let zzoom = null;
let polygons = [];
let sPolygons = [];
let labels = [];
for (let i = 0; i <= lineNumber; i++) {
if (i === lineNumber || line[i].length === 1) {
if (i > 0) {
let sameColor = {};
polygons.push(...sPolygons);
for (let j = 0; j < polygons.length; j++) {
let color = polygons[j][0];
let points = [];
for (let k = 1; k < polygons[j].length; k += 2)
points.push([polygons[j][k], polygons[j][k + 1]]);
if (color in sameColor)
sameColor[color].push(points);
else
sameColor[color] = [points];
}
setData((prevData) => [...prevData, [zzoom, sameColor]]);
setLabel((prevLabel) => [...prevLabel, [zzoom, labels]]);
polygons = [];
sPolygons = [];
labels = [];
}
if (i < lineNumber)
zzoom = Number(line[i][0]);
continue;
}
if (line[i][0] === 'P') {
polygons.push(line[i].slice(1));
}
if (line[i][0] === 'S') {
sPolygons.push(line[i].slice(1));
}
if (line[i][0] === 'L') {
labels.push({
text: line[i][1],
point: [line[i][2], line[i][3]],
size: line[i][4],
color: `#${(Number(line[i][5]) % 0x1000000).toString(16)}`,
opacity: Number(line[i][5]) / 0x1000000 / 255.0,
})
}
}
setisDataProcessing(false);
setData((prevData) => [...prevData]);
setLabel((prevData) => [...prevData]);
};
const parseFile = async (url, key) => {
setData([]);
setLabel([]);
setIsDataFetching(true);
const _cached = await db.get(url);
if (_cached.length) {
getData(url, _cached[0].data, true);
} else {
if (key) {
const response = await axios({
url,
method: 'GET',
responseType: 'blob',
});
const decrypted = decryptPrivateMap(response.data, key);
decrypted &&
Papa.parse(decrypted, {
complete: (result) => getData(url, result.data, false),
});
} else {
Papa.parse(url, {
download: true,
complete: (result) => getData(url, result.data, false),
});
}
}
};
const findZoomLevels = useCallback(() => {
const result = [];
data.map((element) => result.push(element[0]));
return result;
}, [data]);
const findZoom = useCallback(() => {
const inverseZoomLevel = 10 * Math.pow(2, -(map && map.getZoom()));
const zoomLevels = data && findZoomLevels();
for (let i = 0; i < zoomLevels.length - 1; i++) {
if (inverseZoomLevel <= zoomLevels[i]) {
setZoom(i);
break;
} else if (
inverseZoomLevel > zoomLevels[i] &&
inverseZoomLevel <= zoomLevels[i + 1]
) {
setZoom(i + 1);
break;
} else {
setZoom(zoomLevels.length - 1)
}
}
}, [map, data, findZoomLevels]);
useEffect(() => {
findZoom();
}, [findZoom, data]);
useEffect(() => {
map &&
map.on('zoom', function () {
findZoom();
});
});
const hasPrivateAccess = () => {
return (
user &&
user.permissions.filter((perm) => perm === 'webmap').length &&
user.permissions.some((perm) => {
return perm.includes('maps_');
})
);
};
useEffect(() => {
dispatch(fetchMaps());
hasPrivateAccess() && dispatch(fetchPrivateMaps(token));
setMap(
new window.L.Map('map', {
key: process.env.REACT_APP_MAP_TOKEN,
maptype: 'dreamy',
poi: true,
traffic: false,
zoomControl: false,
center: [32.4279, 53.688],
zoom: 4.2,
})
);
}, [dispatch]);
useEffect(() => {
mapList && setChosenMap(mapList[0]);
}, [mapList]);
useEffect(() => {
chosenMap &&
parseFile(
`${process.env.REACT_APP_MAP_CDN}${chosenMap.id}.${chosenMap.version}.csv`,
chosenMap.key
);
}, [chosenMap]);
useEffect(() => {
if (isDataProcessing)
return;
clearPolygon();
if (!((data || {})[zoom] || [])[1]) {
return;
}
console.log("drawpolygon")
for (let key in data[zoom][1]) {
if (Object.prototype.hasOwnProperty.call(data[zoom][1], key))
drawPolygon(key, data[zoom][1][key]);
}
}, [map, zoom, data, clearPolygon, drawPolygon]);
useEffect(() => {
if (isDataProcessing)
return;
clearLabel();
if (!((label || {})[zoom] || [])[1]) {
return;
}
// TODO clean this shit
let root = document.documentElement;
root.style.setProperty('--label-color', '#000000');
root.style.setProperty('--label-size', 10);
for (let entry of label[zoom][1]) {
window.L.marker(entry.point, {
opacity: 0,
}).bindTooltip(entry.text, {
permanent: true,
className: 'map-label',
direction: 'top',
}).addTo(map);
}
}, [map, label, zoom, clearLabel]);
const handleLocate = async () => {
const myLatLngLocation = await utility.getCurrentPosition();
map.flyTo(myLatLngLocation, 15);
};
const clickMenu = (event) => {
setAnchorEl(event.currentTarget);
};
const closeMenu = (value) => {
value && setChosenMap(value);
setAnchorEl(null);
};
const renderMenu = () => {
return (
<Menu
classes={{
paper: 'map-menu',
}}
anchorEl={anchorEl}
keepMounted
open={Boolean(anchorEl)}
onClose={() => closeMenu()}
>
{mapList &&
mapList.map((item) => {
return (
<MenuItem
key={item.id}
classes={{root: 'map-menu-item'}}
onClick={() => closeMenu(item)}
>
{item.name}
</MenuItem>
);
})}
</Menu>
);
};
return (
<div className={`contentWrapper MapWrapper`}>
<div className="alerts">
<Collapse
className="map-alert-wrapper"
in={isDataFetching || isMapFetching || isPrivateMapFetching}
addEndListener={null}
>
<Alert
severity="info"
action={
<IconButton
color="inherit"
size="small"
onClick={() => {
setIsDataFetching(false);
}}
>
<CloseIcon fontSize="inherit"/>
</IconButton>
}
>
تا دریافت اطلاعات منتظر بمانید.
</Alert>
</Collapse>
{serverError && (
<Collapse
className="map-alert-wrapper"
in={vpnAlert}
addEndListener={null}
>
<Alert
severity="warning"
action={
<IconButton
color="inherit"
size="small"
onClick={() => {
setVpnAlert(false);
}}
>
<CloseIcon fontSize="inherit"/>
</IconButton>
}
>
در صورت اتصال، vpn دستگاه را قطع کنید.
</Alert>
</Collapse>
)}
</div>
<div className="map-button-wrapper">
<button
type="button"
className="map-button"
onClick={() => handleLocate()}
>
<MyLocationIcon/>
</button>
<button
type="button"
name="chosenMap"
className="map-button type"
onClick={(e) => clickMenu(e)}
>
<div>{(chosenMap || {}).name}</div>
<ExpandMoreIcon/>
</button>
</div>
<div
id="map"
style={{
position: 'fixed',
top: 0,
right: 0,
width: '100vw',
height: '100vh',
zIndex: 0,
}}
/>
<div className="comment-wrapper">
<div className="map-comment">{(chosenMap || {}).comment || 'ــ'}</div>
</div>
<div className="logo-wrapper right">
<img src={logo} alt=""/>
</div>
<div className="logo-wrapper left">
<img src={neshanLogo} alt=""/>
</div>
{renderMenu()}
</div>
);
}
Example #29
Source File: UserMenu.js From generator-webapp-rocket with MIT License | 4 votes |
function UserMenu({ drawerOpen, avatar, language, changeLanguage, withGradient }) {
const [openAvatar, setOpenAvatar] = useState(false);
const classes = useStyles();
const { t } = useTranslation();
const location = useLocation();
const { oidcUser, logout } = useReactOidc();
<%_ if (withRights){ _%>
const userRoles = oidcUser?.profile?.role || emptyArray;<%_ } _%>
const activeRoute = useCallback(routeName => location.pathname.indexOf(routeName) > -1, [location.pathname])
<%_ if (withRights){ _%>
const { userData } = useUserData();
const userRights = userData?.rights || emptyArray
<%_ } _%>
<% if (withRights){ _%>
const userMenuItems = userMenuConfig.filter(item => isEmpty(item.rights)
? intersect(userRoles, item.roles) || isEmpty(item.roles)
: (intersect(userRoles, item.roles) && intersect(userRights, item.rights)) || isEmpty(item.roles)
)<%_ } else { _%>
const userMenuItems = userMenuConfig
<%_ } _%>
const openCollapseAvatar = useCallback(e => {
setOpenAvatar(!openAvatar);
e.preventDefault();
}, [openAvatar])
<%_ if (withMultiTenancy) { _%>
const setContextTenant = useContext(TenantContext)
// // TODO: might have the issue https://github.com/apollographql/apollo-client/issues/5179
const [callMyTenantsQuery, { called, loading: tenantsLoading, data }] = useLazyQuery(MY_TENANTS_QUERY)
useEffect(() => {
if (!oidcUser || called || tenantsLoading) { return }
callMyTenantsQuery();
}, [callMyTenantsQuery, called, tenantsLoading, oidcUser])
const myTenants = data?.myTenants
<%_}_%>
<%_ if (withMultiTenancy) { _%>
const logoutAction = useCallback(e => {
e.preventDefault();
logout();
setContextTenant();
}, [logout, setContextTenant])
<%_} else { _%>
const logoutAction = useCallback(e => {
e.preventDefault();
logout();
}, [logout])
<%_}_%>
const userName = oidcUser?.profile?.firstName
? `${oidcUser.profile.name} ${oidcUser.profile.lastName}`
: oidcUser?.profile
? oidcUser.profile.name.split('@')[0]
: "User";
<%_ if (withMultiTenancy) { _%>
const [tenant, setTenant] = useState(myTenants && oidcUser?.profile?.tid && myTenants.find(t => t.externalId.toUpperCase() === oidcUser?.profile?.tid.toUpperCase()))
useEffect(() => {
const localTenant = myTenants && oidcUser?.profile?.tid && myTenants.find(t => t.externalId.toUpperCase() === oidcUser?.profile?.tid.toUpperCase())
if (!localTenant || tenant) { return }
setTenant(localTenant)
}, [myTenants, oidcUser, tenant])
const handleTenantChange = useCallback(e => {
setTenant(e)
setContextTenant(e.code)
}, [setContextTenant])
const tenantName = tenant?.name ? ` - ${tenant.name}` : ""
<%_}_%>
const itemText = classes.itemText +
" " +
cx({
[classes.itemTextMini]: !drawerOpen
});
<% if (withMultiTenancy) { %> const displayName = `${userName}${tenantName}` <% } %>
<% if (!withMultiTenancy) { %> const displayName = userName <% } %>
return (
<List className={classes.userMenuContainer}>
<ListItem className={classes.item + " " + classes.userItem}>
<NavLink to={'/'} className={classes.itemLink} onClick={openCollapseAvatar}>
<ListItemIcon className={classes.itemIcon}>
<img src={avatar ? avatar : avatar_default} className={classes.photo} alt='...' />
</ListItemIcon>
<ListItemText
primary={displayName}
secondary={openAvatar ? <ArrowDropUp className={classes.caret} /> : <ArrowDropDown className={classes.caret} />}
disableTypography={true}
className={itemText}
/>
</NavLink>
<Collapse in={openAvatar} unmountOnExit classes={{ wrapper: classes.collapseWrapper }}>
<List className={classes.list + classes.collapseList}>
{userMenuItems.map((userMenu, key) => {
return <UserMenuItem key={key} userMenu={userMenu} drawerOpen={drawerOpen} activeRoute={activeRoute} withGradient={withGradient} />
})}
{oidcUser &&
<Tooltip disableHoverListener={drawerOpen} title={t('Tooltips.Logout')}>
<ListItem className={classes.collapseItem}>
<NavLink to={"/"} className={classes.itemLink} onClick={logoutAction}>
<ListItemIcon className={classes.itemIcon}>
<PowerSettingsNew />
</ListItemIcon>
<ListItemText
primary={t('Tooltips.Logout')}
disableTypography={true}
className={itemText}
/>
</NavLink>
</ListItem>
</Tooltip>
}
<ListItem className={classes.selectorItem}>
<LanguageSelector
language={language}
changeLanguage={changeLanguage}
drawerOpen={drawerOpen}
/>
</ListItem>
<% if (withMultiTenancy) { %> {!tenantsLoading && myTenants?.length > 1 &&
<Tooltip disableHoverListener={drawerOpen} title={t('Tooltips.TenantList')}>
<ListItem className={classes.selectorItem}>
<TenantSelector
tenant={tenant}
tenants={myTenants}
changeTenant={handleTenantChange}
drawerOpen={drawerOpen}
/>
</ListItem>
</Tooltip>
}<% } -%>
</List>
</Collapse>
</ListItem>
</List>
);
}