diff --git a/CHANGELOG b/CHANGELOG index a5cfacd01..c09196ef0 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -14,6 +14,7 @@ Agenda: - New permission for managing lists of speakers [#3366]. - Fixed multiple request on creation of agenda related items [#3341]. - Added possibility to mark speakers [#3570]. +- New DOCX export of agenda [#3569]. Motions: - New export dialog [#3185]. @@ -56,6 +57,8 @@ Motions: - Combined all boolean filters into one dropdown menu and added a filter for amendments [#3501]. - Allow to delete own motions [#3516]. +- Log which comment was updated [#3569]. +- Save pagination sate to session storage [#3569]. Elections: - Added pagination for list view [#3393]. diff --git a/openslides/agenda/static/js/agenda/docx.js b/openslides/agenda/static/js/agenda/docx.js new file mode 100644 index 000000000..1de1c92cb --- /dev/null +++ b/openslides/agenda/static/js/agenda/docx.js @@ -0,0 +1,84 @@ +(function () { + +'use strict'; + +angular.module('OpenSlidesApp.agenda.docx', ['OpenSlidesApp.core.docx']) + +.factory('AgendaDocxExport', [ + '$http', + 'gettextCatalog', + 'FileSaver', + 'Agenda', + 'AgendaTree', + 'Config', + function ($http, gettextCatalog, FileSaver, Agenda, AgendaTree, Config) { + + var getData = function (items) { + // Item structure: The top layer has subitems, that are flat. + // The first layer is bold and all sublayers not. The docx + // templater cannot render items recursively, so the second + // layer are all subitems flated out. Spacing is done with tabs. + var tree = AgendaTree.getTree(items); + var subitems = []; // This will be used as a temporary variable. + var flatSubitems = function (children, parentCount) { + _.forEach(children, function (child) { + var taps = _.repeat('\t', parentCount - 1); + subitems.push({ + item_number: taps + child.item.item_number, + item_title: child.item.list_view_title, + }); + flatSubitems(child.children, parentCount + 1); + }); + }; + var twoLayerTree = _.map(tree, function (mainItem) { + subitems = []; + flatSubitems(mainItem.children, 1); + return { + item_number: mainItem.item.item_number, + item_title: mainItem.item.list_view_title, + subitems: subitems, + }; + }); + + // header + var headerline1 = [ + Config.translate(Config.get('general_event_name').value), + Config.translate(Config.get('general_event_description').value) + ].filter(Boolean).join(' – '); + var headerline2 = [ + Config.get('general_event_location').value, + Config.get('general_event_date').value + ].filter(Boolean).join(', '); + + // Data structure for the docx templater. + return { + header: [headerline1, headerline2].join('\n'), + agenda_translation: gettextCatalog.getString('Agenda'), + top_list: twoLayerTree, + }; + }; + + return { + export: function (items) { + // TODO: use filtered items. + var filename = gettextCatalog.getString('Agenda') + '.docx'; + $http.get('/agenda/docxtemplate/').then(function (success) { + var content = window.atob(success.data); + var doc = new Docxgen(content); + + var data = getData(items); + doc.setData(data); + doc.render(); + + var zip = doc.getZip(); + //zip = converter.updateZipFile(zip); + + var out = zip.generate({type: 'blob'}); + FileSaver.saveAs(out, filename); + }); + }, + }; + } +]); + +})(); diff --git a/openslides/agenda/static/js/agenda/site.js b/openslides/agenda/static/js/agenda/site.js index 262908fd8..cf29def52 100644 --- a/openslides/agenda/static/js/agenda/site.js +++ b/openslides/agenda/static/js/agenda/site.js @@ -7,6 +7,7 @@ angular.module('OpenSlidesApp.agenda.site', [ 'OpenSlidesApp.core.pdf', 'OpenSlidesApp.agenda.pdf', 'OpenSlidesApp.agenda.csv', + 'OpenSlidesApp.agenda.docx', ]) .config([ @@ -100,12 +101,14 @@ angular.module('OpenSlidesApp.agenda.site', [ 'gettextCatalog', 'gettext', 'osTableFilter', + 'osTablePagination', 'AgendaCsvExport', 'AgendaPdfExport', + 'AgendaDocxExport', 'ErrorMessage', function($scope, $filter, $http, $state, DS, operator, ngDialog, Agenda, TopicForm, AgendaTree, Projector, ProjectionDefault, gettextCatalog, gettext, osTableFilter, - AgendaCsvExport, AgendaPdfExport, ErrorMessage) { + osTablePagination, AgendaCsvExport, AgendaPdfExport, AgendaDocxExport, ErrorMessage) { // Bind agenda tree to the scope $scope.$watch(function () { return Agenda.lastModified(); @@ -167,13 +170,7 @@ angular.module('OpenSlidesApp.agenda.site', [ }; // pagination - $scope.currentPage = 1; - $scope.itemsPerPage = 25; - $scope.limitBegin = 0; - $scope.pageChanged = function() { - $scope.limitBegin = ($scope.currentPage - 1) * $scope.itemsPerPage; - $scope.gotoTop(); - }; + $scope.pagination = osTablePagination.createInstance('AgendaTablePagination'); // parse duration for inline editing $scope.generateDurationText = function (item) { @@ -288,6 +285,9 @@ angular.module('OpenSlidesApp.agenda.site', [ $scope.csvExport = function () { AgendaCsvExport.export($scope.itemsFiltered); }; + $scope.docxExport = function () { + AgendaDocxExport.export($scope.itemsFiltered); + }; /** select mode functions **/ $scope.isSelectMode = false; diff --git a/openslides/agenda/static/templates/agenda/item-list.html b/openslides/agenda/static/templates/agenda/item-list.html index 02688c2a2..6e974c87c 100644 --- a/openslides/agenda/static/templates/agenda/item-list.html +++ b/openslides/agenda/static/templates/agenda/item-list.html @@ -111,6 +111,12 @@ CSV +
@@ -120,7 +126,7 @@ | - {{ (currentPage - 1) * itemsPerPage + $index + 1 }} + {{ (pagination.currentPage - 1) * pagination.itemsPerPage + $index + 1 }} | {{ user.title }} | @@ -180,11 +186,11 @@ |