-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adding notification action button to exercise-related pages.
- Loading branch information
1 parent
32e5ff2
commit 992ec01
Showing
11 changed files
with
204 additions
and
3 deletions.
There are no files selected for viewing
135 changes: 135 additions & 0 deletions
135
src/components/Exercises/ExerciseButtons/ExerciseButtons.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
import React, { useState, useRef } from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import { FormattedMessage } from 'react-intl'; | ||
import { Row, Col, Modal, FormGroup, FormControl, FormLabel, Overlay, Popover } from 'react-bootstrap'; | ||
|
||
import Button, { TheButtonGroup } from '../../widgets/TheButton'; | ||
import InsetPanel from '../../widgets/InsetPanel'; | ||
import { BellIcon, CloseIcon, LoadingIcon, SendIcon, WarningIcon } from '../../icons'; | ||
|
||
const ExerciseButtons = ({ id, archivedAt = null, permissionHints = null, sendNotification }) => { | ||
const [message, setMessage] = useState(null); // null = dialog is hidden, string = message (and dialog is open) | ||
const [sendResult, setSendResult] = useState(null); // null = initial, true = pending, false = error, int = result | ||
// the sendResult holds, how many users were notified (-1 is server error) | ||
const buttonTarget = useRef(null); | ||
|
||
return !archivedAt && permissionHints && permissionHints.update ? ( | ||
<> | ||
<Row> | ||
<Col className="mb-3" xs={12} lg={true}> | ||
<TheButtonGroup></TheButtonGroup> | ||
</Col> | ||
|
||
<Col xs={12} lg="auto" className="mb-3"> | ||
<TheButtonGroup className="text-nowrap"> | ||
<Button | ||
variant={ | ||
sendResult === false || sendResult < 0 | ||
? 'danger' | ||
: sendResult === null || sendResult === true | ||
? 'warning' | ||
: 'success' | ||
} | ||
onClick={() => (sendResult !== null && sendResult !== true ? setSendResult(null) : setMessage(''))} | ||
disabled={sendResult !== null} | ||
ref={buttonTarget}> | ||
{sendResult === true ? <LoadingIcon gapRight /> : <BellIcon gapRight />} | ||
<FormattedMessage id="app.exercise.notificationButton" defaultMessage="Send Notification" /> | ||
</Button> | ||
</TheButtonGroup> | ||
|
||
<Overlay target={buttonTarget.current} show={sendResult !== null && sendResult !== true} placement="bottom"> | ||
{props => ( | ||
<Popover id={id} {...props}> | ||
<Popover.Title> | ||
{sendResult === false || sendResult < 0 ? ( | ||
<> | ||
<WarningIcon className="text-danger" gapRight /> | ||
<FormattedMessage | ||
id="app.exercise.notificationButton.failedMessage" | ||
defaultMessage="The operation has failed!" | ||
/> | ||
</> | ||
) : sendResult === 0 ? ( | ||
<FormattedMessage | ||
id="app.exercise.notificationButton.noRecipients" | ||
defaultMessage="No recipients of the notification were found. Please note that the users may choose to ignore these notifications in their personal settings." | ||
/> | ||
) : ( | ||
<FormattedMessage | ||
id="app.exercise.notificationButton.successMessage" | ||
defaultMessage="The notification was successfully sent to {sendResult} {sendResult, plural, one {user} other {users}}." | ||
values={{ sendResult }} | ||
/> | ||
)} | ||
</Popover.Title> | ||
<Popover.Content className="text-center"> | ||
<Button onClick={() => setSendResult(null)} size="xs" variant="success"> | ||
<FormattedMessage id="generic.acknowledge" defaultMessage="Acknowledge" /> | ||
</Button> | ||
</Popover.Content> | ||
</Popover> | ||
)} | ||
</Overlay> | ||
</Col> | ||
</Row> | ||
|
||
<Modal show={message !== null} backdrop="static" onHide={() => setMessage(null)} size="xl"> | ||
<Modal.Header closeButton> | ||
<Modal.Title> | ||
<FormattedMessage | ||
id="app.exercise.notificationModal.title" | ||
defaultMessage="Send a notification to teachers" | ||
/> | ||
</Modal.Title> | ||
</Modal.Header> | ||
|
||
<Modal.Body> | ||
<InsetPanel> | ||
<FormattedMessage | ||
id="app.exercise.notificationModal.explain" | ||
defaultMessage="A notification is sent by email to all group admins and supervisors who have assigned this exercise in their groups. Optionally, you may attach a custom message to the notification. If you leave the message empty, a generic notification informing that the exercise was changed will be sent." | ||
/> | ||
</InsetPanel> | ||
|
||
<FormGroup controlId="message"> | ||
<FormLabel> | ||
<FormattedMessage id="generic.message" defaultMessage="Message" />: | ||
</FormLabel> | ||
<FormControl type="text" value={message || ''} onChange={ev => setMessage(ev.target.value)} /> | ||
</FormGroup> | ||
</Modal.Body> | ||
|
||
<Modal.Footer className="d-block text-center"> | ||
<TheButtonGroup className="text-nowrap"> | ||
<Button | ||
variant="success" | ||
onClick={() => { | ||
if (sendResult !== true) { | ||
setSendResult(true); | ||
sendNotification(message).then(({ value }) => setSendResult(value)); | ||
setMessage(null); | ||
} | ||
}}> | ||
<SendIcon gapRight /> | ||
<FormattedMessage id="generic.send" defaultMessage="Send" /> | ||
</Button> | ||
<Button variant="secondary" onClick={() => setMessage(null)}> | ||
<CloseIcon gapRight /> | ||
<FormattedMessage id="generic.close" defaultMessage="Close" /> | ||
</Button> | ||
</TheButtonGroup> | ||
</Modal.Footer> | ||
</Modal> | ||
</> | ||
) : null; | ||
}; | ||
|
||
ExerciseButtons.propTypes = { | ||
id: PropTypes.string.isRequired, | ||
archivedAt: PropTypes.number, | ||
permissionHints: PropTypes.object, | ||
sendNotification: PropTypes.func.isRequired, | ||
}; | ||
|
||
export default ExerciseButtons; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
import ExerciseButtons from './ExerciseButtons'; | ||
export default ExerciseButtons; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.