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.
|
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:
|
class Meta:
|
||||||
default_permissions = ()
|
default_permissions = ()
|
||||||
|
|
||||||
|
@ -71,6 +71,8 @@ class StateSerializer(ModelSerializer):
|
|||||||
'versioning',
|
'versioning',
|
||||||
'leave_old_version_active',
|
'leave_old_version_active',
|
||||||
'dont_set_identifier',
|
'dont_set_identifier',
|
||||||
|
'show_state_extension_field',
|
||||||
|
'show_recommendation_extension_field',
|
||||||
'next_states',
|
'next_states',
|
||||||
'workflow')
|
'workflow')
|
||||||
|
|
||||||
|
@ -147,11 +147,12 @@ angular.module('OpenSlidesApp.motions', [
|
|||||||
'MotionComment',
|
'MotionComment',
|
||||||
'jsDataModel',
|
'jsDataModel',
|
||||||
'gettext',
|
'gettext',
|
||||||
|
'gettextCatalog',
|
||||||
'operator',
|
'operator',
|
||||||
'Config',
|
'Config',
|
||||||
'lineNumberingService',
|
'lineNumberingService',
|
||||||
'diffService',
|
'diffService',
|
||||||
function(DS, MotionPoll, MotionChangeRecommendation, MotionComment, jsDataModel, gettext, operator, Config,
|
function(DS, MotionPoll, MotionChangeRecommendation, MotionComment, jsDataModel, gettext, gettextCatalog, operator, Config,
|
||||||
lineNumberingService, diffService) {
|
lineNumberingService, diffService) {
|
||||||
var name = 'motions/motion';
|
var name = 'motions/motion';
|
||||||
return DS.defineResource({
|
return DS.defineResource({
|
||||||
@ -288,6 +289,38 @@ angular.module('OpenSlidesApp.motions', [
|
|||||||
getReason: function (versionId) {
|
getReason: function (versionId) {
|
||||||
return this.getVersion(versionId).reason;
|
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
|
// link name which is shown in search result
|
||||||
getSearchResultName: function () {
|
getSearchResultName: function () {
|
||||||
return this.getTitle();
|
return this.getTitle();
|
||||||
@ -450,7 +483,7 @@ angular.module('OpenSlidesApp.motions', [
|
|||||||
getFormFields: function () {
|
getFormFields: function () {
|
||||||
var fields = Config.get('motions_comments').value;
|
var fields = Config.get('motions_comments').value;
|
||||||
return _.map(
|
return _.map(
|
||||||
fields,
|
_.filter(fields, function(element) { return !element.forState && !element.forRecommendation; }),
|
||||||
function (field) {
|
function (field) {
|
||||||
return {
|
return {
|
||||||
key: 'comment ' + field.name,
|
key: 'comment ' + field.name,
|
||||||
@ -484,7 +517,16 @@ angular.module('OpenSlidesApp.motions', [
|
|||||||
for (var i = 0; i < fields.length; i++) {
|
for (var i = 0; i < fields.length; i++) {
|
||||||
motion.comments.push(motion['comment ' + fields[i].name] || '');
|
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(', '),
|
}).join(', '),
|
||||||
signature_translation: signature_translation,
|
signature_translation: signature_translation,
|
||||||
status_translation: status_translation,
|
status_translation: status_translation,
|
||||||
status: gettextCatalog.getString(motion.state.name),
|
status: motion.getStateName(),
|
||||||
text: html2docx(motion.getText()),
|
text: html2docx(motion.getText()),
|
||||||
reason_translation: motion.getReason().length === 0 ? '' : reason_translation,
|
reason_translation: motion.getReason().length === 0 ? '' : reason_translation,
|
||||||
reason: html2docx(motion.getReason()),
|
reason: html2docx(motion.getReason()),
|
||||||
|
@ -42,7 +42,7 @@ angular.module('OpenSlidesApp.motions.pdf', ['OpenSlidesApp.core.pdf'])
|
|||||||
// Generate text of signment
|
// Generate text of signment
|
||||||
var signment = function() {
|
var signment = function() {
|
||||||
var label = converter.createElement("text", gettextCatalog.getString('Submitter') + ':\nStatus:');
|
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%";
|
state.width = "70%";
|
||||||
label.width = "30%";
|
label.width = "30%";
|
||||||
label.bold = true;
|
label.bold = true;
|
||||||
|
@ -1013,6 +1013,7 @@ angular.module('OpenSlidesApp.motions.site', [
|
|||||||
'MotionChangeRecommendation',
|
'MotionChangeRecommendation',
|
||||||
'MotionPDFExport',
|
'MotionPDFExport',
|
||||||
'Motion',
|
'Motion',
|
||||||
|
'MotionComment',
|
||||||
'Category',
|
'Category',
|
||||||
'Mediafile',
|
'Mediafile',
|
||||||
'Tag',
|
'Tag',
|
||||||
@ -1026,9 +1027,8 @@ angular.module('OpenSlidesApp.motions.site', [
|
|||||||
'ProjectionDefault',
|
'ProjectionDefault',
|
||||||
function($scope, $http, operator, ngDialog, MotionForm,
|
function($scope, $http, operator, ngDialog, MotionForm,
|
||||||
ChangeRecommmendationCreate, ChangeRecommmendationView, MotionChangeRecommendation, MotionPDFExport,
|
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) {
|
Projector, ProjectionDefault) {
|
||||||
Motion.bindOne(motion.id, $scope, 'motion');
|
|
||||||
Category.bindAll({}, $scope, 'categories');
|
Category.bindAll({}, $scope, 'categories');
|
||||||
Mediafile.bindAll({}, $scope, 'mediafiles');
|
Mediafile.bindAll({}, $scope, 'mediafiles');
|
||||||
Tag.bindAll({}, $scope, 'tags');
|
Tag.bindAll({}, $scope, 'tags');
|
||||||
@ -1041,10 +1041,17 @@ angular.module('OpenSlidesApp.motions.site', [
|
|||||||
}, function () {
|
}, function () {
|
||||||
$scope.defaultProjectorId = ProjectionDefault.filter({name: 'motions'})[0].projector_id;
|
$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.version = motion.active_version;
|
||||||
$scope.isCollapsed = true;
|
$scope.isCollapsed = true;
|
||||||
$scope.commentsFields = Config.get('motions_comments').value;
|
|
||||||
|
|
||||||
$scope.lineNumberMode = Config.get('motions_default_line_numbering').value;
|
$scope.lineNumberMode = Config.get('motions_default_line_numbering').value;
|
||||||
$scope.setLineNumberMode = function(mode) {
|
$scope.setLineNumberMode = function(mode) {
|
||||||
$scope.lineNumberMode = mode;
|
$scope.lineNumberMode = mode;
|
||||||
@ -1119,6 +1126,26 @@ angular.module('OpenSlidesApp.motions.site', [
|
|||||||
$scope.reset_state = function () {
|
$scope.reset_state = function () {
|
||||||
$http.put('/rest/motions/motion/' + motion.id + '/set_state/', {});
|
$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
|
// update recommendation
|
||||||
$scope.updateRecommendation = function (recommendation_id) {
|
$scope.updateRecommendation = function (recommendation_id) {
|
||||||
$http.put('/rest/motions/motion/' + motion.id + '/set_recommendation/', {'recommendation': 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(
|
isAllowed = operator.hasPerms('motions.can_see_and_manage_comments') || _.find(
|
||||||
$scope.commentsFields,
|
$scope.commentsFields,
|
||||||
function(field) {
|
function(field) {
|
||||||
return field.public;
|
return field.public && !field.forState && !field.forRecommendation;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -65,11 +65,11 @@
|
|||||||
</div>
|
</div>
|
||||||
<td>
|
<td>
|
||||||
<div class="label" ng-class="'label-'+motion.state.css_class">
|
<div class="label" ng-class="'label-'+motion.state.css_class">
|
||||||
{{ motion.state.name | translate }}
|
{{ motion.getStateName() }}
|
||||||
</div>
|
</div>
|
||||||
<td>
|
<td>
|
||||||
<div class="label" ng-class="'label-'+motion.recommendation.css_class">
|
<div class="label" ng-class="'label-'+motion.recommendation.css_class">
|
||||||
{{ motion.recommendation.recommendation_label | translate }}
|
{{ motion.getRecommendationName() }}
|
||||||
</div>
|
</div>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
@ -115,7 +115,19 @@
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="label" ng-class="'label-'+motion.state.css_class">
|
<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>
|
</div>
|
||||||
|
|
||||||
<!-- Recommendation -->
|
<!-- Recommendation -->
|
||||||
@ -142,7 +154,19 @@
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="label" ng-class="'label-'+motion.recommendation.css_class">
|
<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>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -407,9 +431,10 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="details" ng-if="isAllowedToSeeCommentField()">
|
<div class="details" ng-if="isAllowedToSeeCommentField()">
|
||||||
<h3>Motion Comments</h3>
|
<h3 translate>Comments</h3>
|
||||||
<div ng-repeat="field in commentsFields">
|
<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>
|
<h4>
|
||||||
{{ field.name }}
|
{{ field.name }}
|
||||||
<span ng-if="!field.public" class="label label-warning" translate>internal</span>
|
<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>
|
<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 style="padding: 5px;" ng-mouseover="motion.stateHover=true" ng-mouseleave="motion.stateHover=false">
|
||||||
<span class="label" ng-class="'label-'+motion.state.css_class">
|
<span class="label" ng-class="'label-'+motion.state.css_class">
|
||||||
{{ motion.state.name | translate }}
|
{{ motion.getStateName() }}
|
||||||
</span>
|
</span>
|
||||||
<span os-perms="motions.can_manage" ng-class="{'hiddenDiv': !motion.stateHover}" uib-dropdown>
|
<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>
|
<i class="fa fa-cog pointer" uib-dropdown-toggle id="state-dropdown{{ motion.id }}"></i>
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
<div id="sidebox">
|
<div id="sidebox">
|
||||||
<!-- State -->
|
<!-- State -->
|
||||||
<h3 translate>State</h3>
|
<h3 translate>State</h3>
|
||||||
{{ motion.state.name | translate }}
|
{{ motion.getStateName() }}
|
||||||
|
|
||||||
<!-- Submitters -->
|
<!-- Submitters -->
|
||||||
<h3 ng-if="motion.submitters.length > 0" translate>Submitters</h3>
|
<h3 ng-if="motion.submitters.length > 0" translate>Submitters</h3>
|
||||||
|
Loading…
Reference in New Issue
Block a user