Skip to content

Commit

Permalink
#29 - Configuring the PDF Export
Browse files Browse the repository at this point in the history
  • Loading branch information
Gulix committed Jul 7, 2017
1 parent 713c29f commit a3d06f2
Show file tree
Hide file tree
Showing 12 changed files with 280 additions and 59 deletions.
2 changes: 1 addition & 1 deletion src/css/styles.css

Large diffs are not rendered by default.

22 changes: 6 additions & 16 deletions src/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -274,21 +274,6 @@ <h3 data-bind="visible: exportVM.exportActive">Export in Progress ...</h3>
</div>
</div>

<div style="display:none;" class="modal-box" data-bind="visible: pdfGenerator.isModalDisplayed">
<!-- ko with: pdfGenerator -->
<div class="modal-box-content">
<h3>Generate a PDF with all the cards</h3>
<div data-bind="visible: exportInactive">It will take approximatively <span data-bind="text: estimatedTime"></span> to complete.</div>
<h3 data-bind="visible: exportActive">Export in Progress ...</h3>
<div data-bind="visible: exportActive, progressBar: { value : progressPercentage }"></div>
<div class="modal-buttons">
<a class="btn primary mainColor2 iconized icon-file-zip" data-bind="visible: exportInactive, click: launchPdfGeneration">Generate the PDF</a>
<a class="btn secondary iconized icon-dismiss" data-bind="visible: exportInactive, click: cancel">Cancel</a>
</div>
</div>
<!-- /ko -->
</div>

</div>
</div>
</div>
Expand All @@ -310,7 +295,7 @@ <h3 data-bind="visible: exportActive">Export in Progress ...</h3>
data-bind="click: exportVM.exportAsSVG"><span>to SVG</span></a></div>
<div class="sub-menu"><a href="#" class="icon-file-zip" title="Export all the cards to a ZIP file"
data-bind="click: exportVM.exportAllToZip"><span>to Zip</span></a></div>
<div class="sub-menu"><a href="#" class="icon-file-zip" title="Export all the cards to a PDF file"
<div class="sub-menu"><a href="#" class="icon-file-pdf" title="Export all the cards to a PDF file"
data-bind="click: pdfGenerator.showPdfModal"><span>to PDF</span></a></div>
</div>
</li>
Expand All @@ -334,6 +319,11 @@ <h3 data-bind="visible: exportActive">Export in Progress ...</h3>
<!-- /ko -->
<!-- /ko -->

<!-- ko if: pdfGenerator != null -->
<!-- ko with: pdfGenerator -->
<modal-pdf-export params="pdfGenerator: $data"></modal-pdf-export>
<!-- /ko -->
<!-- /ko -->

<!-- ViewModels -->
<script src="js/vendor/require.min.js" data-main="js/main.js"></script>
Expand Down
52 changes: 52 additions & 0 deletions src/js/components/modal-pdf-export/modal-pdf-export.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<!-- ko with: viewModel -->
<div style="display:none;" class="modal-box" data-bind="visible: isModalDisplayed">
<div class="modal-box-content">
<div class="modal-close icon icon-dismiss" data-bind="click: cancel"></div>
<h3><span class="icon icon-file-pdf"></span> Export cards to PDF</h3>

<!-- ko with: messageBar -->
<div style="display: none;" class="message-bar" data-bind="html: message, slideIn: isVisible, css: { error: isError, warning: isWarning, info: isInfo, success: isSuccess}"></div>
<!-- /ko -->

<!-- ko with: config -->
<div class="flex-container">
<h4 class="flex-1">Export Configuration</h4>
<div class="modal-buttons flex-1">
<a class="btn" data-bind="click: setInInches, css: { secondary: configInMM, primary: configInInches, mainColor1: configInInches }">in Inches</a>
<a class="btn" data-bind="click: setInMM, css: { secondary: configInInches, primary: configInMM, mainColor1: configInMM }">in Millimeters</a>
</div>
</div>
<div class="flex-container flex-1">
<a class="btn" data-bind="click: setLandscape, css: { secondary: configIsPortrait, primary: configIsLandscape, mainColor1: configIsLandscape }">Landscape</a>
<a class="btn" data-bind="click: setPortrait, css: { secondary: configIsLandscape, primary: configIsPortrait, mainColor1: configIsPortrait }">Portrait</a>
</div>
<div class="flex-container">
<div class="editable-field input-numeric pdf-card-value">
<label>Card Width</label>
<input data-bind="value: displayedWidth"></input>
</div>
<div class="editable-field input-numeric pdf-card-value">
<label>Card Height</label>
<input data-bind="value: displayedHeight"></input>
</div>
</div>
<div class="flex-container">
<div class="editable-field input-numeric pdf-card-value">
<label>Margin between cards</label>
<input data-bind="value: displayedMargin"></input>
</div>
</div>

<!-- /ko -->

