Error messages and global messaging service (fixes #2949, fixes #1774)

This commit is contained in:
FinnStutzenstein 2017-02-24 15:15:18 +01:00
parent 96cbf17e72
commit 9c89f4d59c
16 changed files with 359 additions and 298 deletions

View File

@ -96,9 +96,10 @@ angular.module('OpenSlidesApp.agenda.site', [
'osTableFilter',
'AgendaCsvExport',
'PdfCreate',
'ErrorMessage',
function($scope, $filter, $http, $state, DS, operator, ngDialog, Agenda, TopicForm,
AgendaTree, Projector, ProjectionDefault, AgendaContentProvider, PdfMakeDocumentProvider,
gettextCatalog, gettext, osTableFilter, AgendaCsvExport, PdfCreate) {
gettextCatalog, gettext, osTableFilter, AgendaCsvExport, PdfCreate, ErrorMessage) {
// Bind agenda tree to the scope
$scope.$watch(function () {
return Agenda.lastModified();
@ -232,15 +233,11 @@ angular.module('OpenSlidesApp.agenda.site', [
// save changed item
$scope.save = function (item) {
Agenda.save(item).then(
function(success) {
function (success) {
$scope.alert.show = false;
},
function(error){
var message = '';
for (var e in error.data) {
message += e + ': ' + error.data[e] + ' ';
}
$scope.alert = { type: 'danger', msg: message, show: true };
function (error) {
$scope.alert = ErrorMessage.forAlert(error);
});
};
// delete related item
@ -393,7 +390,8 @@ angular.module('OpenSlidesApp.agenda.site', [
'itemId',
'Projector',
'ProjectionDefault',
function ($scope, $filter, Agenda, itemId, Projector, ProjectionDefault) {
'ErrorMessage',
function ($scope, $filter, Agenda, itemId, Projector, ProjectionDefault, ErrorMessage) {
$scope.alert = {};
$scope.$watch(function () {
@ -447,16 +445,16 @@ angular.module('OpenSlidesApp.agenda.site', [
// add user to list of speakers
$scope.addSpeaker = function (userId) {
$http.post('/rest/agenda/item/' + $scope.item.id + '/manage_speaker/', {'user': userId})
.success(function (data){
$http.post('/rest/agenda/item/' + $scope.item.id + '/manage_speaker/', {'user': userId}).then(
function (success) {
$scope.alert.show = false;
$scope.speakers = $scope.item.speakers;
$scope.speakerSelectBox = {};
})
.error(function (data){
$scope.alert = {type: 'danger', msg: data.detail, show: true};
}, function (error) {
$scope.alert = ErrorMessage.forAlert(error);
$scope.speakerSelectBox = {};
});
}
);
};
// delete speaker(!) from list of speakers
@ -466,11 +464,10 @@ angular.module('OpenSlidesApp.agenda.site', [
{headers: {'Content-Type': 'application/json'},
data: JSON.stringify({speaker: speakerId})}
)
.success(function(data){
.then(function (success) {
$scope.speakers = $scope.item.speakers;
})
.error(function(data){
$scope.alert = { type: 'danger', msg: data.detail, show: true };
}, function (error) {
$scope.alert = ErrorMessage.forAlert(error);
});
$scope.speakers = $scope.item.speakers;
};
@ -486,11 +483,10 @@ angular.module('OpenSlidesApp.agenda.site', [
{headers: {'Content-Type': 'application/json'},
data: JSON.stringify({speaker: speakersOnList})}
)
.success(function(data){
.then(function (success) {
$scope.speakers = $scope.item.speakers;
})
.error(function(data){
$scope.alert = { type: 'danger', msg: data.detail, show: true };
}, function (error) {
$scope.alert = ErrorMessage.forAlert(error);
});
$scope.speakers = $scope.item.speakers;
};
@ -529,11 +525,10 @@ angular.module('OpenSlidesApp.agenda.site', [
// begin speech of selected/next speaker
$scope.beginSpeech = function (speakerId) {
$http.put('/rest/agenda/item/' + $scope.item.id + '/speak/', {'speaker': speakerId})
.success(function(data){
.then(function (success) {
$scope.alert.show = false;
})
.error(function(data){
$scope.alert = { type: 'danger', msg: data.detail, show: true };
}, function (error) {
$scope.alert = ErrorMessage.forAlert(error);
});
};
@ -542,10 +537,12 @@ angular.module('OpenSlidesApp.agenda.site', [
$http.delete(
'/rest/agenda/item/' + $scope.item.id + '/speak/',
{headers: {'Content-Type': 'application/json'}, data: {}}
)
.error(function(data){
$scope.alert = { type: 'danger', msg: data.detail, show: true };
});
).then(
function (success) {},
function (error) {
$scope.alert = ErrorMessage.forAlert(error);
}
);
};
// gets speech duration of selected speaker in seconds
$scope.getDuration = function (speaker) {
@ -576,7 +573,8 @@ angular.module('OpenSlidesApp.agenda.site', [
'$http',
'Agenda',
'AgendaTree',
function($scope, $http, Agenda, AgendaTree) {
'ErrorMessage',
function($scope, $http, Agenda, AgendaTree, ErrorMessage) {
// Bind agenda tree to the scope
$scope.$watch(function () {
return Agenda.lastModified();
@ -600,7 +598,7 @@ angular.module('OpenSlidesApp.agenda.site', [
).then(
function(success) {},
function(error){
$scope.alert = {type: 'danger', msg: error.data.detail, show: true};
$scope.alert = ErrorMessage.forAlert(error);
}
);
}

View File

@ -422,9 +422,11 @@ angular.module('OpenSlidesApp.assignments.site', [
'gettextCatalog',
'PdfCreate',
'AssignmentPhases',
'ErrorMessage',
function($scope, $http, $filter, filterFilter, gettext, ngDialog, AssignmentForm, operator, Assignment,
User, assignmentId, Projector, ProjectionDefault, AssignmentContentProvider, BallotContentProvider,
PdfMakeDocumentProvider, PdfMakeBallotPaperProvider, gettextCatalog, PdfCreate, AssignmentPhases) {
PdfMakeDocumentProvider, PdfMakeBallotPaperProvider, gettextCatalog, PdfCreate, AssignmentPhases,
ErrorMessage) {
var assignment = Assignment.get(assignmentId);
User.bindAll({}, $scope, 'users');
Assignment.loadRelations(assignment, 'agenda_item');
@ -455,12 +457,11 @@ angular.module('OpenSlidesApp.assignments.site', [
// add (nominate) candidate
$scope.addCandidate = function (userId) {
$http.post('/rest/assignments/assignment/' + assignment.id + '/candidature_other/', {'user': userId})
.success(function(data){
.then(function (success){
$scope.alert.show = false;
$scope.candidateSelectBox = {};
})
.error(function(data){
$scope.alert = { type: 'danger', msg: data.detail, show: true };
}, function (error){
$scope.alert = ErrorMessage.forAlert(error);
$scope.candidateSelectBox = {};
});
};
@ -469,29 +470,31 @@ angular.module('OpenSlidesApp.assignments.site', [
$http.delete('/rest/assignments/assignment/' + assignment.id + '/candidature_other/',
{headers: {'Content-Type': 'application/json'},
data: JSON.stringify({user: userId})})
.error(function(data){
$scope.alert = { type: 'danger', msg: data.detail, show: true };
});
.then(function (success) {},
function (error) {
$scope.alert = ErrorMessage.forAlert(error);
}
);
};
// add me (nominate self as candidate)
$scope.addMe = function () {
$http.post('/rest/assignments/assignment/' + assignment.id + '/candidature_self/', {})
.success(function(data){
$http.post('/rest/assignments/assignment/' + assignment.id + '/candidature_self/', {}).then(
function (success) {
$scope.alert.show = false;
})
.error(function(data){
$scope.alert = { type: 'danger', msg: data.detail, show: true };
});
}, function (error) {
$scope.alert = ErrorMessage.forAlert(error);
}
);
};
// remove me (withdraw own candidature)
$scope.removeMe = function () {
$http.delete('/rest/assignments/assignment/' + assignment.id + '/candidature_self/')
.success(function(data){
$http.delete('/rest/assignments/assignment/' + assignment.id + '/candidature_self/').then(
function (success) {
$scope.alert.show = false;
})
.error(function(data){
$scope.alert = { type: 'danger', msg: data.detail, show: true };
});
}, function (error) {
$scope.alert = ErrorMessage.forAlert(error);
}
);
};
// check if current user is already a candidate (elected==false)
$scope.isCandidate = function () {
@ -525,15 +528,14 @@ angular.module('OpenSlidesApp.assignments.site', [
// create new ballot
$scope.createBallot = function () {
$scope.activeTab = 0;
$http.post('/rest/assignments/assignment/' + assignment.id + '/create_poll/')
.success(function(data){
$http.post('/rest/assignments/assignment/' + assignment.id + '/create_poll/').then(
function (success) {
$scope.alert.show = false;
if (assignment.phase === 0) {
$scope.updatePhase(1);
}
})
.error(function(data){
$scope.alert = { type: 'danger', msg: data.detail, show: true };
}, function (error) {
$scope.alert = ErrorMessage.forAlert(error);
});
};
// delete ballot
@ -560,15 +562,10 @@ angular.module('OpenSlidesApp.assignments.site', [
assignment_id: assignment.id,
published: !poll.published,
})
.then(function(success) {
.then(function (success) {
$scope.alert.show = false;
})
.catch(function(error) {
var message = '';
for (var e in error.data) {
message += e + ': ' + error.data[e] + ' ';
}
$scope.alert = { type: 'danger', msg: message, show: true };
}, function (error) {
$scope.alert = ErrorMessage.forAlert(error);
});
};
@ -637,7 +634,8 @@ angular.module('OpenSlidesApp.assignments.site', [
'AssignmentForm',
'Agenda',
'AgendaUpdate',
function($scope, $state, Assignment, AssignmentForm, Agenda, AgendaUpdate) {
'ErrorMessage',
function($scope, $state, Assignment, AssignmentForm, Agenda, AgendaUpdate, ErrorMessage) {
$scope.model = {};
// set default value for open posts form field
$scope.model.open_posts = 1;
@ -646,7 +644,7 @@ angular.module('OpenSlidesApp.assignments.site', [
// save assignment
$scope.save = function(assignment, gotoDetailView) {
Assignment.create(assignment).then(
function(success) {
function (success) {
// type: Value 1 means a non hidden agenda item, value 2 means a hidden agenda item,
// see openslides.agenda.models.Item.ITEM_TYPE.
var changes = [{key: 'type', value: (assignment.showAsAgendaItem ? 1 : 2)},
@ -656,6 +654,9 @@ angular.module('OpenSlidesApp.assignments.site', [
$state.go('assignments.assignment.detail', {id: success.id});
}
$scope.closeThisDialog();
},
function (error) {
$scope.alert = ErrorMessage.forAlert(error);
}
);
};
@ -670,7 +671,8 @@ angular.module('OpenSlidesApp.assignments.site', [
'Agenda',
'AgendaUpdate',
'assignmentId',
function($scope, $state, Assignment, AssignmentForm, Agenda, AgendaUpdate, assignmentId) {
'ErrorMessage',
function($scope, $state, Assignment, AssignmentForm, Agenda, AgendaUpdate, assignmentId, ErrorMessage) {
var assignment = Assignment.get(assignmentId);
$scope.alert = {};
// set initial values for form model by create deep copy of assignment object
@ -707,11 +709,7 @@ angular.module('OpenSlidesApp.assignments.site', [
// save error: revert all changes by restore
// (refresh) original assignment object from server
Assignment.refresh(assignment);
var message = '';
for (var e in error.data) {
message += e + ': ' + error.data[e] + ' ';
}
$scope.alert = {type: 'danger', msg: message, show: true};
$scope.alert = ErrorMessage.forAlert(error);
}
);
};
@ -725,7 +723,8 @@ angular.module('OpenSlidesApp.assignments.site', [
'AssignmentPoll',
'assignmentpollId',
'ballot',
function($scope, $filter, gettextCatalog, AssignmentPoll, assignmentpollId, ballot) {
'ErrorMessage',
function($scope, $filter, gettextCatalog, AssignmentPoll, assignmentpollId, ballot, ErrorMessage) {
// set initial values for form model by create deep copy of assignmentpoll object
// so detail view is not updated while editing poll
var assignmentpoll = angular.copy(AssignmentPoll.get(assignmentpollId));
@ -879,13 +878,8 @@ angular.module('OpenSlidesApp.assignments.site', [
.then(function(success) {
$scope.alert.show = false;
$scope.closeThisDialog();
})
.catch(function(error) {
var message = '';
for (var e in error.data) {
message += e + ': ' + error.data[e] + ' ';
}
$scope.alert = { type: 'danger', msg: message, show: true };
}, function (error) {
$scope.alert = ErrorMessage.forAlert(error);
});
};
}

View File

@ -1156,42 +1156,46 @@ img {
font-size: 90%;
}
/** Pdf creation status bar **/
#pdf-status {
/** Messaging status bar **/
#messaging {
position: fixed;
bottom: 0;
width: 100%;
z-index: 100;
z-index: 100000;
}
#pdf-status-container {
#messaging-container {
margin: 0 auto 0 auto;
padding: 0px 20px;
max-width: 1400px;
}
#pdf-status-container > div {
#messaging-container > div {
margin-bottom: 10px;
padding: 10px 20px;
border-radius: 6px;
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
}
#pdf-status .generating {
#messaging .info {
color: #222;
background-color: #bed4de;
border-color: #46b8da;
}
#pdf-status .error {
#messaging .error {
color: #a94442;
background-color: #f2dede;
border-color: #ebccd1;
}
#pdf-status .finished {
#messaging .success {
color: #3c763d;
background-color: #dff0d8;
border-color: #d6e9c6;
}
#messaging .warning {
color: #8a6d3b;
background-color: #fcf8e3;
border-color: #faebcc;
}
/** General helper classes **/
.disabled {
color: #555;
cursor: not-allowed !important;

View File

@ -47,7 +47,8 @@ angular.module('OpenSlidesApp.core', [
'REALM',
'ProjectorID',
'$q',
function (DS, REALM, ProjectorID, $q) {
'ErrorMessage',
function (DS, REALM, ProjectorID, $q, ErrorMessage) {
var socket = null;
var recInterval = null;
@ -82,11 +83,12 @@ angular.module('OpenSlidesApp.core', [
Autoupdate.newConnect = function () {
socket = new WebSocket(websocketProtocol + '//' + location.host + websocketPath);
clearInterval(recInterval);
socket.onclose = function () {
socket.onclose = function (event) {
socket = null;
recInterval = setInterval(function () {
Autoupdate.newConnect();
}, 1000);
ErrorMessage.setConnectionError();
};
socket.onmessage = function (event) {
_.forEach(Autoupdate.messageReceivers, function (receiver) {
@ -96,6 +98,7 @@ angular.module('OpenSlidesApp.core', [
if (Autoupdate.firstMessageDeferred.promise.$$state.status === 0) {
Autoupdate.firstMessageDeferred.resolve();
}
ErrorMessage.clearConnectionError();
};
};
return Autoupdate;
@ -460,6 +463,108 @@ angular.module('OpenSlidesApp.core', [
}
])
.factory('ErrorMessage', [
'$timeout',
'gettextCatalog',
'Messaging',
function ($timeout, gettextCatalog, Messaging) {
return {
forAlert: function (error) {
var message = gettextCatalog.getString('Error') + ': ';
if (!error.data) {
message += gettextCatalog.getString("The server didn't respond.");
} else if (error.data.detail) {
message += error.data.detail;
} else {
for (var e in error.data) {
message += e + ': ' + error.data[e] + ' ';
}
}
return { type: 'danger', msg: message, show: true };
},
setConnectionError: function () {
$timeout(function () {
Messaging.createOrEditMessage(
'connectionLostMessage',
gettextCatalog.getString('Connection lost. You are not connected to the server anymore.'),
'error',
{noClose: true});
}, 1);
},
clearConnectionError: function () {
$timeout(function () {
Messaging.deleteMessage('connectionLostMessage');
}, 1);
},
};
}
])
/* Messaging factory. The text is html-binded into the document, so you can
* provide also html markup for the messages. There are 4 types: 'info',
* 'success', 'warning', 'error'. The timeout is for autodeleting the message.
* Args that could be provided:
* - timeout: Milliseconds until autoclose the message
* - noClose: Whether to show the close button*/
.factory('Messaging', [
'$timeout',
function($timeout) {
var callbackList = [],
messages = {},
idCounter = 0;
var onChange = function () {
_.forEach(callbackList, function (callback) {
callback();
});
};
return {
addMessage: function (text, type, args) {
var id = idCounter++;
return this.createOrEditMessage(id, text, type, args);
},
createOrEditMessage: function (id, text, type, args) {
if (!args) {
args = {};
}
if (messages[id] && messages[id].timeout) {
$timeout.cancel(messages[id].timeout);
}
messages[id] = {
text: text,
type: type,
id: id,
args: args,
};
if (typeof args.timeout === 'number' && args.timeout > 0) {
var self = this;
messages[id].timeout = $timeout(function () {
self.deleteMessage(id);
}, args.timeout);
}
onChange();
return id;
},
deleteMessage: function (id) {
delete messages[id];
onChange();
},
getMessages: function () {
return messages;
},
registerMessageChangeCallback: function (fn) {
if (typeof fn === 'function') {
callbackList.push(fn);
} else {
throw 'fn has to be a function';
}
},
};
}
])
.factory('Tag', [
'DS',
function(DS) {

View File

@ -784,8 +784,9 @@ angular.module('OpenSlidesApp.core.pdf', [])
.factory('PdfCreate', [
'$timeout',
'FileSaver',
function ($timeout, FileSaver) {
var stateChangeCallbacks = [];
'Messaging',
function ($timeout, FileSaver, Messaging) {
var filenameMessageMap = {};
var b64toBlob = function(b64Data) {
var byteCharacters = atob(b64Data);
var byteNumbers = new Array(byteCharacters.length);
@ -797,18 +798,36 @@ angular.module('OpenSlidesApp.core.pdf', [])
return blob;
};
var stateChange = function (state, filename, error) {
_.forEach(stateChangeCallbacks, function (cb) {
$timeout(function () {cb(state, filename, error);}, 1);
});
var text, timeout;
switch (state) {
case 'info':
text = '<i class="fa fa-spinner fa-pulse fa-lg spacer-right"></i>' +
'<translate>Generating PDF file ' + filename + ' ...</translate>';
break;
case 'success':
text = '<i class="fa fa-check fa-lg spacer-right"></i>' +
'<translate>PDF successfully generated.</translate>';
timeout = 3000;
break;
case 'error':
text = '<i class="fa fa-exclamation-triangle fa-lg spacer-right"></i>' +
'<translate>Error while generating PDF file</translate> ' + filename + ':' +
'<span ng-if="pdf.errorMessage"><code>{{ pdf.errorMessage | translate }}</code></span>' ;
break;
}
$timeout(function () {
filenameMessageMap[filename] = Messaging.createOrEditMessage(
filenameMessageMap[filename], text, state, {timeout: timeout});
}, 1);
};
return {
download: function (pdfDocument, filename) {
stateChange('generating', filename);
stateChange('info', filename);
var pdfWorker = new Worker('/static/js/workers/pdf-worker.js');
pdfWorker.addEventListener('message', function (event) {
var blob = b64toBlob(event.data);
stateChange('finished', filename);
stateChange('success', filename);
FileSaver.saveAs(blob, filename);
});
pdfWorker.addEventListener('error', function (event) {
@ -816,43 +835,6 @@ angular.module('OpenSlidesApp.core.pdf', [])
});
pdfWorker.postMessage(JSON.stringify(pdfDocument));
},
registerStateChangeCallback: function (cb) {
if (cb && typeof cb === 'function') {
stateChangeCallbacks.push(cb);
}
},
};
}
])
.directive('pdfGenerationStatus', [
'$timeout',
'PdfCreate',
function($timeout, PdfCreate) {
return {
restrict: 'E',
templateUrl: 'static/templates/pdf-status.html',
scope: {},
controller: function ($scope, $element, $attrs, $location) {
$scope.pdfs = {};
var createStateChange = function (state, filename, error) {
$scope.pdfs[filename] = {
state: state,
errorMessage: error
};
if (state === 'finished') {
$timeout(function () {
$scope.close(filename);
}, 3000);
}
};
PdfCreate.registerStateChangeCallback(createStateChange);
$scope.close = function (filename) {
delete $scope.pdfs[filename];
};
},
};
}
]);

View File

@ -806,6 +806,30 @@ angular.module('OpenSlidesApp.core.site', [
}
])
.directive('messaging', [
'$timeout',
'Messaging',
function ($timeout, Messaging) {
return {
restrict: 'E',
templateUrl: 'static/templates/messaging.html',
scope: {},
controller: function ($scope, $element, $attrs, $location) {
$scope.messages = {};
var update = function () {
$scope.messages = Messaging.getMessages();
};
Messaging.registerMessageChangeCallback(update);
$scope.close = function (id) {
Messaging.deleteMessage(id);
};
},
};
}
])
.controller('MainMenuCtrl', [
'$scope',
'mainMenu',
@ -893,9 +917,9 @@ angular.module('OpenSlidesApp.core.site', [
'$scope',
'$http',
function ($scope, $http) {
$http.get('/core/version/').success(function(data) {
$scope.core_version = data.openslides_version;
$scope.plugins = data.plugins;
$http.get('/core/version/').then(function (success) {
$scope.core_version = success.data.openslides_version;
$scope.plugins = success.data.plugins;
});
}
])
@ -1424,7 +1448,8 @@ angular.module('OpenSlidesApp.core.site', [
'ngDialog',
'TagForm',
'gettext',
function($scope, Tag, ngDialog, TagForm, gettext) {
'ErrorMessage',
function($scope, Tag, ngDialog, TagForm, gettext, ErrorMessage) {
Tag.bindAll({}, $scope, 'tags');
$scope.alert = {};
@ -1447,11 +1472,7 @@ angular.module('OpenSlidesApp.core.site', [
show: true,
};
}, function (error) {
var message = '';
for (var e in error.data) {
message += e + ': ' + error.data[e] + ' ';
}
$scope.alert = {type: 'danger', msg: message, show: true};
$scope.alert = ErrorMessage.forAlert(error);
}
);
};
@ -1465,7 +1486,8 @@ angular.module('OpenSlidesApp.core.site', [
'$scope',
'Tag',
'TagForm',
function($scope, Tag, TagForm) {
'ErrorMessage',
function($scope, Tag, TagForm, ErrorMessage) {
$scope.model = {};
$scope.alert = {};
$scope.formFields = TagForm.getFormFields();
@ -1475,11 +1497,7 @@ angular.module('OpenSlidesApp.core.site', [
$scope.closeThisDialog();
},
function (error) {
var message = '';
for (var e in error.data) {
message += e + ': ' + error.data[e] + ' ';
}
$scope.alert = {type: 'danger', msg: message, show: true};
$scope.alert = ErrorMessage.forAlert(error);
}
);
};
@ -1491,7 +1509,8 @@ angular.module('OpenSlidesApp.core.site', [
'Tag',
'tagId',
'TagForm',
function($scope, Tag, tagId, TagForm) {
'ErrorMessage',
function($scope, Tag, tagId, TagForm, ErrorMessage) {
$scope.model = angular.copy(Tag.get(tagId));
$scope.alert = {};
$scope.formFields = TagForm.getFormFields();
@ -1503,11 +1522,7 @@ angular.module('OpenSlidesApp.core.site', [
// save error: revert all changes by restore
// the original object
Tag.refresh(tag);
var message = '';
for (var e in error.data) {
message += e + ': ' + error.data[e] + ' ';
}
$scope.alert = {type: 'danger', msg: message, show: true};
$scope.alert = ErrorMessage.forAlert(error);
});
};
}
@ -1541,16 +1556,14 @@ angular.module('OpenSlidesApp.core.site', [
$http.post(
'/rest/core/chat-message/',
{message: $scope.newMessage}
)
.success(function () {
).then(function (success) {
$scope.newMessage = '';
angular.element('#messageSendButton').removeClass('disabled');
angular.element('#messageInput').removeAttr('disabled');
$timeout(function () {
angular.element('#messageInput').focus();
}, 0);
})
.error(function () {
}, function (error) {
angular.element('#messageSendButton').removeClass('disabled');
angular.element('#messageInput').removeAttr('disabled');
});

View File

@ -14,15 +14,15 @@ angular.module('OpenSlidesApp.core.start', [])
'mainMenu',
function($http, $rootScope, $state, autoupdate, operator, Group, mainMenu) {
$rootScope.openslidesBootstrapDone = false;
$http.get('/users/whoami/').success(function(data) {
$rootScope.guest_enabled = data.guest_enabled;
if (data.user_id === null && !data.guest_enabled) {
$http.get('/users/whoami/').then(function (success) {
$rootScope.guest_enabled = success.data.guest_enabled;
if (success.data.user_id === null && !success.data.guest_enabled) {
// Redirect to login dialog if user is not logged in.
$state.go('login', {guest_enabled: data.guest_enabled});
$state.go('login', {guest_enabled: success.data.guest_enabled});
} else {
autoupdate.newConnect();
autoupdate.firstMessageDeferred.promise.then(function () {
operator.setUser(data.user_id, data.user);
operator.setUser(success.data.user_id, success.data.user);
$rootScope.operator = operator;
mainMenu.updateMainMenu();
$rootScope.openslidesBootstrapDone = true;

View File

@ -218,7 +218,7 @@
</div><!--end content-container-->
</div><!--end content-->
<pdf-generation-status></pdf-generation-status>
<messaging></messaging>
</div><!--end wrapper-->

View File

@ -0,0 +1,10 @@
<div id="messaging">
<div id="messaging-container">
<div ng-repeat="(id, message) in messages" ng-class="message.type">
<span class="close fa fa-times fa-lg" ng-click="close(id)" ng-if="!message.args.noClose"></span>
<span ng-bind-html="message.text | trusted"></span>
</div>
</div>
</div>

View File

@ -9,7 +9,8 @@ angular.module('OpenSlidesApp.mediafiles.create', [
.controller('MediafileCreateCtrl', [
'$scope',
'MediafileForm',
function ($scope, MediafileForm) {
'ErrorMessage',
function ($scope, MediafileForm, ErrorMessage) {
$scope.model = {};
$scope.alert = {};
$scope.formFields = MediafileForm.getFormFields(true);
@ -23,11 +24,7 @@ angular.module('OpenSlidesApp.mediafiles.create', [
},
function (error) {
$scope.activeUpload = void 0;
var message = '';
for (var e in error.data) {
message += e + ': ' + error.data[e] + ' ';
}
$scope.alert = {type: 'danger', msg: message, show: true};
$scope.alert = ErrorMessage.forAlert(error);
},
function (progress) {
$scope.progress = parseInt(100.0 * progress.loaded / progress.total);

View File

@ -14,7 +14,8 @@ angular.module('OpenSlidesApp.mediafiles.update', [
'Mediafile',
'mediafileId',
'MediafileForm',
function ($scope, operator, User, Mediafile, mediafileId, MediafileForm) {
'ErrorMessage',
function ($scope, operator, User, Mediafile, mediafileId, MediafileForm, ErrorMessage) {
$scope.alert = {};
$scope.formFields = MediafileForm.getFormFields();
@ -40,11 +41,7 @@ angular.module('OpenSlidesApp.mediafiles.update', [
},
function (error) {
Mediafile.refresh(mediafile);
var message = '';
for (var e in error.data) {
message += e + ': ' + error.data[e] + ' ';
}
$scope.alert = {type: 'danger', msg: message, show: true};
$scope.alert = ErrorMessage.forAlert(error);
}
);
};

View File

@ -144,7 +144,8 @@ angular.module('OpenSlidesApp.motions.motionBlock', [])
'motionBlockId',
'Projector',
'ProjectionDefault',
function($scope, $http, ngDialog, Motion, MotionBlockForm, MotionBlock, motionBlockId, Projector, ProjectionDefault) {
'ErrorMessage',
function($scope, $http, ngDialog, Motion, MotionBlockForm, MotionBlock, motionBlockId, Projector, ProjectionDefault, ErrorMessage) {
MotionBlock.bindOne(motionBlockId, $scope, 'motionBlock');
Motion.bindAll({}, $scope, 'motions');
$scope.$watch(function () {
@ -159,12 +160,11 @@ angular.module('OpenSlidesApp.motions.motionBlock', [])
ngDialog.open(MotionBlockForm.getDialog(motionBlock));
};
$scope.followRecommendations = function () {
$http.post('/rest/motions/motion-block/' + motionBlockId + '/follow_recommendations/')
.success(function(data) {
$scope.alert = { type: 'success', msg: data.detail, show: true };
})
.error(function(data) {
$scope.alert = { type: 'danger', msg: data.detail, show: true };
$http.post('/rest/motions/motion-block/' + motionBlockId + '/follow_recommendations/').then(
function (success) {
$scope.alert = { type: 'success', msg: success.data.detail, show: true };
}, function (error) {
$scope.alert = ErrorMessage.forAlert(error);
});
};
$scope.delete = function (motion) {

View File

@ -30,8 +30,8 @@ angular.module('OpenSlidesApp.motions.motionservices', ['OpenSlidesApp.motions',
return element.getAttribute("src");
});
$http.post('/core/encode_media/', JSON.stringify(image_sources)).success(function(data) {
var converter = PdfMakeConverter.createInstance(data.images);
$http.post('/core/encode_media/', JSON.stringify(image_sources)).then(function (success) {
var converter = PdfMakeConverter.createInstance(sucess.data.images);
var motionContentProvider = MotionContentProvider.createInstance(converter, $scope.motion, $scope, User, $http);
var documentProvider = PdfMakeDocumentProvider.createInstance(motionContentProvider);
var identifier = $scope.motion.identifier ? '-' + $scope.motion.identifier : '';

View File

@ -912,8 +912,8 @@ angular.module('OpenSlidesApp.motions.site', [
});
//post-request to convert the images. Async.
$http.post('/core/encode_media/', JSON.stringify(image_sources)).success(function(data) {
var converter = PdfMakeConverter.createInstance(data.images);
$http.post('/core/encode_media/', JSON.stringify(image_sources)).then(function (success) {
var converter = PdfMakeConverter.createInstance(success.data.images);
var motionContentProviderArray = [];
//convert the filtered motions to motionContentProviders
@ -1313,7 +1313,8 @@ angular.module('OpenSlidesApp.motions.site', [
'MotionChangeRecommendation',
'ChangeRecommendationForm',
'change',
function ($scope, MotionChangeRecommendation, ChangeRecommendationForm, change) {
'ErrorMessage',
function ($scope, MotionChangeRecommendation, ChangeRecommendationForm, change, ErrorMessage) {
$scope.alert = {};
$scope.model = angular.copy(change);
@ -1330,11 +1331,7 @@ angular.module('OpenSlidesApp.motions.site', [
},
function (error) {
MotionChangeRecommendation.refresh(change);
var message = '';
for (var e in error.data) {
message += e + ': ' + error.data[e] + ' ';
}
$scope.alert = {type: 'danger', msg: message, show: true};
$scope.alert = ErrorMessage.forAlert(error);
}
);
};
@ -1397,8 +1394,9 @@ angular.module('OpenSlidesApp.motions.site', [
'Workflow',
'Agenda',
'AgendaUpdate',
'ErrorMessage',
function($scope, $state, gettext, gettextCatalog, operator, Motion, MotionForm,
Category, Config, Mediafile, Tag, User, Workflow, Agenda, AgendaUpdate) {
Category, Config, Mediafile, Tag, User, Workflow, Agenda, AgendaUpdate, ErrorMessage) {
Category.bindAll({}, $scope, 'categories');
Mediafile.bindAll({}, $scope, 'mediafiles');
Tag.bindAll({}, $scope, 'tags');
@ -1445,11 +1443,7 @@ angular.module('OpenSlidesApp.motions.site', [
$scope.closeThisDialog();
},
function (error) {
var message = '';
for (var e in error.data) {
message += e + ': ' + error.data[e] + ' ';
}
$scope.alert = {type: 'danger', msg: message, show: true};
$scope.alert = ErrorMessage.forAlert(error);
}
);
};
@ -1470,8 +1464,9 @@ angular.module('OpenSlidesApp.motions.site', [
'Agenda',
'AgendaUpdate',
'motionId',
'ErrorMessage',
function($scope, $state, Motion, Category, Config, Mediafile, MotionForm, Tag,
User, Workflow, Agenda, AgendaUpdate, motionId) {
User, Workflow, Agenda, AgendaUpdate, motionId, ErrorMessage) {
Category.bindAll({}, $scope, 'categories');
Mediafile.bindAll({}, $scope, 'mediafiles');
Tag.bindAll({}, $scope, 'tags');
@ -1547,11 +1542,7 @@ angular.module('OpenSlidesApp.motions.site', [
// save error: revert all changes by restore
// (refresh) original motion object from server
Motion.refresh(motion);
var message = '';
for (var e in error.data) {
message += e + ': ' + error.data[e] + ' ';
}
$scope.alert = {type: 'danger', msg: message, show: true};
$scope.alert = ErrorMessage.forAlert(error);
}
);
};
@ -1565,7 +1556,9 @@ angular.module('OpenSlidesApp.motions.site', [
'MotionPollForm',
'motionpollId',
'voteNumber',
function($scope, gettextCatalog, MotionPoll, MotionPollForm, motionpollId, voteNumber) {
'ErrorMessage',
function($scope, gettextCatalog, MotionPoll, MotionPollForm, motionpollId,
voteNumber, ErrorMessage) {
// set initial values for form model by create deep copy of motionpoll object
// so detail view is not updated while editing poll
var motionpoll = MotionPoll.get(motionpollId);
@ -1586,13 +1579,8 @@ angular.module('OpenSlidesApp.motions.site', [
.then(function(success) {
$scope.alert.show = false;
$scope.closeThisDialog();
})
.catch(function(error) {
var message = '';
for (var e in error.data) {
message += e + ': ' + error.data[e] + ' ';
}
$scope.alert = { type: 'danger', msg: message, show: true };
}, function(error) {
$scope.alert = ErrorMessage.forAlert(error);
});
};
}
@ -1865,7 +1853,8 @@ angular.module('OpenSlidesApp.motions.site', [
'$scope',
'Category',
'CategoryForm',
function($scope, Category, CategoryForm) {
'ErrorMessage',
function($scope, Category, CategoryForm, ErrorMessage) {
$scope.model = {};
$scope.alert = {};
$scope.formFields = CategoryForm.getFormFields();
@ -1875,11 +1864,7 @@ angular.module('OpenSlidesApp.motions.site', [
$scope.closeThisDialog();
},
function (error) {
var message = '';
for (var e in error.data) {
message += e + ': ' + error.data[e] + ' ';
}
$scope.alert = {type: 'danger', msg: message, show: true};
$scope.alert = ErrorMessage.forAlert(error);
}
);
};
@ -1891,7 +1876,8 @@ angular.module('OpenSlidesApp.motions.site', [
'Category',
'categoryId',
'CategoryForm',
function($scope, Category, categoryId, CategoryForm) {
'ErrorMessage',
function($scope, Category, categoryId, CategoryForm, ErrorMessage) {
$scope.alert = {};
$scope.model = angular.copy(Category.get(categoryId));
$scope.formFields = CategoryForm.getFormFields();
@ -1905,11 +1891,7 @@ angular.module('OpenSlidesApp.motions.site', [
// save error: revert all changes by restore
// (refresh) original category object from server
Category.refresh(category);
var message = '';
for (var e in error.data) {
message += e + ': ' + error.data[e] + ' ';
}
$scope.alert = {type: 'danger', msg: message, show: true};
$scope.alert = ErrorMessage.forAlert(error);
}
);
};
@ -1924,7 +1906,8 @@ angular.module('OpenSlidesApp.motions.site', [
'Category',
'categoryId',
'Motion',
function($scope, $stateParams, $http, MotionList, Category, categoryId, Motion) {
'ErrorMessage',
function($scope, $stateParams, $http, MotionList, Category, categoryId, Motion, ErrorMessage) {
Category.bindOne(categoryId, $scope, 'category');
Motion.bindAll({}, $scope, 'motions');
$scope.filter = { category_id: categoryId,
@ -1951,12 +1934,11 @@ angular.module('OpenSlidesApp.motions.site', [
// renumber them
$http.post('/rest/motions/category/' + $scope.category.id + '/numbering/',
{'motions': sorted_motions} )
.success(function(data) {
$scope.alert = { type: 'success', msg: data.detail, show: true };
})
.error(function(data) {
$scope.alert = { type: 'danger', msg: data.detail, show: true };
{'motions': sorted_motions} ).then(
function (success) {
$scope.alert = { type: 'success', msg: success.data.detail, show: true };
}, function (error) {
$scope.alert = ErrorMessage.forAlert(error);
});
};
}

View File

@ -178,7 +178,8 @@ angular.module('OpenSlidesApp.topics.site', ['OpenSlidesApp.topics', 'OpenSlides
'TopicForm',
'Agenda',
'AgendaUpdate',
function($scope, $state, Topic, TopicForm, Agenda, AgendaUpdate) {
'ErrorMessage',
function($scope, $state, Topic, TopicForm, Agenda, AgendaUpdate, ErrorMessage) {
$scope.topic = {};
$scope.model = {};
$scope.model.showAsAgendaItem = true;
@ -193,8 +194,11 @@ angular.module('OpenSlidesApp.topics.site', ['OpenSlidesApp.topics', 'OpenSlides
var changes = [{key: 'type', value: (topic.showAsAgendaItem ? 1 : 2)},
{key: 'parent_id', value: topic.agenda_parent_item_id}];
AgendaUpdate.saveChanges(success.agenda_item_id,changes);
});
$scope.closeThisDialog();
}, function (error) {
$scope.alert = ErrorMessage.forAlert(error);
}
);
};
}
])
@ -207,7 +211,8 @@ angular.module('OpenSlidesApp.topics.site', ['OpenSlidesApp.topics', 'OpenSlides
'Agenda',
'AgendaUpdate',
'topicId',
function($scope, $state, Topic, TopicForm, Agenda, AgendaUpdate, topicId) {
'ErrorMessage',
function($scope, $state, Topic, TopicForm, Agenda, AgendaUpdate, topicId, ErrorMessage) {
var topic = Topic.get(topicId);
$scope.alert = {};
// set initial values for form model by create deep copy of topic object
@ -237,11 +242,7 @@ angular.module('OpenSlidesApp.topics.site', ['OpenSlidesApp.topics', 'OpenSlides
// save error: revert all changes by restore
// (refresh) original topic object from server
Topic.refresh(topic);
var message = '';
for (var e in error.data) {
message += e + ': ' + error.data[e] + ' ';
}
$scope.alert = {type: 'danger', msg: message, show: true};
$scope.alert = ErrorMessage.forAlert(error);
}
);
};

View File

@ -603,11 +603,7 @@ angular.module('OpenSlidesApp.users.site', [
$scope.alert.show = false;
},
function(error){
var message = '';
for (var e in error.data) {
message += e + ': ' + error.data[e] + ' ';
}
$scope.alert = { type: 'danger', msg: message, show: true };
$scope.alert = ErrorMessage.forAlert(error);
});
};
// delete single user
@ -744,7 +740,8 @@ angular.module('OpenSlidesApp.users.site', [
'User',
'UserForm',
'Group',
function($scope, $state, User, UserForm, Group) {
'ErrorMessage',
function($scope, $state, User, UserForm, Group, ErrorMessage) {
Group.bindAll({where: {id: {'>': 2}}}, $scope, 'groups');
$scope.alert = {};
// get all form fields
@ -756,15 +753,11 @@ angular.module('OpenSlidesApp.users.site', [
user.groups_id = [];
}
User.create(user).then(
function(success) {
function (success) {
$scope.closeThisDialog();
},
function (error) {
var message = '';
for (var e in error.data) {
message += e + ': ' + error.data[e] + ' ';
}
$scope.alert = {type: 'danger', msg: message, show: true};
$scope.alert = ErrorMessage.forAlert(error);
}
);
};
@ -779,7 +772,8 @@ angular.module('OpenSlidesApp.users.site', [
'UserForm',
'Group',
'userId',
function($scope, $state, $http, User, UserForm, Group, userId) {
'ErrorMessage',
function($scope, $state, $http, User, UserForm, Group, userId, ErrorMessage) {
Group.bindAll({where: {id: {'>': 2}}}, $scope, 'groups');
$scope.alert = {};
// set initial values for form model by create deep copy of user object
@ -805,11 +799,7 @@ angular.module('OpenSlidesApp.users.site', [
// save error: revert all changes by restore
// (refresh) original user object from server
User.refresh(user);
var message = '';
for (var e in error.data) {
message += e + ': ' + error.data[e] + ' ';
}
$scope.alert = {type: 'danger', msg: message, show: true};
$scope.alert = ErrorMessage.forAlert(error);
}
);
};
@ -823,7 +813,8 @@ angular.module('OpenSlidesApp.users.site', [
'operator',
'UserProfileForm',
'gettext',
function($scope, Editor, User, operator, UserProfileForm, gettext) {
'ErrorMessage',
function($scope, Editor, User, operator, UserProfileForm, gettext, ErrorMessage) {
$scope.model = angular.copy(operator.user);
$scope.title = gettext('Edit profile');
$scope.formFields = UserProfileForm.getFormFields();
@ -837,11 +828,7 @@ angular.module('OpenSlidesApp.users.site', [
// save error: revert all changes by restore
// (refresh) original user object from server
User.refresh(user);
var message = '';
for (var e in error.data) {
message += e + ': ' + error.data[e] + ' ';
}
$scope.alert = {type: 'danger', msg: message, show: true};
$scope.alert = ErrorMessage.forAlert(error);
}
);
};
@ -856,7 +843,8 @@ angular.module('OpenSlidesApp.users.site', [
'userId',
'gettextCatalog',
'PasswordGenerator',
function($scope, $state, $http, User, userId, gettextCatalog, PasswordGenerator) {
'ErrorMessage',
function($scope, $state, $http, User, userId, gettextCatalog, PasswordGenerator, ErrorMessage) {
User.bindOne(userId, $scope, 'user');
$scope.alert = {};
$scope.generatePassword = function () {
@ -873,7 +861,7 @@ angular.module('OpenSlidesApp.users.site', [
$scope.new_password = '';
},
function (error) {
$scope.alert = {type: 'danger', msg: error.data.detail, show: true};
$scope.alert = ErrorMessage.forAlert(error);
}
);
}
@ -887,7 +875,8 @@ angular.module('OpenSlidesApp.users.site', [
'$http',
'gettext',
'UserPasswordForm',
function($scope, $state, $http, gettext, UserPasswordForm) {
'ErrorMessage',
function($scope, $state, $http, gettext, UserPasswordForm, ErrorMessage) {
$scope.title = 'Change password';
$scope.alert = {};
$scope.model = {};
@ -911,12 +900,7 @@ angular.module('OpenSlidesApp.users.site', [
function (error) {
// Error, e. g. wrong old password.
$scope.model = {};
var message = '';
for (var e in error.data) {
message += e + ': ' + error.data[e] + ' ';
}
$scope.alert = {type: 'danger', msg: message, show: true};
$scope.alert = ErrorMessage.forAlert(error);
}
);
}
@ -1362,7 +1346,8 @@ angular.module('OpenSlidesApp.users.site', [
'$scope',
'Group',
'group',
function($scope, Group, group) {
'ErrorMessage',
function($scope, Group, group, ErrorMessage) {
$scope.group = group;
$scope.new_name = group.name;
@ -1375,11 +1360,7 @@ angular.module('OpenSlidesApp.users.site', [
$scope.closeThisDialog();
},
function (error) {
var message = '';
for (var e in error.data) {
message += e + ': ' + error.data[e] + ' ';
}
$scope.alert = { msg: message, show: true };
$scope.alert = ErrorMessage.forAlert(error);
$scope.group.name = old_name;
}
);
@ -1390,7 +1371,8 @@ angular.module('OpenSlidesApp.users.site', [
.controller('GroupCreateCtrl', [
'$scope',
'Group',
function($scope, Group) {
'ErrorMessage',
function($scope, Group, ErrorMessage) {
$scope.new_name = '';
$scope.alert = {};
@ -1405,11 +1387,7 @@ angular.module('OpenSlidesApp.users.site', [
$scope.closeThisDialog();
},
function (error) {
var message = '';
for (var e in error.data) {
message += e + ': ' + error.data[e] + ' ';
}
$scope.alert = { msg: message, show: true };
$scope.alert = ErrorMessage.forAlert(error);
}
);
};
@ -1469,11 +1447,11 @@ angular.module('OpenSlidesApp.users.site', [
$scope.guestAllowed = $rootScope.guest_enabled;
// get login info-text from server
$http.get('/users/login/').success(function(data) {
if(data.info_text) {
$http.get('/users/login/').then(function (success) {
if(success.data.info_text) {
$scope.alerts.push({
type: 'success',
msg: data.info_text
msg: success.data.info_text
});
}
});