mirror of
https://github.com/OneUptime/oneuptime
synced 2024-11-21 22:59:07 +00:00
Display proper message and work on notification change when transaction is carried out from notification
This commit is contained in:
parent
140f0f3dd3
commit
5a7550a49e
@ -46,6 +46,24 @@ router.put('/:projectId/:notificationId/read', getUser, isAuthorized, async func
|
||||
}
|
||||
});
|
||||
|
||||
router.put('/:projectId/:notificationId', getUser, isAuthorized, async function (req, res) {
|
||||
var notificationId = req.params.notificationId;
|
||||
var updateObject = req.body;
|
||||
updateObject._id = notificationId
|
||||
try {
|
||||
let notification = await NotificationService.updateBy(updateObject);
|
||||
if (notification) {
|
||||
return sendItemResponse(req, res, notification);
|
||||
} else {
|
||||
var error = new Error('Notification not found.');
|
||||
error.code = 400;
|
||||
return sendErrorResponse(req, res, error);
|
||||
}
|
||||
} catch (error) {
|
||||
return sendErrorResponse(req, res, error);
|
||||
}
|
||||
});
|
||||
|
||||
router.post('/:projectId', getUser, isAuthorized, async function(req, res){
|
||||
var projectId = req.params.projectId;
|
||||
let userId = req.user ? req.user.id : null;
|
||||
|
@ -104,6 +104,7 @@ module.exports = {
|
||||
let createdBy = data.createdBy || notification.createdBy;
|
||||
let message = data.message || notification.message;
|
||||
let read = notification.read;
|
||||
let meta = data.meta || notification.meta;
|
||||
if(data.read){
|
||||
for(let userId of data.read){
|
||||
read.push(userId);
|
||||
@ -118,7 +119,8 @@ module.exports = {
|
||||
createdBy: createdBy,
|
||||
message: message,
|
||||
icon: icon,
|
||||
read: read
|
||||
read: read,
|
||||
meta: meta
|
||||
}},
|
||||
{
|
||||
new: true
|
||||
|
40
dashboard/public/assets/img/error.svg
Normal file
40
dashboard/public/assets/img/error.svg
Normal file
@ -0,0 +1,40 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 50 50" style="enable-background:new 0 0 50 50;" xml:space="preserve">
|
||||
<circle style="fill:#D75A4A;" cx="25" cy="25" r="25"/>
|
||||
<polyline style="fill:none;stroke:#FFFFFF;stroke-width:2;stroke-linecap:round;stroke-miterlimit:10;" points="16,34 25,25 34,16
|
||||
"/>
|
||||
<polyline style="fill:none;stroke:#FFFFFF;stroke-width:2;stroke-linecap:round;stroke-miterlimit:10;" points="16,16 25,25 34,34
|
||||
"/>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 811 B |
@ -100,4 +100,26 @@ export function markAsRead(projectId,notificationId) {
|
||||
dispatch(fetchNotificationsError(errors(error)));
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function billingActionTaken(projectId, notificationId, values) {
|
||||
return function(dispatch){
|
||||
var promise = putApi(`notification/${projectId}/${notificationId}`, values);
|
||||
return promise.then(function(notification){
|
||||
dispatch(notificationReadSuccess(notification));
|
||||
}, function(error){
|
||||
if(error && error.response && error.response.data)
|
||||
error = error.response.data;
|
||||
if(error && error.data){
|
||||
error = error.data;
|
||||
}
|
||||
if(error && error.message){
|
||||
error = error.message;
|
||||
}
|
||||
else{
|
||||
error = 'Network Error';
|
||||
}
|
||||
dispatch(fetchNotificationsError(errors(error)));
|
||||
});
|
||||
};
|
||||
}
|
82
dashboard/src/components/modals/MessageBox.js
Normal file
82
dashboard/src/components/modals/MessageBox.js
Normal file
@ -0,0 +1,82 @@
|
||||
import React, { Component } from 'react';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import { connect } from 'react-redux';
|
||||
import PropTypes from 'prop-types';
|
||||
import { closeModal } from '../../actions/modal';
|
||||
|
||||
|
||||
class MessageBox extends Component {
|
||||
|
||||
handleKeyBoard = (e) => {
|
||||
const { MessageBoxId, closeModal } = this.props;
|
||||
switch (e.key) {
|
||||
case 'Escape':
|
||||
return closeModal({
|
||||
id: MessageBoxId
|
||||
})
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { title, message, MessageBoxId } = this.props;
|
||||
return (
|
||||
<div onKeyDown={this.handleKeyBoard} className="ModalLayer-wash Box-root Flex-flex Flex-alignItems--flexStart Flex-justifyContent--center">
|
||||
<div
|
||||
className="ModalLayer-contents"
|
||||
tabIndex={-1}
|
||||
style={{ marginTop: 40 }}
|
||||
>
|
||||
<div className="bs-BIM">
|
||||
<div className="bs-Modal bs-Modal--medium">
|
||||
<div className="bs-Modal-header">
|
||||
<div className="bs-Modal-header-copy">
|
||||
<span className="Text-color--inherit Text-display--inline Text-fontSize--20 Text-fontWeight--medium Text-lineHeight--24 Text-typeface--base Text-wrap--wrap">
|
||||
<span>{title}</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="bs-Modal-content">
|
||||
<span className="Text-color--inherit Text-display--inline Text-fontSize--14 Text-fontWeight--regular Text-lineHeight--24 Text-typeface--base Text-wrap--wrap">
|
||||
{message}
|
||||
</span>
|
||||
</div>
|
||||
<div className="bs-Modal-footer">
|
||||
<div className="bs-Modal-footer-actions">
|
||||
<button className="bs-Button bs-DeprecatedButton bs-Button--blue" type="button" onClick={() => this.props.closeModal({
|
||||
id: MessageBoxId
|
||||
})}>
|
||||
<span>OK</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
MessageBox.displayName = 'MessageBoxModal';
|
||||
|
||||
MessageBox.propTypes = {
|
||||
closeModal: PropTypes.func.isRequired,
|
||||
title: PropTypes.string,
|
||||
message: PropTypes.string
|
||||
}
|
||||
|
||||
const mapStateToProps = state => {
|
||||
return {
|
||||
MessageBoxId: state.modal.modals[0].id,
|
||||
title: state.modal.modals[0].title,
|
||||
message: state.modal.modals[0].message
|
||||
}
|
||||
}
|
||||
|
||||
const mapDispatchToProps = dispatch => bindActionCreators(
|
||||
{ closeModal }, dispatch
|
||||
)
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(MessageBox);
|
||||
|
@ -2,7 +2,7 @@ import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types'
|
||||
import { bindActionCreators } from 'redux';
|
||||
import { connect } from 'react-redux';
|
||||
import { markAsRead } from '../../actions/notification';
|
||||
import { markAsRead, billingActionTaken} from '../../actions/notification';
|
||||
import { User } from '../../config';
|
||||
import moment from 'moment';
|
||||
import {
|
||||
@ -10,9 +10,16 @@ import {
|
||||
injectStripe,
|
||||
Elements
|
||||
} from 'react-stripe-elements';
|
||||
import { openModal } from '../../actions/modal';
|
||||
import MessageBox from '../modals/MessageBox';
|
||||
import uuid from 'uuid';
|
||||
|
||||
class NotificationMenu extends Component {
|
||||
|
||||
|
||||
state = {
|
||||
MessageBoxId: uuid.v4()
|
||||
}
|
||||
|
||||
markAsRead(notification) {
|
||||
this.props.markAsRead(notification.projectId, notification._id);
|
||||
if (window.location.href.indexOf('localhost') <= -1) {
|
||||
@ -23,15 +30,38 @@ class NotificationMenu extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
handlePaymentIntent = (client_secret) => {
|
||||
const { stripe } = this.props;
|
||||
handlePaymentIntent = (notification) => {
|
||||
var { client_secret } = notification.meta;
|
||||
var { projectId, _id } = notification;
|
||||
var { stripe, billingActionTaken, openModal } = this.props;
|
||||
var { MessageBoxId } = this.props;
|
||||
stripe.handleCardPayment(client_secret)
|
||||
.then(result => {
|
||||
if (result.paymentIntent && result.paymentIntent.status === 'succeeded') {
|
||||
alert('Transaction successful.')
|
||||
billingActionTaken(projectId, _id, {
|
||||
meta: {},
|
||||
icon: 'success',
|
||||
message: "Billing is successful."
|
||||
})
|
||||
openModal({
|
||||
id: MessageBoxId,
|
||||
content: MessageBox,
|
||||
title: "Message",
|
||||
message: "Transaction successful, your balance has been refilled."
|
||||
})
|
||||
}
|
||||
else {
|
||||
alert('Transaction failed.')
|
||||
billingActionTaken(projectId, _id, {
|
||||
meta: {},
|
||||
icon: 'error',
|
||||
message: "Billing failed."
|
||||
})
|
||||
openModal({
|
||||
id: MessageBoxId,
|
||||
content: MessageBox,
|
||||
title: "Message",
|
||||
message: "Transaction failed."
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -62,7 +92,7 @@ class NotificationMenu extends Component {
|
||||
<div className="Box-root db-ListViewItem--hasLink"
|
||||
style={{ padding: '10px 10px', fontWeight: '400', fontSize: '1em', borderBottom: '1px solid rgba(188,188,188,0.5)', borderRadius: '2px' }}
|
||||
key={key}
|
||||
onClick={() => this.handlePaymentIntent(notification.meta.client_secret)}>
|
||||
onClick={() => this.handlePaymentIntent(notification)}>
|
||||
<div className="Notify-fyipe">
|
||||
<img src={`/assets/img/${notification.icon ? notification.icon : 'information'}.svg`} className="Notify-fyipe-row-primary" style={{ height: '20px', width: '20px' }} alt="notify" />
|
||||
<span className="Notify-fyipe-row-secondary" style={{ cursor: 'pointer' }}>{notification.message} on {moment(notification.createdAt).format('MMMM Do YYYY, h:mm a')}</span>
|
||||
@ -104,11 +134,12 @@ const mapStateToProps = (state) => {
|
||||
}
|
||||
|
||||
const mapDispatchToProps = dispatch => {
|
||||
return bindActionCreators({ markAsRead }, dispatch);
|
||||
return bindActionCreators({ markAsRead, billingActionTaken, openModal }, dispatch);
|
||||
};
|
||||
|
||||
NotificationMenu.propTypes = {
|
||||
markAsRead: PropTypes.func,
|
||||
billingActionTaken: PropTypes.func,
|
||||
notifications: PropTypes.oneOfType([
|
||||
PropTypes.object,
|
||||
PropTypes.oneOf([null, undefined])
|
||||
|
@ -13,9 +13,18 @@ import {
|
||||
injectStripe,
|
||||
Elements
|
||||
} from 'react-stripe-elements';
|
||||
import { openModal } from '../../actions/modal';
|
||||
import MessageBox from '../modals/MessageBox';
|
||||
import uuid from 'uuid';
|
||||
|
||||
|
||||
|
||||
export class AlertAdvanceOption extends Component {
|
||||
|
||||
state = {
|
||||
MessageBoxId: uuid.v4()
|
||||
}
|
||||
|
||||
submitForm = (value) => {
|
||||
value._id = this.props.projectId;
|
||||
this.props.alertOptionsUpdate(this.props.projectId, value)
|
||||
@ -29,18 +38,29 @@ export class AlertAdvanceOption extends Component {
|
||||
}
|
||||
|
||||
handlePaymentIntent = (paymentIntentClientSecret) => {
|
||||
const { stripe } = this.props;
|
||||
const { stripe, openModal } = this.props;
|
||||
const { MessageBoxId } = this.state;
|
||||
stripe.handleCardPayment(paymentIntentClientSecret)
|
||||
.then(result => {
|
||||
if (result.paymentIntent && result.paymentIntent.status === 'succeeded') {
|
||||
alert('Transaction successful')
|
||||
openModal({
|
||||
id: MessageBoxId,
|
||||
content: MessageBox,
|
||||
title: "Message",
|
||||
message: "Transaction successful, your balance has been refilled."
|
||||
})
|
||||
}
|
||||
else {
|
||||
alert('Transaction failed')
|
||||
openModal({
|
||||
id: MessageBoxId,
|
||||
content: MessageBox,
|
||||
title: "Message",
|
||||
message: "Transaction failed, try again later or use a different card."
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
componentDidUpdate() {
|
||||
let { formValues } = this.props;
|
||||
let rechargeToBalance = Number(formValues.rechargeToBalance);
|
||||
@ -308,7 +328,8 @@ AlertAdvanceOption.propTypes = {
|
||||
change:PropTypes.func,
|
||||
alertEnable:PropTypes.bool,
|
||||
stripe: PropTypes.object,
|
||||
paymentIntent: PropTypes.string
|
||||
paymentIntent: PropTypes.string,
|
||||
openModal: PropTypes.func.isRequired
|
||||
}
|
||||
|
||||
let formName = 'AlertAdvanceOption';
|
||||
@ -319,7 +340,7 @@ let AlertAdvanceOptionForm = new reduxForm({
|
||||
})(AlertAdvanceOption);
|
||||
|
||||
const mapDispatchToProps = dispatch => (
|
||||
bindActionCreators({ change, alertOptionsUpdate }, dispatch)
|
||||
bindActionCreators({ change, alertOptionsUpdate, openModal }, dispatch)
|
||||
)
|
||||
|
||||
const mapStateToProps = state => (
|
||||
|
Loading…
Reference in New Issue
Block a user