@material-ui/core#Popover TypeScript Examples
The following examples show how to use
@material-ui/core#Popover.
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: AutoCompletedResults.tsx From crossfeed with Creative Commons Zero v1.0 Universal | 6 votes |
AutoCompleteResults: React.FC<Props> = (props) => {
const { values, ...rest } = props;
return (
<Popover {...rest}>
{values.map((value) => (
<MenuItem key={value.id.raw}>{value.text.raw}</MenuItem>
))}
</Popover>
);
}
Example #2
Source File: Info.tsx From swap-ui with Apache License 2.0 | 6 votes |
function InfoButton() {
const styles = useStyles();
return (
<PopupState variant="popover">
{
//@ts-ignore
(popupState) => (
<div style={{ display: "flex" }}>
<IconButton
{...bindTrigger(popupState)}
className={styles.infoButton}
>
<Info fontSize="small" />
</IconButton>
<Popover
{...bindPopover(popupState)}
anchorOrigin={{
vertical: "bottom",
horizontal: "left",
}}
transformOrigin={{
vertical: "top",
horizontal: "right",
}}
PaperProps={{ style: { borderRadius: "10px" } }}
disableRestoreFocus
>
<InfoDetails />
</Popover>
</div>
)
}
</PopupState>
);
}
Example #3
Source File: PopupHover.tsx From frontegg-react with MIT License | 5 votes |
PopupHover = forwardRef<HTMLElement, IPopoverProps>((props, ref) => {
const { trigger, content, anchorOrigin, transformOrigin, mountNode } = props;
const debounceRef = useRef<any>(0);
const classes = useStyles();
const [anchorEl, setAnchorEl] = useState<HTMLElement | null>(null);
const open = Boolean(anchorEl);
const onMouseEnter = useCallback((e: MouseEvent<HTMLElement>) => {
clearTimeout(debounceRef.current);
setAnchorEl(e.currentTarget);
}, []);
const onMouseLeave = useCallback((e: MouseEvent<HTMLElement>) => {
clearTimeout(debounceRef.current);
debounceRef.current = setTimeout(() => {
setAnchorEl(null);
}, debounceDelay);
}, []);
const onMouseEnterPopup = useCallback((e: MouseEvent<HTMLElement>) => {
clearTimeout(debounceRef.current);
}, []);
useEffect(() => {
if (open) {
props.onOpen?.();
} else {
props.onClose?.();
}
}, [open]);
return (
<>
{React.cloneElement(trigger, { ref, onMouseEnter, onMouseLeave })}
<Popover
className={classes.popover}
container={mountNode}
open={open}
anchorEl={anchorEl}
anchorOrigin={anchorOrigin}
transformOrigin={transformOrigin}
onClose={() => setAnchorEl(null)}
disableRestoreFocus
>
<Box
className={classnames(classes.box, 'fe-material-popup-content')}
onMouseEnter={onMouseEnterPopup}
onMouseLeave={onMouseLeave}
>
{content}
</Box>
</Popover>
</>
);
})
Example #4
Source File: PopupFocus.tsx From frontegg-react with MIT License | 5 votes |
PopupFocus = forwardRef<HTMLElement, IPopoverProps>((props, ref) => {
const { trigger, content, anchorOrigin, transformOrigin, mountNode } = props;
const classes = useStyles();
const [open, setOpen] = useState<boolean>(false);
const [anchorEl, setAnchorEl] = useState<HTMLElement | null>(null);
const [focused, setFocused] = useState<boolean>(false);
const handleFocus = useCallback(
(event: React.FocusEvent<HTMLButtonElement>) => {
if (focused) {
setFocused(false);
} else {
setAnchorEl(event.currentTarget);
setOpen(true);
setFocused(true);
}
},
[focused]
);
const handleClose = useCallback(() => {
setAnchorEl(null);
setOpen(false);
props.onClose?.();
}, []);
useEffect(() => {
if (open) {
props.onOpen?.();
}
}, [open]);
return (
<>
{React.cloneElement(trigger, { onFocus: handleFocus, ref })}
<Popover
open={open}
anchorEl={anchorEl}
onClose={handleClose}
container={mountNode}
anchorOrigin={anchorOrigin}
transformOrigin={transformOrigin}
>
<Box className={classnames(classes.box, 'fe-m-popup-content')}>{content}</Box>
</Popover>
</>
);
})
Example #5
Source File: PopupClick.tsx From frontegg-react with MIT License | 5 votes |
PopupClick = forwardRef<HTMLElement, IPopoverProps>((props, ref) => {
const { trigger, content, anchorOrigin, transformOrigin, mountNode } = props;
const classes = useStyles();
const [open, setOpen] = useState<boolean>(false);
const [anchorEl, setAnchorEl] = useState<HTMLElement | null>(null);
useImperativeHandle<any, any>(ref, () => ({
closePopup: () => handleClose(),
}));
const handleClick = useCallback((event: React.MouseEvent<HTMLButtonElement>) => {
setAnchorEl(event.currentTarget);
setOpen(true);
}, []);
const handleClose = useCallback(() => {
setAnchorEl(null);
setOpen(false);
props.onClose?.();
}, []);
useEffect(() => {
if (open) {
props.onOpen?.();
}
}, [open]);
useEffect(() => {
if (props.open != null) {
setOpen(props.open);
}
}, [props.open]);
return (
<>
{React.cloneElement(trigger, { onClick: handleClick, ref: ref })}
<Popover
open={open}
anchorEl={anchorEl}
onClose={handleClose}
container={mountNode}
anchorOrigin={anchorOrigin}
transformOrigin={transformOrigin}
>
<Box className={classnames(classes.box, 'fe-m-popup-content')}>{content}</Box>
</Popover>
</>
);
})
Example #6
Source File: Toolbar.tsx From homebase-app with MIT License | 5 votes |
StyledPopover = styled(Popover)({
".MuiPaper-root": {
borderRadius: 4,
},
})
Example #7
Source File: ChangeNetworkButton.tsx From homebase-app with MIT License | 5 votes |
StyledPopover = styled(Popover)({
".MuiPaper-root": {
borderRadius: 4,
},
})
Example #8
Source File: ERC721Token.tsx From safe-airdrop with MIT License | 5 votes |
ERC721Token = (props: TokenProps) => {
const [anchorEl, setAnchorEl] = useState<HTMLImageElement | null>(null);
const [isMetaDataLoading, setIsMetaDataLoading] = useState(false);
const [tokenMetaData, setTokenMetaData] = useState<CollectibleTokenMetaInfo | undefined>(undefined);
const collectibleTokenInfoProvider = useCollectibleTokenInfoProvider();
const { tokenAddress, id, token_type, hasMetaData } = props;
const imageZoomedIn = Boolean(anchorEl);
useEffect(() => {
let isMounted = true;
if (hasMetaData) {
setIsMetaDataLoading(true);
collectibleTokenInfoProvider.fetchMetaInfo(tokenAddress, id, token_type).then((result) => {
if (isMounted) {
setTokenMetaData(result);
setIsMetaDataLoading(false);
}
});
}
return function callback() {
isMounted = false;
};
}, [hasMetaData, collectibleTokenInfoProvider, tokenAddress, id, token_type]);
return (
<Container>
{isMetaDataLoading ? (
<Loader size="sm" />
) : (
tokenMetaData?.imageURI && (
<>
<img
alt={""}
src={tokenMetaData?.imageURI}
onClick={(event) => {
setAnchorEl(event.currentTarget);
}}
style={{
maxWidth: 20,
marginRight: 3,
verticalAlign: "middle",
cursor: "pointer",
}}
/>{" "}
<Popover
style={{ padding: 8 }}
anchorEl={anchorEl}
open={imageZoomedIn}
onClose={() => setAnchorEl(null)}
anchorOrigin={{
vertical: "bottom",
horizontal: "center",
}}
transformOrigin={{
vertical: "top",
horizontal: "center",
}}
>
<img
alt={""}
src={tokenMetaData?.imageURI}
style={{
maxWidth: 320,
marginRight: 3,
verticalAlign: "middle",
}}
/>{" "}
</Popover>
</>
)
)}
<Text size="md">{tokenMetaData?.name || tokenAddress}</Text>
</Container>
);
}
Example #9
Source File: MenuAction.tsx From parity-bridges-ui with GNU General Public License v3.0 | 5 votes |
MenuAction = ({ actions, changeMenu, action }: MenuActionProps) => {
const classes = useStyles();
const [anchorEl, setAnchorEl] = React.useState<HTMLButtonElement | null>(null);
const [id, setId] = React.useState<string | undefined>(undefined);
const [open, setOpen] = React.useState<boolean>(false);
const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
setAnchorEl(event.currentTarget);
setOpen(!open);
};
useEffect(() => {
setOpen(Boolean(anchorEl));
setId(anchorEl ? 'simple-popover' : undefined);
}, [anchorEl]);
const item = actions.find(({ type }) => type === action);
return (
<>
<ButtonBase className={`${classes.item} current`} onClick={handleClick}>
{item?.title || '-'}
<ArrowDropDownIcon />
</ButtonBase>
<Popover
id={id}
open={open}
anchorEl={anchorEl}
onClose={() => setOpen(false)}
anchorOrigin={{
vertical: 'bottom',
horizontal: 'right'
}}
transformOrigin={{
vertical: 'top',
horizontal: 24
}}
PaperProps={{
className: classes.menu
}}
>
{actions.map((i, n) => (
<ButtonBase
className={`${classes.item} ${!i.isEnabled && 'disabled'}`}
key={n}
onClick={() => {
setOpen(!open);
changeMenu(i.type);
}}
>
{i.title}
</ButtonBase>
))}
</Popover>
</>
);
}
Example #10
Source File: AddShortcut.tsx From backstage with Apache License 2.0 | 5 votes |
AddShortcut = ({ onClose, anchorEl, api }: Props) => {
const classes = useStyles();
const alertApi = useApi(alertApiRef);
const { pathname } = useLocation();
const [formValues, setFormValues] = useState<FormValues>();
const open = Boolean(anchorEl);
const handleSave: SubmitHandler<FormValues> = async ({ url, title }) => {
const shortcut: Omit<Shortcut, 'id'> = { url, title };
try {
await api.add(shortcut);
alertApi.post({
message: `Added shortcut '${title}' to your sidebar`,
severity: 'success',
});
} catch (error) {
alertApi.post({
message: `Could not add shortcut: ${error.message}`,
severity: 'error',
});
}
onClose();
};
const handlePaste = () => {
setFormValues({ url: pathname, title: document.title });
};
const handleClose = () => {
setFormValues(undefined);
onClose();
};
return (
<Popover
open={open}
anchorEl={anchorEl}
TransitionProps={{ onExit: handleClose }}
onClose={onClose}
anchorOrigin={{
vertical: 'top',
horizontal: 'right',
}}
>
<Card className={classes.card}>
<CardHeader
className={classes.header}
title="Add Shortcut"
titleTypographyProps={{ variant: 'subtitle2' }}
action={
<Button
className={classes.button}
variant="text"
size="small"
color="primary"
onClick={handlePaste}
>
Use current page
</Button>
}
/>
<ShortcutForm
onClose={handleClose}
onSave={handleSave}
formValues={formValues}
/>
</Card>
</Popover>
);
}
Example #11
Source File: SenderDropdown.tsx From parity-bridges-ui with GNU General Public License v3.0 | 5 votes |
export default function SenderDropdown({ anchorEl, removeAnchor }: Props) {
const classes = useStyles();
const [showEmpty, setShowEmpty] = useState(true);
const [showCompanion, setShowCompanion] = useState(true);
const [filterInput, setFilterInput] = useState<string | null>(null);
const { initialLoadingAccounts } = useAccountContext();
const open = Boolean(anchorEl);
const id = open ? 'test-sender-component' : undefined;
const handleClose = useCallback(() => {
removeAnchor();
setFilterInput(null);
}, [removeAnchor]);
return (
<Popover
id={id}
open={open}
anchorEl={anchorEl}
onClose={handleClose}
anchorOrigin={{
vertical: 'top',
horizontal: 'center'
}}
transformOrigin={{
vertical: 'top',
horizontal: 'center'
}}
classes={{
paper: classes.paper
}}
>
{initialLoadingAccounts ? (
<SenderAccountsLoading />
) : (
<>
<SenderFilters
setFilterInput={setFilterInput}
setShowEmpty={setShowEmpty}
setShowCompanion={setShowCompanion}
showEmpty={showEmpty}
showCompanion={showCompanion}
/>
<SenderAccountsSection
showEmpty={showEmpty}
showCompanion={showCompanion}
filterInput={filterInput}
handleClose={handleClose}
/>
</>
)}
</Popover>
);
}
Example #12
Source File: index.tsx From prism-frontend with MIT License | 5 votes |
function MenuItem({ classes, title, icon, layersCategories }: MenuItemProps) {
const { t } = useSafeTranslation();
const [anchorEl, setAnchorEl] = useState<HTMLButtonElement | null>(null);
const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};
const open = Boolean(anchorEl);
const id = open ? 'menu-item-popover' : undefined;
return (
<>
<Button
className={classes.title}
onClick={handleClick}
aria-describedby={id}
>
<img className={classes.icon} src={`/images/${icon}`} alt={title} />
<Typography variant="body2">{t(title)}</Typography>
</Button>
<Popover
id={id}
open={open}
anchorEl={anchorEl}
onClose={handleClose}
className={classes.popover}
anchorOrigin={{
vertical: 'bottom',
horizontal: 'center',
}}
transformOrigin={{
vertical: 'top',
horizontal: 'center',
}}
PaperProps={{
className: classes.paper,
}}
>
{layersCategories.map(({ title: categoryTitle, layers, tables }) => (
<MenuSwitch
key={categoryTitle}
title={t(categoryTitle)}
layers={layers}
tables={tables}
/>
))}
</Popover>
</>
);
}
Example #13
Source File: Settings.tsx From swap-ui with Apache License 2.0 | 5 votes |
export function SettingsButton() {
const styles = useStyles();
return (
<PopupState variant="popover">
{
//@ts-ignore
(popupState) => (
<div>
<IconButton
{...bindTrigger(popupState)}
className={styles.settingsButton}
>
<Settings />
</IconButton>
<Popover
{...bindPopover(popupState)}
anchorOrigin={{
vertical: "bottom",
horizontal: "left",
}}
transformOrigin={{
vertical: "top",
horizontal: "right",
}}
PaperProps={{
style: {
borderRadius: "10px",
boxShadow: "0px 0px 30px 5px rgba(0,0,0,0.075)",
},
}}
>
<SettingsDetails />
</Popover>
</div>
)
}
</PopupState>
);
}
Example #14
Source File: Footer.tsx From knboard with MIT License | 5 votes |
Footer = () => {
const [anchorEl, setAnchorEl] = React.useState<HTMLButtonElement | null>(
null
);
const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};
const open = Boolean(anchorEl);
const id = open ? "about-popover" : undefined;
return (
<Container>
<List>
<Item>
<Button
aria-describedby={id}
onClick={handleClick}
css={css`
padding: 0;
text-transform: initial;
color: #888;
font-weight: 400;
&:hover {
background-color: initial;
}
`}
>
About
</Button>
</Item>
</List>
<Popover
id={id}
open={open}
anchorEl={anchorEl}
onClose={handleClose}
anchorOrigin={{
vertical: "top",
horizontal: "center",
}}
transformOrigin={{
vertical: "bottom",
horizontal: "center",
}}
>
<Alert
severity="info"
css={css`
padding: 1rem 1rem 2rem 1rem;
max-width: 400px;
`}
>
<AlertTitle>About</AlertTitle>
<p>
<b>Knboard</b> is an app that helps visualize your work using kanban
boards, maximizing efficiency.
</p>
It is an <b>open-source</b> project built using Django & React,
available on{" "}
<Link
href="https://github.com/rrebase/knboard"
target="_blank"
rel="noopener"
>
GitHub
</Link>
.
</Alert>
</Popover>
</Container>
);
}
Example #15
Source File: PlayersContainer.tsx From cards-against-formality-pwa with BSD 2-Clause "Simplified" License | 5 votes |
MobilePlayer = ({ player, isHost, isCzar, onPlayerKick, isCurrentUserHost }: any) => {
const anchorEl = useRef<any>();
const [isOpen, setIsOpen] = useState(false);
if (!player) {
return null;
}
function renderKick() {
if (isHost || !isCurrentUserHost) {
return null;
}
return <List>
<ListItem style={{ padding: 0 }}>
<Button size="small" color="secondary" onClick={() => { onPlayerKick(player?._id) }}>Kick</Button>
</ListItem>
</List>;
}
return <>
<div className={`player ${isCzar ? 'special' : ''}`} ref={anchorEl} onClick={() => setIsOpen(prev => !prev)}>
<Badge badgeContent={player.score} color="error">
{player?.username}
</Badge>
</div>
<Popover
anchorEl={anchorEl.current}
open={isHost || !isCurrentUserHost ? false : isOpen}
onClose={() => setIsOpen(false)}
anchorOrigin={{
vertical: 'top',
horizontal: 'right',
}}
transformOrigin={{
vertical: 'bottom',
horizontal: 'left',
}}
>
{renderKick()}
</Popover>
</>
}
Example #16
Source File: index.tsx From firetable with Apache License 2.0 | 5 votes |
Notification = () => {
const classes = useStyles();
const [anchorEl, setAnchorEl] = React.useState<HTMLButtonElement | null>(
null
);
const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};
const open = Boolean(anchorEl);
const id = open ? "simple-popover" : undefined;
const notifications: Notification[] = [
{
title: "a",
subtitle: "a",
variant: "error",
link:
"https://console.cloud.google.com/cloud-build/builds;region=global/f7b8fd9b-eb6e-401f-a889-73c4bf75f232?project=antler-vc",
},
];
const notificationsCount = notifications.length;
return (
<>
<IconButton onClick={handleClick}>
<Badge
color={"primary"}
variant="standard"
badgeContent={notificationsCount}
>
<BellIcon />
</Badge>
</IconButton>
<Popover
id={id}
open={open}
anchorEl={anchorEl}
onClose={handleClose}
anchorOrigin={{
vertical: "bottom",
horizontal: "center",
}}
transformOrigin={{
vertical: "top",
horizontal: "center",
}}
>
<List>
{notifications.map((notification) => (
<ListItem>
<ListItemAvatar>
<Avatar>
<ErrorIcon />
</Avatar>
</ListItemAvatar>
<ListItemText
primary={notification.title}
secondary={notification.subtitle}
/>
<ListItemSecondaryAction>
<IconButton edge="end" aria-label="delete">
<DeleteIcon />
</IconButton>
</ListItemSecondaryAction>
</ListItem>
))}
</List>
</Popover>
</>
);
}
Example #17
Source File: MoreMenu.tsx From anchor-web-app with Apache License 2.0 | 5 votes |
function MoreMenuBase({ children, className }: MoreMenuProps) {
const [anchorEl, setAnchorEl] = useState<HTMLElement | null>(null);
return (
<>
<MoreButton
onClick={(event: MouseEvent<HTMLButtonElement>) =>
setAnchorEl(event.currentTarget)
}
>
More {anchorEl ? <ExpandLess /> : <ExpandMore />}
</MoreButton>
<Popover
open={!!anchorEl}
anchorEl={anchorEl}
onClose={() => setAnchorEl(null)}
anchorOrigin={{
vertical: 'bottom',
horizontal: 'right',
}}
transformOrigin={{
vertical: 'top',
horizontal: 'right',
}}
className={className}
>
<MenuList variant="menu">
{Children.map(children, (child) => {
return cloneElement(child, {
children: (
<IconSpan>
{child.props.children} <ChevronRightRounded />
</IconSpan>
),
});
})}
</MenuList>
</Popover>
</>
);
}
Example #18
Source File: ColumnTitle.tsx From knboard with MIT License | 4 votes |
ColumnTitle = ({ id, title, tasksCount, ...props }: Props) => {
const dispatch = useDispatch();
const [anchorEl, setAnchorEl] = React.useState<HTMLButtonElement | null>(
null
);
const [pendingTitle, setPendingTitle] = useState<string>(title);
const [editing, setEditing] = useState<boolean>(false);
const titleTextAreaRef = useRef<HTMLTextAreaElement>(null);
useEffect(() => {
if (!editing && title === pendingTitle) {
titleTextAreaRef?.current?.blur();
}
}, [pendingTitle, editing]);
const handleKeyDown = (e: React.KeyboardEvent) => {
if (e.keyCode === Key.Enter) {
e.preventDefault();
if (pendingTitle.length > 0) {
titleTextAreaRef?.current?.blur();
}
}
if (e.keyCode === Key.Escape) {
e.preventDefault();
setPendingTitle(title);
setEditing(false);
// blur via useEffect
}
};
const handleSave = () => {
if (editing && pendingTitle.length > 0) {
setEditing(false);
if (pendingTitle !== title) {
dispatch(patchColumn({ id, fields: { title: pendingTitle } }));
}
}
};
const handleChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
setPendingTitle(e.target.value);
};
const handleFocus = (e: React.FocusEvent<HTMLTextAreaElement>) => {
e.target.select();
};
const handleOptionsClick = (event: React.MouseEvent<HTMLButtonElement>) => {
setAnchorEl(event.currentTarget);
};
const handleOptionsClose = () => {
setAnchorEl(null);
};
const handleDelete = () => {
if (
window.confirm(
"Are you sure? Deleting the column will also delete related tasks and this cannot be undone."
)
) {
dispatch(deleteColumn(id));
handleOptionsClose();
}
};
const open = Boolean(anchorEl);
const popoverId = open ? `col-${id}options-popover` : undefined;
return (
<Container {...props}>
{editing ? (
<InputTitle>
<TextareaAutosize
ref={titleTextAreaRef}
value={pendingTitle}
onChange={handleChange}
onBlur={handleSave}
onKeyDown={handleKeyDown}
data-testid="column-title-textarea"
onFocus={handleFocus}
autoFocus
/>
</InputTitle>
) : (
<RegularTitle onClick={() => setEditing(true)}>
{pendingTitle}
</RegularTitle>
)}
<Extra>
<InnerExtra>
<Count>{tasksCount}</Count>
<Button
onClick={handleOptionsClick}
data-testid="col-options"
css={css`
margin-left: 0.25rem;
min-width: 0;
padding: 2px 8px;
height: 22px;
`}
>
<FontAwesomeIcon icon={faEllipsisV} />
</Button>
</InnerExtra>
<Popover
id={popoverId}
open={open}
anchorEl={anchorEl}
onClose={handleOptionsClose}
anchorOrigin={{
vertical: "bottom",
horizontal: "left",
}}
transformOrigin={{
vertical: "top",
horizontal: "left",
}}
>
<OptionsContent>
<Button
startIcon={<FontAwesomeIcon fixedWidth icon={faTrash} />}
onClick={handleDelete}
data-testid="delete-column"
size="small"
css={css`
font-size: 12px;
font-weight: bold;
color: ${ACTION_G};
`}
>
Delete column
</Button>
</OptionsContent>
</Popover>
</Extra>
</Container>
);
}
Example #19
Source File: MemberFilter.tsx From knboard with MIT License | 4 votes |
MemberFilter = ({ boardId }: Props) => {
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
const [filteredAssignee, setFilteredAssignee] = useState<BoardMember[]>([]);
const dispatch = useDispatch();
const members = useSelector(selectAllMembers);
const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};
const postFilterMember = async (users: BoardMember[]) => {
dispatch(
fetchBoardById({
boardId: boardId,
assigneeIds: users.map((m) => m.id),
})
);
handleClose();
};
const handleClickFilter = () => {
postFilterMember(filteredAssignee);
};
const handleClickClearFilter = () => {
setFilteredAssignee([]);
postFilterMember([]);
};
const ClearFilterButton = () => (
<FilterButton>
<Button
variant="outlined"
size="small"
css={css`
text-transform: none;
`}
onClick={handleClickClearFilter}
data-testid="clear-filter"
>
Clear Filters
</Button>
</FilterButton>
);
return (
<>
<FilterButton>
<Button
variant="outlined"
size="small"
css={css`
text-transform: none;
`}
onClick={handleClick}
aria-controls="member-filter-menu"
aria-haspopup="true"
data-testid="member-filter"
>
Filter
</Button>
</FilterButton>
{filteredAssignee.length > 0 ? <ClearFilterButton /> : null}
<Popover
id="member-filter-menu"
anchorEl={anchorEl}
getContentAnchorEl={null}
anchorOrigin={{
vertical: "bottom",
horizontal: "left",
}}
transformOrigin={{
vertical: "top",
horizontal: "left",
}}
open={Boolean(anchorEl)}
onClose={handleClose}
transitionDuration={0}
>
<Content>
<Description>Filter tasks by assignees</Description>
<Box display="flex" alignItems="center">
<Box flexGrow={1}>
<AssigneeAutoComplete
assignee={filteredAssignee}
members={members}
controlId={"assignee-filter"}
dataTestId={"filter-assignees"}
setAssignee={setFilteredAssignee}
/>
</Box>
<Button
color="primary"
variant="contained"
css={css`
font-size: 0.625rem;
margin-left: 0.5rem;
`}
onClick={handleClickFilter}
data-testid="filter-selected"
disabled={filteredAssignee.length === 0}
>
Filter
</Button>
</Box>
</Content>
</Popover>
</>
);
}
Example #20
Source File: WebhookLogsList.tsx From glific-frontend with GNU Affero General Public License v3.0 | 4 votes |
WebhookLogsList: React.SFC<WebhookLogsListProps> = () => {
const [anchorEl, setAnchorEl] = useState(null);
const [open, setOpen] = useState(false);
const [text, setText] = useState<any>();
const { t } = useTranslation();
const handleClick = (event: any) => {
setAnchorEl(event.currentTarget);
};
const getCroppedText = (croppedtext: string, isUrl: boolean = false) => {
if (!croppedtext) {
return <div className={styles.TableText}>NULL</div>;
}
let newtext = croppedtext;
if (isUrl) {
newtext = JSON.stringify(croppedtext);
}
const Menus = [
{
title: t('Copy text'),
icon: <img src={CopyIcon} alt="copy" />,
onClick: () => {
copyToClipboard(croppedtext);
},
},
{
title: t('View'),
icon: <ViewIcon />,
onClick: () => {
setText(newtext);
setOpen(true);
},
},
];
return (
<Menu menus={Menus}>
<div
className={styles.CroppedText}
onClick={handleClick}
onKeyDown={handleClick}
aria-hidden="true"
>
{newtext.length > 21 ? `${newtext.slice(0, 21)}...` : newtext}
</div>
</Menu>
);
};
const getColumns = ({
url,
method,
status,
requestHeaders,
requestJson,
statusCode,
responseJson,
error,
updatedAt,
}: any) => ({
updatedAt: getTime(updatedAt),
url: getCroppedText(url, true),
status: getStatus(status),
statusCode: getText(statusCode),
error: getCroppedText(error, true),
method: getText(method),
requestHeaders: getCroppedText(requestHeaders),
requestJson: getCroppedText(requestJson),
responseJson: getCroppedText(responseJson),
});
const handleClose = () => {
setOpen(false);
setAnchorEl(null);
};
const columnAttributes = {
columnNames,
columns: getColumns,
columnStyles,
};
const popover = (
<Popover open={open} anchorEl={anchorEl} onClose={handleClose}>
<div className={styles.PopoverText}>
<pre>{JSON.stringify(text ? JSON.parse(text) : '', null, 2)}</pre>
</div>
<div className={styles.PopoverActions}>
<span
onClick={() => copyToClipboard(text)}
aria-hidden="true"
data-testid="copyToClipboard"
>
<img src={CopyIcon} alt="copy" />
{t('Copy text')}
</span>
<Button variant="contained" color="default" onClick={handleClose}>
{t('Done')}
</Button>
</div>
</Popover>
);
return (
<div className={styles.Container}>
<List
title={t('Webhook Logs')}
listItem="webhookLogs"
listItemName="webhookLog"
pageLink="webhookLog"
listIcon={webhookLogsIcon}
searchParameter={['contact_phone', 'url']}
button={{ show: false, label: '' }}
{...queries}
dialogMessage=""
restrictedAction={restrictedAction}
{...columnAttributes}
removeSortBy={['STATUS']}
listOrder="desc"
/>
{popover}
</div>
);
}
Example #21
Source File: NotificationList.tsx From glific-frontend with GNU Affero General Public License v3.0 | 4 votes |
NotificationList: React.SFC<NotificationListProps> = () => {
const client = useApolloClient();
const [open, setOpen] = useState(false);
const [text, setText] = useState<any>();
const { t } = useTranslation();
const history = useHistory();
const [filters, setFilters] = useState<any>({
Critical: true,
Warning: false,
});
const menuRef = useRef(null);
let filterValue: any = '';
const [markNotificationAsRead] = useMutation(MARK_NOTIFICATIONS_AS_READ, {
onCompleted: (data) => {
if (data.markNotificationAsRead) {
client.writeQuery({
query: GET_NOTIFICATIONS_COUNT,
variables: {
filter: {
is_read: false,
severity: 'critical',
},
},
data: { countNotifications: 0 },
});
}
},
});
useEffect(() => {
setTimeout(() => {
markNotificationAsRead();
}, 1000);
}, []);
const setDialog = (id: any, item: any) => {
if (item.category === 'Message') {
const chatID = JSON.parse(item.entity).id;
history.push({ pathname: `/chat/${chatID}` });
} else if (item.category === 'Flow') {
const uuidFlow = JSON.parse(item.entity).flow_uuid;
history.push({ pathname: `/flow/configure/${uuidFlow}` });
} else {
// this is item.category == Partner
// need to figure out what should be done
}
};
const additionalAction = [
{
icon: <ArrowForwardIcon className={styles.RedirectArrow} />,
parameter: 'id',
label: 'Check',
dialog: setDialog,
},
];
const getCroppedText = (croppedtext: string) => {
if (!croppedtext) {
return <div className={styles.TableText}>NULL</div>;
}
const entityObj = JSON.parse(croppedtext);
const Menus = [
{
title: t('Copy text'),
icon: <img src={CopyIcon} alt="copy" />,
onClick: () => {
copyToClipboard(croppedtext);
},
},
{
title: t('View'),
icon: <ViewIcon />,
onClick: () => {
setText(croppedtext);
setOpen(true);
},
},
];
return (
<Menu menus={Menus}>
<div
className={styles.CroppedText}
data-testid="NotificationRowMenu"
ref={menuRef}
aria-hidden="true"
>
{entityObj.name ? (
<span>
Contact: {entityObj.name}
<br />
{croppedtext.slice(0, 25)}...
</span>
) : (
`${croppedtext.slice(0, 25)}...`
)}
</div>
</Menu>
);
};
const getColumns = ({ category, entity, message, severity, updatedAt, isRead }: any) => ({
isRead: getDot(isRead),
updatedAt: getTime(updatedAt),
category: getText(category),
severity: getText(severity.replace(/"/g, '')),
entity: getCroppedText(entity),
message: getText(message),
});
const handleClose = () => {
setOpen(false);
};
const columnNames = ['', 'TIMESTAMP', 'CATEGORY', 'SEVERITY', 'ENTITY', 'MESSAGE'];
const columnAttributes = {
columnNames,
columns: getColumns,
columnStyles,
};
const popover = (
<Popover open={open} anchorEl={menuRef.current} onClose={handleClose}>
<div className={styles.PopoverText}>
<pre>{JSON.stringify(text ? JSON.parse(text) : '', null, 2)}</pre>
</div>
<div className={styles.PopoverActions}>
<span
onClick={() => copyToClipboard(text)}
aria-hidden="true"
data-testid="copyToClipboard"
>
<img src={CopyIcon} alt="copy" />
{t('Copy text')}
</span>
<Button variant="contained" color="default" onClick={handleClose}>
{t('Done')}
</Button>
</div>
</Popover>
);
const severityList = ['Critical', 'Warning'];
const handleCheckedBox = (event: any) => {
setFilters({ ...filters, [event.target.name]: event.target.checked });
};
const filterName = Object.keys(filters).filter((k) => filters[k] === true);
if (filterName.length === 1) {
[filterValue] = filterName;
}
const filterOnSeverity = (
<div className={styles.Filters}>
{severityList.map((label, index) => {
const key = index;
return (
<FormControlLabel
key={key}
control={
<Checkbox
checked={filters[label]}
color="primary"
onChange={handleCheckedBox}
name={severityList[index]}
/>
}
label={severityList[index]}
classes={{
label: styles.FilterLabel,
}}
/>
);
})}
</div>
);
return (
<div>
<List
title="Notifications"
listItem="notifications"
listItemName="notification"
pageLink="notifications"
listIcon={notificationIcon}
searchParameter={['message']}
button={{ show: false }}
dialogMessage=""
{...queries}
restrictedAction={restrictedAction}
additionalAction={additionalAction}
{...columnAttributes}
removeSortBy={[t('Entity'), t('Severity'), t('Category')]}
filters={{ severity: filterValue }}
filterList={filterOnSeverity}
listOrder="desc"
/>
{popover}
</div>
);
}
Example #22
Source File: MemberInvite.tsx From knboard with MIT License | 4 votes |
MemberInvite = ({ boardId }: Props) => {
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
const [tagsValue, setTagsValue] = useState<UserOption[]>([]);
const dispatch = useDispatch();
const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};
const postInviteMember = async (users: number[]) => {
try {
const response = await api.post(
`${API_BOARDS}${boardId}/invite_member/`,
{ users }
);
const newMembers = response.data as BoardMember[];
dispatch(addBoardMembers(newMembers));
dispatch(
createSuccessToast(
`Invited ${newMembers.map((m) => m.username).join(", ")}`
)
);
handleClose();
setTagsValue([]);
} catch (err) {
dispatch(createErrorToast(err.toString()));
}
};
const handleClickInvite = () => {
postInviteMember(tagsValue.map((v) => v.id));
};
return (
<>
<InviteMember>
<Button
variant="outlined"
size="small"
css={css`
text-transform: none;
`}
onClick={handleClick}
aria-controls="member-invite-menu"
aria-haspopup="true"
data-testid="member-invite"
>
Invite
</Button>
</InviteMember>
<Popover
id="member-invite-menu"
anchorEl={anchorEl}
getContentAnchorEl={null}
anchorOrigin={{
vertical: "bottom",
horizontal: "left",
}}
transformOrigin={{
vertical: "top",
horizontal: "left",
}}
open={Boolean(anchorEl)}
onClose={handleClose}
transitionDuration={0}
>
<Content>
<Description>Invite to this board</Description>
<Box display="flex" alignItems="center">
<UserSearch
boardId={boardId}
tagsValue={tagsValue}
setTagsValue={setTagsValue}
/>
<Button
color="primary"
variant="contained"
css={css`
font-size: 0.625rem;
margin-left: 0.5rem;
`}
onClick={handleClickInvite}
data-testid="invite-selected"
disabled={tagsValue.length === 0}
>
Invite
</Button>
</Box>
</Content>
</Popover>
</>
);
}
Example #23
Source File: UserAvatar.tsx From knboard with MIT License | 4 votes |
UserAvatar = () => {
const user = useSelector((state: RootState) => state.profile.userDetail);
const avatars = useSelector((state: RootState) => state.profile.avatars);
const loading = useSelector(
(state: RootState) => state.profile.avatarLoading
);
const dispatch = useDispatch();
const popupState = usePopupState({
variant: "popover",
popupId: "avatarPopover",
});
const handleChangeAvatar = async (id: number) => {
dispatch(updateAvatar(id));
};
return (
<Container>
<Avatar
src={user?.avatar?.photo}
alt={user?.avatar?.name}
css={css`
height: 6rem;
width: 6rem;
font-size: 36px;
`}
/>
<Button
css={css`
text-transform: initial;
margin-top: 0.75rem;
font-size: 0.75rem;
padding: 4px 12px;
`}
variant="outlined"
{...bindTrigger(popupState)}
data-testid="change-avatar"
>
Change
</Button>
<Popover
{...bindPopover(popupState)}
keepMounted
anchorOrigin={{ vertical: "top", horizontal: "center" }}
transformOrigin={{ vertical: "top", horizontal: "center" }}
>
<AvatarListContainer>
<GridTitle>
<Text>Pick an Avatar</Text>
<Button
size="small"
onClick={() => popupState.close()}
css={css`
min-width: 0;
`}
data-testid="close-avatar-picker"
>
<FontAwesomeIcon icon={faTimes} />
</Button>
</GridTitle>
<Grid container>
{avatars.map((avatar) => (
<Grid item xs={3} key={avatar.id}>
<img
onClick={() => handleChangeAvatar(avatar.id)}
css={css`
&:hover {
${avatarBorderStyles}
}
${avatar.id === loading && pulseStyles}
`}
src={avatar.photo}
alt={avatar.name}
width={60}
height={60}
data-testid={`avatar-${avatar.name}`}
/>
</Grid>
))}
</Grid>
<GridFooter>
<Alert
severity="info"
variant="outlined"
css={css`
font-size: 12px;
`}
>
<span>
Icons made by{" "}
<Link
href="https://www.flaticon.com/authors/pixel-perfect"
title="Pixel perfect"
>
Pixel perfect
</Link>{" "}
from{" "}
<Link href="https://www.flaticon.com/" title="Flaticon">
www.flaticon.com
</Link>
</span>
</Alert>
</GridFooter>
</AvatarListContainer>
</Popover>
</Container>
);
}
Example #24
Source File: TaskAssignees.tsx From knboard with MIT License | 4 votes |
TaskAssignees = ({ task }: Props) => {
const dispatch = useDispatch();
const membersById = useSelector(selectMembersEntities);
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
const [pendingAssignees, setPendingAssignees] = useState<BoardMember[]>([]);
const members = useSelector(selectAllMembers);
const assignees = task.assignees.map(
(id) => membersById[id]
) as BoardMember[];
const handleClick = (event: React.MouseEvent<HTMLElement>) => {
setPendingAssignees(assignees);
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
const currentIds = assignees.map((a) => a.id);
const pendingIds = pendingAssignees.map((member) => member.id);
if (
!(
pendingIds.length === currentIds.length &&
pendingIds
.sort()
.every((value, index) => value === currentIds.sort()[index])
)
) {
dispatch(
patchTask({
id: task.id,
fields: { assignees: pendingIds },
})
);
}
setAnchorEl(null);
};
const open = Boolean(anchorEl);
const popoverId = open ? "task-assignees-popover" : undefined;
return (
<Container>
<Label>Assignees</Label>
{assignees.map((assignee) => (
<List key={assignee.id}>
<div>
<Avatar
css={css`
height: 2rem;
width: 2rem;
margin-right: 0.5rem;
`}
src={assignee.avatar?.photo}
alt={assignee.avatar?.name}
>
{assignee.username.charAt(0)}
</Avatar>
</div>
<div>{assignee.username}</div>
</List>
))}
<Button
size="small"
onClick={handleClick}
data-testid="open-edit-assignees"
css={css`
color: ${PRIMARY};
font-size: 0.7rem;
`}
>
Change
</Button>
<Popover
id={popoverId}
open={open}
anchorEl={anchorEl}
transitionDuration={0}
style={{ zIndex: modalPopperIndex }}
onClose={handleClose}
css={css`
.MuiPaper-rounded {
border-radius: 0;
}
`}
>
<Content>
<Close onClose={handleClose} onPopper />
<ContentTitle>Assigned board members</ContentTitle>
<AssigneeContainer>
<AssigneeAutoComplete
assignee={pendingAssignees}
members={members}
setAssignee={setPendingAssignees}
controlId="assignee-select"
dataTestId={"edit-assignees"}
/>
</AssigneeContainer>
</Content>
</Popover>
</Container>
);
}
Example #25
Source File: Settings.tsx From Twenty48 with GNU General Public License v3.0 | 4 votes |
Settings: React.FC = () => {
const version = packJson['version']
const [theme, setTheme] = useRecoilState<ThemeType>(ThemeState)
const [anchorEl, setAnchorEl] = useState<Element | null | undefined>(null)
const [isCacheClear, setIsCacheClear] = useState(() => {
if (
localStorage.getItem(BESTSCORE) ||
localStorage.getItem(GAMESTATE) ||
localStorage.getItem(THEME)
) {
return false
}
return true
})
const cacheClearText = isCacheClear ? 'Cache is Clear' : 'Clear Cache'
useEffect(() => {
localStorage.setItem(THEME, theme)
}, [theme])
const removeLocalStorage = (): void => {
localStorage.removeItem(THEME)
localStorage.removeItem(GAMESTATE)
localStorage.removeItem(BESTSCORE)
setIsCacheClear(true)
}
const setSelectedTheme = (
e: React.ChangeEvent<{ name?: string; value: unknown }>,
): void => {
setTheme(e.target.value as ThemeType)
}
const getPopoverBody = (): React.ReactElement => {
return (
<div className={`popover-body popover-body-${theme}`}>
<div className="settings-item center">
<h3 onClick={removeLocalStorage}>{cacheClearText}</h3>
</div>
<Divider />
<div className="settings-item">
<h3>Theme:</h3>
<div className="center-item">
{theme === ThemeType.DARK ? (
<GiMoonBats size="22px" className="theme-icon" />
) : (
<GiUbisoftSun size="22px" className="theme-icon" />
)}
<FormControl className="no-decoration">
<NativeSelect
value={theme}
className={`select-${theme}`}
onChange={setSelectedTheme}
>
{Object.values(ThemeType).map((type, idx) => {
return (
<option key={idx} value={type}>
{type}
</option>
)
})}
</NativeSelect>
</FormControl>
</div>
</div>
<Divider />
<div className="settings-item">
<h3>Version:</h3>
<h4 className="center-item">{version}</h4>
</div>
<Divider />
<div className="settings-item ">
<h3>Made with:</h3>
<img src={logo} className="react-icon" />
</div>
</div>
)
}
return (
<>
<div>
<FiSettings
id="settings-cog"
className="settings-cog"
size="30px"
onClick={(e): void => setAnchorEl(e.currentTarget)}
/>
</div>
{/* Popover component: hidden until above button click */}
<Popover
open={anchorEl !== null}
anchorEl={anchorEl}
onClose={(): void => setAnchorEl(null)}
anchorOrigin={{
vertical: 'bottom',
horizontal: 'center',
}}
transformOrigin={{
vertical: 'top',
horizontal: 'center',
}}
>
{getPopoverBody()}
</Popover>
</>
)
}
Example #26
Source File: NotesPanel.tsx From vscode-crossnote with GNU Affero General Public License v3.0 | 4 votes |
export function NotesPanel(props: Props) {
const classes = useStyles(props);
const { t } = useTranslation();
const [selectedSection, setSelectedSection] = useState<SelectedSection>(null);
const [selectedNote, setSelectedNote] = useState<Note>(null);
const [notes, setNotes] = useState<Note[]>([]);
const [searchValue, setSearchValue] = useState<string>("");
const [searchValueInputTimeout, setSearchValueInputTimeout] = useState<
NodeJS.Timeout
>(null);
const [finalSearchValue, setFinalSearchValue] = useState<string>("");
const [sortMenuAnchorEl, setSortMenuAnchorEl] = useState<HTMLElement>(null);
const [orderBy, setOrderBy] = useState<OrderBy>(OrderBy.ModifiedAt);
const [orderDirection, setOrderDirection] = useState<OrderDirection>(
OrderDirection.DESC
);
const createNewNote = useCallback(() => {
if (!selectedSection) {
return;
}
const message: Message = {
action: MessageAction.CreateNewNote,
data: selectedSection,
};
vscode.postMessage(message);
}, [selectedSection]);
const onChangeSearchValue = useCallback(
(event: React.ChangeEvent<HTMLTextAreaElement | HTMLInputElement>) => {
const value = event.target.value;
setSearchValue(value);
if (searchValueInputTimeout) {
clearTimeout(searchValueInputTimeout);
}
const timeout = setTimeout(() => {
setFinalSearchValue(value);
}, 400);
setSearchValueInputTimeout(timeout);
},
[searchValueInputTimeout]
);
useEffect(() => {
const message: Message = {
action: MessageAction.InitializedNotesPanelWebview,
data: {},
};
vscode.postMessage(message);
}, []);
useEffect(() => {
const onMessage = (event) => {
const message: Message = event.data;
let note: Note;
switch (message.action) {
case MessageAction.SelectedSection:
setSelectedSection(message.data);
if (
selectedSection &&
message.data.notebook.dir !== selectedSection.notebook.dir
) {
setSearchValue("");
}
break;
case MessageAction.SendNotes:
const notes: Note[] = message.data;
notes.forEach((note) => {
note.config.createdAt = new Date(note.config.createdAt || 0);
note.config.modifiedAt = new Date(note.config.modifiedAt || 0);
});
setNotes(message.data || []);
break;
case MessageAction.CreatedNewNote:
note = message.data;
note.config.createdAt = new Date(note.config.createdAt || 0);
note.config.modifiedAt = new Date(note.config.modifiedAt || 0);
setNotes((notes) => [note, ...notes]);
setSelectedNote(note);
break;
case MessageAction.SelectedNote:
note = message.data;
note.config.createdAt = new Date(note.config.createdAt || 0);
note.config.modifiedAt = new Date(note.config.modifiedAt || 0);
setSelectedNote(note);
break;
default:
break;
}
};
window.addEventListener("message", onMessage);
return () => {
window.removeEventListener("message", onMessage);
};
}, [selectedSection]);
return (
<Box className={clsx(classes.notesPanel)}>
<Card className={clsx(classes.topPanel)}>
<Box className={clsx(classes.row)}>
<div className={clsx(classes.search)}>
<div className={clsx(classes.searchIcon)}>
<Magnify />
</div>
<InputBase
placeholder={t("search/placeholder")}
classes={{
root: classes.inputRoot,
input: classes.inputInput,
}}
value={searchValue}
inputProps={{ "aria-label": "search" }}
onChange={onChangeSearchValue}
autoComplete={"off"}
autoCorrect={"off"}
/>
</div>
<IconButton onClick={createNewNote}>
<FileEditOutline></FileEditOutline>
</IconButton>
</Box>
<Box
className={clsx(classes.row)}
style={{ justifyContent: "space-between" }}
>
{selectedSection?.type === CrossnoteSectionType.Notes ||
selectedSection?.type === CrossnoteSectionType.Notebook ? (
<Box className={clsx(classes.row)}>
<span role="img" aria-label="notes">
?
</span>
<Typography className={clsx(classes.sectionName)}>
{selectedSection.notebook.name}
</Typography>
</Box>
) : selectedSection?.type === CrossnoteSectionType.Today ? (
<Box className={clsx(classes.row)}>
<span role="img" aria-label="today-notes">
?
</span>
<Typography className={clsx(classes.sectionName)}>
{t("general/today")}
</Typography>
</Box>
) : selectedSection?.type === CrossnoteSectionType.Todo ? (
<Box className={clsx(classes.row)}>
<span role="img" aria-label="todo-notes">
☑️
</span>
<Typography className={clsx(classes.sectionName)}>
{t("general/todo")}
</Typography>
</Box>
) : selectedSection?.type === CrossnoteSectionType.Tagged ? (
<Box className={clsx(classes.row)}>
<span role="img" aria-label="tagged-notes">
?️
</span>
<Typography className={clsx(classes.sectionName)}>
{t("general/tagged")}
</Typography>
</Box>
) : selectedSection?.type === CrossnoteSectionType.Untagged ? (
<Box className={clsx(classes.row)}>
<span role="img" aria-label="untagged-notes">
?
</span>
<Typography className={clsx(classes.sectionName)}>
{t("general/untagged")}
</Typography>
</Box>
) : selectedSection?.type === CrossnoteSectionType.Tag ? (
<Box className={clsx(classes.row)}>
<span role="img" aria-label="tag">
?️
</span>
<Typography className={clsx(classes.sectionName)}>
{selectedSection.path}
</Typography>
</Box>
) : selectedSection?.type === CrossnoteSectionType.Encrypted ? (
<Box className={clsx(classes.row)}>
<span role="img" aria-label="encrypted-notes">
?
</span>
<Typography className={clsx(classes.sectionName)}>
{t("general/encrypted")}
</Typography>
</Box>
) : selectedSection?.type === CrossnoteSectionType.Conflicted ? (
<Box className={clsx(classes.row)}>
<span role="img" aria-label="conflicted-notes">
⚠️
</span>
<Typography className={clsx(classes.sectionName)}>
{t("general/conflicted")}
</Typography>
</Box>
) : (
selectedSection?.type === CrossnoteSectionType.Directory && (
<Box className={clsx(classes.row)}>
<span role="img" aria-label="folder">
{"?"}
</span>
<Typography className={clsx(classes.sectionName)}>
{selectedSection.path}
</Typography>
</Box>
)
)}
<Box>
<IconButton
onClick={(event) => setSortMenuAnchorEl(event.currentTarget)}
>
<SortVariant></SortVariant>
</IconButton>
<Popover
anchorEl={sortMenuAnchorEl}
keepMounted
open={Boolean(sortMenuAnchorEl)}
onClose={() => setSortMenuAnchorEl(null)}
>
<List>
<ListItem
button
onClick={() => setOrderBy(OrderBy.ModifiedAt)}
className={clsx(
orderBy === OrderBy.ModifiedAt && classes.sortSelected
)}
>
<ListItemText
primary={t("general/date-modified")}
></ListItemText>
</ListItem>
<ListItem
button
onClick={() => setOrderBy(OrderBy.CreatedAt)}
className={clsx(
orderBy === OrderBy.CreatedAt && classes.sortSelected
)}
>
<ListItemText
primary={t("general/date-created")}
></ListItemText>
</ListItem>
<ListItem
button
onClick={() => setOrderBy(OrderBy.Title)}
className={clsx(
orderBy === OrderBy.Title && classes.sortSelected
)}
>
<ListItemText primary={t("general/title")}></ListItemText>
</ListItem>
<Divider></Divider>
<ListItem
button
onClick={() => setOrderDirection(OrderDirection.DESC)}
className={clsx(
orderDirection === OrderDirection.DESC &&
classes.sortSelected
)}
>
<ListItemText primary={"Desc"}></ListItemText>
<ListItemIcon style={{ marginLeft: "8px" }}>
<SortDescending></SortDescending>
</ListItemIcon>
</ListItem>
<ListItem
button
onClick={() => setOrderDirection(OrderDirection.ASC)}
className={clsx(
orderDirection === OrderDirection.ASC &&
classes.sortSelected
)}
>
<ListItemText primary={"Asc"}></ListItemText>
<ListItemIcon style={{ marginLeft: "8px" }}>
<SortAscending></SortAscending>
</ListItemIcon>
</ListItem>
</List>
</Popover>
</Box>
</Box>
</Card>
<Notes
searchValue={finalSearchValue}
notes={notes}
orderBy={orderBy}
orderDirection={orderDirection}
selectedNote={selectedNote}
setSelectedNote={setSelectedNote}
></Notes>
</Box>
);
}
Example #27
Source File: Home.tsx From signer with Apache License 2.0 | 4 votes |
renderCreateNewVault() {
const showPasswordHelp = (event: React.MouseEvent<HTMLButtonElement>) => {
this.setState({ helpAnchorEl: event.currentTarget });
};
const helpOpen = Boolean(showPasswordHelp);
const helpId = helpOpen ? 'password-help' : undefined;
const closePasswordHelp = () => {
this.setState({ helpAnchorEl: null });
};
return (
<div>
<Grid
container
spacing={4}
direction={'column'}
justify={'flex-start'}
alignItems={'center'}
>
<Grid item className={this.props.classes.alignCenter}>
<img src={logo} alt="logo" width={80} />
<Typography variant={'h6'} align={'center'}>
New Vault
</Typography>
<Typography>
Please set a password for your vault. You will need it later to
unlock it so keep it safe.
</Typography>
</Grid>
<Grid item container>
<form
style={{ textAlign: 'center', width: '100%' }}
onSubmit={e => e.preventDefault()}
>
<FormControl style={{ width: '80%', float: 'left' }}>
<TextFieldWithFormState
autoFocus
fieldState={
this.props.homeContainer.homeForm.$.setPasswordField
}
required
label={'Set Password'}
type={'password'}
/>
</FormControl>
<IconButton
onClick={showPasswordHelp}
style={{
float: 'right',
transform: 'translateY(.3em)'
}}
>
<HelpIcon />
</IconButton>
{this.state.helpAnchorEl && (
<Popover
id={helpId}
open={helpOpen}
anchorEl={this.state.helpAnchorEl}
onClose={closePasswordHelp}
anchorOrigin={{
vertical: 'top',
horizontal: 'right'
}}
transformOrigin={{
vertical: 'bottom',
horizontal: 'right'
}}
>
<Typography
component={'summary'}
style={{
padding: '1.4em',
backgroundColor: 'var(--cspr-dark-blue)',
color: 'white'
}}
>
For a password of min. length 10 please include at least one
of each of the following:
<ul>
<li>lowercase letter</li>
<li>UPPERCASE letter</li>
<li>Number</li>
<li>Special character</li>
</ul>
Or you can enter a >20 char passphrase if you would
prefer e.g. 'correct horse battery staple'
</Typography>
</Popover>
)}
{this.props.homeContainer.homeForm.$.setPasswordField
.hasBeenValidated &&
!this.props.homeContainer.homeForm.$.setPasswordField
.hasError && (
<FormControl style={{ width: '80%', float: 'left' }}>
<TextFieldWithFormState
fieldState={
this.props.homeContainer.homeForm.$.confirmPasswordField
}
required
label={'Confirm Password'}
type={'password'}
/>
</FormControl>
)}
<Typography variant="subtitle2" className="text-danger">
{this.props.homeContainer.homeForm.showFormError &&
this.props.homeContainer.homeForm.formError}
</Typography>
<FormControl fullWidth className={this.props.classes.margin}>
<Button
type="submit"
variant="contained"
color="primary"
disabled={this.props.homeContainer.createVaultDisabled}
onClick={async () => {
const password =
this.props.homeContainer.homeForm.$.setPasswordField.$;
await this.props.accountManager.createNewVault(password);
this.props.homeContainer.homeForm.$.setPasswordField.reset();
this.props.homeContainer.homeForm.$.confirmPasswordField.reset();
}}
>
Create Vault
</Button>
</FormControl>
</form>
</Grid>
</Grid>
</div>
);
}
Example #28
Source File: EditShortcut.tsx From backstage with Apache License 2.0 | 4 votes |
EditShortcut = ({ shortcut, onClose, anchorEl, api }: Props) => {
const classes = useStyles();
const alertApi = useApi(alertApiRef);
const open = Boolean(anchorEl);
const handleSave: SubmitHandler<FormValues> = async ({ url, title }) => {
const newShortcut: Shortcut = {
...shortcut,
url,
title,
};
try {
await api.update(newShortcut);
alertApi.post({
message: `Updated shortcut '${title}'`,
severity: 'success',
});
} catch (error) {
alertApi.post({
message: `Could not update shortcut: ${error.message}`,
severity: 'error',
});
}
onClose();
};
const handleRemove = async () => {
try {
await api.remove(shortcut.id);
alertApi.post({
message: `Removed shortcut '${shortcut.title}' from your sidebar`,
severity: 'success',
});
} catch (error) {
alertApi.post({
message: `Could not delete shortcut: ${error.message}`,
severity: 'error',
});
}
};
const handleClose = () => {
onClose();
};
return (
<Popover
open={open}
anchorEl={anchorEl}
onClose={onClose}
anchorOrigin={{
vertical: 'top',
horizontal: 'right',
}}
>
<Card className={classes.card}>
<CardHeader
className={classes.header}
title="Edit Shortcut"
titleTypographyProps={{ variant: 'subtitle2' }}
action={
<Button
className={classes.button}
variant="text"
size="small"
color="secondary"
startIcon={<DeleteIcon />}
onClick={handleRemove}
>
Remove
</Button>
}
/>
<ShortcutForm
formValues={{ url: shortcut.url, title: shortcut.title }}
onClose={handleClose}
onSave={handleSave}
/>
</Card>
</Popover>
);
}
Example #29
Source File: CalendarEvent.tsx From backstage with Apache License 2.0 | 4 votes |
CalendarEvent = ({ event }: { event: GCalendarEvent }) => {
const classes = useStyles({ event });
const popoverState = usePopupState({
variant: 'popover',
popupId: event.id,
disableAutoFocus: true,
});
const [hovered, setHovered] = useState(false);
const analytics = useAnalytics();
const zoomLink = getZoomLink(event);
const { onClick, ...restBindProps } = bindTrigger(popoverState);
return (
<>
<Paper
onClick={e => {
onClick(e);
analytics.captureEvent('click', 'event info');
}}
{...restBindProps}
onMouseEnter={() => setHovered(true)}
onMouseLeave={() => setHovered(false)}
elevation={hovered ? 4 : 1}
className={classnames(classes.event, {
[classes.passed]: isPassed(event),
})}
data-testid="calendar-event"
>
<Box className={classes.calendarColor} mr={1} alignSelf="stretch" />
<Box flex={1} pt={1} pb={1}>
<Typography
variant="subtitle2"
className={classnames({
[classes.declined]:
event.responseStatus === ResponseStatus.declined,
})}
>
{event.summary}
</Typography>
{!isAllDay(event) && (
<Typography variant="body2" data-testid="calendar-event-time">
{getTimePeriod(event)}
</Typography>
)}
</Box>
{zoomLink && (
<Tooltip title="Join Zoom Meeting">
<Link
data-testid="calendar-event-zoom-link"
className={classes.link}
href={zoomLink}
target="_blank"
onClick={e => {
e.stopPropagation();
analytics.captureEvent('click', 'zoom link');
}}
>
<img src={zoomIcon} alt="Zoom link" />
</Link>
</Tooltip>
)}
</Paper>
<Popover
{...bindPopover(popoverState)}
anchorOrigin={{
vertical: 'top',
horizontal: 'left',
}}
transformOrigin={{
vertical: 'top',
horizontal: 'center',
}}
data-testid="calendar-event-popover"
>
<CalendarEventPopoverContent event={event} />
</Popover>
</>
);
}