diff --git a/CHANGELOG b/CHANGELOG
index f775be81c..960a0a9d0 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -4,9 +4,11 @@
https://openslides.org/
-Version 2.1.2 (unreleased)
+Version 2.2 (unreleased)
==========================
+Motions:
+- New export dialog.
Version 2.1.1 (2017-04-05)
==========================
diff --git a/openslides/core/static/css/app.css b/openslides/core/static/css/app.css
index befe406b0..ca8755442 100644
--- a/openslides/core/static/css/app.css
+++ b/openslides/core/static/css/app.css
@@ -1346,6 +1346,10 @@ img {
padding: 0;
}
+.btn-group > label > input[type=radio] {
+ display: none;
+}
+
/* user details */
.user_details fieldset {
margin-bottom: 10px;
diff --git a/openslides/core/static/js/core/site.js b/openslides/core/static/js/core/site.js
index 984eb51fe..8ef9bce61 100644
--- a/openslides/core/static/js/core/site.js
+++ b/openslides/core/static/js/core/site.js
@@ -648,6 +648,10 @@ angular.module('OpenSlidesApp.core.site', [
templateUrl: 'static/templates/core/checkbox.html',
overwriteOk: true,
});
+ formlyConfig.setType({
+ name: 'select-radio',
+ templateUrl: 'static/templates/core/select-radio.html',
+ });
formlyConfig.setType({
name: 'select-single',
extends: 'select',
diff --git a/openslides/core/static/templates/core/select-radio.html b/openslides/core/static/templates/core/select-radio.html
new file mode 100644
index 000000000..a4c286c8a
--- /dev/null
+++ b/openslides/core/static/templates/core/select-radio.html
@@ -0,0 +1,17 @@
+
diff --git a/openslides/motions/static/js/motions/csv.js b/openslides/motions/static/js/motions/csv.js
index 1fdba56e2..feacfcf98 100644
--- a/openslides/motions/static/js/motions/csv.js
+++ b/openslides/motions/static/js/motions/csv.js
@@ -6,8 +6,10 @@ angular.module('OpenSlidesApp.motions.csv', [])
.factory('MotionCsvExport', [
'gettextCatalog',
+ 'Config',
'CsvDownload',
- function (gettextCatalog, CsvDownload) {
+ 'lineNumberingService',
+ function (gettextCatalog, Config, CsvDownload, lineNumberingService) {
var makeHeaderline = function () {
var headerline = ['Identifier', 'Title', 'Text', 'Reason', 'Submitter', 'Category', 'Origin'];
return _.map(headerline, function (entry) {
@@ -15,16 +17,36 @@ angular.module('OpenSlidesApp.motions.csv', [])
});
};
return {
- export: function (motions) {
+ export: function (motions, params) {
+ if (!params) {
+ params = {};
+ }
+ _.defaults(params, {
+ filename: 'motions-export.csv',
+ changeRecommendationMode: Config.get('motions_recommendation_text_mode').value,
+ includeReason: true,
+ });
+ if (!_.includes(['original', 'changed', 'agreed'], params.changeRecommendationMode)) {
+ params.changeRecommendationMode = 'original';
+ }
+
var csvRows = [
makeHeaderline()
];
_.forEach(motions, function (motion) {
+ // TODO: Add a parameter 'noLineBreaks' to 'getTextByMode'. Currently linenumbers are
+ // removed directy after inserting --> not necessary. (See issue 3183)
+ var text = motion.getTextByMode(params.changeRecommendationMode);
+ text = lineNumberingService.stripLineNumbers(text);
var row = [];
row.push('"' + motion.identifier !== null ? motion.identifier : '' + '"');
row.push('"' + motion.getTitle() + '"');
- row.push('"' + motion.getText() + '"');
- row.push('"' + motion.getReason() + '"');
+ row.push('"' + text + '"');
+ if (params.includeReason) {
+ row.push('"' + motion.getReason() + '"');
+ } else {
+ row.push('""');
+ }
var submitter = motion.submitters[0] ? motion.submitters[0].get_full_name() : '';
row.push('"' + submitter + '"');
var category = motion.category ? motion.category.name : '';
diff --git a/openslides/motions/static/js/motions/docx.js b/openslides/motions/static/js/motions/docx.js
index 1065ca8a1..b09759578 100644
--- a/openslides/motions/static/js/motions/docx.js
+++ b/openslides/motions/static/js/motions/docx.js
@@ -8,9 +8,11 @@ angular.module('OpenSlidesApp.motions.docx', [])
'$http',
'$q',
'Config',
+ 'Category',
'gettextCatalog',
'FileSaver',
- function ($http, $q, Config, gettextCatalog, FileSaver) {
+ 'lineNumberingService',
+ function ($http, $q, Config, Category, gettextCatalog, FileSaver, lineNumberingService) {
var PAGEBREAK = '';
var TAGS_NO_PARAM = ['b', 'strong', 'em', 'i'];
@@ -19,10 +21,9 @@ angular.module('OpenSlidesApp.motions.docx', [])
var relationships;
var contentTypes;
- // $scope.motionsFiltered, $scope.categories
-
- var getData = function (motions, categories) {
+ var getData = function (motions, params) {
var data = {};
+ var categories = Category.getAll();
// header
var headerline1 = [
Config.translate(Config.get('general_event_name').value),
@@ -47,7 +48,7 @@ angular.module('OpenSlidesApp.motions.docx', [])
// motions
data.tableofcontents_translation = gettextCatalog.getString('Table of contents');
- data.motions = getMotionFullData(motions);
+ data.motions = getMotionFullData(motions, params);
data.motions_list = getMotionShortData(motions);
data.no_motions = gettextCatalog.getString('No motions available.');
@@ -72,13 +73,18 @@ angular.module('OpenSlidesApp.motions.docx', [])
});
};
- var getMotionFullData = function (motions) {
+ var getMotionFullData = function (motions, params) {
var translation = gettextCatalog.getString('Motion'),
sequential_translation = gettextCatalog.getString('Sequential number'),
submitters_translation = gettextCatalog.getString('Submitters'),
status_translation = gettextCatalog.getString('Status'),
reason_translation = gettextCatalog.getString('Reason'),
data = _.map(motions, function (motion) {
+ // TODO: Add a parameter 'noLineBreaks' to 'getTextByMode'. Currently linenumbers are
+ // removed directy after inserting --> not necessary. (See issue #3183)
+ var text = motion.getTextByMode(params.changeRecommendationMode);
+ text = lineNumberingService.stripLineNumbers(text);
+ var reason = params.includeReason ? motion.getReason() : '';
return {
motion_translation: translation,
sequential_translation: sequential_translation,
@@ -92,9 +98,9 @@ angular.module('OpenSlidesApp.motions.docx', [])
status_translation: status_translation,
status: motion.getStateName(),
preamble: gettextCatalog.getString(Config.get('motions_preamble').value),
- text: html2docx(motion.getText()),
- reason_translation: motion.getReason().length === 0 ? '' : reason_translation,
- reason: html2docx(motion.getReason()),
+ text: html2docx(text),
+ reason_translation: reason.length === 0 ? '' : reason_translation,
+ reason: html2docx(reason),
pagebreak: PAGEBREAK,
};
});
@@ -353,7 +359,19 @@ angular.module('OpenSlidesApp.motions.docx', [])
};
return {
- export: function (motions, categories) {
+ export: function (motions, params) {
+ if (!params) {
+ params = {};
+ }
+ _.defaults(params, {
+ filename: 'motions-export.docx',
+ changeRecommendationMode: Config.get('motions_recommendation_text_mode').value,
+ includeReason: true,
+ });
+ if (!_.includes(['original', 'changed', 'agreed'], params.changeRecommendationMode)) {
+ params.changeRecommendationMode = 'original';
+ }
+
images = [];
relationships = [];
contentTypes = [];
@@ -361,7 +379,7 @@ angular.module('OpenSlidesApp.motions.docx', [])
var content = window.atob(success.data);
var doc = new Docxgen(content);
- doc.setData(getData(motions, categories));
+ doc.setData(getData(motions, params));
doc.render();
var zip = doc.getZip();
@@ -384,7 +402,7 @@ angular.module('OpenSlidesApp.motions.docx', [])
// wait for all images to be resolved
$q.all(imgPromises).then(function () {
var out = zip.generate({type: 'blob'});
- FileSaver.saveAs(out, 'motions-export.docx');
+ FileSaver.saveAs(out, params.filename);
});
});
},
diff --git a/openslides/motions/static/js/motions/motion-services.js b/openslides/motions/static/js/motions/motion-services.js
index b533dad92..cb9fd768e 100644
--- a/openslides/motions/static/js/motions/motion-services.js
+++ b/openslides/motions/static/js/motions/motion-services.js
@@ -4,60 +4,6 @@
angular.module('OpenSlidesApp.motions.motionservices', ['OpenSlidesApp.motions', 'OpenSlidesApp.motions.lineNumbering'])
-.factory('MotionPDFExport', [
- 'HTMLValidizer',
- 'Motion',
- 'User',
- 'PdfMakeConverter',
- 'PdfMakeDocumentProvider',
- 'PdfMakeBallotPaperProvider',
- 'MotionContentProvider',
- 'PollContentProvider',
- 'gettextCatalog',
- '$http',
- 'PdfCreate',
- function (HTMLValidizer, Motion, User, PdfMakeConverter, PdfMakeDocumentProvider, PdfMakeBallotPaperProvider,
- MotionContentProvider, PollContentProvider, gettextCatalog, $http, PdfCreate) {
- var obj = {};
-
- var $scope;
-
- obj.createMotion = function() {
- var text = $scope.motion.getTextByMode($scope.viewChangeRecommendations.mode, $scope.version);
- var content = HTMLValidizer.validize(text) + HTMLValidizer.validize($scope.motion.getReason($scope.version));
- var map = Function.prototype.call.bind([].map);
- var image_sources = map($(content).find("img"), function(element) {
- return element.getAttribute("src");
- });
-
- $http.post('/core/encode_media/', JSON.stringify(image_sources)).then(function (success) {
- var converter = PdfMakeConverter.createInstance(success.data.images);
- var motionContentProvider = MotionContentProvider.createInstance(converter, $scope.motion, $scope, User, $http);
- var documentProvider = PdfMakeDocumentProvider.createInstance(motionContentProvider);
- var identifier = $scope.motion.identifier ? '-' + $scope.motion.identifier : '';
- var filename = gettextCatalog.getString("Motion") + identifier + ".pdf";
- PdfCreate.download(documentProvider.getDocument(), filename);
- });
- };
-
- //make PDF for polls
- obj.createPoll = function() {
- var id = $scope.motion.identifier.replace(" ", "");
- var title = $scope.motion.getTitle($scope.version);
- var filename = gettextCatalog.getString("Motion") + "-" + id + "-" + gettextCatalog.getString("ballot-paper") + ".pdf";
- var pollContentProvider = PollContentProvider.createInstance(title, id, gettextCatalog);
- var documentProvider = PdfMakeBallotPaperProvider.createInstance(pollContentProvider);
- PdfCreate.download(documentProvider.getDocument(), filename);
- };
-
- obj.init = function (_scope) {
- $scope = _scope;
- };
-
- return obj;
- }
-])
-
.factory('MotionInlineEditing', [
'Editor',
'Motion',
diff --git a/openslides/motions/static/js/motions/pdf.js b/openslides/motions/static/js/motions/pdf.js
index 806b38b20..1376907ff 100644
--- a/openslides/motions/static/js/motions/pdf.js
+++ b/openslides/motions/static/js/motions/pdf.js
@@ -5,24 +5,26 @@
angular.module('OpenSlidesApp.motions.pdf', ['OpenSlidesApp.core.pdf'])
.factory('MotionContentProvider', [
+ 'operator',
'gettextCatalog',
'PDFLayout',
'Category',
'Config',
'Motion',
- function(gettextCatalog, PDFLayout, Category, Config, Motion) {
+ function(operator, gettextCatalog, PDFLayout, Category, Config, Motion) {
/**
* Provides the content as JS objects for Motions in pdfMake context
* @constructor
*/
- var createInstance = function(converter, motion, $scope) {
+ var createInstance = function(converter, motion, motionVersion, changeRecommendationMode,
+ changeRecommendations, lineNumberMode, includeReason, includeComments) {
// title
var identifier = motion.identifier ? ' ' + motion.identifier : '';
var title = PDFLayout.createTitle(
gettextCatalog.getString('Motion') + identifier + ': ' +
- motion.getTitle($scope.version)
+ motion.getTitle(motionVersion)
);
// subtitle
@@ -175,51 +177,49 @@ angular.module('OpenSlidesApp.motions.pdf', ['OpenSlidesApp.core.pdf'])
}
// summary of change recommendations (for motion diff version only)
- if ($scope.viewChangeRecommendations) {
- if ($scope.viewChangeRecommendations.mode == "diff") {
- var columnLineNumbers = [];
- var columnChangeType = [];
- angular.forEach(_.orderBy($scope.change_recommendations, ['line_from']), function(change) {
- // line numbers column
- var line;
- if (change.line_from >= change.line_to - 1) {
- line = change.line_from;
- } else {
- line = change.line_from + ' - ' + (change.line_to - 1);
- }
- columnLineNumbers.push(
- gettextCatalog.getString('Line') + ' ' + line + ': '
- );
- // change type column
- if (change.getType(motion.getVersion($scope.version).text) === 0) {
- columnChangeType.push(gettextCatalog.getString("Replacement"));
- } else if (change.getType(motion.getVersion($scope.version).text) === 1) {
- columnChangeType.push(gettextCatalog.getString("Insertion"));
- } else if (change.getType(motion.getVersion($scope.version).text) === 2) {
- columnChangeType.push(gettextCatalog.getString("Deletion"));
- }
- });
- metaTableBody.push([
- {
- text: gettextCatalog.getString('Summary of change recommendations'),
- style: ['bold', 'grey']
- },
- {
- columns: [
- {
- text: columnLineNumbers.join('\n'),
- width: 'auto'
- },
- {
- text: columnChangeType.join('\n'),
- width: 'auto'
- }
- ],
- columnGap: 7,
- style: 'grey'
- }
- ]);
- }
+ if (changeRecommendationMode == "diff") {
+ var columnLineNumbers = [];
+ var columnChangeType = [];
+ angular.forEach(_.orderBy(changeRecommendations, ['line_from']), function(change) {
+ // line numbers column
+ var line;
+ if (change.line_from >= change.line_to - 1) {
+ line = change.line_from;
+ } else {
+ line = change.line_from + ' - ' + (change.line_to - 1);
+ }
+ columnLineNumbers.push(
+ gettextCatalog.getString('Line') + ' ' + line + ': '
+ );
+ // change type column
+ if (change.getType(motion.getVersion(motionVersion).text) === 0) {
+ columnChangeType.push(gettextCatalog.getString("Replacement"));
+ } else if (change.getType(motion.getVersion(motionVersion).text) === 1) {
+ columnChangeType.push(gettextCatalog.getString("Insertion"));
+ } else if (change.getType(motion.getVersion(motionVersion).text) === 2) {
+ columnChangeType.push(gettextCatalog.getString("Deletion"));
+ }
+ });
+ metaTableBody.push([
+ {
+ text: gettextCatalog.getString('Summary of change recommendations'),
+ style: ['bold', 'grey']
+ },
+ {
+ columns: [
+ {
+ text: columnLineNumbers.join('\n'),
+ width: 'auto'
+ },
+ {
+ text: columnChangeType.join('\n'),
+ width: 'auto'
+ }
+ ],
+ columnGap: 7,
+ style: 'grey'
+ }
+ ]);
}
// build table
@@ -241,7 +241,7 @@ angular.module('OpenSlidesApp.motions.pdf', ['OpenSlidesApp.core.pdf'])
// motion title
var motionTitle = function() {
return [{
- text: motion.getTitle($scope.version),
+ text: motion.getTitle(motionVersion),
style: 'heading3'
}];
};
@@ -257,28 +257,56 @@ angular.module('OpenSlidesApp.motions.pdf', ['OpenSlidesApp.core.pdf'])
// motion text (with line-numbers)
var motionText = function() {
- var motionTextContent = motion.getTextByMode($scope.viewChangeRecommendations.mode, $scope.version);
- return converter.convertHTML(motionTextContent, $scope.lineNumberMode);
+ var motionTextContent = motion.getTextByMode(changeRecommendationMode, motionVersion);
+ return converter.convertHTML(motionTextContent, lineNumberMode);
};
// motion reason heading
var motionReason = function() {
- var reason = [];
- if (motion.getReason($scope.version)) {
- reason.push({
- text: gettextCatalog.getString('Reason'),
- style: 'heading3',
- marginTop: 25,
- });
- reason.push(converter.convertHTML(motion.getReason($scope.version), $scope.lineNumberMode));
+ if (includeReason) {
+ var reason = [];
+ if (motion.getReason(motionVersion)) {
+ reason.push({
+ text: gettextCatalog.getString('Reason'),
+ style: 'heading3',
+ marginTop: 25,
+ });
+ reason.push(converter.convertHTML(motion.getReason(motionVersion), lineNumberMode));
+ }
+ return reason;
}
- return reason;
};
+ // motion comments handling
+ var motionComments = function () {
+ if (includeComments) {
+ var fields = Config.get('motions_comments').value;
+ var canSeeComment = function (index) {
+ return fields[index].public || operator.hasPerms('motions.can_manage');
+ };
+ var comments = [];
+ for (var i = 0; i < fields.length; i++) {
+ if (motion.comments[i] && canSeeComment(i)) {
+ var title = gettextCatalog.getString('Comment') + ' ' + fields[i].name;
+ console.log(fields[i]);
+ if (!fields[i].public) {
+ title += ' (' + gettextCatalog.getString('private') + ')';
+ }
+ comments.push({
+ text: title,
+ style: 'heading3',
+ marginTop: 25,
+ });
+ comments.push(converter.convertHTML(motion.comments[i]));
+ }
+ }
+ return comments;
+ }
+ };
// getters
var getTitle = function() {
- return motion.getTitle($scope.version);
+ return motion.getTitle(motionVersion);
};
var getIdentifier = function() {
@@ -299,8 +327,13 @@ angular.module('OpenSlidesApp.motions.pdf', ['OpenSlidesApp.core.pdf'])
motionPreamble(),
motionText(),
];
- if (motionReason()) {
- content.push(motionReason());
+ var reason = motionReason();
+ if (reason) {
+ content.push(reason);
+ }
+ var comments = motionComments();
+ if (comments) {
+ content.push(comments);
}
return content;
};
@@ -319,17 +352,17 @@ angular.module('OpenSlidesApp.motions.pdf', ['OpenSlidesApp.core.pdf'])
.factory('PollContentProvider', [
'PDFLayout',
+ 'gettextCatalog',
'Config',
'User',
- function(PDFLayout, Config, User) {
+ function(PDFLayout, gettextCatalog, Config, User) {
/**
* Generates a content provider for polls
* @constructor
* @param {string} title - title of poll
* @param {string} id - if of poll
- * @param {object} gettextCatalog - for translation
*/
- var createInstance = function(title, id, gettextCatalog) {
+ var createInstance = function(title, id) {
/**
* Returns a single section on the ballot paper
@@ -440,9 +473,8 @@ angular.module('OpenSlidesApp.motions.pdf', ['OpenSlidesApp.core.pdf'])
* Constructor
* @function
* @param {object} allMotions - A sorted array of all motions to parse
- * @param {object} $scope - Current $scope
*/
- var createInstance = function(allMotions, $scope) {
+ var createInstance = function(allMotions) {
var title = PDFLayout.createTitle(
Config.translate(Config.get('motions_export_title').value)
@@ -566,6 +598,101 @@ angular.module('OpenSlidesApp.motions.pdf', ['OpenSlidesApp.core.pdf'])
return {
createInstance: createInstance
};
-}]);
+}])
+
+.factory('MotionPdfExport', [
+ '$http',
+ 'Config',
+ 'gettextCatalog',
+ 'MotionChangeRecommendation',
+ 'HTMLValidizer',
+ 'PdfMakeConverter',
+ 'MotionContentProvider',
+ 'MotionCatalogContentProvider',
+ 'PdfMakeDocumentProvider',
+ 'PollContentProvider',
+ 'PdfMakeBallotPaperProvider',
+ 'PdfCreate',
+ function ($http, Config, gettextCatalog, MotionChangeRecommendation, HTMLValidizer, PdfMakeConverter,
+ MotionContentProvider, MotionCatalogContentProvider, PdfMakeDocumentProvider, PollContentProvider,
+ PdfMakeBallotPaperProvider, PdfCreate) {
+ return {
+ export: function (motions, params, singleMotion) {
+ if (!params) {
+ params = {};
+ }
+ _.defaults(params, {
+ filename: gettextCatalog.getString('motions') + '.pdf',
+ changeRecommendationMode: Config.get('motions_recommendation_text_mode').value,
+ lineNumberMode: Config.get('motions_default_line_numbering').value,
+ includeReason: true,
+ includeComments: false,
+ });
+ var image_sources = [];
+
+ if (singleMotion) {
+ _.defaults(params, {
+ version: motions.active_version,
+ });
+ motions = [motions];
+ }
+
+ //save the arrays of all motions to an array
+ angular.forEach(motions, function (motion) {
+ if (singleMotion) {
+ motion.changeRecommendations = MotionChangeRecommendation.filter({
+ 'where': {'motion_version_id': {'==': motion.active_version}}
+ });
+ } else {
+ motion.changeRecommendations = MotionChangeRecommendation.filter({
+ 'where': {'motion_version_id': {'==': params.version}}
+ });
+ }
+ var text = motion.getTextByMode(params.changeRecommendationMode, null);
+ var content = HTMLValidizer.validize(text) + HTMLValidizer.validize(motion.getReason());
+ var map = Function.prototype.call.bind([].map);
+ var tmp_image_sources = map($(content).find('img'), function(element) {
+ return element.getAttribute('src');
+ });
+ image_sources = image_sources.concat(tmp_image_sources);
+ });
+
+ //post-request to convert the images. Async.
+ $http.post('/core/encode_media/', JSON.stringify(image_sources)).then(function (success) {
+ var converter = PdfMakeConverter.createInstance(success.data.images);
+ var motionContentProviderArray = [];
+
+ //convert all motions to motionContentProviders
+ angular.forEach(motions, function (motion) {
+ var version = (singleMotion ? params.version : motion.active_version);
+ motionContentProviderArray.push(MotionContentProvider.createInstance(
+ converter, motion, version, params.changeRecommendationMode,
+ motion.changeRecommendations, params.lineNumberMode,
+ params.includeReason, params.includeComments
+ ));
+ });
+
+ var documentProvider;
+ if (singleMotion) {
+ documentProvider = PdfMakeDocumentProvider.createInstance(motionContentProviderArray[0]);
+ } else {
+ var motionCatalogContentProvider = MotionCatalogContentProvider.createInstance(motionContentProviderArray);
+ documentProvider = PdfMakeDocumentProvider.createInstance(motionCatalogContentProvider);
+ }
+
+ PdfCreate.download(documentProvider.getDocument(), params.filename);
+ });
+ },
+ createPollPdf: function (motion, version) {
+ var id = motion.identifier.replace(' ', '');
+ var title = motion.getTitle(version);
+ var filename = gettextCatalog.getString('Motion') + '-' + id + '-' + gettextCatalog.getString('ballot-paper') + '.pdf';
+ var pollContentProvider = PollContentProvider.createInstance(title, id);
+ var documentProvider = PdfMakeBallotPaperProvider.createInstance(pollContentProvider);
+ PdfCreate.download(documentProvider.getDocument(), filename);
+ },
+ };
+ }
+]);
}());
diff --git a/openslides/motions/static/js/motions/site.js b/openslides/motions/static/js/motions/site.js
index 115479679..6bae75a30 100644
--- a/openslides/motions/static/js/motions/site.js
+++ b/openslides/motions/static/js/motions/site.js
@@ -613,6 +613,179 @@ angular.module('OpenSlidesApp.motions.site', [
}
])
+.factory('MotionExportForm', [
+ 'operator',
+ 'gettextCatalog',
+ 'Config',
+ function (operator, gettextCatalog, Config) {
+ return {
+ getDialog: function (motions, params, singleMotion) {
+ return {
+ template: 'static/templates/motions/motion-export-form.html',
+ controller: 'MotionExportCtrl',
+ className: 'ngdialog-theme-default wide-form',
+ closeByEscape: false,
+ closeByDocument: false,
+ resolve: {
+ motions: function () {return motions;},
+ params: function () {return params;},
+ singleMotion: function () {return singleMotion;},
+ },
+ };
+ },
+ getFormFields: function (singleMotion, formatChangeCallback) {
+ var fields = [];
+ var commentsAvailable = Config.get('motions_comments').value.length !== 0;
+ if (!singleMotion) {
+ fields = [
+ {
+ key: 'format',
+ type: 'select-radio',
+ templateOptions: {
+ label: gettextCatalog.getString('Format'),
+ options: [
+ {name: gettextCatalog.getString('PDF'), value: 'pdf'},
+ {name: gettextCatalog.getString('CSV'), value: 'csv'},
+ {name: gettextCatalog.getString('DOCX'), value: 'docx'},
+ ],
+ change: formatChangeCallback,
+ },
+ }
+ ];
+ }
+ if (operator.hasPerms('motions.can_manage')) {
+ fields.push.apply(fields, [
+ {
+ key: 'lineNumberMode',
+ type: 'select-radio',
+ templateOptions: {
+ label: gettextCatalog.getString('Line numbering'),
+ options: [
+ {name: gettextCatalog.getString('None'), value: 'none'},
+ {name: gettextCatalog.getString('inline'), value: 'inline'},
+ {name: gettextCatalog.getString('outside'), value: 'outside'},
+ ],
+ },
+ hideExpression: "model.format !== 'pdf'",
+ },
+ {
+ key: 'lineNumberMode',
+ type: 'select-radio',
+ templateOptions: {
+ label: gettextCatalog.getString('Line numbering'),
+ options: [
+ {name: gettextCatalog.getString('None'), value: 'none'},
+ {name: gettextCatalog.getString('inline'), value: 'inline', disabled: true},
+ {name: gettextCatalog.getString('outside'), value: 'outside', disabled: true},
+ ],
+ },
+ hideExpression: "model.format === 'pdf'",
+ },
+ {
+ key: 'changeRecommendationMode',
+ type: 'select-radio',
+ templateOptions: {
+ label: gettextCatalog.getString('Change recommendations'),
+ options: [
+ {name: gettextCatalog.getString('Original version'), value: 'original'},
+ {name: gettextCatalog.getString('Changed version'), value: 'changed'},
+ {name: gettextCatalog.getString('Diff version'), value: 'diff'},
+ {name: gettextCatalog.getString('Final version'), value: 'agreed'},
+ ],
+ },
+ hideExpression: "model.format !== 'pdf'",
+ },
+ {
+ key: 'changeRecommendationMode',
+ type: 'select-radio',
+ templateOptions: {
+ label: gettextCatalog.getString('Change recommendations'),
+ options: [
+ {name: gettextCatalog.getString('Original version'), value: 'original'},
+ {name: gettextCatalog.getString('Changed version'), value: 'changed'},
+ {name: gettextCatalog.getString('Diff version'), value: 'diff', disabled: true},
+ {name: gettextCatalog.getString('Final version'), value: 'agreed'},
+ ],
+ },
+ hideExpression: "model.format === 'pdf'",
+ },
+ {
+ key: 'includeReason',
+ type: 'select-radio',
+ templateOptions: {
+ label: gettextCatalog.getString('Reason'),
+ options: [
+ {name: gettextCatalog.getString('Yes'), value: true},
+ {name: gettextCatalog.getString('No'), value: false},
+ ],
+ },
+ },
+ ]);
+ if (commentsAvailable) {
+ fields.push({
+ key: 'includeComments',
+ type: 'select-radio',
+ templateOptions: {
+ label: gettextCatalog.getString('Kommentare'),
+ options: [
+ {name: gettextCatalog.getString('Yes'), value: true},
+ {name: gettextCatalog.getString('No'), value: false},
+ ],
+ },
+ hideExpression: "model.format !== 'pdf'",
+ });
+ }
+ }
+ return fields;
+ },
+ };
+ }
+])
+
+.controller('MotionExportCtrl', [
+ '$scope',
+ 'Config',
+ 'MotionExportForm',
+ 'MotionPdfExport',
+ 'MotionCsvExport',
+ 'MotionDocxExport',
+ 'motions',
+ 'params',
+ 'singleMotion',
+ function ($scope, Config, MotionExportForm, MotionPdfExport, MotionCsvExport,
+ MotionDocxExport, motions, params, singleMotion) {
+ $scope.formFields = MotionExportForm.getFormFields(singleMotion, function () {
+ $scope.params.changeRecommendationMode = 'original';
+ $scope.params.lineNumberMode = 'none';
+ });
+ $scope.params = params || {};
+ _.defaults($scope.params, {
+ format: 'pdf',
+ changeRecommendationMode: Config.get('motions_recommendation_text_mode').value,
+ lineNumberMode: Config.get('motions_default_line_numbering').value,
+ includeReason: true,
+ includeComments: false,
+ });
+ $scope.motions = motions;
+ $scope.singleMotion = singleMotion;
+
+ $scope.export = function () {
+ switch ($scope.params.format) {
+ case 'pdf':
+ MotionPdfExport.export(motions, $scope.params, singleMotion);
+ break;
+ case 'csv':
+ MotionCsvExport.export(motions, $scope.params);
+ break;
+ case 'docx':
+ MotionDocxExport.export(motions, $scope.params);
+ break;
+ }
+ $scope.closeThisDialog();
+ };
+ }
+])
+
// Cache for MotionPollDetailCtrl so that users choices are keeped during user actions (e. g. save poll form).
.value('MotionPollDetailCtrlCache', {})
@@ -672,24 +845,15 @@ angular.module('OpenSlidesApp.motions.site', [
'User',
'Agenda',
'MotionBlock',
- 'MotionChangeRecommendation',
- 'MotionCsvExport',
- 'MotionDocxExport',
- 'MotionContentProvider',
- 'MotionCatalogContentProvider',
- 'PdfMakeConverter',
- 'PdfMakeDocumentProvider',
- 'HTMLValidizer',
'Projector',
'ProjectionDefault',
'osTableFilter',
'osTableSort',
- 'PdfCreate',
+ 'MotionExportForm',
+ 'MotionPdfExport',
function($scope, $state, $http, gettext, gettextCatalog, ngDialog, MotionForm, Motion,
- Category, Config, Tag, Workflow, User, Agenda, MotionBlock, MotionChangeRecommendation,
- MotionCsvExport, MotionDocxExport, MotionContentProvider, MotionCatalogContentProvider,
- PdfMakeConverter, PdfMakeDocumentProvider, HTMLValidizer, Projector, ProjectionDefault,
- osTableFilter, osTableSort, PdfCreate) {
+ Category, Config, Tag, Workflow, User, Agenda, MotionBlock, Projector,
+ ProjectionDefault, osTableFilter, osTableSort, MotionExportForm, MotionPdfExport) {
Motion.bindAll({}, $scope, 'motions');
Category.bindAll({}, $scope, 'categories');
MotionBlock.bindAll({}, $scope, 'motionBlocks');
@@ -883,52 +1047,12 @@ angular.module('OpenSlidesApp.motions.site', [
$scope.openDialog = function (motion) {
ngDialog.open(MotionForm.getDialog(motion));
};
-
- // Export as a pdf file
- $scope.pdfExport = function() {
- var filename = gettextCatalog.getString("Motions") + ".pdf";
- var image_sources = [];
- $scope.viewChangeRecommendations = {};
- $scope.viewChangeRecommendations.mode = Config.get('motions_recommendation_text_mode').value;
- $scope.lineNumberMode = Config.get('motions_default_line_numbering').value;
-
- //save the arrays of the filtered motions to an array
- angular.forEach($scope.motionsFiltered, function (motion) {
- $scope.change_recommendations = MotionChangeRecommendation.filter({
- 'where': {'motion_version_id': {'==': motion.active_version}}
- });
- var text = motion.getTextByMode($scope.viewChangeRecommendations.mode, null);
- var content = HTMLValidizer.validize(text) + HTMLValidizer.validize(motion.getReason());
- var map = Function.prototype.call.bind([].map);
- var tmp_image_sources = map($(content).find("img"), function(element) {
- return element.getAttribute("src");
- });
- image_sources = image_sources.concat(tmp_image_sources);
- });
-
- //post-request to convert the images. Async.
- $http.post('/core/encode_media/', JSON.stringify(image_sources)).then(function (success) {
- var converter = PdfMakeConverter.createInstance(success.data.images);
- var motionContentProviderArray = [];
-
- //convert the filtered motions to motionContentProviders
- angular.forEach($scope.motionsFiltered, function (motion) {
- motionContentProviderArray.push(MotionContentProvider.createInstance(converter, motion, $scope, User, $http));
- });
- var motionCatalogContentProvider = MotionCatalogContentProvider.createInstance(motionContentProviderArray, $scope, User, Category);
- var documentProvider = PdfMakeDocumentProvider.createInstance(motionCatalogContentProvider);
-
- PdfCreate.download(documentProvider.getDocument(), filename);
- });
+ // Export dialog
+ $scope.openExportDialog = function () {
+ ngDialog.open(MotionExportForm.getDialog($scope.motionsFiltered));
};
-
- // Export as a csv file
- $scope.csvExport = function () {
- MotionCsvExport.export($scope.motionsFiltered);
- };
- // Export as docx file
- $scope.docxExport = function () {
- MotionDocxExport.export($scope.motionsFiltered, $scope.categories);
+ $scope.pdfExport = function () {
+ MotionPdfExport.export($scope.motionsFiltered);
};
// *** select mode functions ***
@@ -993,11 +1117,11 @@ angular.module('OpenSlidesApp.motions.site', [
'$timeout',
'operator',
'ngDialog',
+ 'gettextCatalog',
'MotionForm',
'ChangeRecommmendationCreate',
'ChangeRecommmendationView',
'MotionChangeRecommendation',
- 'MotionPDFExport',
'Motion',
'MotionComment',
'Category',
@@ -1012,10 +1136,11 @@ angular.module('OpenSlidesApp.motions.site', [
'Projector',
'ProjectionDefault',
'MotionBlock',
- function($scope, $http, $timeout, operator, ngDialog, MotionForm,
- ChangeRecommmendationCreate, ChangeRecommmendationView, MotionChangeRecommendation, MotionPDFExport,
+ 'MotionPdfExport',
+ function($scope, $http, $timeout, operator, ngDialog, gettextCatalog, MotionForm,
+ ChangeRecommmendationCreate, ChangeRecommmendationView, MotionChangeRecommendation,
Motion, MotionComment, Category, Mediafile, Tag, User, Workflow, Config, motionId, MotionInlineEditing,
- MotionCommentsInlineEditing, Projector, ProjectionDefault, MotionBlock) {
+ MotionCommentsInlineEditing, Projector, ProjectionDefault, MotionBlock, MotionPdfExport) {
var motion = Motion.get(motionId);
Category.bindAll({}, $scope, 'categories');
Mediafile.bindAll({}, $scope, 'mediafiles');
@@ -1296,8 +1421,19 @@ angular.module('OpenSlidesApp.motions.site', [
$scope.viewChangeRecommendations.init($scope, Config.get('motions_recommendation_text_mode').value);
// PDF creating functions
- $scope.pdfExport = MotionPDFExport;
- $scope.pdfExport.init($scope);
+ $scope.pdfExport = function () {
+ var identifier = $scope.motion.identifier ? '-' + $scope.motion.identifier : '';
+ var params = {
+ filename: gettextCatalog.getString('Motion') + identifier + '.pdf',
+ version: $scope.version,
+ changeRecommendationMode: $scope.viewChangeRecommendations.mode,
+ lineNumberMode: $scope.lineNumberMode,
+ };
+ MotionPdfExport.export(motion, params, true);
+ };
+ $scope.createPollPdf = function () {
+ MotionPdfExport.createPollPdf($scope.motion, $scope.version);
+ };
}
])
diff --git a/openslides/motions/static/templates/motions/motion-detail.html b/openslides/motions/static/templates/motions/motion-detail.html
index e11f64738..3016bbe77 100644
--- a/openslides/motions/static/templates/motions/motion-detail.html
+++ b/openslides/motions/static/templates/motions/motion-detail.html
@@ -54,7 +54,7 @@
-
+
PDF
@@ -310,7 +310,7 @@
-
diff --git a/openslides/motions/static/templates/motions/motion-export-form.html b/openslides/motions/static/templates/motions/motion-export-form.html
new file mode 100644
index 000000000..f0fefa826
--- /dev/null
+++ b/openslides/motions/static/templates/motions/motion-export-form.html
@@ -0,0 +1,14 @@
+Export motions
+Export motion
+Export motion "{{ motions.getTitle() }}"
+
+
diff --git a/openslides/motions/static/templates/motions/motion-list.html b/openslides/motions/static/templates/motions/motion-list.html
index a5ebfdf0c..c6039b1c0 100644
--- a/openslides/motions/static/templates/motions/motion-list.html
+++ b/openslides/motions/static/templates/motions/motion-list.html
@@ -36,43 +36,27 @@
Select ...
-
-
-
-
-
+
+
+