<div data-bind="visible: exportInactive">It will take approximatively <span data-bind="text: estimatedTime"></span> to complete.</div>
<h3 data-bind="visible: exportActive">Export in Progress ...</h3>
<div data-bind="visible: exportActive, progressBar: { value : progressPercentage }"></div>

<div class="modal-buttons">
<a class="btn primary mainColor1 iconized icon-file-pdf" data-bind="visible: exportInactive, click: launchPdfGeneration">Generate PDF</a>
<a class="btn secondary iconized icon-dismiss" data-bind="visible: exportInactive, click: cancel">Close</a>
</div>
</div>
</div>
<!-- /ko -->
10 changes: 10 additions & 0 deletions src/js/components/modal-pdf-export/modal-pdf-export.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
define([], function(ko) {

function modalPdfExport(params) {
var self = this;

self.viewModel = params.pdfGenerator;
}

return modalPdfExport;
});
4 changes: 4 additions & 0 deletions src/js/components/registration.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,10 @@ define(['knockout'], function(ko) {
viewModel: { require: 'components/modal-load-save/modal-load-save' },
template: { require: 'text!components/modal-load-save/modal-load-save.html' }
});
ko.components.register('modal-pdf-export', {
viewModel: { require: 'components/modal-pdf-export/modal-pdf-export' },
template: { require: 'text!components/modal-pdf-export/modal-pdf-export.html' }
});

