From b6a7844aa577401497dfa3a3eee25afaa3663952 Mon Sep 17 00:00:00 2001 From: wiadev Date: Mon, 7 Aug 2017 20:44:47 +0200 Subject: [PATCH] Show lengthy uploads progress #1097 --- package.json | 2 +- src/actions/AppActions.js | 8 ++++ src/actions/WindowActions.js | 25 ++++++++-- src/assets/css/styles.css | 48 ++++++++++++++++++++ src/components/notifications/Notification.js | 40 ++++++++++------ src/constants/ActionTypes.js | 1 + src/reducers/appHandler.js | 11 +++++ 7 files changed, 114 insertions(+), 21 deletions(-) diff --git a/package.json b/package.json index f0303fe3c..730cc4515 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,7 @@ "webpack-dev-server": "~1.12.1" }, "dependencies": { - "axios": "~0.13.1", + "axios": "^0.16.2", "bootstrap": "4.0.0-alpha.5", "counterpart": "~0.18.0", "d3": "^4.4.0", diff --git a/src/actions/AppActions.js b/src/actions/AppActions.js index 469ac6bde..14acce84a 100644 --- a/src/actions/AppActions.js +++ b/src/actions/AppActions.js @@ -307,6 +307,14 @@ export function addNotification(title, msg, time, notifType, shortMsg){ } } +export function setNotificationProgress(key, progress){ + return { + type: types.SET_NOTIFICATION_PROGRESS, + key: key, + progress: progress + } +} + export function deleteNotification(key){ return { type: types.DELETE_NOTIFICATION, diff --git a/src/actions/WindowActions.js b/src/actions/WindowActions.js index 74d3ab08f..7d8561d42 100644 --- a/src/actions/WindowActions.js +++ b/src/actions/WindowActions.js @@ -18,6 +18,7 @@ import { import { addNotification, + setNotificationProgress, setProcessSaved, setProcessPending } from './AppActions'; @@ -575,22 +576,36 @@ export function updatePropertyValue(property, value, tabid, rowid, isModal) { } } +function handleUploadProgress(dispatch, notificationTitle, progressEvent) { + let percentLeft = Math.min(Math.floor((progressEvent.loaded * 100) / progressEvent.total), 98); + + dispatch(setNotificationProgress(notificationTitle, percentLeft)); +} + export function attachFileAction(windowType, docId, data){ - return dispatch => { + return (dispatch) => { + const notificationTitle = 'Attachment'; + dispatch(addNotification( - 'Attachment', 'Uploading attachment', 5000, 'primary' + notificationTitle, 'Uploading attachment', 0, 'primary' )); + let requestConfig = { + onUploadProgress: handleUploadProgress.bind(this, dispatch, notificationTitle) + }; + return axios.post( - `${config.API_URL}/window/${windowType}/${docId}/attachments`, data + `${config.API_URL}/window/${windowType}/${docId}/attachments`, data, requestConfig ).then(() => { + dispatch(setNotificationProgress(notificationTitle, 100)); + dispatch(addNotification( - 'Attachment', 'Uploading attachment succeeded.', 5000, 'primary' + notificationTitle, 'Uploading attachment succeeded.', 5000, 'primary' )) }) .catch(() => { dispatch(addNotification( - 'Attachment', 'Uploading attachment error.', 5000, 'error' + notificationTitle, 'Uploading attachment error.', 5000, 'error' )) }) } diff --git a/src/assets/css/styles.css b/src/assets/css/styles.css index 0eb979f5b..a12b64fb6 100644 --- a/src/assets/css/styles.css +++ b/src/assets/css/styles.css @@ -1061,9 +1061,57 @@ td.pulse-off input { bottom:0; left:0; height: 3px; + width: 100%; background-color: rgba(0,0,0,.3); } +@-moz-keyframes infinite_progress { + from { + width: 100%; + } + + to { + width: 0%; + } +} + +@-webkit-keyframes infinite_progress { + from { + width: 100%; + } + + to { + width: 0%; + } +} + +@-ms-keyframes infinite_progress { + from { + width: 100%; + } + + to { + width: 0%; + } +} + +@keyframes infinite_progress { + from { + width: 100%; + } + + to { + width: 0%; + } +} + +.progress-bar.progress-infinite { + -webkit-animation: infinite_progress 5s infinite; + -moz-animation: infinite_progress 5s infinite; + -ms-animation: infinite_progress 5s infinite; + animation: infinite_progress 5s infinite; +} + .progress-bar.error { background-color: $brand-danger-color; } diff --git a/src/components/notifications/Notification.js b/src/components/notifications/Notification.js index 82c946e0b..fb3e47c5c 100644 --- a/src/components/notifications/Notification.js +++ b/src/components/notifications/Notification.js @@ -20,12 +20,12 @@ class Notification extends Component { componentDidMount() { const {item} = this.props; - if(item.time > 0) { + if (item.time > 0) { this.setClosing(); } const th = this; - setTimeout(() => { + setTimeout( () => { th.setState({ isClosing: true }) @@ -48,9 +48,15 @@ class Notification extends Component { setClosing = () => { const {dispatch, item} = this.props; - this.closing = setTimeout(() => { - dispatch(deleteNotification(item.title)); - }, item.time); + + if (item.time === 0) { + this.closing = null; + } + else { + this.closing = setTimeout(() => { + dispatch(deleteNotification(item.title)); + }, item.time); + } } handleCloseButton = () => { @@ -62,13 +68,15 @@ class Notification extends Component { } handleClosing = (shouldClose) => { - shouldClose ? - this.setClosing() : - clearInterval(this.closing); + if (this.props.item && this.props.item.time !== 0) { + shouldClose ? + this.setClosing() : + clearInterval(this.closing); - this.setState({ - isClosing: shouldClose - }) + this.setState({ + isClosing: shouldClose + }) + } } handleToggleMore = () => { @@ -80,6 +88,7 @@ class Notification extends Component { render() { const {item} = this.props; const {isClosing, isDisplayedMore} = this.state; + let progress = item.progress; return (
diff --git a/src/constants/ActionTypes.js b/src/constants/ActionTypes.js index 16e2b0176..d298d584e 100644 --- a/src/constants/ActionTypes.js +++ b/src/constants/ActionTypes.js @@ -35,6 +35,7 @@ export const CHANGE_INDICATOR_STATE = 'CHANGE_INDICATOR_STATE'; // NOTIFICATION ACTIONS export const ADD_NOTIFICATION = 'ADD_NOTIFICATION'; +export const SET_NOTIFICATION_PROGRESS = 'SET_NOTIFICATION_PROGRESS'; export const DELETE_NOTIFICATION = 'DELETE_NOTIFICATION'; // END OF NOTIFICATION ACTIONS diff --git a/src/reducers/appHandler.js b/src/reducers/appHandler.js index a5fd20bd1..ed4693be4 100644 --- a/src/reducers/appHandler.js +++ b/src/reducers/appHandler.js @@ -48,6 +48,17 @@ export default function appHandler(state = initialState, action) { }) }); + case types.SET_NOTIFICATION_PROGRESS: + let notifications = Object.assign({}, state.notifications, { + [action.key]: Object.assign({}, state.notifications[action.key], { + progress: action.progress + }) + }); + + return Object.assign({}, state, { + notifications: notifications + }); + case types.DELETE_NOTIFICATION: return Object.assign({}, state, { notifications: Object.keys(state.notifications)