bugfix (UI): If an operation failed, the UI were giving the impression

to do something - #33
This commit is contained in:
Mickael KERJEAN
2018-04-12 23:45:12 +10:00
parent 13a6fb0004
commit 5a913d44d1
4 changed files with 117 additions and 81 deletions

View File

@ -98,19 +98,22 @@ function handle_error_response(xhr, err){
return message;
})(xhr.responseText);
if(xhr.status === 500){
err({message: message || "Oups something went wrong with our servers"})
if(navigator.onLine === false){
err({message: 'Connection Lost', code: "NO_INTERNET"});
}else if(xhr.status === 500){
err({message: message || "Oups something went wrong with our servers", code: "INTERNAL_SERVER_ERROR"});
}else if(xhr.status === 401){
if(location.pathname !== '/login'){ location.pathname = "/login"; }
err({message: message || "Authentication error"});
err({message: message || "Authentication error", code: "Unauthorized"});
}else if(xhr.status === 403){
err({message: message || "You can\'t do that"});
err({message: message || "You can\'t do that", code: "Forbidden"});
}else if(xhr.status === 413){
err({message: message || "Payload too large"});
}else if(navigator.onLine === false){
err({status: xhr.status, code: "CONNECTION_LOST", message: 'Connection Lost'});
err({message: message || "Payload too large", code: "PAYLOAD_TOO_LARGE"});
}else if(xhr.status === 502){
err({message: message || "The destination is acting weird", code: "BAD_GATEWAY"});
}else if(xhr.status === 409){
err({message: message || "Oups you just ran into a conflict", code: "CONFLICT"});
}else{
err({status: xhr.status, message: xhr.responseText || 'Oups something went wrong'});
err({message: message || 'Oups something went wrong'});
}
}

View File

