Change recommendations for titles
This commit is contained in:
parent
d073cbbf6f
commit
9f8dce6e34
@ -21,6 +21,7 @@ Agenda:
|
|||||||
Motions:
|
Motions:
|
||||||
- New export dialog [#3185].
|
- New export dialog [#3185].
|
||||||
- New feature: Personal notes for motions [#3190, #3267, #3404].
|
- New feature: Personal notes for motions [#3190, #3267, #3404].
|
||||||
|
- New feature: Change recommendations for the title of a motion [#3626].
|
||||||
- Fixed issue when creating/deleting motion comment fields in the
|
- Fixed issue when creating/deleting motion comment fields in the
|
||||||
settings [#3187].
|
settings [#3187].
|
||||||
- Fixed empty motion comment field in motion update form [#3194].
|
- Fixed empty motion comment field in motion update form [#3194].
|
||||||
|
@ -280,8 +280,12 @@ class MotionChangeRecommendationSerializer(ModelSerializer):
|
|||||||
'text',
|
'text',
|
||||||
'creation_time',)
|
'creation_time',)
|
||||||
|
|
||||||
|
def is_title_cr(self, data):
|
||||||
|
return int(data['line_from']) == 0 and int(data['line_to']) == 0
|
||||||
|
|
||||||
def validate(self, data):
|
def validate(self, data):
|
||||||
if 'text' in data:
|
# Change recommendations for titles are stored as plain-text, thus they don't need to be html-escaped
|
||||||
|
if 'text' in data and not self.is_title_cr(data):
|
||||||
data['text'] = validate_html(data['text'])
|
data['text'] = validate_html(data['text'])
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
margin-bottom: 5px;
|
margin-bottom: 5px;
|
||||||
margin-top: -15px;
|
margin-top: -15px;
|
||||||
padding-top: 5px;
|
padding: 5px 5px 0 5px;
|
||||||
|
|
||||||
h3 {
|
h3 {
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
|
@ -106,16 +106,12 @@
|
|||||||
left: 20px;
|
left: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.line-numbers-outside .os-line-number.selectable:hover:before, .line-numbers-outside .os-line-number.selected:before {
|
@mixin addChangeRecommendationBtn {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
content: "\f067";
|
content: "\f067";
|
||||||
display: inline-block;
|
|
||||||
position: absolute;
|
|
||||||
width: 14px;
|
width: 14px;
|
||||||
height: 14px;
|
height: 14px;
|
||||||
border-radius: 0.25em;
|
border-radius: 0.25em;
|
||||||
top: 4px;
|
|
||||||
left: 43px;
|
|
||||||
font-family: FontAwesome;
|
font-family: FontAwesome;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: white;
|
color: white;
|
||||||
@ -124,6 +120,55 @@
|
|||||||
background-color: #337ab7;
|
background-color: #337ab7;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.line-numbers-outside .os-line-number.selectable:hover:before, .line-numbers-outside .os-line-number.selected:before {
|
||||||
|
position: absolute;
|
||||||
|
top: 4px;
|
||||||
|
left: 43px;
|
||||||
|
display: inline-block;
|
||||||
|
@include addChangeRecommendationBtn();
|
||||||
|
}
|
||||||
|
|
||||||
|
.motion-header {
|
||||||
|
.submenu {
|
||||||
|
position: relative;
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
.motion-title {
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
|
||||||
|
// Grab the left padding of the parent element to catch hover-events for the :before element
|
||||||
|
margin-left: -20px;
|
||||||
|
padding-left: 20px;
|
||||||
|
|
||||||
|
.change-title {
|
||||||
|
position: relative;
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
.change-title:before {
|
||||||
|
position: absolute;
|
||||||
|
top: 18px;
|
||||||
|
left: -17px;
|
||||||
|
@include addChangeRecommendationBtn();
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
&:hover .change-title.selectable:before {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
.title-change-indicator {
|
||||||
|
background-color: #0333ff;
|
||||||
|
position: absolute;
|
||||||
|
width: 4px;
|
||||||
|
height: 32px;
|
||||||
|
left: 10px;
|
||||||
|
top: 5px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
.tt_change_recommendation_create_help {
|
.tt_change_recommendation_create_help {
|
||||||
display: none;
|
display: none;
|
||||||
max-width: 150px;
|
max-width: 150px;
|
||||||
@ -190,6 +235,13 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.diff-box-title {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
.description {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.motion-text-with-diffs.line-numbers-inline .diff-box, .motion-text-with-diffs.line-numbers-none .diff-box {
|
.motion-text-with-diffs.line-numbers-inline .diff-box, .motion-text-with-diffs.line-numbers-none .diff-box {
|
||||||
margin-right: -220px;
|
margin-right: -220px;
|
||||||
}
|
}
|
||||||
|
@ -272,6 +272,22 @@ angular.module('OpenSlidesApp.motions', [
|
|||||||
title += this.getTitle();
|
title += this.getTitle();
|
||||||
return title;
|
return title;
|
||||||
},
|
},
|
||||||
|
getTitleWithChanges: function (changeRecommendationMode, versionId) {
|
||||||
|
var titleChange = this.getTitleChangeRecommendation(versionId);
|
||||||
|
var title;
|
||||||
|
if (titleChange) {
|
||||||
|
if (changeRecommendationMode === "changed") {
|
||||||
|
title = titleChange.text;
|
||||||
|
} else if (changeRecommendationMode === 'agreed' && !titleChange.rejected) {
|
||||||
|
title = titleChange.text;
|
||||||
|
} else {
|
||||||
|
title = this.getTitle();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
title = this.getTitle();
|
||||||
|
}
|
||||||
|
return title;
|
||||||
|
},
|
||||||
getSequentialNumber: function () {
|
getSequentialNumber: function () {
|
||||||
var id = this.id + '';
|
var id = this.id + '';
|
||||||
var zeros = Math.max(0, OpenSlidesSettings.MOTION_IDENTIFIER_MIN_DIGITS - id.length);
|
var zeros = Math.max(0, OpenSlidesSettings.MOTION_IDENTIFIER_MIN_DIGITS - id.length);
|
||||||
@ -359,7 +375,7 @@ angular.module('OpenSlidesApp.motions', [
|
|||||||
_getTextWithChangeRecommendations: function (versionId, highlight, lineBreaks, statusCompareCb) {
|
_getTextWithChangeRecommendations: function (versionId, highlight, lineBreaks, statusCompareCb) {
|
||||||
var lineLength = Config.get('motions_line_length').value,
|
var lineLength = Config.get('motions_line_length').value,
|
||||||
html = this.getVersion(versionId).text,
|
html = this.getVersion(versionId).text,
|
||||||
changes = this.getChangeRecommendations(versionId, 'DESC');
|
changes = this.getTextChangeRecommendations(versionId, 'DESC');
|
||||||
|
|
||||||
for (var i = 0; i < changes.length; i++) {
|
for (var i = 0; i < changes.length; i++) {
|
||||||
var change = changes[i];
|
var change = changes[i];
|
||||||
@ -405,7 +421,7 @@ angular.module('OpenSlidesApp.motions', [
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'diff':
|
case 'diff':
|
||||||
var changes = this.getChangeRecommendations(versionId, 'ASC');
|
var changes = this.getTextChangeRecommendations(versionId, 'ASC');
|
||||||
text = '';
|
text = '';
|
||||||
for (var i = 0; i < changes.length; i++) {
|
for (var i = 0; i < changes.length; i++) {
|
||||||
text += this.getTextBetweenChangeRecommendations(versionId, (i === 0 ? null : changes[i - 1]), changes[i], highlight);
|
text += this.getTextBetweenChangeRecommendations(versionId, (i === 0 ? null : changes[i - 1]), changes[i], highlight);
|
||||||
@ -500,7 +516,7 @@ angular.module('OpenSlidesApp.motions', [
|
|||||||
}
|
}
|
||||||
return foundSomething;
|
return foundSomething;
|
||||||
},
|
},
|
||||||
getChangeRecommendations: function (versionId, order) {
|
getTextChangeRecommendations: function (versionId, order) {
|
||||||
/*
|
/*
|
||||||
* Returns all change recommendations for this given version, sorted by line
|
* Returns all change recommendations for this given version, sorted by line
|
||||||
* @param versionId
|
* @param versionId
|
||||||
@ -516,8 +532,26 @@ angular.module('OpenSlidesApp.motions', [
|
|||||||
orderBy: [
|
orderBy: [
|
||||||
['line_from', order]
|
['line_from', order]
|
||||||
]
|
]
|
||||||
|
}).filter(function(change) {
|
||||||
|
return change.isTextRecommendation();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
getTitleChangeRecommendation: function (versionId) {
|
||||||
|
/**
|
||||||
|
* Returns the change recommendation affecting the title, or null
|
||||||
|
* @param versionId
|
||||||
|
* @returns MotionChangeRecommendation|null
|
||||||
|
*/
|
||||||
|
versionId = versionId || this.active_version;
|
||||||
|
var changes = MotionChangeRecommendation.filter({
|
||||||
|
where: {
|
||||||
|
motion_version_id: versionId,
|
||||||
|
line_from: 0,
|
||||||
|
line_to: 0
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return (changes.length > 0 ? changes[0] : null);
|
||||||
|
},
|
||||||
hasAmendments: function () {
|
hasAmendments: function () {
|
||||||
return DS.filter('motions/motion', {parent_id: this.id}).length > 0;
|
return DS.filter('motions/motion', {parent_id: this.id}).length > 0;
|
||||||
},
|
},
|
||||||
@ -861,6 +895,12 @@ angular.module('OpenSlidesApp.motions', [
|
|||||||
saveStatus: function() {
|
saveStatus: function() {
|
||||||
this.DSSave();
|
this.DSSave();
|
||||||
},
|
},
|
||||||
|
isTitleRecommendation: function() {
|
||||||
|
return (this.line_from === 0 && this.line_to === 0);
|
||||||
|
},
|
||||||
|
isTextRecommendation: function() {
|
||||||
|
return (this.line_from !== 0 || this.line_to !== 0);
|
||||||
|
},
|
||||||
getDiff: function(motion, version, highlight) {
|
getDiff: function(motion, version, highlight) {
|
||||||
var lineLength = Config.get('motions_line_length').value,
|
var lineLength = Config.get('motions_line_length').value,
|
||||||
html = lineNumberingService.insertLineNumbers(motion.getVersion(version).text, lineLength),
|
html = lineNumberingService.insertLineNumbers(motion.getVersion(version).text, lineLength),
|
||||||
|
@ -49,7 +49,7 @@ angular.module('OpenSlidesApp.motions.docx', ['OpenSlidesApp.core.docx'])
|
|||||||
|
|
||||||
// motions
|
// motions
|
||||||
data.tableofcontents_translation = gettextCatalog.getString('Table of contents');
|
data.tableofcontents_translation = gettextCatalog.getString('Table of contents');
|
||||||
data.motions_list = getMotionShortData(motions);
|
data.motions_list = getMotionShortData(motions, params);
|
||||||
data.no_motions = gettextCatalog.getString('No motions available.');
|
data.no_motions = gettextCatalog.getString('No motions available.');
|
||||||
|
|
||||||
return $q(function (resolve) {
|
return $q(function (resolve) {
|
||||||
@ -77,11 +77,11 @@ angular.module('OpenSlidesApp.motions.docx', ['OpenSlidesApp.core.docx'])
|
|||||||
return _.orderBy(categories, [sortKey]);
|
return _.orderBy(categories, [sortKey]);
|
||||||
};
|
};
|
||||||
|
|
||||||
var getMotionShortData = function (motions) {
|
var getMotionShortData = function (motions, params) {
|
||||||
return _.map(motions, function (motion) {
|
return _.map(motions, function (motion) {
|
||||||
return {
|
return {
|
||||||
identifier: motion.identifier || '',
|
identifier: motion.identifier || '',
|
||||||
title: motion.getTitle(),
|
title: motion.getTitleWithChanges(params.changeRecommendationMode),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -97,6 +97,7 @@ angular.module('OpenSlidesApp.motions.docx', ['OpenSlidesApp.core.docx'])
|
|||||||
var sequential_enabled = Config.get('motions_export_sequential_number').value;
|
var sequential_enabled = Config.get('motions_export_sequential_number').value;
|
||||||
// promises for create the actual motion data
|
// promises for create the actual motion data
|
||||||
var promises = _.map(motions, function (motion) {
|
var promises = _.map(motions, function (motion) {
|
||||||
|
var title = motion.getTitleWithChanges(params.changeRecommendationMode);
|
||||||
var text = params.include.text ? motion.getTextByMode(params.changeRecommendationMode, null, null, false) : '';
|
var text = params.include.text ? motion.getTextByMode(params.changeRecommendationMode, null, null, false) : '';
|
||||||
var reason = params.include.reason ? motion.getReason() : '';
|
var reason = params.include.reason ? motion.getReason() : '';
|
||||||
var comments = getMotionComments(motion, params.includeComments);
|
var comments = getMotionComments(motion, params.includeComments);
|
||||||
@ -114,7 +115,7 @@ angular.module('OpenSlidesApp.motions.docx', ['OpenSlidesApp.core.docx'])
|
|||||||
// Actual data
|
// Actual data
|
||||||
id: motion.id,
|
id: motion.id,
|
||||||
identifier: motion.identifier || '',
|
identifier: motion.identifier || '',
|
||||||
title: motion.getTitle(),
|
title: title,
|
||||||
submitters: params.include.submitters ? _.map(motion.submitters, function (submitter) {
|
submitters: params.include.submitters ? _.map(motion.submitters, function (submitter) {
|
||||||
return submitter.get_full_name();
|
return submitter.get_full_name();
|
||||||
}).join(', ') : '',
|
}).join(', ') : '',
|
||||||
|
@ -43,7 +43,7 @@ angular.module('OpenSlidesApp.motions.motionservices', ['OpenSlidesApp.motions',
|
|||||||
obj.editor = CKEDITOR.inline(selector, ckeditorOptions);
|
obj.editor = CKEDITOR.inline(selector, ckeditorOptions);
|
||||||
obj.editor.on('change', function () {
|
obj.editor.on('change', function () {
|
||||||
$timeout(function() {
|
$timeout(function() {
|
||||||
if (obj.editor.getData() != obj.originalHtml) {
|
if (obj.editor.getData() !== obj.originalHtml) {
|
||||||
obj.changed = true;
|
obj.changed = true;
|
||||||
} else {
|
} else {
|
||||||
obj.changed = false;
|
obj.changed = false;
|
||||||
@ -183,11 +183,14 @@ angular.module('OpenSlidesApp.motions.motionservices', ['OpenSlidesApp.motions',
|
|||||||
|
|
||||||
.factory('ChangeRecommendationCreate', [
|
.factory('ChangeRecommendationCreate', [
|
||||||
'ngDialog',
|
'ngDialog',
|
||||||
'ChangeRecommendationForm',
|
'ChangeRecommendationTitleForm',
|
||||||
function(ngDialog, ChangeRecommendationForm) {
|
'ChangeRecommendationTextForm',
|
||||||
|
function(ngDialog, ChangeRecommendationTitleForm, ChangeRecommendationTextForm) {
|
||||||
var MODE_INACTIVE = 0,
|
var MODE_INACTIVE = 0,
|
||||||
MODE_SELECTING_FROM = 1,
|
MODE_SELECTING_FROM = 1,
|
||||||
MODE_SELECTING_TO = 2;
|
MODE_SELECTING_TO = 2,
|
||||||
|
|
||||||
|
TITLE_DUMMY_LINE_NUMBER = 0;
|
||||||
|
|
||||||
var obj = {
|
var obj = {
|
||||||
mode: MODE_INACTIVE,
|
mode: MODE_INACTIVE,
|
||||||
@ -200,7 +203,7 @@ angular.module('OpenSlidesApp.motions.motionservices', ['OpenSlidesApp.motions',
|
|||||||
var $scope, motion, version;
|
var $scope, motion, version;
|
||||||
|
|
||||||
obj._getAffectedLineNumbers = function () {
|
obj._getAffectedLineNumbers = function () {
|
||||||
var changeRecommendations = motion.getChangeRecommendations(version),
|
var changeRecommendations = motion.getTextChangeRecommendations(version.id),
|
||||||
affectedLines = [];
|
affectedLines = [];
|
||||||
for (var i = 0; i < changeRecommendations.length; i++) {
|
for (var i = 0; i < changeRecommendations.length; i++) {
|
||||||
var change = changeRecommendations[i];
|
var change = changeRecommendations[i];
|
||||||
@ -211,23 +214,29 @@ angular.module('OpenSlidesApp.motions.motionservices', ['OpenSlidesApp.motions',
|
|||||||
return affectedLines;
|
return affectedLines;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// startCreating is called right at the beginning after the users interacts with the text for the first time.
|
||||||
|
// This ensures all necessary nodes have been initialized
|
||||||
obj.startCreating = function () {
|
obj.startCreating = function () {
|
||||||
if (obj.mode > MODE_SELECTING_FROM || !motion.isAllowed('can_manage')) {
|
if (obj.mode > MODE_SELECTING_FROM || !motion.isAllowed('can_manage')) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$(".tt_change_recommendation_create_help").removeClass("opened");
|
$(".tt_change_recommendation_create_help").removeClass("opened");
|
||||||
var $lineNumbers = $(".motion-text-original .os-line-number");
|
var $lineNumbers = $(".motion-text-original .os-line-number"),
|
||||||
|
$title = $(".motion-title .change-title");
|
||||||
if ($lineNumbers.filter(".selectable").length === 0) {
|
if ($lineNumbers.filter(".selectable").length === 0) {
|
||||||
obj.mode = MODE_SELECTING_FROM;
|
obj.mode = MODE_SELECTING_FROM;
|
||||||
var alreadyAffectedLines = obj._getAffectedLineNumbers();
|
var alreadyAffectedLines = obj._getAffectedLineNumbers();
|
||||||
$lineNumbers.each(function () {
|
$lineNumbers.each(function () {
|
||||||
var $this = $(this),
|
var $this = $(this),
|
||||||
lineNumber = $this.data("line-number");
|
lineNumber = $this.data("line-number");
|
||||||
if (alreadyAffectedLines.indexOf(lineNumber) == -1) {
|
if (alreadyAffectedLines.indexOf(lineNumber) === -1) {
|
||||||
$(this).addClass("selectable");
|
$(this).addClass("selectable");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
if (alreadyAffectedLines.indexOf(TITLE_DUMMY_LINE_NUMBER) === -1) {
|
||||||
|
$title.addClass("selectable");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -253,7 +262,7 @@ angular.module('OpenSlidesApp.motions.motionservices', ['OpenSlidesApp.motions',
|
|||||||
$(".motion-text-original .os-line-number").each(function () {
|
$(".motion-text-original .os-line-number").each(function () {
|
||||||
var $this = $(this);
|
var $this = $(this);
|
||||||
if ($this.data("line-number") >= line && !foundCollission) {
|
if ($this.data("line-number") >= line && !foundCollission) {
|
||||||
if (alreadyAffectedLines.indexOf($this.data("line-number")) == -1) {
|
if (alreadyAffectedLines.indexOf($this.data("line-number")) === -1) {
|
||||||
$(this).addClass("selectable");
|
$(this).addClass("selectable");
|
||||||
} else {
|
} else {
|
||||||
$(this).removeClass("selectable");
|
$(this).removeClass("selectable");
|
||||||
@ -268,18 +277,22 @@ angular.module('OpenSlidesApp.motions.motionservices', ['OpenSlidesApp.motions',
|
|||||||
$(".tt_change_recommendation_create_help").css("top", tt_pos).addClass("opened");
|
$(".tt_change_recommendation_create_help").css("top", tt_pos).addClass("opened");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
obj.titleClicked = function () {
|
||||||
|
ngDialog.open(ChangeRecommendationTitleForm.getCreateDialog(motion, version));
|
||||||
|
|
||||||
|
obj.mode = MODE_INACTIVE;
|
||||||
|
obj.lineFrom = 0;
|
||||||
|
obj.lineTo = 0;
|
||||||
|
$(".motion-text-original .os-line-number").removeClass("selected selectable");
|
||||||
|
obj.startCreating();
|
||||||
|
};
|
||||||
|
|
||||||
obj.setToLine = function (line) {
|
obj.setToLine = function (line) {
|
||||||
if (line < obj.lineFrom) {
|
if (line < obj.lineFrom) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
obj.mode = MODE_INACTIVE;
|
obj.mode = MODE_INACTIVE;
|
||||||
obj.lineTo = line + 1;
|
ngDialog.open(ChangeRecommendationTextForm.getCreateDialog(motion, version, obj.lineFrom, line + 1));
|
||||||
ngDialog.open(ChangeRecommendationForm.getCreateDialog(
|
|
||||||
motion,
|
|
||||||
version,
|
|
||||||
obj.lineFrom,
|
|
||||||
obj.lineTo
|
|
||||||
));
|
|
||||||
|
|
||||||
obj.lineFrom = 0;
|
obj.lineFrom = 0;
|
||||||
obj.lineTo = 0;
|
obj.lineTo = 0;
|
||||||
@ -288,19 +301,19 @@ angular.module('OpenSlidesApp.motions.motionservices', ['OpenSlidesApp.motions',
|
|||||||
};
|
};
|
||||||
|
|
||||||
obj.lineClicked = function (ev) {
|
obj.lineClicked = function (ev) {
|
||||||
if (obj.mode == MODE_INACTIVE) {
|
if (obj.mode === MODE_INACTIVE) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (obj.mode == MODE_SELECTING_FROM) {
|
if (obj.mode === MODE_SELECTING_FROM) {
|
||||||
obj.setFromLine($(ev.target).data("line-number"));
|
obj.setFromLine($(ev.target).data("line-number"));
|
||||||
$(ev.target).addClass("selected");
|
$(ev.target).addClass("selected");
|
||||||
} else if (obj.mode == MODE_SELECTING_TO) {
|
} else if (obj.mode === MODE_SELECTING_TO) {
|
||||||
obj.setToLine($(ev.target).data("line-number"));
|
obj.setToLine($(ev.target).data("line-number"));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
obj.mouseOver = function (ev) {
|
obj.mouseOver = function (ev) {
|
||||||
if (obj.mode != MODE_SELECTING_TO) {
|
if (obj.mode !== MODE_SELECTING_TO) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var hoverLine = $(ev.target).data("line-number");
|
var hoverLine = $(ev.target).data("line-number");
|
||||||
@ -316,31 +329,37 @@ angular.module('OpenSlidesApp.motions.motionservices', ['OpenSlidesApp.motions',
|
|||||||
|
|
||||||
obj.setVersion = function (_motion, _version) {
|
obj.setVersion = function (_motion, _version) {
|
||||||
motion = _motion;
|
motion = _motion;
|
||||||
version = _version;
|
version = motion.getVersion(_version);
|
||||||
};
|
};
|
||||||
|
|
||||||
obj.editDialog = function(change_recommendation) {
|
obj.editTextDialog = function(change_recommendation) {
|
||||||
ngDialog.open(ChangeRecommendationForm.getEditDialog(change_recommendation));
|
ngDialog.open(ChangeRecommendationTextForm.getEditDialog(change_recommendation));
|
||||||
|
};
|
||||||
|
|
||||||
|
obj.editTitleDialog = function(change_recommendation) {
|
||||||
|
ngDialog.open(ChangeRecommendationTitleForm.getEditDialog(change_recommendation));
|
||||||
};
|
};
|
||||||
|
|
||||||
obj.init = function (_scope, _motion) {
|
obj.init = function (_scope, _motion) {
|
||||||
$scope = _scope;
|
$scope = _scope;
|
||||||
motion = _motion;
|
motion = _motion;
|
||||||
version = $scope.version;
|
version = motion.getVersion($scope.version);
|
||||||
|
|
||||||
var $content = $("#content");
|
var $content = $("#content");
|
||||||
$content.on("click", ".line-numbers-outside .os-line-number.selectable", obj.lineClicked);
|
$content.on("click", ".line-numbers-outside .os-line-number.selectable", obj.lineClicked);
|
||||||
|
$content.on("click", ".motion-title .change-title.selectable", obj.titleClicked);
|
||||||
$content.on("click", obj.cancelCreating);
|
$content.on("click", obj.cancelCreating);
|
||||||
$content.on("mouseover", ".line-numbers-outside .os-line-number.selectable", obj.mouseOver);
|
$content.on("mouseover", ".line-numbers-outside .os-line-number.selectable", obj.mouseOver);
|
||||||
$content.on("mouseover", ".motion-text-original", obj.startCreating);
|
$content.on("mouseover", ".motion-text-original, .motion-title", obj.startCreating);
|
||||||
|
|
||||||
$scope.$watch(function () {
|
$scope.$watch(function () {
|
||||||
return $scope.change_recommendations.length;
|
return $scope.change_recommendations.length;
|
||||||
}, function () {
|
}, function () {
|
||||||
if (obj.mode == MODE_INACTIVE || obj.mode == MODE_SELECTING_FROM) {
|
if (obj.mode === MODE_INACTIVE || obj.mode === MODE_SELECTING_FROM) {
|
||||||
// Recalculate the affected lines so we cannot select lines affected by a recommendation
|
// Recalculate the affected lines so we cannot select lines affected by a recommendation
|
||||||
// that has just been created
|
// that has just been created
|
||||||
$(".motion-text-original .os-line-number").removeClass("selected selectable");
|
$(".motion-text-original .os-line-number").removeClass("selected selectable");
|
||||||
|
$(".motion-title .change-title").removeClass("selected selectable");
|
||||||
obj.startCreating();
|
obj.startCreating();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -353,9 +372,10 @@ angular.module('OpenSlidesApp.motions.motionservices', ['OpenSlidesApp.motions',
|
|||||||
obj.destroy = function () {
|
obj.destroy = function () {
|
||||||
var $content = $("#content");
|
var $content = $("#content");
|
||||||
$content.off("click", ".line-numbers-outside .os-line-number.selectable", obj.lineClicked);
|
$content.off("click", ".line-numbers-outside .os-line-number.selectable", obj.lineClicked);
|
||||||
|
$content.off("click", ".motion-title .change-title.selectable", obj.titleClicked);
|
||||||
$content.off("click", obj.cancelCreating);
|
$content.off("click", obj.cancelCreating);
|
||||||
$content.off("mouseover", ".line-numbers-outside .os-line-number.selectable", obj.mouseOver);
|
$content.off("mouseover", ".line-numbers-outside .os-line-number.selectable", obj.mouseOver);
|
||||||
$content.off("mouseover", ".motion-text-original", obj.startCreating);
|
$content.off("mouseover", ".motion-text-original, .motion-title", obj.startCreating);
|
||||||
};
|
};
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
|
@ -63,10 +63,8 @@ angular.module('OpenSlidesApp.motions.pdf', ['OpenSlidesApp.core.pdf'])
|
|||||||
|
|
||||||
// title
|
// title
|
||||||
var identifier = motion.identifier ? ' ' + motion.identifier : '';
|
var identifier = motion.identifier ? ' ' + motion.identifier : '';
|
||||||
var title = PDFLayout.createTitle(
|
var titlePlain = motion.getTitleWithChanges(params.changeRecommendationMode, motionVersion);
|
||||||
gettextCatalog.getString('Motion') + identifier + ': ' +
|
var title = PDFLayout.createTitle(gettextCatalog.getString('Motion') + identifier + ': ' + titlePlain);
|
||||||
motion.getTitle(motionVersion)
|
|
||||||
);
|
|
||||||
|
|
||||||
// subtitle and sequential number
|
// subtitle and sequential number
|
||||||
var subtitleLines = [];
|
var subtitleLines = [];
|
||||||
@ -251,10 +249,15 @@ 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) {
|
||||||
|
if (change.isTitleRecommendation()) {
|
||||||
|
columnLineNumbers.push(
|
||||||
|
gettextCatalog.getString('Title') + ': '
|
||||||
|
);
|
||||||
|
} else {
|
||||||
// line numbers column
|
// line numbers column
|
||||||
var line;
|
var line;
|
||||||
if (change.line_from >= change.line_to - 1) {
|
if (change.line_from >= change.line_to - 1) {
|
||||||
@ -265,6 +268,7 @@ angular.module('OpenSlidesApp.motions.pdf', ['OpenSlidesApp.core.pdf'])
|
|||||||
columnLineNumbers.push(
|
columnLineNumbers.push(
|
||||||
gettextCatalog.getString('Line') + ' ' + line + ': '
|
gettextCatalog.getString('Line') + ' ' + line + ': '
|
||||||
);
|
);
|
||||||
|
}
|
||||||
// change type column
|
// change type column
|
||||||
if (change.getType(motion.getVersion(motionVersion).text) === 0) {
|
if (change.getType(motion.getVersion(motionVersion).text) === 0) {
|
||||||
columnChangeType.push(gettextCatalog.getString("Replacement"));
|
columnChangeType.push(gettextCatalog.getString("Replacement"));
|
||||||
@ -322,7 +326,7 @@ angular.module('OpenSlidesApp.motions.pdf', ['OpenSlidesApp.core.pdf'])
|
|||||||
var motionTitle = function() {
|
var motionTitle = function() {
|
||||||
if (params.include.text) {
|
if (params.include.text) {
|
||||||
return [{
|
return [{
|
||||||
text: motion.getTitle(motionVersion),
|
text: titlePlain,
|
||||||
style: 'heading3'
|
style: 'heading3'
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
@ -338,10 +342,20 @@ angular.module('OpenSlidesApp.motions.pdf', ['OpenSlidesApp.core.pdf'])
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var escapeHtml = function(text) {
|
||||||
|
return text.replace(/&/, "&").replace(/</, "<").replace(/>/, ">");
|
||||||
|
};
|
||||||
|
|
||||||
// motion text (with line-numbers)
|
// motion text (with line-numbers)
|
||||||
var motionText = function() {
|
var motionText = function() {
|
||||||
if (params.include.text) {
|
if (params.include.text) {
|
||||||
var motionTextContent = motion.getTextByMode(params.changeRecommendationMode, motionVersion);
|
var motionTextContent = '';
|
||||||
|
var titleChange = motion.getTitleChangeRecommendation();
|
||||||
|
if (params.changeRecommendationMode === 'diff' && titleChange) {
|
||||||
|
motionTextContent += '<p><strong>' + gettextCatalog.getString('New title') + ':</strong> ' +
|
||||||
|
escapeHtml(titleChange.text) + '</p>';
|
||||||
|
}
|
||||||
|
motionTextContent += motion.getTextByMode(params.changeRecommendationMode, motionVersion);
|
||||||
return converter.convertHTML(motionTextContent, params.lineNumberMode);
|
return converter.convertHTML(motionTextContent, params.lineNumberMode);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -159,17 +159,88 @@ angular.module('OpenSlidesApp.motions.site', [
|
|||||||
}
|
}
|
||||||
])
|
])
|
||||||
|
|
||||||
.factory('ChangeRecommendationForm', [
|
.factory('ChangeRecommendationTitleForm', [
|
||||||
'gettextCatalog',
|
'gettextCatalog',
|
||||||
'Editor',
|
'Editor',
|
||||||
'Config',
|
'Config',
|
||||||
function(gettextCatalog, Editor, Config) {
|
function(gettextCatalog) {
|
||||||
|
return {
|
||||||
|
// ngDialog for motion form
|
||||||
|
getCreateDialog: function (motion, version) {
|
||||||
|
return {
|
||||||
|
template: 'static/templates/motions/change-recommendation-form.html',
|
||||||
|
controller: 'ChangeRecommendationTitleCreateCtrl',
|
||||||
|
className: 'ngdialog-theme-default wide-form',
|
||||||
|
closeByEscape: false,
|
||||||
|
closeByDocument: false,
|
||||||
|
resolve: {
|
||||||
|
motion: function() {
|
||||||
|
return motion;
|
||||||
|
},
|
||||||
|
version: function() {
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
getEditDialog: function(change) {
|
||||||
|
return {
|
||||||
|
template: 'static/templates/motions/change-recommendation-form.html',
|
||||||
|
controller: 'ChangeRecommendationTitleUpdateCtrl',
|
||||||
|
className: 'ngdialog-theme-default wide-form',
|
||||||
|
closeByEscape: false,
|
||||||
|
closeByDocument: false,
|
||||||
|
resolve: {
|
||||||
|
change: function() {
|
||||||
|
return change;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
// angular-formly fields for motion form
|
||||||
|
getFormFields: function () {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
key: 'identifier',
|
||||||
|
type: 'input',
|
||||||
|
templateOptions: {
|
||||||
|
label: gettextCatalog.getString('Identifier')
|
||||||
|
},
|
||||||
|
hide: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'motion_version_id',
|
||||||
|
type: 'input',
|
||||||
|
templateOptions: {
|
||||||
|
label: gettextCatalog.getString('Motion')
|
||||||
|
},
|
||||||
|
hide: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'text',
|
||||||
|
type: 'input',
|
||||||
|
templateOptions: {
|
||||||
|
label: gettextCatalog.getString('New title'),
|
||||||
|
required: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
.factory('ChangeRecommendationTextForm', [
|
||||||
|
'gettextCatalog',
|
||||||
|
'Editor',
|
||||||
|
'Config',
|
||||||
|
function(gettextCatalog, Editor) {
|
||||||
return {
|
return {
|
||||||
// ngDialog for motion form
|
// ngDialog for motion form
|
||||||
getCreateDialog: function (motion, version, lineFrom, lineTo) {
|
getCreateDialog: function (motion, version, lineFrom, lineTo) {
|
||||||
return {
|
return {
|
||||||
template: 'static/templates/motions/change-recommendation-form.html',
|
template: 'static/templates/motions/change-recommendation-form.html',
|
||||||
controller: 'ChangeRecommendationCreateCtrl',
|
controller: 'ChangeRecommendationTextCreateCtrl',
|
||||||
className: 'ngdialog-theme-default wide-form',
|
className: 'ngdialog-theme-default wide-form',
|
||||||
closeByEscape: false,
|
closeByEscape: false,
|
||||||
closeByDocument: false,
|
closeByDocument: false,
|
||||||
@ -192,7 +263,7 @@ angular.module('OpenSlidesApp.motions.site', [
|
|||||||
getEditDialog: function(change) {
|
getEditDialog: function(change) {
|
||||||
return {
|
return {
|
||||||
template: 'static/templates/motions/change-recommendation-form.html',
|
template: 'static/templates/motions/change-recommendation-form.html',
|
||||||
controller: 'ChangeRecommendationUpdateCtrl',
|
controller: 'ChangeRecommendationTextUpdateCtrl',
|
||||||
className: 'ngdialog-theme-default wide-form',
|
className: 'ngdialog-theme-default wide-form',
|
||||||
closeByEscape: false,
|
closeByEscape: false,
|
||||||
closeByDocument: false,
|
closeByDocument: false,
|
||||||
@ -1362,9 +1433,19 @@ angular.module('OpenSlidesApp.motions.site', [
|
|||||||
$scope.$watch(function () {
|
$scope.$watch(function () {
|
||||||
return MotionChangeRecommendation.lastModified();
|
return MotionChangeRecommendation.lastModified();
|
||||||
}, function () {
|
}, function () {
|
||||||
$scope.change_recommendations = MotionChangeRecommendation.filter({
|
$scope.change_recommendations = [];
|
||||||
|
$scope.title_change_recommendation = null;
|
||||||
|
MotionChangeRecommendation.filter({
|
||||||
'where': {'motion_version_id': {'==': motion.active_version}}
|
'where': {'motion_version_id': {'==': motion.active_version}}
|
||||||
|
}).forEach(function(change) {
|
||||||
|
if (change.isTextRecommendation()) {
|
||||||
|
$scope.change_recommendations.push(change);
|
||||||
|
}
|
||||||
|
if (change.isTitleRecommendation()) {
|
||||||
|
$scope.title_change_recommendation = change;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if ($scope.change_recommendations.length === 0) {
|
if ($scope.change_recommendations.length === 0) {
|
||||||
$scope.setProjectionMode($scope.projectionModes[0]);
|
$scope.setProjectionMode($scope.projectionModes[0]);
|
||||||
}
|
}
|
||||||
@ -1399,6 +1480,8 @@ angular.module('OpenSlidesApp.motions.site', [
|
|||||||
}
|
}
|
||||||
webpageTitle += $scope.motion.getTitle();
|
webpageTitle += $scope.motion.getTitle();
|
||||||
WebpageTitle.updateTitle(webpageTitle);
|
WebpageTitle.updateTitle(webpageTitle);
|
||||||
|
|
||||||
|
$scope.createChangeRecommendation.setVersion(motion, motion.active_version);
|
||||||
});
|
});
|
||||||
$scope.projectionModes = [
|
$scope.projectionModes = [
|
||||||
{mode: 'original',
|
{mode: 'original',
|
||||||
@ -1783,27 +1866,26 @@ angular.module('OpenSlidesApp.motions.site', [
|
|||||||
}
|
}
|
||||||
])
|
])
|
||||||
|
|
||||||
.controller('ChangeRecommendationUpdateCtrl', [
|
.controller('ChangeRecommendationTitleUpdateCtrl', [
|
||||||
'$scope',
|
'$scope',
|
||||||
'MotionChangeRecommendation',
|
'MotionChangeRecommendation',
|
||||||
'ChangeRecommendationForm',
|
'ChangeRecommendationTitleForm',
|
||||||
'diffService',
|
'diffService',
|
||||||
'change',
|
'change',
|
||||||
'ErrorMessage',
|
'ErrorMessage',
|
||||||
function ($scope, MotionChangeRecommendation, ChangeRecommendationForm, diffService, change, ErrorMessage) {
|
function ($scope, MotionChangeRecommendation, ChangeRecommendationTitleForm, diffService, change, ErrorMessage) {
|
||||||
$scope.alert = {};
|
$scope.alert = {};
|
||||||
$scope.model = angular.copy(change);
|
$scope.model = angular.copy(change);
|
||||||
|
|
||||||
// get all form fields
|
// get all form fields
|
||||||
$scope.formFields = ChangeRecommendationForm.getFormFields(change.line_from, change.line_to);
|
$scope.formFields = ChangeRecommendationTitleForm.getFormFields();
|
||||||
// save motion
|
// save motion
|
||||||
$scope.save = function (change) {
|
$scope.save = function (change) {
|
||||||
change.text = diffService.removeDuplicateClassesInsertedByCkeditor(change.text);
|
|
||||||
// inject the changed change recommendation (copy) object back into DS store
|
// inject the changed change recommendation (copy) object back into DS store
|
||||||
MotionChangeRecommendation.inject(change);
|
MotionChangeRecommendation.inject(change);
|
||||||
// save changed change recommendation object on server
|
// save changed change recommendation object on server
|
||||||
MotionChangeRecommendation.save(change).then(
|
MotionChangeRecommendation.save(change).then(
|
||||||
function(success) {
|
function() {
|
||||||
$scope.closeThisDialog();
|
$scope.closeThisDialog();
|
||||||
},
|
},
|
||||||
function (error) {
|
function (error) {
|
||||||
@ -1815,22 +1897,87 @@ angular.module('OpenSlidesApp.motions.site', [
|
|||||||
}
|
}
|
||||||
])
|
])
|
||||||
|
|
||||||
.controller('ChangeRecommendationCreateCtrl', [
|
.controller('ChangeRecommendationTitleCreateCtrl', [
|
||||||
'$scope',
|
'$scope',
|
||||||
'Motion',
|
'Motion',
|
||||||
'MotionChangeRecommendation',
|
'MotionChangeRecommendation',
|
||||||
'ChangeRecommendationForm',
|
'ChangeRecommendationTitleForm',
|
||||||
|
'Config',
|
||||||
|
'diffService',
|
||||||
|
'motion',
|
||||||
|
'version',
|
||||||
|
function($scope, Motion, MotionChangeRecommendation, ChangeRecommendationTitleForm, Config, diffService, motion,
|
||||||
|
version) {
|
||||||
|
$scope.alert = {};
|
||||||
|
|
||||||
|
$scope.model = {
|
||||||
|
text: version.title,
|
||||||
|
motion_version_id: version.id
|
||||||
|
};
|
||||||
|
|
||||||
|
// get all form fields
|
||||||
|
$scope.formFields = ChangeRecommendationTitleForm.getFormFields();
|
||||||
|
// save motion
|
||||||
|
$scope.save = function (change) {
|
||||||
|
change.line_from = 0;
|
||||||
|
change.line_to = 0;
|
||||||
|
MotionChangeRecommendation.create(change).then(
|
||||||
|
function() {
|
||||||
|
$scope.closeThisDialog();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
.controller('ChangeRecommendationTextUpdateCtrl', [
|
||||||
|
'$scope',
|
||||||
|
'MotionChangeRecommendation',
|
||||||
|
'ChangeRecommendationTextForm',
|
||||||
|
'diffService',
|
||||||
|
'change',
|
||||||
|
'ErrorMessage',
|
||||||
|
function ($scope, MotionChangeRecommendation, ChangeRecommendationTextForm, diffService, change, ErrorMessage) {
|
||||||
|
$scope.alert = {};
|
||||||
|
$scope.model = angular.copy(change);
|
||||||
|
|
||||||
|
// get all form fields
|
||||||
|
$scope.formFields = ChangeRecommendationTextForm.getFormFields(change.line_from, change.line_to);
|
||||||
|
// save motion
|
||||||
|
$scope.save = function (change) {
|
||||||
|
change.text = diffService.removeDuplicateClassesInsertedByCkeditor(change.text);
|
||||||
|
// inject the changed change recommendation (copy) object back into DS store
|
||||||
|
MotionChangeRecommendation.inject(change);
|
||||||
|
// save changed change recommendation object on server
|
||||||
|
MotionChangeRecommendation.save(change).then(
|
||||||
|
function() {
|
||||||
|
$scope.closeThisDialog();
|
||||||
|
},
|
||||||
|
function (error) {
|
||||||
|
MotionChangeRecommendation.refresh(change);
|
||||||
|
$scope.alert = ErrorMessage.forAlert(error);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
.controller('ChangeRecommendationTextCreateCtrl', [
|
||||||
|
'$scope',
|
||||||
|
'Motion',
|
||||||
|
'MotionChangeRecommendation',
|
||||||
|
'ChangeRecommendationTextForm',
|
||||||
'Config',
|
'Config',
|
||||||
'diffService',
|
'diffService',
|
||||||
'motion',
|
'motion',
|
||||||
'version',
|
'version',
|
||||||
'lineFrom',
|
'lineFrom',
|
||||||
'lineTo',
|
'lineTo',
|
||||||
function($scope, Motion, MotionChangeRecommendation, ChangeRecommendationForm, Config, diffService, motion,
|
function($scope, Motion, MotionChangeRecommendation, ChangeRecommendationTextForm, Config, diffService, motion,
|
||||||
version, lineFrom, lineTo) {
|
version, lineFrom, lineTo) {
|
||||||
$scope.alert = {};
|
$scope.alert = {};
|
||||||
|
|
||||||
var html = motion.getTextWithLineBreaks(version),
|
var html = motion.getTextWithLineBreaks(version.id),
|
||||||
lineData = diffService.extractRangeByLineNumbers(html, lineFrom, lineTo);
|
lineData = diffService.extractRangeByLineNumbers(html, lineFrom, lineTo);
|
||||||
|
|
||||||
$scope.model = {
|
$scope.model = {
|
||||||
@ -1838,17 +1985,17 @@ angular.module('OpenSlidesApp.motions.site', [
|
|||||||
lineData.html + lineData.innerContextEnd + lineData.outerContextEnd,
|
lineData.html + lineData.innerContextEnd + lineData.outerContextEnd,
|
||||||
line_from: lineFrom,
|
line_from: lineFrom,
|
||||||
line_to: lineTo,
|
line_to: lineTo,
|
||||||
motion_version_id: version,
|
motion_version_id: version.id,
|
||||||
type: 0
|
type: 0
|
||||||
};
|
};
|
||||||
|
|
||||||
// get all form fields
|
// get all form fields
|
||||||
$scope.formFields = ChangeRecommendationForm.getFormFields(lineFrom, lineTo);
|
$scope.formFields = ChangeRecommendationTextForm.getFormFields(lineFrom, lineTo);
|
||||||
// save motion
|
// save motion
|
||||||
$scope.save = function (motion) {
|
$scope.save = function (motion) {
|
||||||
motion.text = diffService.removeDuplicateClassesInsertedByCkeditor(motion.text);
|
motion.text = diffService.removeDuplicateClassesInsertedByCkeditor(motion.text);
|
||||||
MotionChangeRecommendation.create(motion).then(
|
MotionChangeRecommendation.create(motion).then(
|
||||||
function(success) {
|
function() {
|
||||||
$scope.closeThisDialog();
|
$scope.closeThisDialog();
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<div class="header">
|
<div class="header motion-header">
|
||||||
<div class="title">
|
<div class="title">
|
||||||
<div class="submenu">
|
<div class="submenu">
|
||||||
<a ui-sref="motions.motion.list" class="btn btn-sm btn-default">
|
<a ui-sref="motions.motion.list" class="btn btn-sm btn-default">
|
||||||
@ -59,12 +59,21 @@
|
|||||||
<translate>PDF</translate>
|
<translate>PDF</translate>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<h1>
|
|
||||||
{{ motion.getTitle() }}
|
<h1 class="motion-title">
|
||||||
|
<span class="title-change-indicator"
|
||||||
|
ng-if="viewChangeRecommendations.mode == 'original' && title_change_recommendation"
|
||||||
|
ng-click="viewChangeRecommendations.scrollToDiffBox(title_change_recommendation.id)"></span>
|
||||||
|
<span class="change-title"
|
||||||
|
ng-if="motion.isAllowed('update') && viewChangeRecommendations.mode == 'original' && !title_change_recommendation"></span>
|
||||||
|
|
||||||
|
<span>{{ motion.getTitleWithChanges(viewChangeRecommendations.mode) }}</span>
|
||||||
|
|
||||||
<i class="fa pointer" ng-class="motion.personalNote.star ? 'fa-star' : 'fa-star-o'"
|
<i class="fa pointer" ng-class="motion.personalNote.star ? 'fa-star' : 'fa-star-o'"
|
||||||
ng-if="operator.user"
|
ng-if="operator.user"
|
||||||
title="{{ 'Set as favorite' | translate }}" ng-click="toggleStar()"></i>
|
title="{{ 'Set as favorite' | translate }}" ng-click="toggleStar()"></i>
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-6">
|
||||||
<h2>
|
<h2>
|
||||||
|
@ -11,7 +11,16 @@
|
|||||||
<translate>Reject all change recommendations</translate>
|
<translate>Reject all change recommendations</translate>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<ul ng-if="change_recommendations.length > 0">
|
<ul ng-if="change_recommendations.length > 0 || title_change_recommendation">
|
||||||
|
<li ng-if="title_change_recommendation">
|
||||||
|
<a href='' ng-click="viewChangeRecommendations.scrollToDiffBox(title_change_recommendation.id)">
|
||||||
|
<span class="line-number"><translate>Title</translate>:</span>
|
||||||
|
<span class="operation"><translate>Replacement</translate></span>
|
||||||
|
<span class="status">
|
||||||
|
<translate ng-if="title_change_recommendation.rejected">Rejected</translate>
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
<li ng-repeat="change in (changes = (change_recommendations | filter:{motion_version_id:version}:true | orderBy: 'line_from')) ">
|
<li ng-repeat="change in (changes = (change_recommendations | filter:{motion_version_id:version}:true | orderBy: 'line_from')) ">
|
||||||
<a href='' ng-click="viewChangeRecommendations.scrollToDiffBox(change.id)">
|
<a href='' ng-click="viewChangeRecommendations.scrollToDiffBox(change.id)">
|
||||||
<span ng-if="change.line_from >= change.line_to - 1" class="line-number">
|
<span ng-if="change.line_from >= change.line_to - 1" class="line-number">
|
||||||
@ -35,7 +44,7 @@
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<div ng-if="change_recommendations.length == 0" class="no-changes">
|
<div ng-if="change_recommendations.length == 0 && !title_change_recommendation" class="no-changes">
|
||||||
<translate>No change recommendations yet</translate>
|
<translate>No change recommendations yet</translate>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
@ -92,7 +92,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- View Modes (Original, Diff, Changed) -->
|
<!-- View Modes (Original, Diff, Changed) -->
|
||||||
<div class="motion-toolbar" ng-if="change_recommendations.length > 0">
|
<div class="motion-toolbar" ng-if="change_recommendations.length > 0 || title_change_recommendation">
|
||||||
<div class="toolbar-left">
|
<div class="toolbar-left">
|
||||||
|
|
||||||
<!-- change recommendations for resonsive size medium/large (button group) -->
|
<!-- change recommendations for resonsive size medium/large (button group) -->
|
||||||
|
@ -1,4 +1,48 @@
|
|||||||
<div ng-if="viewChangeRecommendations.mode == 'diff'">
|
<div ng-if="viewChangeRecommendations.mode == 'diff'">
|
||||||
|
<!-- The changed title -->
|
||||||
|
<div ng-if="title_change_recommendation" ng-class="motion.isAllowed('can_manage') ? 'diff-box' : ''"
|
||||||
|
class="diff-box-{{ title_change_recommendation.id }} diff-box-title clearfix">
|
||||||
|
<div class="action-row" ng-if="motion.isAllowed('can_manage')">
|
||||||
|
<div class="btn-group" data-toggle="buttons">
|
||||||
|
<label class="btn btn-sm btn-default" ng-class="{active: !title_change_recommendation.rejected}"
|
||||||
|
title="{{ 'Not rejected' | translate }}"
|
||||||
|
ng-click="title_change_recommendation.rejected = false; title_change_recommendation.saveStatus();">
|
||||||
|
<input type="radio" name="changeRecommendationRejected[{{ title_change_recommendation.id }}]" value="0"
|
||||||
|
ng-change="title_change_recommendation.saveStatus()" ng-model="change.rejected"
|
||||||
|
ng-checked="title_change_recommendation.rejected == false">
|
||||||
|
<i class="fa fa-thumbs-up"></i>
|
||||||
|
</label>
|
||||||
|
<label class="btn btn-sm btn-default" ng-class="{active: title_change_recommendation.rejected}"
|
||||||
|
title="{{ 'Rejected' | translate }}" ng-click="title_change_recommendation.rejected = true; title_change_recommendation.saveStatus();">
|
||||||
|
<input type="radio" name="changeRecommendationRejected[{{ title_change_recommendation.id }}]" value="1"
|
||||||
|
ng-change="title_change_recommendation.saveStatus()" ng-model="change.rejected"
|
||||||
|
ng-checked="title_change_recommendation.rejected == true">
|
||||||
|
<i class="fa fa-thumbs-down"></i>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button class="btn btn-default btn-sm pull-right btn-delete"
|
||||||
|
ng-bootbox-confirm="{{ 'Are you sure you want to delete this change recommendation?' | translate }}"
|
||||||
|
ng-bootbox-confirm-action="viewChangeRecommendations.delete(title_change_recommendation.id)"
|
||||||
|
title="{{ 'Delete' | translate }}">
|
||||||
|
<i class="fa fa-trash"></i>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button class="btn btn-default btn-sm pull-right btn-edit"
|
||||||
|
ng-click="createChangeRecommendation.editTitleDialog(title_change_recommendation)"
|
||||||
|
title="{{ 'Edit' | translate }}">
|
||||||
|
<i class="fa fa-pencil"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="status-row" ng-if="!motion.isAllowed('can_manage') && title_change_recommendation.rejected">
|
||||||
|
<translate>Rejected</translate>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="motion-text motion-text-diff line-numbers-{{ lineNumberMode }}">
|
||||||
|
<div class="description"><translate>New title</translate>:</div>
|
||||||
|
<div>{{ title_change_recommendation.text }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- The actual diff view -->
|
<!-- The actual diff view -->
|
||||||
<div class="motion-text-with-diffs line-numbers-{{ lineNumberMode }}">
|
<div class="motion-text-with-diffs line-numbers-{{ lineNumberMode }}">
|
||||||
@ -31,7 +75,7 @@
|
|||||||
<i class="fa fa-trash"></i>
|
<i class="fa fa-trash"></i>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button class="btn btn-default btn-sm pull-right btn-edit" ng-click="createChangeRecommendation.editDialog(change)"
|
<button class="btn btn-default btn-sm pull-right btn-edit" ng-click="createChangeRecommendation.editTextDialog(change)"
|
||||||
title="{{ 'Edit' | translate }}">
|
title="{{ 'Edit' | translate }}">
|
||||||
<i class="fa fa-pencil"></i>
|
<i class="fa fa-pencil"></i>
|
||||||
</button>
|
</button>
|
||||||
|
Loading…
Reference in New Issue
Block a user