@material-ui/icons#Done JavaScript Examples
The following examples show how to use
@material-ui/icons#Done.
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: Toast.js From jobtriage with MIT License | 6 votes |
StatusIcon = ({ type }) => {
const getIcon = () => {
if (type === 'success') {
return <Done fontSize="small" style={{ color: theme.palette.success.main }} />;
} if (type === 'error') {
return <Error fontSize="small" style={{ color: theme.palette.error.main }} />;
}
return <InfoOutlined fontSize="small" style={{ color: theme.palette.info.main }} />;
};
return (
<IconButton size="small">
{getIcon()}
</IconButton>
);
}
Example #2
Source File: GrowerDetail.js From treetracker-admin-client with GNU Affero General Public License v3.0 | 4 votes |
GrowerDetail = ({ open, growerId, onClose }) => {
// console.log('render: grower detail');
const classes = useStyle();
const appContext = useContext(AppContext);
const { growers } = useContext(GrowerContext);
const { sendMessageFromGrower } = useContext(MessagingContext);
const [growerRegistrations, setGrowerRegistrations] = useState(null);
const [editDialogOpen, setEditDialogOpen] = useState(false);
const [grower, setGrower] = useState({});
const [deviceIdentifiers, setDeviceIdentifiers] = useState([]);
const [snackbarOpen, setSnackbarOpen] = useState(false);
const [snackbarLabel, setSnackbarLabel] = useState('');
const [verificationStatus, setVerificationStatus] = useState({});
const [loading, setLoading] = useState(false);
const [errorMessage, setErrorMessage] = useState(null);
useEffect(() => {
setErrorMessage(null);
async function loadGrowerDetail() {
if (grower && grower.growerAccountUuid !== growerId) {
setGrower({});
setDeviceIdentifiers([]);
}
if (growerId) {
let match;
if (isNaN(Number(growerId))) {
match = await getGrower({
id: undefined,
growerAccountUuid: growerId,
});
} else {
match = await getGrower({
id: growerId,
growerAccountUuid: undefined,
});
}
if (match.error) {
setErrorMessage(match.message);
}
setGrower(match);
if (
match.id &&
(!growerRegistrations ||
(growerRegistrations.length > 0 &&
growerRegistrations[0].planter_id !== match.id))
) {
setGrowerRegistrations(null);
api.getGrowerRegistrations(match.id).then((registrations) => {
if (registrations && registrations.length) {
const sortedReg = registrations.sort((a, b) =>
a.created_at > b.created_at ? 1 : -1
);
const uniqueDevices = {};
const devices = sortedReg.reduce((result, reg) => {
if (!reg.device_identifier) {
return result;
}
if (!uniqueDevices[reg.device_identifier]) {
uniqueDevices[reg.device_identifier] = true;
// if manufacturer isn't 'apple' it's an android phone
result.push({
id: reg.device_identifier,
os:
reg.manufacturer?.toLowerCase() === 'apple'
? 'iOS'
: 'Android',
});
}
return result;
}, []);
setDeviceIdentifiers(devices);
setGrowerRegistrations(sortedReg);
}
});
}
}
}
loadGrowerDetail();
// eslint-disable-next-line
}, [growerId, growers]);
useEffect(() => {
async function loadCaptures() {
if (grower.id) {
setLoading(true);
const [
approvedCount,
awaitingCount,
rejectedCount,
] = await Promise.all([
getCaptureCountGrower(true, true, grower.id),
getCaptureCountGrower(true, false, grower.id),
getCaptureCountGrower(false, false, grower.id),
]);
setVerificationStatus({
approved: approvedCount,
awaiting: awaitingCount,
rejected: rejectedCount,
});
setLoading(false);
}
}
loadCaptures();
}, [grower]);
async function getCaptureCountGrower(active, approved, growerId) {
let filter = new FilterModel();
filter.planterId = growerId?.toString();
filter.active = active;
filter.approved = approved;
const countResponse = await treeTrackerApi.getCaptureCount(filter);
return countResponse && countResponse.count ? countResponse.count : 0;
}
async function getGrower(payload) {
const { id, growerAccountUuid } = payload;
let grower = growers?.find(
(p) =>
(growerAccountUuid && p.growerAccountUuid === growerAccountUuid) ||
p.id === id
); // Look for a match in the context first
if (!grower && !id) {
const filter = new FilterGrower();
filter.growerAccountUuid = growerAccountUuid;
[grower] = await api.getGrowers({ filter }); // Otherwise query the API
}
if (!grower && !growerAccountUuid) {
grower = await api.getGrower(id);
}
// throw error if no match at all
return grower || { error: true, message: 'Sorry! No grower info found' };
}
function handleEditClick() {
setEditDialogOpen(true);
}
function handleEditClose() {
setEditDialogOpen(false);
setSnackbarOpen(false);
setSnackbarLabel('');
}
function confirmCopy(label) {
setSnackbarOpen(false);
setSnackbarLabel(label);
setSnackbarOpen(true);
}
return (
<>
<Drawer anchor="right" open={open} onClose={onClose}>
<Grid
style={{
width: GROWER_IMAGE_SIZE,
}}
>
{errorMessage ? (
<Grid container direction="column">
<Grid item>
<Grid container justify="space-between" alignItems="center">
<Grid item>
<Box m={4}>
<Typography color="primary" variant="h6">
Grower Detail
</Typography>
<Typography variant="h4">{errorMessage}</Typography>
</Box>
</Grid>
<Grid item>
<IconButton onClick={() => onClose()}>
<Close />
</IconButton>
</Grid>
</Grid>
</Grid>
<Grid item className={classes.imageContainer}>
<CardMedia className={classes.cardMedia}>
<Grid container className={classes.personBox}>
<Person className={classes.person} />
</Grid>
</CardMedia>
</Grid>
</Grid>
) : (
<Grid container direction="column">
<Grid item>
<Grid container justify="space-between" alignItems="center">
<Grid item>
<Box m={4}>
<Typography color="primary" variant="h6">
Grower Detail
</Typography>
</Box>
</Grid>
<Grid item>
<IconButton onClick={() => onClose()}>
<Close />
</IconButton>
</Grid>
</Grid>
</Grid>
<Grid item className={classes.imageContainer}>
{grower?.imageUrl && (
<OptimizedImage
src={grower.imageUrl}
width={GROWER_IMAGE_SIZE}
height={GROWER_IMAGE_SIZE}
className={classes.cardMedia}
fixed
rotation={grower.imageRotation}
alertTitleSize="1.6rem"
alertTextSize="1rem"
alertHeight="50%"
/>
)}
{!grower.imageUrl && (
<CardMedia className={classes.cardMedia}>
<Grid container className={classes.personBox}>
<Person className={classes.person} />
</Grid>
</CardMedia>
)}
{hasPermission(appContext.user, [
POLICIES.SUPER_PERMISSION,
POLICIES.MANAGE_GROWER,
]) && (
<Fab
data-testid="edit-grower"
className={classes.editButton}
onClick={() => handleEditClick()}
>
<EditIcon />
</Fab>
)}
</Grid>
<Grid item className={classes.box}>
<Typography
variant="h5"
color="primary"
className={classes.name}
>
{grower.firstName} {grower.lastName}
</Typography>
<Typography variant="body2">
ID: <LinkToWebmap value={grower.id} type="user" />
</Typography>
</Grid>
{process.env.REACT_APP_ENABLE_MESSAGING === 'true' &&
hasPermission(appContext.user, [POLICIES.SUPER_PERMISSION]) && (
<Grid item>
<Button
className={classes.messageButton}
onClick={() => sendMessageFromGrower(grower)}
component={Link}
to={'/messaging'}
>
Send Message
</Button>
</Grid>
)}
<Divider />
<Grid container direction="column" className={classes.box}>
<Typography variant="subtitle1">Captures</Typography>
{loading ? (
<LinearProgress color="primary" />
) : (
<List className={classes.listCaptures}>
<Box
borderColor="grey.300"
borderRadius={10}
border={0.5}
m={0.5}
>
<ListItem>
<ListItemAvatar>
<Avatar className={classes.approvedChip}>
<Done />
</Avatar>
</ListItemAvatar>
<ListItemText
primary={
<Typography variant="h5">
{verificationStatus.approved || 0}
</Typography>
}
secondary="Approved"
/>
</ListItem>
</Box>
<Box
borderColor="grey.300"
borderRadius={10}
border={0.5}
m={0.5}
>
<ListItem>
<ListItemAvatar>
<Avatar className={classes.awaitingChip}>
<HourglassEmptyOutlined />
</Avatar>
</ListItemAvatar>
<ListItemText
primary={
<Typography variant="h5">
{verificationStatus.awaiting || 0}
</Typography>
}
secondary="Awaiting"
/>
</ListItem>
</Box>
<Box
borderColor="grey.300"
borderRadius={10}
border={0.5}
m={0.5}
>
<ListItem>
<ListItemAvatar>
<Avatar className={classes.rejectedChip}>
<Clear />
</Avatar>
</ListItemAvatar>
<ListItemText
primary={
<Typography variant="h5">
{verificationStatus.rejected || 0}
</Typography>
}
secondary="Rejected"
/>
</ListItem>
</Box>
</List>
)}
</Grid>
<Divider />
<Grid container direction="column" className={classes.box}>
<Typography variant="subtitle1">Email address</Typography>
<Typography variant="body1">{grower.email || '---'}</Typography>
</Grid>
<Divider />
<Grid container direction="column" className={classes.box}>
<Typography variant="subtitle1">Phone number</Typography>
<Typography variant="body1">{grower.phone || '---'}</Typography>
</Grid>
<Divider />
<Grid container direction="column" className={classes.box}>
<Typography variant="subtitle1">Person ID</Typography>
<Typography variant="body1">
{grower.personId || '---'}
</Typography>
</Grid>
<Divider />
<Grid container direction="column" className={classes.box}>
<Typography variant="subtitle1">Organization</Typography>
{grower.organization || grower.organizationId ? (
<GrowerOrganization
organizationName={grower.organization}
assignedOrganizationId={grower.organizationId}
/>
) : (
<Typography variant="body1">---</Typography>
)}
</Grid>
<Divider />
<Grid container direction="column" className={classes.box}>
<Typography variant="subtitle1">Country</Typography>
<Typography variant="body1">
{(growerRegistrations &&
growerRegistrations
.map((item) => item.country)
.filter(
(country, i, arr) =>
country && arr.indexOf(country) === i
)
.join(', ')) ||
'---'}
</Typography>
</Grid>
<Divider />
<Grid container direction="column" className={classes.box}>
<Typography variant="subtitle1">Registered</Typography>
<Typography variant="body1">
{(growerRegistrations &&
growerRegistrations.length > 0 &&
getDateTimeStringLocale(
growerRegistrations[0].created_at
)) ||
'---'}
</Typography>
</Grid>
<Divider />
<Grid container direction="column" className={classes.box}>
<Typography variant="subtitle1">
Device Identifier{deviceIdentifiers.length >= 2 ? 's' : ''}
</Typography>
{(deviceIdentifiers.length && (
<table>
<tbody>
{deviceIdentifiers.map((device, i) => (
<tr key={i}>
<td>
<Typography variant="body1">
{device.id}
<CopyButton
label={'Device Identifier'}
value={device.id}
confirmCopy={confirmCopy}
/>
</Typography>
</td>
<td>
<Typography variant="body1">
({device.os})
</Typography>
</td>
</tr>
))}
</tbody>
</table>
)) || <Typography variant="body1">---</Typography>}
</Grid>
</Grid>
)}
</Grid>
</Drawer>
<CopyNotification
snackbarLabel={snackbarLabel}
snackbarOpen={snackbarOpen}
setSnackbarOpen={setSnackbarOpen}
/>
<EditGrower
isOpen={editDialogOpen}
grower={grower}
onClose={handleEditClose}
></EditGrower>
</>
);
}
Example #3
Source File: index.js From whaticket with MIT License | 4 votes |
MessagesList = ({ ticketId, isGroup }) => {
const classes = useStyles();
const [messagesList, dispatch] = useReducer(reducer, []);
const [pageNumber, setPageNumber] = useState(1);
const [hasMore, setHasMore] = useState(false);
const [loading, setLoading] = useState(false);
const lastMessageRef = useRef();
const [selectedMessage, setSelectedMessage] = useState({});
const [anchorEl, setAnchorEl] = useState(null);
const messageOptionsMenuOpen = Boolean(anchorEl);
const currentTicketId = useRef(ticketId);
useEffect(() => {
dispatch({ type: "RESET" });
setPageNumber(1);
currentTicketId.current = ticketId;
}, [ticketId]);
useEffect(() => {
setLoading(true);
const delayDebounceFn = setTimeout(() => {
const fetchMessages = async () => {
try {
const { data } = await api.get("/messages/" + ticketId, {
params: { pageNumber },
});
if (currentTicketId.current === ticketId) {
dispatch({ type: "LOAD_MESSAGES", payload: data.messages });
setHasMore(data.hasMore);
setLoading(false);
}
if (pageNumber === 1 && data.messages.length > 1) {
scrollToBottom();
}
} catch (err) {
setLoading(false);
toastError(err);
}
};
fetchMessages();
}, 500);
return () => {
clearTimeout(delayDebounceFn);
};
}, [pageNumber, ticketId]);
useEffect(() => {
const socket = openSocket();
socket.on("connect", () => socket.emit("joinChatBox", ticketId));
socket.on("appMessage", (data) => {
if (data.action === "create") {
dispatch({ type: "ADD_MESSAGE", payload: data.message });
scrollToBottom();
}
if (data.action === "update") {
dispatch({ type: "UPDATE_MESSAGE", payload: data.message });
}
});
return () => {
socket.disconnect();
};
}, [ticketId]);
const loadMore = () => {
setPageNumber((prevPageNumber) => prevPageNumber + 1);
};
const scrollToBottom = () => {
if (lastMessageRef.current) {
lastMessageRef.current.scrollIntoView({});
}
};
const handleScroll = (e) => {
if (!hasMore) return;
const { scrollTop } = e.currentTarget;
if (scrollTop === 0) {
document.getElementById("messagesList").scrollTop = 1;
}
if (loading) {
return;
}
if (scrollTop < 50) {
loadMore();
}
};
const handleOpenMessageOptionsMenu = (e, message) => {
setAnchorEl(e.currentTarget);
setSelectedMessage(message);
};
const handleCloseMessageOptionsMenu = (e) => {
setAnchorEl(null);
};
const checkMessageMedia = (message) => {
if(message.mediaType === "location" && message.body.split('|').length >= 2) {
let locationParts = message.body.split('|')
let imageLocation = locationParts[0]
let linkLocation = locationParts[1]
let descriptionLocation = null
if(locationParts.length > 2)
descriptionLocation = message.body.split('|')[2]
return <LocationPreview image={imageLocation} link={linkLocation} description={descriptionLocation} />
}
else if (message.mediaType === "vcard") {
//console.log("vcard")
//console.log(message)
let array = message.body.split("\n");
let obj = [];
let contact = "";
for (let index = 0; index < array.length; index++) {
const v = array[index];
let values = v.split(":");
for (let ind = 0; ind < values.length; ind++) {
if (values[ind].indexOf("+") !== -1) {
obj.push({ number: values[ind] });
}
if (values[ind].indexOf("FN") !== -1) {
contact = values[ind + 1];
}
}
}
return <VcardPreview contact={contact} numbers={obj[0].number} />
}
/*else if (message.mediaType === "multi_vcard") {
console.log("multi_vcard")
console.log(message)
if(message.body !== null && message.body !== "") {
let newBody = JSON.parse(message.body)
return (
<>
{
newBody.map(v => (
<VcardPreview contact={v.name} numbers={v.number} />
))
}
</>
)
} else return (<></>)
}*/
else if (message.mediaType === "image") {
return <ModalImageCors imageUrl={message.mediaUrl} />;
} else if (message.mediaType === "audio") {
return (
<audio controls>
<source src={message.mediaUrl} type="audio/ogg"></source>
</audio>
);
} else if (message.mediaType === "video") {
return (
<video
className={classes.messageMedia}
src={message.mediaUrl}
controls
/>
);
} else {
return (
<>
<div className={classes.downloadMedia}>
<Button
startIcon={<GetApp />}
color="primary"
variant="outlined"
target="_blank"
href={message.mediaUrl}
>
Download
</Button>
</div>
<Divider />
</>
);
}
};
const renderMessageAck = (message) => {
if (message.ack === 0) {
return <AccessTime fontSize="small" className={classes.ackIcons} />;
}
if (message.ack === 1) {
return <Done fontSize="small" className={classes.ackIcons} />;
}
if (message.ack === 2) {
return <DoneAll fontSize="small" className={classes.ackIcons} />;
}
if (message.ack === 3 || message.ack === 4) {
return <DoneAll fontSize="small" className={classes.ackDoneAllIcon} />;
}
};
const renderDailyTimestamps = (message, index) => {
if (index === 0) {
return (
<span
className={classes.dailyTimestamp}
key={`timestamp-${message.id}`}
>
<div className={classes.dailyTimestampText}>
{format(parseISO(messagesList[index].createdAt), "dd/MM/yyyy")}
</div>
</span>
);
}
if (index < messagesList.length - 1) {
let messageDay = parseISO(messagesList[index].createdAt);
let previousMessageDay = parseISO(messagesList[index - 1].createdAt);
if (!isSameDay(messageDay, previousMessageDay)) {
return (
<span
className={classes.dailyTimestamp}
key={`timestamp-${message.id}`}
>
<div className={classes.dailyTimestampText}>
{format(parseISO(messagesList[index].createdAt), "dd/MM/yyyy")}
</div>
</span>
);
}
}
if (index === messagesList.length - 1) {
return (
<div
key={`ref-${message.createdAt}`}
ref={lastMessageRef}
style={{ float: "left", clear: "both" }}
/>
);
}
};
const renderMessageDivider = (message, index) => {
if (index < messagesList.length && index > 0) {
let messageUser = messagesList[index].fromMe;
let previousMessageUser = messagesList[index - 1].fromMe;
if (messageUser !== previousMessageUser) {
return (
<span style={{ marginTop: 16 }} key={`divider-${message.id}`}></span>
);
}
}
};
const renderQuotedMessage = (message) => {
return (
<div
className={clsx(classes.quotedContainerLeft, {
[classes.quotedContainerRight]: message.fromMe,
})}
>
<span
className={clsx(classes.quotedSideColorLeft, {
[classes.quotedSideColorRight]: message.quotedMsg?.fromMe,
})}
></span>
<div className={classes.quotedMsg}>
{!message.quotedMsg?.fromMe && (
<span className={classes.messageContactName}>
{message.quotedMsg?.contact?.name}
</span>
)}
{message.quotedMsg?.body}
</div>
</div>
);
};
const renderMessages = () => {
if (messagesList.length > 0) {
const viewMessagesList = messagesList.map((message, index) => {
if (!message.fromMe) {
return (
<React.Fragment key={message.id}>
{renderDailyTimestamps(message, index)}
{renderMessageDivider(message, index)}
<div className={classes.messageLeft}>
<IconButton
variant="contained"
size="small"
id="messageActionsButton"
disabled={message.isDeleted}
className={classes.messageActionsButton}
onClick={(e) => handleOpenMessageOptionsMenu(e, message)}
>
<ExpandMore />
</IconButton>
{isGroup && (
<span className={classes.messageContactName}>
{message.contact?.name}
</span>
)}
{(message.mediaUrl || message.mediaType === "location" || message.mediaType === "vcard"
//|| message.mediaType === "multi_vcard"
) && checkMessageMedia(message)}
<div className={classes.textContentItem}>
{message.quotedMsg && renderQuotedMessage(message)}
<MarkdownWrapper>{message.body}</MarkdownWrapper>
<span className={classes.timestamp}>
{format(parseISO(message.createdAt), "HH:mm")}
</span>
</div>
</div>
</React.Fragment>
);
} else {
return (
<React.Fragment key={message.id}>
{renderDailyTimestamps(message, index)}
{renderMessageDivider(message, index)}
<div className={classes.messageRight}>
<IconButton
variant="contained"
size="small"
id="messageActionsButton"
disabled={message.isDeleted}
className={classes.messageActionsButton}
onClick={(e) => handleOpenMessageOptionsMenu(e, message)}
>
<ExpandMore />
</IconButton>
{(message.mediaUrl || message.mediaType === "location" || message.mediaType === "vcard"
//|| message.mediaType === "multi_vcard"
) && checkMessageMedia(message)}
<div
className={clsx(classes.textContentItem, {
[classes.textContentItemDeleted]: message.isDeleted,
})}
>
{message.isDeleted && (
<Block
color="disabled"
fontSize="small"
className={classes.deletedIcon}
/>
)}
{message.quotedMsg && renderQuotedMessage(message)}
<MarkdownWrapper>{message.body}</MarkdownWrapper>
<span className={classes.timestamp}>
{format(parseISO(message.createdAt), "HH:mm")}
{renderMessageAck(message)}
</span>
</div>
</div>
</React.Fragment>
);
}
});
return viewMessagesList;
} else {
return <div>Say hello to your new contact!</div>;
}
};
return (
<div className={classes.messagesListWrapper}>
<MessageOptionsMenu
message={selectedMessage}
anchorEl={anchorEl}
menuOpen={messageOptionsMenuOpen}
handleClose={handleCloseMessageOptionsMenu}
/>
<div
id="messagesList"
className={classes.messagesList}
onScroll={handleScroll}
>
{messagesList.length > 0 ? renderMessages() : []}
</div>
{loading && (
<div>
<CircularProgress className={classes.circleLoading} />
</div>
)}
</div>
);
}