@ -46,8 +46,7 @@ class FileSystem{
return cache.get(cache.FILE_PATH, path, false).then((_files) => {
if(_files && _files.results){
let _files_virtual_to_keep = _files.results.filter((file) => {
return file.icon === 'loading' &&
(new Date()).getTime() - file._timestamp < 1000*60*60;
return file.icon === 'loading';
});
// update file results
for(let i=0; i<_files_virtual_to_keep.length; i++){
@ -95,6 +94,10 @@ class FileSystem{
}else{
return this._replace(path, 'error');
}
})
.catch((err) => {
this._replace(path, 'error');
return Promise.reject(err);
});
}
@ -135,7 +138,11 @@ class FileSystem{
return this._replace(path, 'loading')
.then(() => cache.put(cache.FILE_CONTENT, path, file))
.then(() => http_post(url, formData, 'multipart'))
.then((res)=> res.status === 'ok'? this._replace(path) : this._replace(path, 'error'));
.then((res)=> res.status === 'ok'? this._replace(path) : this._replace(path, 'error'))
.catch((err) => {
this._replace(path, 'error');
return Promise.reject(err);
});
}
mkdir(path){
@ -143,7 +150,11 @@ class FileSystem{
return this._add(path, 'loading')
.then(() => this._add(path, 'loading'))
.then(() => http_get(url))
.then((res) => res.status === 'ok'? this._replace(path) : this._replace(path, 'error'));
.then((res) => res.status === 'ok'? this._replace(path) : this._replace(path, 'error'))
.catch((err) => {
this._replace(path, 'error');
return Promise.reject(err);
});
}
touch(path, file){
@ -159,7 +170,11 @@ class FileSystem{
return http_get(url);
}
})
.then((res) => res.status === 'ok'? this._replace(path) : this._replace(path, 'error'));
.then((res) => res.status === 'ok'? this._replace(path) : this._replace(path, 'error'))
.catch((err) => {
this._replace(path, 'error');
return Promise.reject(err);
});
}
mv(from, to){
@ -168,18 +183,23 @@ class FileSystem{
return ui_before_request(from, to)
.then(() => this._ls_from_cache(dirname(from)))
.then(() => this._ls_from_cache(dirname(to)))
.then(() => http_get(url)
.then((res) => {
if(res.status === 'ok'){
return ui_when_success.call(this, from, to)
.then(() => this._ls_from_cache(dirname(from)))
.then(() => this._ls_from_cache(dirname(to)));
}else{
return ui_when_fail.call(this, from, to)
.then(() => this._ls_from_cache(dirname(from)))
.then(() => this._ls_from_cache(dirname(to)));
}
}));
.then(() => http_get(url).then((res) => {
if(res.status === 'ok'){
return ui_when_success.call(this, from, to)
.then(() => this._ls_from_cache(dirname(from)))
.then(() => this._ls_from_cache(dirname(to)));
}else{
return ui_when_fail.call(this, from, to)
.then(() => this._ls_from_cache(dirname(from)))
.then(() => this._ls_from_cache(dirname(to)));
}
}))
.catch((err) => {
ui_when_fail.call(this, from, to)
.then(() => this._ls_from_cache(dirname(from)))
.then(() => this._ls_from_cache(dirname(to)));
return Promise.reject(err);
});
function ui_before_request(from, to){
return update_from()
@ -201,7 +221,6 @@ class FileSystem{
if(file.name === basename(from)){
file.name = basename(to);
file.icon = 'loading';
file._timestamp = (new Date()).getTime();
_file = file;
}
return file;
@ -232,7 +251,10 @@ class FileSystem{
.then((res_from) => {
if(!res_from || !res_from.results) return Promise.reject();
res_from.results = res_from.results.map((file) => {
if(file.name === basename(from)){
if(
(dirname(from) === dirname(to) && file.name === basename(to)) ||
(dirname(from) !== dirname(to) && file.name === basename(from))
){
file.icon = 'error';
}
return file;
@ -339,11 +361,9 @@ class FileSystem{
if(file.name === basename(path)){
if(!icon){
delete file.icon;
delete file._timestamp;
}
if(icon){
file.icon = icon;
file._timestamp = (new Date()).getTime();
}
}
return file;
@ -360,8 +380,7 @@ class FileSystem{
if(!res) return Promise.resolve();
let file = {
name: basename(path),
type: /\/$/.test(path) ? 'directory' : 'file',
_timestamp: (new Date()).getTime()
type: /\/$/.test(path) ? 'directory' : 'file'
};
if(icon) file.icon = icon;
res.results.push(file);

View File

@ -18,16 +18,12 @@ app.use(function(req, res, next){
// list files
app.get('/ls', function(req, res){
let path = pathBuilder(req);
const path = pathBuilder(req);
if(path){
Files
.ls(path, req.cookies.auth)
.then(function(results){
res.send({status: 'ok', results: results});
})
.catch(function(err){
res.send({status: 'error', message: err.message || 'cannot fetch files', trace: err});
});
.then(function(results){ res.send({status: 'ok', results: results}); })
.catch(function(err){ errorHandler(res, err, 'cannot fetch files'); });
}else{
res.send({status: 'error', message: 'unknown path'});
}
@ -35,7 +31,7 @@ app.get('/ls', function(req, res){
// get a file content
app.get('/cat', function(req, res){
let path = pathBuilder(req);
const path = pathBuilder(req);
res.clearCookie("download");
if(path){
Files.cat(path, req.cookies.auth, res)
@ -43,9 +39,7 @@ app.get('/cat', function(req, res){
res.set('Content-Type', mime.getMimeType(path));
stream.pipe(res);
})
.catch(function(err){
res.send({status: 'error', message: err.message || 'couldn\t read the file', trace: err});
});
.catch(function(err){ errorHandler(res, err, 'couldn\'t read the file'); });
}else{
res.send({status: 'error', message: 'unknown path'});
}
@ -54,22 +48,20 @@ app.get('/cat', function(req, res){
// create/update a file
// https://github.com/pillarjs/multiparty
app.post('/cat', function(req, res){
var form = new multiparty.Form(),
path = pathBuilder(req);
const form = new multiparty.Form(),
path = pathBuilder(req);
if(path){
form.on('part', function(part) {
part.on('error', function(err){
res.send({status: 'error', message: 'internal error'});
errorHandler(res, {code: "INTERNAL_ERROR", message: "internal error"}, 'internal error');
});
Files.write(path, part, req.cookies.auth)
.then(function(result){
res.send({status: 'ok'});
})
.catch(function(err){
res.send({status: 'error', message: err.message || 'couldn\'t write the file', code: err.code});
});
.catch(function(err){ errorHandler(res, err, 'couldn\'t write the file'); });
});
form.parse(req);
}else{
@ -79,19 +71,17 @@ app.post('/cat', function(req, res){
// rename a file/directory
app.get('/mv', function(req, res){
let from = decodeURIComponent(req.query.from),
to = decodeURIComponent(req.query.to);
req.query.path = req.query.from;
const from = pathBuilder(req);
req.query.path = req.query.to;
const to = pathBuilder(req)
if(from === to){
res.send({status: 'ok'});
}else if(from && to){
Files.mv(from, to, req.cookies.auth)
.then((message) => {
res.send({status: 'ok'});
})
.catch((err) => {
res.send({status: 'error', message: err.message || 'couldn\'t rename your file', trace: err});
});
.then(function(message){ res.send({status: 'ok'}); })
.catch(function(err){ errorHandler(res, err, 'couldn\'t rename your file'); });
}else{
res.send({status: 'error', message: 'unknown path'});
}
@ -99,15 +89,11 @@ app.get('/mv', function(req, res){
// delete a file/directory
app.get('/rm', function(req, res){
let path = pathBuilder(req);
const path = pathBuilder(req);
if(path){
Files.rm(path, req.cookies.auth)
.then((message) => {
res.send({status: 'ok'});
})
.catch((err) => {
res.send({status: 'error', message: err.message || 'couldn\'t delete your file', trace: err});
});
.then(function(message){ res.send({status: 'ok'}); })
.catch(function(err){ errorHandler(res, err, 'couldn\'t delete your file'); });
}else{
res.send({status: 'error', message: 'unknown path'});
}
@ -115,30 +101,22 @@ app.get('/rm', function(req, res){
// create a directory
app.get('/mkdir', function(req, res){
let path = pathBuilder(req);
const path = pathBuilder(req);
if(path){
Files.mkdir(path, req.cookies.auth)
.then((message) => {
res.send({status: 'ok'});
})
.catch((err) => {
res.send({status: 'error', message: err.message || 'couldn\'t create a directory', trace: err});
});
.then(function(message){ res.send({status: 'ok'}); })
.catch(function(err){ errorHandler(res, err, 'couldn\'t create the directory'); });
}else{
res.send({status: 'error', message: 'unknown path'});
}
});
app.get('/touch', function(req, res){
let path = pathBuilder(req);
const path = pathBuilder(req);
if(path){
Files.touch(path, req.cookies.auth)
.then((message) => {
res.send({status: 'ok'});
})
.catch((err) => {
res.send({status: 'error', message: err.message || 'couldn\'t create a file', trace: err});
});
.then(function(message){ res.send({status: 'ok'}); })
.catch(function(err){ errorHandler(res, err, 'couldn\'t create the file'); });
}else{
res.send({status: 'error', message: 'unknown path'});
}
@ -150,3 +128,39 @@ module.exports = app;
function pathBuilder(req){
return path.join(req.cookies.auth.payload.path || '', decodeURIComponent(req.query.path) || '');
}
function errorHandler(res, err, defaultMessage){
const code = {
"INTERNAL_ERROR": {message: "Oops, it seems we had a problem", status: 500},
"ECONNREFUSED": {message: "Oops, the service you are connected on is not available", status: 502}
};
const status = function(_code, _status){
if(code[_code]){
return code[_code]['status'];
}
_status = parseInt(_status);
if(_status >= 400 && _status < 600){
return _status;
}
return 404;
}(err.code || err.errno, err.status);
if(code[err.code || err.errno]){
res.status(status).send({
status: 'error',
message: code[err.code]['message']
});
}else if(err.message){
res.status(status).send({
status: 'error',
message: err.message || 'cannot fetch files',
trace: err
});
}else{
res.status(status).send({
status: 'error',
message: defaultMessage,
trace: err
});
}
}

View File

@ -7,7 +7,7 @@ var backend = {
s3: require('./backend/s3'),
git: require('./backend/git')
};
exports.cat = function(path, params, res){
try{
if(backend[params.type] && typeof backend[params.type].cat === 'function'){
@ -22,7 +22,7 @@ exports.cat = function(path, params, res){
exports.write = function(path, content, params){
try{
if(backend[params.type] && typeof backend[params.type].write === 'function'){
if(backend[params.type] && typeof backend[params.type].write === 'function'){
return backend[params.type].write(path, content, params.payload);
}else{
return error('not implemented');
@ -46,7 +46,7 @@ exports.ls = function(path, params){
exports.mv = function(from, to, params){
try{
if(backend[params.type] && typeof backend[params.type].mv === 'function'){
if(backend[params.type] && typeof backend[params.type].mv === 'function'){
return backend[params.type].mv(from, to, params.payload);
}else{
return error('not implemented');