2015-11-23 21:31:15 +01:00
|
|
|
(function () {
|
|
|
|
|
2015-07-06 09:19:42 +02:00
|
|
|
"use strict";
|
|
|
|
|
2015-11-23 22:01:30 +01:00
|
|
|
angular.module('OpenSlidesApp.motions', ['OpenSlidesApp.users'])
|
2015-03-09 15:40:54 +01:00
|
|
|
|
2015-11-03 10:03:44 +01:00
|
|
|
.factory('WorkflowState', [
|
|
|
|
'DS',
|
|
|
|
function (DS) {
|
|
|
|
return DS.defineResource({
|
|
|
|
name: 'motions/workflowstate',
|
|
|
|
methods: {
|
|
|
|
getNextStates: function () {
|
|
|
|
var states = [];
|
|
|
|
_.forEach(this.next_states_id, function (stateId) {
|
|
|
|
states.push(DS.get('motions/workflowstate', stateId));
|
|
|
|
})
|
|
|
|
return states;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
])
|
|
|
|
|
|
|
|
.factory('Workflow', [
|
2015-10-13 21:23:21 +02:00
|
|
|
'DS',
|
2015-10-15 17:25:40 +02:00
|
|
|
'jsDataModel',
|
2015-11-03 10:03:44 +01:00
|
|
|
'WorkflowState',
|
|
|
|
function (DS, jsDataModel, WorkflowState) {
|
2015-10-13 21:23:21 +02:00
|
|
|
return DS.defineResource({
|
2015-11-03 10:03:44 +01:00
|
|
|
name: 'motions/workflow',
|
2015-10-15 17:25:40 +02:00
|
|
|
useClass: jsDataModel,
|
2015-11-03 10:03:44 +01:00
|
|
|
relations: {
|
|
|
|
hasMany: {
|
|
|
|
'motions/workflowstate': {
|
|
|
|
localField: 'states',
|
|
|
|
foreignKey: 'workflow_id',
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
])
|
|
|
|
|
2015-11-03 21:38:53 +01:00
|
|
|
// Load all MotionWorkflows at startup
|
2015-11-03 10:03:44 +01:00
|
|
|
.run([
|
|
|
|
'Workflow',
|
|
|
|
function (Workflow) {
|
|
|
|
Workflow.findAll();
|
|
|
|
}
|
|
|
|
])
|
|
|
|
|
|
|
|
.factory('MotionPoll', [
|
|
|
|
'DS',
|
|
|
|
'Config',
|
|
|
|
function (DS, Config) {
|
|
|
|
return DS.defineResource({
|
2015-11-03 21:38:53 +01:00
|
|
|
name: 'motions/motionpoll',
|
2015-10-15 17:25:40 +02:00
|
|
|
relations: {
|
|
|
|
belongsTo: {
|
|
|
|
'motions/motion': {
|
|
|
|
localField: 'motion',
|
|
|
|
localKey: 'motion_id',
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
methods: {
|
2015-11-03 21:38:53 +01:00
|
|
|
getYesPercent: function (valueOnly) {
|
2015-10-15 17:25:40 +02:00
|
|
|
var config = Config.get('motions_poll_100_percent_base').value;
|
2015-11-03 21:38:53 +01:00
|
|
|
var returnvalue;
|
|
|
|
if (config == "WITHOUT_INVALID" && this.votesvalid > 0 && this.yes >= 0) {
|
|
|
|
returnvalue = Math.round(this.yes * 100 / this.votesvalid * 10) / 10;
|
|
|
|
} else if (config == "WITH_INVALID" && this.votescast > 0 && this.yes >= 0) {
|
|
|
|
returnvalue = Math.round(this.yes * 100 / (this.votescast) * 10) / 10;
|
2015-10-15 17:25:40 +02:00
|
|
|
} else {
|
2015-11-03 21:38:53 +01:00
|
|
|
returnvalue = null;
|
2015-10-15 17:25:40 +02:00
|
|
|
}
|
2015-11-03 21:38:53 +01:00
|
|
|
if (!valueOnly && returnvalue != null) {
|
|
|
|
returnvalue = "(" + returnvalue + "%)";
|
|
|
|
}
|
|
|
|
return returnvalue;
|
2015-10-15 17:25:40 +02:00
|
|
|
},
|
2015-11-03 21:38:53 +01:00
|
|
|
getNoPercent: function (valueOnly) {
|
2015-10-15 17:25:40 +02:00
|
|
|
var config = Config.get('motions_poll_100_percent_base').value;
|
2015-11-03 21:38:53 +01:00
|
|
|
var returnvalue;
|
|
|
|
if (config == "WITHOUT_INVALID" && this.votesvalid > 0 && this.no >= 0) {
|
|
|
|
returnvalue = Math.round(this.no * 100 / this.votesvalid * 10) / 10;
|
|
|
|
} else if (config == "WITH_INVALID" && this.votescast > 0 && this.no >= 0) {
|
|
|
|
returnvalue = Math.round(this.no * 100 / (this.votescast) * 10) / 10;
|
2015-10-15 17:25:40 +02:00
|
|
|
} else {
|
2015-11-03 21:38:53 +01:00
|
|
|
returnvalue = null;
|
|
|
|
}
|
|
|
|
if (!valueOnly && returnvalue != null) {
|
|
|
|
returnvalue = "(" + returnvalue + "%)";
|
2015-10-15 17:25:40 +02:00
|
|
|
}
|
2015-11-03 21:38:53 +01:00
|
|
|
return returnvalue;
|
2015-10-15 17:25:40 +02:00
|
|
|
},
|
2015-11-03 21:38:53 +01:00
|
|
|
getAbstainPercent: function (valueOnly) {
|
2015-10-15 17:25:40 +02:00
|
|
|
var config = Config.get('motions_poll_100_percent_base').value;
|
2015-11-03 21:38:53 +01:00
|
|
|
var returnvalue;
|
|
|
|
if (config == "WITHOUT_INVALID" && this.votesvalid > 0 && this.abstain >= 0) {
|
|
|
|
returnvalue = Math.round(this.abstain * 100 / this.votesvalid * 10) / 10;
|
|
|
|
} else if (config == "WITH_INVALID" && this.votescast > 0 && this.abstain >= 0) {
|
|
|
|
returnvalue = Math.round(this.abstain * 100 / (this.votescast) * 10) / 10;
|
2015-10-15 17:25:40 +02:00
|
|
|
} else {
|
2015-11-03 21:38:53 +01:00
|
|
|
returnvalue = null;
|
|
|
|
}
|
|
|
|
if (!valueOnly && returnvalue != null) {
|
|
|
|
returnvalue = "(" + returnvalue + "%)";
|
2015-10-15 17:25:40 +02:00
|
|
|
}
|
2015-11-03 21:38:53 +01:00
|
|
|
return returnvalue;
|
2015-10-15 17:25:40 +02:00
|
|
|
},
|
2015-11-03 21:38:53 +01:00
|
|
|
getVotesValidPercent: function (valueOnly) {
|
2015-10-15 17:25:40 +02:00
|
|
|
var config = Config.get('motions_poll_100_percent_base').value;
|
2015-11-03 21:38:53 +01:00
|
|
|
var returnvalue;
|
|
|
|
if (config == "WITHOUT_INVALID" && this.votevalid >= 0) {
|
|
|
|
returnvalue = 100;
|
|
|
|
} else if (config == "WITH_INVALID" && this.votevalid >= 0) {
|
|
|
|
returnvalue = Math.round(this.votesvalid * 100 / (this.votescast) * 10) / 10;
|
2015-10-15 17:25:40 +02:00
|
|
|
} else {
|
2015-11-03 21:38:53 +01:00
|
|
|
returnvalue = null;
|
2015-10-15 17:25:40 +02:00
|
|
|
}
|
2015-11-03 21:38:53 +01:00
|
|
|
if (!valueOnly && returnvalue != null) {
|
|
|
|
returnvalue = "(" + returnvalue + "%)";
|
|
|
|
}
|
|
|
|
return returnvalue;
|
2015-10-15 17:25:40 +02:00
|
|
|
},
|
2015-11-03 21:38:53 +01:00
|
|
|
getVotesInvalidPercent: function (valueOnly) {
|
2015-10-15 17:25:40 +02:00
|
|
|
var config = Config.get('motions_poll_100_percent_base').value;
|
2015-11-03 21:38:53 +01:00
|
|
|
var returnvalue;
|
|
|
|
if (config == "WITH_INVALID" && this.voteinvalid >= 0) {
|
|
|
|
returnvalue = Math.round(this.votesinvalid * 100 / (this.votescast) * 10) / 10;
|
2015-10-15 17:25:40 +02:00
|
|
|
} else {
|
2015-11-03 21:38:53 +01:00
|
|
|
returnvalue = null;
|
|
|
|
}
|
|
|
|
if (!valueOnly && returnvalue != null) {
|
|
|
|
returnvalue = "(" + returnvalue + "%)";
|
2015-10-15 17:25:40 +02:00
|
|
|
}
|
2015-11-03 21:38:53 +01:00
|
|
|
return returnvalue;
|
2015-10-15 17:25:40 +02:00
|
|
|
},
|
2015-11-03 21:38:53 +01:00
|
|
|
getVotesCastPercent: function (valueOnly) {
|
2015-10-15 17:25:40 +02:00
|
|
|
var config = Config.get('motions_poll_100_percent_base').value;
|
2015-11-03 21:38:53 +01:00
|
|
|
var returnvalue;
|
|
|
|
if (config == "WITH_INVALID" && this.votecast >= 0) {
|
|
|
|
returnvalue = 100;
|
2015-10-15 17:25:40 +02:00
|
|
|
} else {
|
2015-11-03 21:38:53 +01:00
|
|
|
returnvalue = null;
|
2015-10-15 17:25:40 +02:00
|
|
|
}
|
2015-11-03 21:38:53 +01:00
|
|
|
if (!valueOnly && returnvalue != null) {
|
|
|
|
returnvalue = "(" + returnvalue + "%)";
|
|
|
|
}
|
|
|
|
return returnvalue;
|
2015-10-15 17:25:40 +02:00
|
|
|
}
|
|
|
|
}
|
2015-10-13 21:23:21 +02:00
|
|
|
});
|
|
|
|
}
|
|
|
|
])
|
|
|
|
|
2015-10-24 19:02:43 +02:00
|
|
|
.factory('Motion', [
|
|
|
|
'DS',
|
2015-10-13 21:23:21 +02:00
|
|
|
'MotionPoll',
|
2015-10-24 19:02:43 +02:00
|
|
|
'jsDataModel',
|
2015-11-19 20:51:39 +01:00
|
|
|
'gettext',
|
|
|
|
'operator',
|
|
|
|
'Config',
|
2016-01-27 13:41:19 +01:00
|
|
|
function(DS, MotionPoll, jsDataModel, gettext, operator, Config) {
|
2016-01-10 10:52:44 +01:00
|
|
|
var name = 'motions/motion';
|
2015-10-24 19:02:43 +02:00
|
|
|
return DS.defineResource({
|
|
|
|
name: name,
|
|
|
|
useClass: jsDataModel,
|
2016-01-10 13:47:59 +01:00
|
|
|
verboseName: gettext('Motion'),
|
2015-10-24 19:02:43 +02:00
|
|
|
methods: {
|
|
|
|
getResourceName: function () {
|
|
|
|
return name;
|
|
|
|
},
|
|
|
|
getVersion: function (versionId) {
|
|
|
|
versionId = versionId || this.active_version;
|
|
|
|
var index;
|
|
|
|
if (versionId == -1) {
|
|
|
|
index = this.versions.length - 1;
|
|
|
|
} else {
|
|
|
|
index = _.findIndex(this.versions, function (element) {
|
|
|
|
return element.id == versionId
|
|
|
|
});
|
|
|
|
}
|
|
|
|
return this.versions[index];
|
|
|
|
},
|
|
|
|
getTitle: function (versionId) {
|
|
|
|
return this.getVersion(versionId).title;
|
|
|
|
},
|
|
|
|
getText: function (versionId) {
|
|
|
|
return this.getVersion(versionId).text;
|
|
|
|
},
|
|
|
|
getReason: function (versionId) {
|
|
|
|
return this.getVersion(versionId).reason;
|
2015-07-06 09:19:42 +02:00
|
|
|
},
|
2016-01-27 00:16:30 +01:00
|
|
|
// link name which is shown in search result
|
|
|
|
getSearchResultName: function () {
|
2016-01-25 21:22:22 +01:00
|
|
|
return this.getTitle();
|
2016-01-27 00:16:30 +01:00
|
|
|
},
|
|
|
|
// subtitle of search result
|
|
|
|
getSearchResultSubtitle: function () {
|
|
|
|
return "Motion";
|
|
|
|
},
|
2015-11-19 20:51:39 +01:00
|
|
|
isAllowed: function (action) {
|
|
|
|
/*
|
|
|
|
* Return true if the requested user is allowed to do the specific action.
|
|
|
|
* There are the following possible actions.
|
|
|
|
* - see
|
|
|
|
* - update
|
|
|
|
* - delete
|
|
|
|
* - create_poll
|
|
|
|
* - support
|
|
|
|
* - unsupport
|
|
|
|
* - change_state
|
|
|
|
* - reset_state
|
|
|
|
*
|
|
|
|
* NOTE: If you update this function please also update the
|
|
|
|
* 'get_allowed_actions' function on server side in motions/models.py.
|
|
|
|
*/
|
|
|
|
switch (action) {
|
|
|
|
case 'see':
|
|
|
|
return (operator.hasPerms('motions.can_see') &&
|
|
|
|
(!this.state.required_permission_to_see ||
|
|
|
|
operator.hasPerms(this.state.required_permission_to_see) ||
|
|
|
|
(operator.user in this.submitters)));
|
|
|
|
case 'update':
|
|
|
|
return (operator.hasPerms('motions.can_manage') ||
|
|
|
|
(($.inArray(operator.user, this.submitters) != -1) &&
|
|
|
|
this.state.allow_submitter_edit));
|
|
|
|
case 'quickedit':
|
|
|
|
return operator.hasPerms('motions.can_manage');
|
|
|
|
case 'delete':
|
|
|
|
return operator.hasPerms('motions.can_manage');
|
|
|
|
case 'create_poll':
|
|
|
|
return (operator.hasPerms('motions.can_manage') &&
|
|
|
|
this.state.allow_create_poll);
|
|
|
|
case 'support':
|
|
|
|
return (operator.hasPerms('motions.can_support') &&
|
|
|
|
this.state.allow_support &&
|
|
|
|
Config.get('motions_min_supporters').value > 0 &&
|
|
|
|
!($.inArray(operator.user, this.submitters) != -1) &&
|
|
|
|
!($.inArray(operator.user, this.supporters) != -1));
|
|
|
|
case 'unsupport':
|
|
|
|
return (this.state.allow_support &&
|
|
|
|
($.inArray(operator.user, this.supporters) != -1));
|
|
|
|
case 'change_state':
|
|
|
|
return operator.hasPerms('motions.can_manage');
|
|
|
|
case 'reset_state':
|
|
|
|
return operator.hasPerms('motions.can_manage');
|
2016-02-08 20:34:12 +01:00
|
|
|
case 'can_manage':
|
|
|
|
return operator.hasPerms('motions.can_manage');
|
2015-11-19 20:51:39 +01:00
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
2015-10-24 19:02:43 +02:00
|
|
|
}
|
2015-07-06 09:19:42 +02:00
|
|
|
},
|
2015-10-24 19:02:43 +02:00
|
|
|
relations: {
|
|
|
|
belongsTo: {
|
|
|
|
'motions/category': {
|
|
|
|
localField: 'category',
|
|
|
|
localKey: 'category_id',
|
2015-07-06 09:19:42 +02:00
|
|
|
},
|
2015-10-24 19:02:43 +02:00
|
|
|
'agenda/item': {
|
|
|
|
localKey: 'agenda_item_id',
|
|
|
|
localField: 'agenda_item',
|
2015-07-06 09:19:42 +02:00
|
|
|
}
|
2015-10-24 19:02:43 +02:00
|
|
|
},
|
|
|
|
hasMany: {
|
|
|
|
'core/tag': {
|
|
|
|
localField: 'tags',
|
|
|
|
localKeys: 'tags_id',
|
|
|
|
},
|
2015-11-03 21:38:53 +01:00
|
|
|
'mediafiles/mediafile': {
|
|
|
|
localField: 'attachments',
|
|
|
|
localKeys: 'attachments_id',
|
|
|
|
},
|
2015-10-24 19:02:43 +02:00
|
|
|
'users/user': [
|
|
|
|
{
|
|
|
|
localField: 'submitters',
|
|
|
|
localKeys: 'submitters_id',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
localField: 'supporters',
|
|
|
|
localKeys: 'supporters_id',
|
|
|
|
}
|
|
|
|
],
|
2015-11-03 21:38:53 +01:00
|
|
|
'motions/motionpoll': {
|
2015-10-13 21:23:21 +02:00
|
|
|
localField: 'polls',
|
|
|
|
foreignKey: 'motion_id',
|
|
|
|
}
|
2015-11-03 10:03:44 +01:00
|
|
|
},
|
|
|
|
hasOne: {
|
|
|
|
'motions/workflowstate': {
|
|
|
|
localField: 'state',
|
|
|
|
localKey: 'state_id',
|
|
|
|
}
|
2015-10-24 19:02:43 +02:00
|
|
|
}
|
2015-07-06 09:19:42 +02:00
|
|
|
}
|
2015-10-24 19:02:43 +02:00
|
|
|
});
|
|
|
|
}
|
|
|
|
])
|
2015-07-06 09:19:42 +02:00
|
|
|
|
2016-01-17 21:16:04 +01:00
|
|
|
.factory('Category', [
|
|
|
|
'DS',
|
|
|
|
function(DS) {
|
|
|
|
return DS.defineResource({
|
|
|
|
name: 'motions/category',
|
|
|
|
});
|
|
|
|
}
|
|
|
|
])
|
2015-06-17 09:45:00 +02:00
|
|
|
|
2016-01-17 21:16:04 +01:00
|
|
|
.run([
|
|
|
|
'Motion',
|
|
|
|
'Category',
|
|
|
|
function(Motion, Category) {}
|
2016-01-22 20:46:20 +01:00
|
|
|
])
|
|
|
|
|
|
|
|
|
|
|
|
// Mark all motion workflow state strings for translation in JavaScript.
|
|
|
|
// (see motions/signals.py)
|
|
|
|
.config([
|
|
|
|
'gettext',
|
|
|
|
function (gettext) {
|
|
|
|
// workflow 1
|
|
|
|
gettext('Simple Workflow')
|
|
|
|
gettext('submitted')
|
|
|
|
gettext('accepted')
|
|
|
|
gettext('Accept')
|
|
|
|
gettext('rejected')
|
|
|
|
gettext('Reject')
|
|
|
|
gettext('not decided')
|
|
|
|
gettext('Do not decide')
|
|
|
|
// workflow 2
|
|
|
|
gettext('Complex Workflow')
|
|
|
|
gettext('published')
|
|
|
|
gettext('permitted')
|
|
|
|
gettext('Permit')
|
|
|
|
gettext('accepted')
|
|
|
|
gettext('Accept')
|
|
|
|
gettext('rejected')
|
|
|
|
gettext('Reject')
|
|
|
|
gettext('withdrawed')
|
|
|
|
gettext('Withdraw')
|
|
|
|
gettext('adjourned')
|
|
|
|
gettext('Adjourn')
|
|
|
|
gettext('not concerned')
|
|
|
|
gettext('Do not concern')
|
|
|
|
gettext('commited a bill')
|
|
|
|
gettext('Commit a bill')
|
|
|
|
gettext('needs review')
|
|
|
|
gettext('Needs review')
|
|
|
|
gettext('rejected (not authorized)')
|
|
|
|
gettext('Reject (not authorized)')
|
|
|
|
}
|
2016-01-17 21:16:04 +01:00
|
|
|
]);
|
2016-01-22 20:46:20 +01:00
|
|
|
|
2015-11-23 21:31:15 +01:00
|
|
|
}());
|