/************/
/* Sections */
Expand Down
2 changes: 1 addition & 1 deletion src/js/viewModels/engineVM.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ define(['knockout',
'viewModels/menuManager',
'viewModels/datastorage/loadsaveVM',
'viewModels/messagebar',
'viewModels/pdfGenerator',
'viewModels/pdf/pdfGenerator',
'FileSaver'
], function(ko, fabric, FieldFactory, CardTemplateVM, UITemplates, Export, MenuManager, LoadSaveVM, MessageBar, PdfGenerator) {

Expand Down
112 changes: 112 additions & 0 deletions src/js/viewModels/pdf/pdfConfig.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
define(['knockout'], function(ko) {

/************************************/
/* Configuration for the PDF Export */
/************************************/
function pdfConfig() {
var self = this;

/*************************/
/* Variables declaration */
/*************************/
self.displayedUnit = ko.observable('i');
self.orientation = ko.observable('l');
self.cardWidthInPoints = ko.observable(200);
self.cardHeightInPoints = ko.observable(300);
self.marginInPoints = ko.observable(0);
self.scale = ko.observable(1.0);

/********************************/
/* End of Variables declaration */
/********************************/
// Displayed Unit
self.configInMM = ko.computed(function() {
return self.displayedUnit() == 'm';
})
self.configInInches = ko.computed(function() {
return self.displayedUnit() == 'i';
})

// Orientation
self.configIsLandscape = ko.computed(function() {
return self.orientation() == 'l';
})
self.configIsPortrait = ko.computed(function() {
return self.orientation() == 'p';
})

// Width & Height
self.setCardDimensions = function(width, height) {
self.cardWidthInPoints(width);
self.cardHeightInPoints(height);
}
self.convertFromDisplayedUnitToPoints = function(unitValue) {
if (self.configInInches()) {
return Math.round(unitValue * 72);
} else if (self.configInMM()) {
return Math.round(unitValue / 0.35277);
}
return unitValue;
}
self.convertFromPointsToDisplayedUnit = function(pointsValue) {
if (self.configInInches()) {
return (pointsValue / 72).toFixed(2);
} else if (self.configInMM()) {
return Math.round(pointsValue * 0.35277);
}
return pointsValue;
}
self.displayedWidth = ko.computed({
read: function () {
return self.convertFromPointsToDisplayedUnit(self.cardWidthInPoints() * self.scale());
},
write: function (value) {
var newWidth = self.convertFromDisplayedUnitToPoints(value);
self.scale(newWidth / self.cardWidthInPoints());
}
});
self.displayedHeight = ko.computed({
read: function () {
return self.convertFromPointsToDisplayedUnit(self.cardHeightInPoints() * self.scale());
},
write: function (value) {
var newHeight = self.convertFromDisplayedUnitToPoints(value);
self.scale(newHeight / self.cardHeightInPoints());
}
});
self.displayedMargin = ko.computed({
read: function () {
return self.convertFromPointsToDisplayedUnit(self.marginInPoints());
},
write: function (value) {
var newMargin = self.convertFromDisplayedUnitToPoints(value);
self.marginInPoints(newMargin);
}
});

/*************************/
/* Functions declaration */
/*************************/
self.setInInches = function() {
self.displayedUnit('i');
}
self.setInMM = function() {
self.displayedUnit('m');
}
self.setLandscape = function() {
self.orientation('l');
}
self.setPortrait = function() {
self.orientation('p');
}

/*******************************/
/*End of Functions declaration */
/*******************************/
}
return {
getPdfConfig: function(cardWidth, cardHeight) {
return new pdfConfig(cardWidth, cardHeight);
}
}
});
Original file line number Diff line number Diff line change
@@ -1,21 +1,26 @@
define(['knockout', 'pdfmake'], function(ko, pdfMake) {
define(['knockout', 'pdfmake', 'viewModels/messagebar', 'viewModels/pdf/pdfConfig'],
function(ko, pdfMake, MessageBar, pdfConfig) {

/***********************************************************************/
/* ViewModel for Exporting the Cards (unique or list, svg or png, ...) */
/***********************************************************************/
/***************************************************/
/* ViewModel for Exporting the Cards as a PDF file */
/***************************************************/
function pdfGenerator(engineVM) {
var self = this;

/*************************/
/* Variables declaration */
/*************************/
self.mainEngineVM = engineVM;
self.messageBar = MessageBar.getMessageBar();

// Displaying the Modal Export Frame
self.isModalDisplayed = ko.observable(false);
self.indexCurrentExportedFile = ko.observable(-1);
self.totalExportedFiles = ko.observable(-1);

// Export configuration
self.config = pdfConfig.getPdfConfig();

// Export currently in progress
self.isExportInProgress = ko.observable(false);

Expand Down Expand Up @@ -50,6 +55,10 @@ define(['knockout', 'pdfmake'], function(ko, pdfMake) {
self.totalExportedFiles(self.mainEngineVM.listCards().length);
self.isExportInProgress(false);
self.listDataUrls = [];
if (self.mainEngineVM.cardTemplate() != null) {
self.config.scale(1.0);
self.config.setCardDimensions(self.mainEngineVM.cardTemplate().canvasWidth(), self.mainEngineVM.cardTemplate().canvasHeight());
}
}
self.cancel = function() {
self.isModalDisplayed(false);
Expand Down Expand Up @@ -78,10 +87,44 @@ define(['knockout', 'pdfmake'], function(ko, pdfMake) {
}

self.integratesCardsIntoPdf = function() {
var docDef = { content: [] };
var docDef = { };
docDef.pageOrientation = self.config.configIsLandscape() ? 'landscape' : 'portrait';
docDef.pageSize = 'A4';
docDef.pageMargins = [ 40, 60, 40, 60 ];
var pageWidthContent = (self.config.configIsLandscape() ? 841.89 : 595.28) - 40*2;
var pageHeightContent = (self.config.configIsLandscape() ? 595.28 : 841.89) - 60*2;
var startX = 40;
var startY = 60;
var currentX = 0;
var currentY = 0;
var maxHeightInRow = 0;
var margin = self.config.marginInPoints();
docDef.content = [];

_.forEach(self.listDataUrls, function(dataUrl) {
docDef.content.push({ image: dataUrl, width: 250 });
})
var elementWidth = dataUrl.width * self.config.scale();
var elementHeight = dataUrl.height * self.config.scale();
var element = { image: dataUrl.dataUrl, width: elementWidth, height: elementHeight };

// New Row !
if ((currentX != 0) && ((currentX + elementWidth) > pageWidthContent)) {
currentX = 0;
currentY += margin + maxHeightInRow;
maxHeightInRow = 0;
}
// New Page !
if ((currentY != 0) && ((currentY + elementHeight) > pageHeightContent)) {
currentY = 0;
currentX = 0;
element.pageBreak = 'before';
}
element.absolutePosition = { x: startX + currentX, y: startY + currentY };
docDef.content.push(element);

currentX += margin + elementWidth;
maxHeightInRow = Math.max(maxHeightInRow, elementHeight);
});

pdfMake.createPdf(docDef).download();
self.cancel();
}
Expand All @@ -90,7 +133,11 @@ define(['knockout', 'pdfmake'], function(ko, pdfMake) {
if (self.mainEngineVM.editableCard() != null) {
//var canvas = document.getElementById('fabricjs-canvas');
var dataUrl = self.mainEngineVM.canvas.toDataURL({ format: 'png' });
self.listDataUrls.push(dataUrl);
self.listDataUrls.push({
dataUrl: dataUrl,
width: 340,
height: 495
});
}
}

Expand Down
33 changes: 33 additions & 0 deletions src/less/basic-flex.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// main: ./styles.less

/*******************/
/* Flex management */
/*******************/

.flex-container {
display: flex;
}

.flex-1 {
flex: 1;
}

.flex-2 {
flex: 2;
}

.flex-3 {
flex: 3;
}

.flex-4 {
flex: 4;
}

.flex-5 {
flex: 5;
}

.flex-6 {
flex: 6;
}
6 changes: 5 additions & 1 deletion src/less/modal-export.less
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@

&.selected {
background: darken(@mainColor1, 10%);
color: @verticalMenuHighlight;
color: @verticalMenuHighlight;
}
}
}
Expand All @@ -60,3 +60,7 @@
.format-description {
text-align: center;
}

.pdf-card-value {
margin-right: 30px;
}

0 comments on commit a3d06f2

Please sign in to comment.