Merge pull request #2535 from emanuelschuetze/state-recommendation-extra-fields
Added new motion state flags to show an additional fields
This commit is contained in:
commit
7ce479a511
25
openslides/motions/migrations/0007_auto_20161027_1406.py
Normal file
25
openslides/motions/migrations/0007_auto_20161027_1406.py
Normal file
@ -0,0 +1,25 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.10.2 on 2016-10-27 12:06
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('motions', '0006_auto_20161017_2020'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='state',
|
||||
name='show_recommendation_extension_field',
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='state',
|
||||
name='show_state_extension_field',
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
]
|
@ -1085,6 +1085,20 @@ class State(RESTModelMixin, models.Model):
|
||||
this one, else it does.
|
||||
"""
|
||||
|
||||
show_state_extension_field = models.BooleanField(default=False)
|
||||
"""
|
||||
If true, an additional input field (from motion comment) is visible
|
||||
to extend the state name. The full state name is composed of the given
|
||||
state name and the entered value of this input field.
|
||||
"""
|
||||
|
||||
show_recommendation_extension_field = models.BooleanField(default=False)
|
||||
"""
|
||||
If true, an additional input field (from motion comment) is visible
|
||||
to extend the recommendation label. The full recommendation string is
|
||||
composed of the given recommendation label and the entered value of this input field.
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
default_permissions = ()
|
||||
|
||||
|
@ -71,6 +71,8 @@ class StateSerializer(ModelSerializer):
|
||||
'versioning',
|
||||
'leave_old_version_active',
|
||||
'dont_set_identifier',
|
||||
'show_state_extension_field',
|
||||
'show_recommendation_extension_field',
|
||||
'next_states',
|
||||
'workflow')
|
||||
|
||||
|
@ -147,11 +147,12 @@ angular.module('OpenSlidesApp.motions', [
|
||||
'MotionComment',
|
||||
'jsDataModel',
|
||||
'gettext',
|
||||
'gettextCatalog',
|
||||
'operator',
|
||||
'Config',
|
||||
'lineNumberingService',
|
||||
'diffService',
|
||||
function(DS, MotionPoll, MotionChangeRecommendation, MotionComment, jsDataModel, gettext, operator, Config,
|
||||
function(DS, MotionPoll, MotionChangeRecommendation, MotionComment, jsDataModel, gettext, gettextCatalog, operator, Config,
|
||||
lineNumberingService, diffService) {
|
||||
var name = 'motions/motion';
|
||||
return DS.defineResource({
|
||||
@ -288,6 +289,38 @@ angular.module('OpenSlidesApp.motions', [
|
||||
getReason: function (versionId) {
|
||||
return this.getVersion(versionId).reason;
|
||||
},
|
||||
// full state name - optional with custom state name extension
|
||||
// depended by state and provided by a custom comment field
|
||||
getStateName: function () {
|
||||
var additionalName = '';
|
||||
if (this.state.show_state_extension_field) {
|
||||
// check motion comment fields for flag 'forState'
|
||||
var fields = Config.get('motions_comments').value;
|
||||
var index = _.findIndex(fields, ['forState', true]);
|
||||
if (index > -1) {
|
||||
additionalName = ' ' + this.comments[index];
|
||||
}
|
||||
}
|
||||
return gettextCatalog.getString(this.state.name) + additionalName;
|
||||
},
|
||||
// full recommendation string - optional with custom recommendationextension
|
||||
// depended by state and provided by a custom comment field
|
||||
getRecommendationName: function () {
|
||||
var recommendation = '';
|
||||
var additionalName = '';
|
||||
if (this.recommendation) {
|
||||
recommendation = gettextCatalog.getString(this.recommendation.recommendation_label);
|
||||
if (this.recommendation.show_recommendation_extension_field) {
|
||||
// check motion comment fields for flag 'forRecommendation'
|
||||
var fields = Config.get('motions_comments').value;
|
||||
var index = _.findIndex(fields, ['forRecommendation', true]);
|
||||
if (index > -1) {
|
||||
additionalName = ' ' + this.comments[index];
|
||||
}
|
||||
}
|
||||
}
|
||||
return recommendation + additionalName;
|
||||
},
|
||||
// link name which is shown in search result
|
||||
getSearchResultName: function () {
|
||||
return this.getTitle();
|
||||
@ -450,7 +483,7 @@ angular.module('OpenSlidesApp.motions', [
|
||||
getFormFields: function () {
|
||||
var fields = Config.get('motions_comments').value;
|
||||
return _.map(
|
||||
fields,
|
||||
_.filter(fields, function(element) { return !element.forState && !element.forRecommendation; }),
|
||||
function (field) {
|
||||
return {
|
||||
key: 'comment ' + field.name,
|
||||
@ -484,7 +517,16 @@ angular.module('OpenSlidesApp.motions', [
|
||||
for (var i = 0; i < fields.length; i++) {
|
||||
motion.comments.push(motion['comment ' + fields[i].name] || '');
|
||||
}
|
||||
},
|
||||
getFieldNameForFlag: function (flag) {
|
||||
var fields = Config.get('motions_comments').value;
|
||||
var fieldName = '';
|
||||
var index = _.findIndex(fields, [flag, true]);
|
||||
if (index > -1) {
|
||||
fieldName = fields[index].name;
|
||||
}
|
||||
return fieldName;
|
||||
},
|
||||
};
|
||||
}
|
||||
])
|
||||
|
@ -82,7 +82,7 @@ angular.module('OpenSlidesApp.motions.DOCX', [])
|
||||
}).join(', '),
|
||||
signature_translation: signature_translation,
|
||||
status_translation: status_translation,
|
||||
status: gettextCatalog.getString(motion.state.name),
|
||||
status: motion.getStateName(),
|
||||
text: html2docx(motion.getText()),
|
||||
reason_translation: motion.getReason().length === 0 ? '' : reason_translation,
|
||||
reason: html2docx(motion.getReason()),
|
||||
|
@ -42,7 +42,7 @@ angular.module('OpenSlidesApp.motions.pdf', ['OpenSlidesApp.core.pdf'])
|
||||
// Generate text of signment
|
||||
var signment = function() {
|
||||
var label = converter.createElement("text", gettextCatalog.getString('Submitter') + ':\nStatus:');
|
||||
var state = converter.createElement("text", User.get(motion.submitters_id[0]).full_name + '\n'+gettextCatalog.getString(motion.state.name));
|
||||
var state = converter.createElement("text", User.get(motion.submitters_id[0]).full_name + '\n' + motion.getStateName());
|
||||
state.width = "70%";
|
||||
label.width = "30%";
|
||||
label.bold = true;
|
||||
|
@ -1013,6 +1013,7 @@ angular.module('OpenSlidesApp.motions.site', [
|
||||
'MotionChangeRecommendation',
|
||||
'MotionPDFExport',
|
||||
'Motion',
|
||||
'MotionComment',
|
||||
'Category',
|
||||
'Mediafile',
|
||||
'Tag',
|
||||
@ -1026,9 +1027,8 @@ angular.module('OpenSlidesApp.motions.site', [
|
||||
'ProjectionDefault',
|
||||
function($scope, $http, operator, ngDialog, MotionForm,
|
||||
ChangeRecommmendationCreate, ChangeRecommmendationView, MotionChangeRecommendation, MotionPDFExport,
|
||||
Motion, Category, Mediafile, Tag, User, Workflow, Config, motion, MotionInlineEditing, gettextCatalog,
|
||||
Motion, MotionComment, Category, Mediafile, Tag, User, Workflow, Config, motion, MotionInlineEditing, gettextCatalog,
|
||||
Projector, ProjectionDefault) {
|
||||
Motion.bindOne(motion.id, $scope, 'motion');
|
||||
Category.bindAll({}, $scope, 'categories');
|
||||
Mediafile.bindAll({}, $scope, 'mediafiles');
|
||||
Tag.bindAll({}, $scope, 'tags');
|
||||
@ -1041,10 +1041,17 @@ angular.module('OpenSlidesApp.motions.site', [
|
||||
}, function () {
|
||||
$scope.defaultProjectorId = ProjectionDefault.filter({name: 'motions'})[0].projector_id;
|
||||
});
|
||||
$scope.$watch(function () {
|
||||
return Motion.lastModified(motion.id);
|
||||
}, function () {
|
||||
$scope.motion = Motion.get(motion.id);
|
||||
MotionComment.populateFields($scope.motion);
|
||||
});
|
||||
$scope.commentsFields = Config.get('motions_comments').value;
|
||||
$scope.commentFieldForState = MotionComment.getFieldNameForFlag('forState');
|
||||
$scope.commentFieldForRecommendation = MotionComment.getFieldNameForFlag('forRecommendation');
|
||||
$scope.version = motion.active_version;
|
||||
$scope.isCollapsed = true;
|
||||
$scope.commentsFields = Config.get('motions_comments').value;
|
||||
|
||||
$scope.lineNumberMode = Config.get('motions_default_line_numbering').value;
|
||||
$scope.setLineNumberMode = function(mode) {
|
||||
$scope.lineNumberMode = mode;
|
||||
@ -1119,6 +1126,26 @@ angular.module('OpenSlidesApp.motions.site', [
|
||||
$scope.reset_state = function () {
|
||||
$http.put('/rest/motions/motion/' + motion.id + '/set_state/', {});
|
||||
};
|
||||
// save additional state field
|
||||
$scope.saveAdditionalStateField = function (stateExtension) {
|
||||
if (stateExtension) {
|
||||
motion["comment " + $scope.commentFieldForState] = stateExtension;
|
||||
motion.title = motion.getTitle(-1);
|
||||
motion.text = motion.getText(-1);
|
||||
motion.reason = motion.getReason(-1);
|
||||
Motion.save(motion);
|
||||
}
|
||||
};
|
||||
// save additional recommendation field
|
||||
$scope.saveAdditionalRecommendationField = function (recommendationExtension) {
|
||||
if (recommendationExtension) {
|
||||
motion["comment " + $scope.commentFieldForRecommendation] = recommendationExtension;
|
||||
motion.title = motion.getTitle(-1);
|
||||
motion.text = motion.getText(-1);
|
||||
motion.reason = motion.getReason(-1);
|
||||
Motion.save(motion);
|
||||
}
|
||||
};
|
||||
// update recommendation
|
||||
$scope.updateRecommendation = function (recommendation_id) {
|
||||
$http.put('/rest/motions/motion/' + motion.id + '/set_recommendation/', {'recommendation': recommendation_id});
|
||||
@ -1183,7 +1210,7 @@ angular.module('OpenSlidesApp.motions.site', [
|
||||
isAllowed = operator.hasPerms('motions.can_see_and_manage_comments') || _.find(
|
||||
$scope.commentsFields,
|
||||
function(field) {
|
||||
return field.public;
|
||||
return field.public && !field.forState && !field.forRecommendation;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
@ -65,11 +65,11 @@
|
||||
</div>
|
||||
<td>
|
||||
<div class="label" ng-class="'label-'+motion.state.css_class">
|
||||
{{ motion.state.name | translate }}
|
||||
{{ motion.getStateName() }}
|
||||
</div>
|
||||
<td>
|
||||
<div class="label" ng-class="'label-'+motion.recommendation.css_class">
|
||||
{{ motion.recommendation.recommendation_label | translate }}
|
||||
{{ motion.getRecommendationName() }}
|
||||
</div>
|
||||
</table>
|
||||
</div>
|
||||
|
@ -115,7 +115,19 @@
|
||||
</span>
|
||||
</div>
|
||||
<div class="label" ng-class="'label-'+motion.state.css_class">
|
||||
{{ motion.state.name | translate }}
|
||||
{{ motion.getStateName() }}
|
||||
</div>
|
||||
<div os-perms="motions.can_manage" class="input-group spacer"
|
||||
ng-show="motion.state.show_state_extension_field">
|
||||
<label class="sr-only" for="stateExtensionField">{{ commentFieldForState }}</label>
|
||||
<input type="text" ng-model="stateExtension"
|
||||
id="stateNameExtensionField" class="form-control input-sm"
|
||||
placeholder="{{ commentFieldForState }}">
|
||||
<span class="input-group-btn">
|
||||
<button ng-click="saveAdditionalStateField(stateExtension)" class="btn btn-default btn-sm">
|
||||
<i class="fa fa-check"></i>
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Recommendation -->
|
||||
@ -142,7 +154,19 @@
|
||||
</span>
|
||||
</div>
|
||||
<div class="label" ng-class="'label-'+motion.recommendation.css_class">
|
||||
{{ motion.recommendation.recommendation_label | translate }}
|
||||
{{ motion.getRecommendationName() }}
|
||||
</div>
|
||||
<div class="input-group spacer"
|
||||
ng-show="motion.recommendation.show_recommendation_extension_field">
|
||||
<label class="sr-only" for="recommendationExtensionField">{{ commentFieldForRecommendation }}</label>
|
||||
<input type="text" ng-model="recommendationExtension"
|
||||
id="recommendationExtensionField" class="form-control input-sm"
|
||||
placeholder="{{ commentFieldForRecommendation }}">
|
||||
<span class="input-group-btn">
|
||||
<button ng-click="saveAdditionalRecommendationField(recommendationExtension)" class="btn btn-default btn-sm">
|
||||
<i class="fa fa-check"></i>
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -407,9 +431,10 @@
|
||||
</div>
|
||||
|
||||
<div class="details" ng-if="isAllowedToSeeCommentField()">
|
||||
<h3>Motion Comments</h3>
|
||||
<h3 translate>Comments</h3>
|
||||
<div ng-repeat="field in commentsFields">
|
||||
<div ng-if="field.public || operator.hasPerms('motions.can_see_and_manage_comments')">
|
||||
<div ng-if="(field.public && !field.forState && !field.forRecommendation) ||
|
||||
(operator.hasPerms('motions.can_see_and_manage_comments') && !field.forState && !field.forRecommendation)">
|
||||
<h4>
|
||||
{{ field.name }}
|
||||
<span ng-if="!field.public" class="label label-warning" translate>internal</span>
|
||||
|
@ -389,7 +389,7 @@
|
||||
<i class="fa fa-paperclip" ng-if="motion.attachments_id.length > 0"></i>
|
||||
<span style="padding: 5px;" ng-mouseover="motion.stateHover=true" ng-mouseleave="motion.stateHover=false">
|
||||
<span class="label" ng-class="'label-'+motion.state.css_class">
|
||||
{{ motion.state.name | translate }}
|
||||
{{ motion.getStateName() }}
|
||||
</span>
|
||||
<span os-perms="motions.can_manage" ng-class="{'hiddenDiv': !motion.stateHover}" uib-dropdown>
|
||||
<i class="fa fa-cog pointer" uib-dropdown-toggle id="state-dropdown{{ motion.id }}"></i>
|
||||
|
@ -3,7 +3,7 @@
|
||||
<div id="sidebox">
|
||||
<!-- State -->
|
||||
<h3 translate>State</h3>
|
||||
{{ motion.state.name | translate }}
|
||||
{{ motion.getStateName() }}
|
||||
|
||||
<!-- Submitters -->
|
||||
<h3 ng-if="motion.submitters.length > 0" translate>Submitters</h3>
|
||||
|
Loading…
Reference in New Issue
Block a user