Merge pull request #3781 from FinnStutzenstein/modified-final-version
New temporal field for editing the final version of a motion.
This commit is contained in:
commit
4b6936572f
@ -15,9 +15,13 @@ Motions:
|
|||||||
- New feature to customize workflows and states [#3772].
|
- New feature to customize workflows and states [#3772].
|
||||||
- New config options to show logos on the right side in PDF [#3768].
|
- New config options to show logos on the right side in PDF [#3768].
|
||||||
- New table of contents with page numbers and categories in PDF [#3766].
|
- New table of contents with page numbers and categories in PDF [#3766].
|
||||||
- Updated pdfMake to 0.1.37 [#3766].
|
- New teporal field "modified final version" where the final version can
|
||||||
|
be edited [#3781].
|
||||||
|
|
||||||
|
Core:
|
||||||
- Python 3.4 is not supported anymore [#3777].
|
- Python 3.4 is not supported anymore [#3777].
|
||||||
- Support Python 3.7.
|
- Support Python 3.7.
|
||||||
|
- Updated pdfMake to 0.1.37 [#3766].
|
||||||
|
|
||||||
|
|
||||||
Version 2.2 (2018-06-06)
|
Version 2.2 (2018-06-06)
|
||||||
|
@ -0,0 +1,20 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.10.8 on 2018-07-13 08:02
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('motions', '0008_auto_20180702_1128'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='motionversion',
|
||||||
|
name='modified_final_version',
|
||||||
|
field=models.TextField(blank=True, null=True),
|
||||||
|
),
|
||||||
|
]
|
@ -214,9 +214,10 @@ class Motion(RESTModelMixin, models.Model):
|
|||||||
* Else the given version is used.
|
* Else the given version is used.
|
||||||
|
|
||||||
To create and use a new version object, you have to set it via the
|
To create and use a new version object, you have to set it via the
|
||||||
use_version argument. You have to set the title, text/amendment_paragraphs and reason into
|
use_version argument. You have to set the title, text/amendment_paragraphs,
|
||||||
this version object before giving it to this save method. The properties
|
modified final version and reason into this version object before giving it
|
||||||
motion.title, motion.text, motion.amendment_paragraphs and motion.reason will be ignored.
|
to this save method. The properties motion.title, motion.text,
|
||||||
|
motion.amendment_paragraphs, motion.modified_final_version and motion.reason will be ignored.
|
||||||
|
|
||||||
text and amendment_paragraphs are mutually exclusive; if both are given,
|
text and amendment_paragraphs are mutually exclusive; if both are given,
|
||||||
amendment_paragraphs takes precedence.
|
amendment_paragraphs takes precedence.
|
||||||
@ -264,8 +265,8 @@ class Motion(RESTModelMixin, models.Model):
|
|||||||
return
|
return
|
||||||
elif use_version is None:
|
elif use_version is None:
|
||||||
use_version = self.get_last_version()
|
use_version = self.get_last_version()
|
||||||
# Save title, text, amendment paragraphs and reason into the version object.
|
# Save title, text, amendment paragraphs, modified final version and reason into the version object.
|
||||||
for attr in ['title', 'text', 'amendment_paragraphs', 'reason']:
|
for attr in ['title', 'text', 'amendment_paragraphs', 'modified_final_version', 'reason']:
|
||||||
_attr = '_%s' % attr
|
_attr = '_%s' % attr
|
||||||
data = getattr(self, _attr, None)
|
data = getattr(self, _attr, None)
|
||||||
if data is not None:
|
if data is not None:
|
||||||
@ -318,7 +319,8 @@ class Motion(RESTModelMixin, models.Model):
|
|||||||
"""
|
"""
|
||||||
Compare the version with the last version of the motion.
|
Compare the version with the last version of the motion.
|
||||||
|
|
||||||
Returns True if the version data (title, text, reason) is different,
|
Returns True if the version data (title, text, amendment_paragraphs,
|
||||||
|
modified_final_version, reason) is different,
|
||||||
else returns False.
|
else returns False.
|
||||||
"""
|
"""
|
||||||
if not self.versions.exists():
|
if not self.versions.exists():
|
||||||
@ -326,7 +328,7 @@ class Motion(RESTModelMixin, models.Model):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
last_version = self.get_last_version()
|
last_version = self.get_last_version()
|
||||||
for attr in ['title', 'text', 'amendment_paragraphs', 'reason']:
|
for attr in ['title', 'text', 'amendment_paragraphs', 'modified_final_version', 'reason']:
|
||||||
if getattr(last_version, attr) != getattr(version, attr):
|
if getattr(last_version, attr) != getattr(version, attr):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
@ -494,6 +496,32 @@ class Motion(RESTModelMixin, models.Model):
|
|||||||
Is saved in a MotionVersion object.
|
Is saved in a MotionVersion object.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
def get_modified_final_version(self):
|
||||||
|
"""
|
||||||
|
Get the modified_final_version of the motion.
|
||||||
|
|
||||||
|
Simular to get_title().
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
return self._modified_final_version
|
||||||
|
except AttributeError:
|
||||||
|
return self.get_active_version().modified_final_version
|
||||||
|
|
||||||
|
def set_modified_final_version(self, modified_final_version):
|
||||||
|
"""
|
||||||
|
Set the modified_final_version of the motion.
|
||||||
|
|
||||||
|
Simular to set_title().
|
||||||
|
"""
|
||||||
|
self._modified_final_version = modified_final_version
|
||||||
|
|
||||||
|
modified_final_version = property(get_modified_final_version, set_modified_final_version)
|
||||||
|
"""
|
||||||
|
The modified_final_version for the motion.
|
||||||
|
|
||||||
|
Is saved in a MotionVersion object.
|
||||||
|
"""
|
||||||
|
|
||||||
def get_reason(self):
|
def get_reason(self):
|
||||||
"""
|
"""
|
||||||
Get the reason of the motion.
|
Get the reason of the motion.
|
||||||
@ -525,8 +553,9 @@ class Motion(RESTModelMixin, models.Model):
|
|||||||
Return a version object, not saved in the database.
|
Return a version object, not saved in the database.
|
||||||
|
|
||||||
The version data of the new version object is populated with the data
|
The version data of the new version object is populated with the data
|
||||||
set via motion.title, motion.text, motion.amendment_paragraphs and motion.reason if these data are
|
set via motion.title, motion.text, motion.amendment_paragraphs,
|
||||||
not given as keyword arguments. If the data is not set in the motion
|
motion.modified_final_version and motion.reason if these data are not
|
||||||
|
given as keyword arguments. If the data is not set in the motion
|
||||||
attributes, it is populated with the data from the last version
|
attributes, it is populated with the data from the last version
|
||||||
object if such object exists.
|
object if such object exists.
|
||||||
"""
|
"""
|
||||||
@ -539,7 +568,7 @@ class Motion(RESTModelMixin, models.Model):
|
|||||||
last_version = self.get_last_version()
|
last_version = self.get_last_version()
|
||||||
else:
|
else:
|
||||||
last_version = None
|
last_version = None
|
||||||
for attr in ['title', 'text', 'amendment_paragraphs', 'reason']:
|
for attr in ['title', 'text', 'amendment_paragraphs', 'modified_final_version', 'reason']:
|
||||||
if attr in kwargs:
|
if attr in kwargs:
|
||||||
continue
|
continue
|
||||||
_attr = '_%s' % attr
|
_attr = '_%s' % attr
|
||||||
@ -840,6 +869,9 @@ class MotionVersion(RESTModelMixin, models.Model):
|
|||||||
amendment_paragraphs and text are mutually exclusive.
|
amendment_paragraphs and text are mutually exclusive.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
modified_final_version = models.TextField(null=True, blank=True)
|
||||||
|
"""A field to copy in the final version of the motion and edit it there."""
|
||||||
|
|
||||||
reason = models.TextField(null=True, blank=True)
|
reason = models.TextField(null=True, blank=True)
|
||||||
"""The reason for a motion."""
|
"""The reason for a motion."""
|
||||||
|
|
||||||
|
@ -317,6 +317,7 @@ class MotionVersionSerializer(ModelSerializer):
|
|||||||
'title',
|
'title',
|
||||||
'text',
|
'text',
|
||||||
'amendment_paragraphs',
|
'amendment_paragraphs',
|
||||||
|
'modified_final_version',
|
||||||
'reason',)
|
'reason',)
|
||||||
|
|
||||||
|
|
||||||
@ -369,6 +370,7 @@ class MotionSerializer(ModelSerializer):
|
|||||||
comments = MotionCommentsJSONSerializerField(required=False)
|
comments = MotionCommentsJSONSerializerField(required=False)
|
||||||
log_messages = MotionLogSerializer(many=True, read_only=True)
|
log_messages = MotionLogSerializer(many=True, read_only=True)
|
||||||
polls = MotionPollSerializer(many=True, read_only=True)
|
polls = MotionPollSerializer(many=True, read_only=True)
|
||||||
|
modified_final_version = CharField(allow_blank=True, required=False, write_only=True)
|
||||||
reason = CharField(allow_blank=True, required=False, write_only=True)
|
reason = CharField(allow_blank=True, required=False, write_only=True)
|
||||||
state_required_permission_to_see = SerializerMethodField()
|
state_required_permission_to_see = SerializerMethodField()
|
||||||
text = CharField(write_only=True, allow_blank=True)
|
text = CharField(write_only=True, allow_blank=True)
|
||||||
@ -392,6 +394,7 @@ class MotionSerializer(ModelSerializer):
|
|||||||
'title',
|
'title',
|
||||||
'text',
|
'text',
|
||||||
'amendment_paragraphs',
|
'amendment_paragraphs',
|
||||||
|
'modified_final_version',
|
||||||
'reason',
|
'reason',
|
||||||
'versions',
|
'versions',
|
||||||
'active_version',
|
'active_version',
|
||||||
@ -419,6 +422,9 @@ class MotionSerializer(ModelSerializer):
|
|||||||
if 'text'in data:
|
if 'text'in data:
|
||||||
data['text'] = validate_html(data['text'])
|
data['text'] = validate_html(data['text'])
|
||||||
|
|
||||||
|
if 'modified_final_version' in data:
|
||||||
|
data['modified_final_version'] = validate_html(data['modified_final_version'])
|
||||||
|
|
||||||
if 'reason' in data:
|
if 'reason' in data:
|
||||||
data['reason'] = validate_html(data['reason'])
|
data['reason'] = validate_html(data['reason'])
|
||||||
|
|
||||||
@ -451,6 +457,7 @@ class MotionSerializer(ModelSerializer):
|
|||||||
motion.title = validated_data['title']
|
motion.title = validated_data['title']
|
||||||
motion.text = validated_data['text']
|
motion.text = validated_data['text']
|
||||||
motion.amendment_paragraphs = validated_data.get('amendment_paragraphs')
|
motion.amendment_paragraphs = validated_data.get('amendment_paragraphs')
|
||||||
|
motion.modified_final_version = validated_data.get('modified_final_version', '')
|
||||||
motion.reason = validated_data.get('reason', '')
|
motion.reason = validated_data.get('reason', '')
|
||||||
motion.identifier = validated_data.get('identifier')
|
motion.identifier = validated_data.get('identifier')
|
||||||
motion.category = validated_data.get('category')
|
motion.category = validated_data.get('category')
|
||||||
@ -489,8 +496,8 @@ class MotionSerializer(ModelSerializer):
|
|||||||
else:
|
else:
|
||||||
version = motion.get_last_version()
|
version = motion.get_last_version()
|
||||||
|
|
||||||
# Title, text, reason.
|
# Title, text, reason, ...
|
||||||
for key in ('title', 'text', 'amendment_paragraphs', 'reason'):
|
for key in ('title', 'text', 'amendment_paragraphs', 'modified_final_version', 'reason'):
|
||||||
if key in validated_data.keys():
|
if key in validated_data.keys():
|
||||||
setattr(version, key, validated_data[key])
|
setattr(version, key, validated_data[key])
|
||||||
|
|
||||||
|
@ -322,7 +322,8 @@ angular.module('OpenSlidesApp.motions', [
|
|||||||
if (titleChange) {
|
if (titleChange) {
|
||||||
if (changeRecommendationMode === "changed") {
|
if (changeRecommendationMode === "changed") {
|
||||||
title = titleChange.text;
|
title = titleChange.text;
|
||||||
} else if (changeRecommendationMode === 'agreed' && !titleChange.rejected) {
|
} else if ((changeRecommendationMode === 'agreed' ||
|
||||||
|
changeRecommendationMode === 'modified_agreed') && !titleChange.rejected) {
|
||||||
title = titleChange.text;
|
title = titleChange.text;
|
||||||
} else {
|
} else {
|
||||||
title = this.getTitle();
|
title = this.getTitle();
|
||||||
@ -349,6 +350,12 @@ angular.module('OpenSlidesApp.motions', [
|
|||||||
|
|
||||||
return lineNumberingService.insertLineNumbers(html, lineLength, highlight, callback);
|
return lineNumberingService.insertLineNumbers(html, lineLength, highlight, callback);
|
||||||
},
|
},
|
||||||
|
getModifiedFinalVersionWithLineBreaks: function (versionId) {
|
||||||
|
var lineLength = Config.get('motions_line_length').value,
|
||||||
|
html = this.getVersion(versionId).modified_final_version;
|
||||||
|
|
||||||
|
return lineNumberingService.insertLineNumbers(html, lineLength);
|
||||||
|
},
|
||||||
getTextBetweenChanges: function (versionId, change1, change2, highlight) {
|
getTextBetweenChanges: function (versionId, change1, change2, highlight) {
|
||||||
var line_from = (change1 ? change1.line_to : 1),
|
var line_from = (change1 ? change1.line_to : 1),
|
||||||
line_to = (change2 ? change2.line_from : null);
|
line_to = (change2 ? change2.line_from : null);
|
||||||
@ -490,7 +497,7 @@ angular.module('OpenSlidesApp.motions', [
|
|||||||
},
|
},
|
||||||
getTextByMode: function(mode, versionId, highlight, lineBreaks) {
|
getTextByMode: function(mode, versionId, highlight, lineBreaks) {
|
||||||
/*
|
/*
|
||||||
* @param mode ['original', 'diff', 'changed', 'agreed']
|
* @param mode ['original', 'diff', 'changed', 'agreed', 'modified_agreed']
|
||||||
* @param versionId [if undefined, active_version will be used]
|
* @param versionId [if undefined, active_version will be used]
|
||||||
* @param highlight [the line number to highlight]
|
* @param highlight [the line number to highlight]
|
||||||
* @param lineBreaks [if line numbers / breaks should be included in the result]
|
* @param lineBreaks [if line numbers / breaks should be included in the result]
|
||||||
@ -547,6 +554,17 @@ angular.module('OpenSlidesApp.motions', [
|
|||||||
case 'agreed':
|
case 'agreed':
|
||||||
text = this.getTextWithAgreedChanges(versionId, highlight, lineBreaks);
|
text = this.getTextWithAgreedChanges(versionId, highlight, lineBreaks);
|
||||||
break;
|
break;
|
||||||
|
case 'modified_agreed':
|
||||||
|
text = this.getModifiedFinalVersion(versionId);
|
||||||
|
if (text) {
|
||||||
|
// Insert line numbers
|
||||||
|
var lineLength = Config.get('motions_line_length').value;
|
||||||
|
text = lineNumberingService.insertLineNumbers(text, lineLength);
|
||||||
|
} else {
|
||||||
|
// Use the agreed version as fallback
|
||||||
|
text = this.getTextByMode('agreed', versionId, highlight, lineBreaks);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return text;
|
return text;
|
||||||
},
|
},
|
||||||
@ -855,6 +873,17 @@ angular.module('OpenSlidesApp.motions', [
|
|||||||
setTextStrippingLineBreaks: function (text) {
|
setTextStrippingLineBreaks: function (text) {
|
||||||
this.text = lineNumberingService.stripLineNumbers(text);
|
this.text = lineNumberingService.stripLineNumbers(text);
|
||||||
},
|
},
|
||||||
|
setModifiedFinalVersionStrippingLineBreaks: function (html) {
|
||||||
|
this.modified_final_version = lineNumberingService.stripLineNumbers(html);
|
||||||
|
},
|
||||||
|
// Copies to final version to the modified_final_version field
|
||||||
|
copyModifiedFinalVersionStrippingLineBreaks: function () {
|
||||||
|
var finalVersion = this.getTextByMode('agreed');
|
||||||
|
this.setModifiedFinalVersionStrippingLineBreaks(finalVersion);
|
||||||
|
},
|
||||||
|
getModifiedFinalVersion: function (versionId) {
|
||||||
|
return this.getVersion(versionId).modified_final_version;
|
||||||
|
},
|
||||||
getReason: function (versionId) {
|
getReason: function (versionId) {
|
||||||
return this.getVersion(versionId).reason;
|
return this.getVersion(versionId).reason;
|
||||||
},
|
},
|
||||||
@ -1457,6 +1486,7 @@ angular.module('OpenSlidesApp.motions', [
|
|||||||
// Properties that are guaranteed to be constant
|
// Properties that are guaranteed to be constant
|
||||||
this._change_object = {
|
this._change_object = {
|
||||||
"type": "recommendation",
|
"type": "recommendation",
|
||||||
|
"other_description": recommendation.other_description,
|
||||||
"id": "recommendation-" + recommendation.id,
|
"id": "recommendation-" + recommendation.id,
|
||||||
"original": recommendation,
|
"original": recommendation,
|
||||||
"saveStatus": function () {
|
"saveStatus": function () {
|
||||||
|
@ -472,6 +472,54 @@ angular.module('OpenSlidesApp.motions.motionservices', ['OpenSlidesApp.motions',
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
obj.copyToModifiedFinalVersion = function (motion, version) {
|
||||||
|
if (!motion.isAllowed('update')) {
|
||||||
|
throw 'No permission to update motion';
|
||||||
|
}
|
||||||
|
|
||||||
|
motion.copyModifiedFinalVersionStrippingLineBreaks();
|
||||||
|
|
||||||
|
Motion.inject(motion);
|
||||||
|
// save change motion object on server
|
||||||
|
Motion.save(motion, {method: 'PATCH'}).then(null, function (error) {
|
||||||
|
// 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};
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
obj.deleteModifiedFinalVersion = function (motion, version) {
|
||||||
|
if (!motion.isAllowed('update')) {
|
||||||
|
throw 'No permission to update motion';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!motion.getModifiedFinalVersion(version)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
motion.modified_final_version = '';
|
||||||
|
|
||||||
|
Motion.inject(motion);
|
||||||
|
// save change motion object on server
|
||||||
|
Motion.save(motion, {method: 'PATCH'}).then(function (success) {
|
||||||
|
$scope.viewChangeRecommendations.mode = 'agreed';
|
||||||
|
}, function (error) {
|
||||||
|
// 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};
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
obj.newVersionIncludingChanges = function (motion, version) {
|
obj.newVersionIncludingChanges = function (motion, version) {
|
||||||
if (!motion.isAllowed('update')) {
|
if (!motion.isAllowed('update')) {
|
||||||
throw 'No permission to update motion';
|
throw 'No permission to update motion';
|
||||||
|
@ -252,7 +252,7 @@ angular.module('OpenSlidesApp.motions.pdf', ['OpenSlidesApp.core.pdf'])
|
|||||||
}
|
}
|
||||||
|
|
||||||
// summary of change recommendations (for motion diff version only)
|
// summary of change recommendations (for motion diff version only)
|
||||||
if (params.changeRecommendationMode === "diff" && motion.changeRecommendations.length) {
|
if (params.changeRecommendationMode === 'diff' && motion.changeRecommendations.length) {
|
||||||
var columnLineNumbers = [];
|
var columnLineNumbers = [];
|
||||||
var columnChangeType = [];
|
var columnChangeType = [];
|
||||||
angular.forEach(_.orderBy(motion.changeRecommendations, ['line_from']), function(change) {
|
angular.forEach(_.orderBy(motion.changeRecommendations, ['line_from']), function(change) {
|
||||||
|
@ -938,7 +938,7 @@ angular.module('OpenSlidesApp.motions.site', [
|
|||||||
{name: gettextCatalog.getString('Original version'), value: 'original'},
|
{name: gettextCatalog.getString('Original version'), value: 'original'},
|
||||||
{name: gettextCatalog.getString('Changed version'), value: 'changed'},
|
{name: gettextCatalog.getString('Changed version'), value: 'changed'},
|
||||||
{name: gettextCatalog.getString('Diff version'), value: 'diff'},
|
{name: gettextCatalog.getString('Diff version'), value: 'diff'},
|
||||||
{name: gettextCatalog.getString('Final version'), value: 'agreed'},
|
{name: gettextCatalog.getString('Final version'), value: 'modified_agreed'},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
hideExpression: "model.format !== 'pdf'",
|
hideExpression: "model.format !== 'pdf'",
|
||||||
@ -952,7 +952,7 @@ angular.module('OpenSlidesApp.motions.site', [
|
|||||||
{name: gettextCatalog.getString('Original version'), value: 'original'},
|
{name: gettextCatalog.getString('Original version'), value: 'original'},
|
||||||
{name: gettextCatalog.getString('Changed version'), value: 'changed'},
|
{name: gettextCatalog.getString('Changed version'), value: 'changed'},
|
||||||
{name: gettextCatalog.getString('Diff version'), value: 'diff', disabled: true},
|
{name: gettextCatalog.getString('Diff version'), value: 'diff', disabled: true},
|
||||||
{name: gettextCatalog.getString('Final version'), value: 'agreed'},
|
{name: gettextCatalog.getString('Final version'), value: 'modified_agreed'},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
hideExpression: "model.format === 'pdf'",
|
hideExpression: "model.format === 'pdf'",
|
||||||
@ -1078,6 +1078,11 @@ angular.module('OpenSlidesApp.motions.site', [
|
|||||||
},
|
},
|
||||||
includeComments: {},
|
includeComments: {},
|
||||||
});
|
});
|
||||||
|
// Always change the mode from agreed to modified_agreed. If a motion does not have a modified
|
||||||
|
// final version, the agreed will be taken.
|
||||||
|
if ($scope.params.changeRecommendationMode === 'agreed') {
|
||||||
|
$scope.params.changeRecommendationMode = 'modified_agreed';
|
||||||
|
}
|
||||||
$scope.motions = motions;
|
$scope.motions = motions;
|
||||||
$scope.singleMotion = singleMotion;
|
$scope.singleMotion = singleMotion;
|
||||||
|
|
||||||
@ -1614,10 +1619,16 @@ angular.module('OpenSlidesApp.motions.site', [
|
|||||||
label: 'Diff version'},
|
label: 'Diff version'},
|
||||||
{mode: 'agreed',
|
{mode: 'agreed',
|
||||||
label: 'Final version'},
|
label: 'Final version'},
|
||||||
|
{mode: 'modified_agreed',
|
||||||
|
label: 'Modified final version'},
|
||||||
];
|
];
|
||||||
var motionDefaultTextMode = Config.get('motions_recommendation_text_mode').value;
|
var motionDefaultRecommendationTextMode = Config.get('motions_recommendation_text_mode').value;
|
||||||
|
// Change to the modified final version, if exists
|
||||||
|
if (motionDefaultRecommendationTextMode === 'agreed' && motion.getModifiedFinalVersion()) {
|
||||||
|
motionDefaultRecommendationTextMode = 'modified_agreed';
|
||||||
|
}
|
||||||
$scope.projectionMode = _.find($scope.projectionModes, function (mode) {
|
$scope.projectionMode = _.find($scope.projectionModes, function (mode) {
|
||||||
return mode.mode == motionDefaultTextMode;
|
return mode.mode == motionDefaultRecommendationTextMode;
|
||||||
});
|
});
|
||||||
if (motion.isProjected().length) {
|
if (motion.isProjected().length) {
|
||||||
var modeMapping = motion.isProjectedWithMode();
|
var modeMapping = motion.isProjectedWithMode();
|
||||||
@ -1919,6 +1930,17 @@ angular.module('OpenSlidesApp.motions.site', [
|
|||||||
Config.get('motions_allow_disable_versioning').value);
|
Config.get('motions_allow_disable_versioning').value);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
$scope.modifiedFinalVersionInlineEditing = MotionInlineEditing.createInstance($scope, motion,
|
||||||
|
'view-modified-agreed-inline-editor', true, Editor.getOptions('inline'),
|
||||||
|
function (obj) {
|
||||||
|
return motion.getModifiedFinalVersionWithLineBreaks($scope.version);
|
||||||
|
},
|
||||||
|
function (obj) {
|
||||||
|
motion.setModifiedFinalVersionStrippingLineBreaks(obj.editor.getData());
|
||||||
|
motion.disable_versioning = (obj.trivialChange &&
|
||||||
|
Config.get('motions_allow_disable_versioning').value);
|
||||||
|
}
|
||||||
|
);
|
||||||
// Wrapper functions for $scope.inlineEditing, to warn other users.
|
// Wrapper functions for $scope.inlineEditing, to warn other users.
|
||||||
var editingStoppedCallback;
|
var editingStoppedCallback;
|
||||||
$scope.enableMotionInlineEditing = function () {
|
$scope.enableMotionInlineEditing = function () {
|
||||||
@ -1978,7 +2000,7 @@ angular.module('OpenSlidesApp.motions.site', [
|
|||||||
|
|
||||||
// Change recommendation and amendment viewing
|
// Change recommendation and amendment viewing
|
||||||
$scope.viewChangeRecommendations = ChangeRecommendationView;
|
$scope.viewChangeRecommendations = ChangeRecommendationView;
|
||||||
$scope.viewChangeRecommendations.initSite($scope, motion, Config.get('motions_recommendation_text_mode').value);
|
$scope.viewChangeRecommendations.initSite($scope, motion, motionDefaultRecommendationTextMode);
|
||||||
|
|
||||||
// PDF creating functions
|
// PDF creating functions
|
||||||
$scope.pdfExport = function () {
|
$scope.pdfExport = function () {
|
||||||
@ -2083,6 +2105,7 @@ angular.module('OpenSlidesApp.motions.site', [
|
|||||||
function ($scope, MotionChangeRecommendation, ChangeRecommendationTextForm, diffService, change, ErrorMessage) {
|
function ($scope, MotionChangeRecommendation, ChangeRecommendationTextForm, diffService, change, ErrorMessage) {
|
||||||
$scope.alert = {};
|
$scope.alert = {};
|
||||||
$scope.model = angular.copy(change);
|
$scope.model = angular.copy(change);
|
||||||
|
$scope.model._change_object = undefined;
|
||||||
|
|
||||||
// get all form fields
|
// get all form fields
|
||||||
$scope.formFields = ChangeRecommendationTextForm.getFormFields(change.line_from, change.line_to);
|
$scope.formFields = ChangeRecommendationTextForm.getFormFields(change.line_from, change.line_to);
|
||||||
|
@ -555,6 +555,15 @@
|
|||||||
<div ng-bind-html="motion.getTextByMode('agreed', version, highlight) | trusted"
|
<div ng-bind-html="motion.getTextByMode('agreed', version, highlight) | trusted"
|
||||||
class="motion-text motion-text-changed line-numbers-{{ lineNumberMode }}"></div>
|
class="motion-text motion-text-changed line-numbers-{{ lineNumberMode }}"></div>
|
||||||
|
|
||||||
|
<div style="text-align: right;" ng-if="(change_recommendations | filter:{motion_version_id:version}:true).length > 0">
|
||||||
|
<button class="btn btn-default"
|
||||||
|
ng-bootbox-confirm="{{ 'Do you want to copy the final version to the modified final version field?' | translate }}"
|
||||||
|
ng-bootbox-confirm-action="viewChangeRecommendations.copyToModifiedFinalVersion(motion, version)">
|
||||||
|
<i class="fa fa-file-text"></i>
|
||||||
|
<translate>Copy to modified final version</translate>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div style="text-align: right;" ng-if="motion.state.versioning && (change_recommendations | filter:{motion_version_id:version}:true).length > 0">
|
<div style="text-align: right;" ng-if="motion.state.versioning && (change_recommendations | filter:{motion_version_id:version}:true).length > 0">
|
||||||
<button class="btn btn-default"
|
<button class="btn btn-default"
|
||||||
ng-bootbox-confirm="{{ 'Do you want to create a new version of this motion based on this changes?' | translate }}"
|
ng-bootbox-confirm="{{ 'Do you want to create a new version of this motion based on this changes?' | translate }}"
|
||||||
@ -564,6 +573,10 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- modified agreed view -->
|
||||||
|
<ng-include src="'static/templates/motions/motion-detail/view-modified-agreed.html'"></ng-include>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<div class="motion-toolbar">
|
<div class="motion-toolbar">
|
||||||
<!-- inline editing -->
|
<!-- inline editing for original mode -->
|
||||||
<div class="pull-right inline-editing-activator"
|
<div class="pull-right inline-editing-activator"
|
||||||
ng-if="motion.isAllowed('update') && version == motion.getVersion(-1).id && viewChangeRecommendations.mode == 'original'">
|
ng-if="motion.isAllowed('update') && version == motion.getVersion(-1).id && viewChangeRecommendations.mode == 'original'">
|
||||||
<button ng-if="!inlineEditing.active && !has_proposed_changes" ng-click="enableMotionInlineEditing()"
|
<button ng-if="!inlineEditing.active && !has_proposed_changes" ng-click="enableMotionInlineEditing()"
|
||||||
@ -19,6 +19,23 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- inline editing for modified agreed view -->
|
||||||
|
<div class="pull-right inline-editing-activator"
|
||||||
|
ng-if="motion.isAllowed('update') && version == motion.getVersion(-1).id && viewChangeRecommendations.mode == 'modified_agreed'">
|
||||||
|
<button ng-if="!modifiedFinalVersionInlineEditing.active"
|
||||||
|
ng-click="modifiedFinalVersionInlineEditing.enable()"
|
||||||
|
class="btn btn-sm btn-default">
|
||||||
|
<i class="fa fa-pencil-square-o"></i>
|
||||||
|
<translate>Inline editing</translate>
|
||||||
|
</button>
|
||||||
|
<button ng-if="modifiedFinalVersionInlineEditing.active"
|
||||||
|
ng-click="modifiedFinalVersionInlineEditing.disable()"
|
||||||
|
class="btn btn-sm btn-default">
|
||||||
|
<i class="fa fa-times-circle"></i>
|
||||||
|
<translate>Inline editing</translate>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="toolbar-left {{ lineNumberMode }}">
|
<div class="toolbar-left {{ lineNumberMode }}">
|
||||||
|
|
||||||
<ng-include src="'static/templates/motions/motion-detail/toolbar-line-numbering.html'"></ng-include>
|
<ng-include src="'static/templates/motions/motion-detail/toolbar-line-numbering.html'"></ng-include>
|
||||||
@ -86,6 +103,14 @@
|
|||||||
ng-checked="viewChangeRecommendations.mode == 'agreed'">
|
ng-checked="viewChangeRecommendations.mode == 'agreed'">
|
||||||
<translate>Final version</translate>
|
<translate>Final version</translate>
|
||||||
</label>
|
</label>
|
||||||
|
<label class="btn btn-sm btn-default" ng-if="motion.getModifiedFinalVersion()"
|
||||||
|
ng-class="{active: (viewChangeRecommendations.mode == 'modified_agreed')}"
|
||||||
|
ng-click="viewChangeRecommendations.mode = 'modified_agreed'">
|
||||||
|
<input type="radio" name="viewChangeRecommendations.mode" value="modified_agreed"
|
||||||
|
ng-model="viewChangeRecommendations.mode"
|
||||||
|
ng-checked="viewChangeRecommendations.mode == 'modified_agreed'">
|
||||||
|
<translate>Modified final version</translate>
|
||||||
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- change recommendations for resonsive size small/extra small (dropdown) -->
|
<!-- change recommendations for resonsive size small/extra small (dropdown) -->
|
||||||
|
@ -0,0 +1,28 @@
|
|||||||
|
<!-- Modified agreed view -->
|
||||||
|
<div ng-if="viewChangeRecommendations.mode == 'modified_agreed'">
|
||||||
|
<div id="view-modified-agreed-inline-editor" ng-bind-html="motion.getModifiedFinalVersionWithLineBreaks(version) | trusted"
|
||||||
|
class="motion-text motion-text-original line-numbers-{{ lineNumberMode }}"
|
||||||
|
contenteditable="{{ modifiedFinalVersionInlineEditing.isEditable }}">
|
||||||
|
</div>
|
||||||
|
<div style="text-align: right;">
|
||||||
|
<button class="btn btn-default btn-danger"
|
||||||
|
ng-bootbox-confirm="{{ 'Do you want to delete the modified final version?' | translate }}"
|
||||||
|
ng-bootbox-confirm-action="viewChangeRecommendations.deleteModifiedFinalVersion(motion, version)">
|
||||||
|
<i class="fa fa-trash"></i>
|
||||||
|
<translate>Delete modified final version</translate>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="motion-save-toolbar" ng-class="{ 'visible': modifiedFinalVersionInlineEditing.active && modifiedFinalVersionInlineEditing.changed }">
|
||||||
|
<div class="changed-hint" translate>The modified final version have been changed.</div>
|
||||||
|
<button type="button" ng-click="modifiedFinalVersionInlineEditing.save()" class="btn btn-primary" translate>
|
||||||
|
Save
|
||||||
|
</button>
|
||||||
|
<button type="button" ng-click="modifiedFinalVersionInlineEditing.revert()" class="btn btn-default" translate>
|
||||||
|
Revert
|
||||||
|
</button>
|
||||||
|
<label ng-if="motion.state.versioning && config('motions_allow_disable_versioning')">
|
||||||
|
<input type="checkbox" ng-model="modifiedFinalVersionInlineEditing.trivialChange" value="1">
|
||||||
|
<span translate>Trivial change</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
@ -140,6 +140,12 @@
|
|||||||
class="motion-text motion-text-changed line-numbers-{{ config('motions_default_line_numbering') }}"></div>
|
class="motion-text motion-text-changed line-numbers-{{ config('motions_default_line_numbering') }}"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Modified agreed View -->
|
||||||
|
<div ng-if="mode == 'modified_agreed'">
|
||||||
|
<div ng-bind-html="motion.getTextByMode('modified_agreed', null, line) | trusted"
|
||||||
|
class="motion-text motion-text-changed line-numbers-{{ config('motions_default_line_numbering') }}"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Reason -->
|
<!-- Reason -->
|
||||||
<div ng-if="motion.getReason() && !config('motions_disable_reason_on_projector')">
|
<div ng-if="motion.getReason() && !config('motions_disable_reason_on_projector')">
|
||||||
<h3 translate>Reason</h3>
|
<h3 translate>Reason</h3>
|
||||||
|
Loading…
Reference in New Issue
Block a user