diff --git a/ui/src/actions/AppAction.js b/ui/src/actions/AppAction.js index 69df5a8..bbe06a4 100644 --- a/ui/src/actions/AppAction.js +++ b/ui/src/actions/AppAction.js @@ -1,6 +1,7 @@ import dispatcher from '../stores/dispatcher'; import config from 'react-global-configuration'; import axios from 'axios'; +import {snack} from './GlobalAction'; /** Fetches all applications. */ export function fetchApps() { @@ -14,7 +15,7 @@ export function fetchApps() { * @param {int} id the application id */ export function deleteApp(id) { - axios.delete(config.get('url') + 'application/' + id).then(fetchApps); + axios.delete(config.get('url') + 'application/' + id).then(fetchApps).then(() => snack('Application deleted')); } /** @@ -23,7 +24,9 @@ export function deleteApp(id) { * @param {string} description the description of the application. */ export function createApp(name, description) { - axios.post(config.get('url') + 'application', {name, description}).then(fetchApps); + axios.post(config.get('url') + 'application', {name, description}) + .then(fetchApps) + .then(() => snack('Application created')); } /** @@ -35,5 +38,6 @@ export function uploadImage(id, file) { const formData = new FormData(); formData.append('file', file); axios.post(config.get('url') + 'application/' + id + '/image', formData, - {headers: {'content-type': 'multipart/form-data'}}).then(fetchApps); + {headers: {'content-type': 'multipart/form-data'}}).then(fetchApps) + .then(() => snack('Application image updated')); } diff --git a/ui/src/actions/ClientAction.js b/ui/src/actions/ClientAction.js index 17ba0e9..6f0ae38 100644 --- a/ui/src/actions/ClientAction.js +++ b/ui/src/actions/ClientAction.js @@ -1,6 +1,7 @@ import dispatcher from '../stores/dispatcher'; import config from 'react-global-configuration'; import axios from 'axios'; +import {snack} from './GlobalAction'; /** Fetches all clients. */ export function fetchClients() { @@ -17,7 +18,7 @@ export function fetchClients() { * @param {int} id the client id */ export function deleteClient(id) { - axios.delete(config.get('url') + 'client/' + id).then(fetchClients); + axios.delete(config.get('url') + 'client/' + id).then(fetchClients).then(() => snack('Client deleted')); } /** @@ -25,5 +26,5 @@ export function deleteClient(id) { * @param {string} name the client name */ export function createClient(name) { - axios.post(config.get('url') + 'client', {name}).then(fetchClients); + axios.post(config.get('url') + 'client', {name}).then(fetchClients).then(() => snack('Client created')); } diff --git a/ui/src/actions/MessageAction.js b/ui/src/actions/MessageAction.js index 4ad831f..bfd8e41 100644 --- a/ui/src/actions/MessageAction.js +++ b/ui/src/actions/MessageAction.js @@ -2,6 +2,7 @@ import dispatcher from '../stores/dispatcher'; import config from 'react-global-configuration'; import axios from 'axios'; import {getToken} from './defaultAxios'; +import {snack} from './GlobalAction'; /** Fetches all messages from the current user. */ export function fetchMessages() { @@ -12,7 +13,7 @@ export function fetchMessages() { /** Deletes all messages from the current user. */ export function deleteMessages() { - axios.delete(config.get('url') + 'message').then(fetchMessages); + axios.delete(config.get('url') + 'message').then(fetchMessages).then(() => snack('Messages deleted')); } /** @@ -20,7 +21,8 @@ export function deleteMessages() { * @param {int} id the application id */ export function deleteMessagesByApp(id) { - axios.delete(config.get('url') + 'application/' + id + '/message').then(fetchMessages); + axios.delete(config.get('url') + 'application/' + id + '/message').then(fetchMessages) + .then(() => snack('Deleted all messages from the application')); } /** @@ -28,7 +30,7 @@ export function deleteMessagesByApp(id) { * @param {int} id the message id */ export function deleteMessage(id) { - axios.delete(config.get('url') + 'message/' + id).then(fetchMessages); + axios.delete(config.get('url') + 'message/' + id).then(fetchMessages).then(() => snack('Message deleted')); } /** @@ -43,6 +45,7 @@ export function listenToWebSocket() { ws.onerror = (e) => { console.log('WebSocket connection errored; trying again in 60 seconds', e); + snack('Could not connect to the web socket, trying again in 60 seconds.'); setTimeout(listenToWebSocket, 60000); }; diff --git a/ui/src/actions/UserAction.js b/ui/src/actions/UserAction.js index 1da06b2..c15d679 100644 --- a/ui/src/actions/UserAction.js +++ b/ui/src/actions/UserAction.js @@ -5,6 +5,7 @@ import * as GlobalAction from './GlobalAction'; import axios from 'axios'; import {detect} from 'detect-browser'; import ClientStore from '../stores/ClientStore'; +import {snack} from './GlobalAction'; /** * Login the user. @@ -14,14 +15,16 @@ import ClientStore from '../stores/ClientStore'; export function login(username, password) { const browser = detect(); const name = (browser && browser.name + ' ' + browser.version) || 'unknown browser'; - axios.request(config.get('url') + 'client', { + axios.create().request(config.get('url') + 'client', { method: 'POST', data: {name: name}, auth: {username: username, password: password}, }).then(function(resp) { + snack(`A client named '${name}' was created for your session.`); setAuthorizationToken(resp.data.token); GlobalAction.initialLoad(); }).catch(() => { + snack('Login failed'); dispatcher.dispatch({type: 'LOGIN_FAILED'}); }); } @@ -48,7 +51,7 @@ export function fetchCurrentUser() { * @param {string} pass */ export function changeCurrentUser(pass) { - axios.post(config.get('url') + 'current/user/password', {pass}); + axios.post(config.get('url') + 'current/user/password', {pass}).then(() => snack('Password changed')); } /** Fetches all users. */ @@ -63,9 +66,7 @@ export function fetchUsers() { * @param {int} id the user id */ export function deleteUser(id) { - axios.delete(config.get('url') + 'user/' + id).then(function() { - fetchUsers(); - }); + axios.delete(config.get('url') + 'user/' + id).then(fetchUsers).then(() => snack('User deleted')); } /** @@ -75,9 +76,7 @@ export function deleteUser(id) { * @param {bool} admin if true, the user is an administrator */ export function createUser(name, pass, admin) { - axios.post(config.get('url') + 'user', {name, pass, admin}).then(function() { - fetchUsers(); - }); + axios.post(config.get('url') + 'user', {name, pass, admin}).then(fetchUsers).then(() => snack('User created')); } /** @@ -91,5 +90,6 @@ export function updateUser(id, name, pass, admin) { axios.post(config.get('url') + 'user/' + id, {name, pass, admin}).then(function() { fetchUsers(); fetchCurrentUser(); // just in case update current user + snack('User updated'); }); } diff --git a/ui/src/actions/defaultAxios.js b/ui/src/actions/defaultAxios.js index c755c12..132e819 100644 --- a/ui/src/actions/defaultAxios.js +++ b/ui/src/actions/defaultAxios.js @@ -1,6 +1,7 @@ import axios from 'axios'; import dispatcher from '../stores/dispatcher'; import * as GlobalAction from './GlobalAction'; +import {snack} from './GlobalAction'; let currentToken = null; const tokenKey = 'gotify-login-key'; @@ -20,8 +21,14 @@ export function setAuthorizationToken(token) { } } -axios.interceptors.response.use(null, (error) => { +axios.interceptors.response.use(undefined, (error) => { + if (!error.response) { + snack('Gotify server is not reachable, try refreshing the page.'); + return Promise.reject(error); + } + if (error.response.status === 401) { + snack('Authentication failed'); setAuthorizationToken(null); dispatcher.dispatch({type: 'REMOVE_CURRENT_USER'}); }