Protocol error (page.printToPdf) page range exceeds page count Puppeteer - node.js

const webPage = await browser.newPage();
await webPage.goto(printUrl, { waitUntil: 'networkidle2',});
const pdf1Bytes= await webPage.pdf({
path: filePartOne,
format: 'Letter',
printBackground: true,
preferCSSPageSize: true,
displayHeaderFooter: true,
footerTemplate:footer,
headerTemplate:headerOne,
defaultFontSize:'40px',
margin: {
top: "30mm",
bottom: "25mm",
right: "10mm",
left: "15mm",
},
pageRanges: '1-'+(headerStartPage-1),
});
const pdf2Bytes = await webPage.pdf({
path: filePartTwo,
format: 'Letter',
printBackground: true,
preferCSSPageSize: true,
displayHeaderFooter: true,
footerTemplate:footer,
headerTemplate:headerTwo,
defaultFontSize:'40px',
margin: {
top: "30mm",
bottom: "25mm",
right: "10mm",
left: "15mm",
},
pageRanges: headerStartPage+'-',
});
await browser.close();

Related

ChartJS label font size is scaled up and squeezed together

I have a nodejs app which is generating chartjs diagram images. In local the label is fine it looks like this:
But when I deploy exactly the same code to azure it looks like the label is scaled up and jammed.
My dependencies are "dependencies": { "chart.js": "2.7.3", "chartjs-node-canvas": "3.2.0"} and this is my chart config:
options: {
maintainAspectRatio: false,
legend: {
display: false
},
tooltips: {
enabled: false
},
animation: {
duration: 0
},
elements: {
line: {
cubicInterpolationMode: 'monotone'
}
},
scales: {
xAxes: [{
type: 'linear',
display: true,
ticks: {
autoSkip: true,
fontColor: gray,
fontSize: 14,
maxRotation: 0,
min: 0,
minRotation: 0,
padding: 10
},
gridLines: {
color: 'transparent',
lineWidth: 0,
drawTicks: false,
zeroLineColor: gray,
zeroLineWidth: 2
},
scaleLabel: {
display: true,
labelString: xLabel,
fontColor: gray,
fontSize: 14
}
}],
yAxes: [{
display: true,
id: this.yAxisId,
position: 'left',
ticks,
gridLines: {
color: transparentGray,
lineWidth: 1,
drawTicks: false,
zeroLineColor: gray,
zeroLineWidth: 2
},
scaleLabel: {
display: true,
labelString: yLabel,
fontColor: gray,
fontSize: 14
}
}]
}
Something is wrong with my options and then why it works perfectly fine on local?

JointJS how to create a HTML select (drop down) inside a shape object

I am looking for best practises or advice in how to create interactive elements within Shapes (elements) using the JointJS (Rappid) library.
This is what I have done currently:
The code
const shape = new joint.shapes.basic.Generic({
type: 'shape',
attrs: {},
markup: [
{
tagName: 'foreignObject',
selector: 'foreignObject',
attributes: {
x: '10',
y: '10',
width: '60',
height: '100',
},
children: [
{
tagName: 'div',
namespaceURI: 'http://www.w3.org/1999/xhtml',
selector: 'content',
style: {
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
},
children: [
{
tagName: 'select',
selector: 'select',
style: {
'z-index': 1,
},
children: [
{
tagName: 'option',
value: 'test1',
textContent: 'test 1',
},
{
tagName: 'option',
value: 'test2',
textContent: 'test 2',
},
],
},
],
},
],
},
],
});
You can see there is a shape rendered and it has a select element in it by using a foreignObject (https://developer.mozilla.org/en-US/docs/Web/SVG/Element/foreignObject).
However, using foreignObject is troublesome due to that they do not play well in browsers and the drop down you see here doesn't actually work.
I could start hacking around and get it to work but this is the point of the question, is there a cleaner way in achieving this?
I need something like this
https://resources.jointjs.com/tutorial/html-elements
But the html library is now decrepitated and JointJS wants you to use markup JSON instead.
Lastly, I have seen this post which doesn't fill me much with confidence...
https://groups.google.com/g/jointjs/c/-yXXlnreq6M
But I am hoping as this is from 5 years ago, it is outdated and we don't need to have to do the workarounds as it suggests?
HTML can be added inside foreignObject, but as you mentioned there can be some issues in browsers. One example of using foreignObject can be found here.
The code demonstrates how to create a text input with foreignObject.
var paper = new joint.dia.Paper({
el: document.getElementById('paper'),
width: 650,
height: 400,
gridSize: 10,
model: graph,
guard: function(evt) {
return evt.target instanceof HTMLInputElement;
}
});
paper.on('blank:pointerdown cell:pointerdown', function() {
document.activeElement.blur();
});
var Example = joint.dia.Element.define('example.ForeignObject', {
attrs: {
body: {
refWidth: '100%',
refHeight: '100%',
stroke: '#333333',
fill: '#ffffff',
strokeWidth: 2
},
foreignObject: {
refWidth: '100%',
refHeight: '100%'
}
}
}, {
markup: [{
tagName: 'rect',
selector: 'body'
}, {
tagName: 'foreignObject',
selector: 'foreignObject',
attributes: {
'overflow': 'hidden'
},
children: [{
tagName: 'div',
namespaceURI: 'http://www.w3.org/1999/xhtml',
selector: 'content',
style: {
fontSize: 14,
width: '100%',
height: '100%',
position: 'static',
backgroundColor: 'transparent',
textAlign: 'center',
margin: 0,
padding: '0px 10px',
boxSizing: 'border-box',
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center'
},
children: [{
tagName: 'span',
textContent: 'First Name'
}, {
tagName: 'input',
selector: 'firstname',
attributes: {
'type': 'input',
'name': 'firstname'
},
style: {
position: 'static',
width: '100%'
}
}, {
tagName: 'span',
textContent: 'Last Name'
}, {
tagName: 'input',
selector: 'lastname',
attributes: {
'type': 'input',
'name': 'lastname'
},
style: {
position: 'static',
width: '100%'
}
}]
}]
}]
}, {
attributes: {
value: {
set: function(text, _, node) {
if ('value' in node) node.value = text;
}
}
}
});
joint.shapes.example.ForeignObjectView = joint.dia.ElementView.extend({
events: {
'change input': 'onInputChange'
},
onInputChange: function(evt) {
var input = evt.target;
this.model.attr(input.name + '/value', input.value);
}
});
The article that you linked is deprecated, but there is an updated version of creating elements with a HTML face here. You can see some select fields demonstrated there, but it is a little more involved.

Have jest log parameters passed into a function that resulted in a test failure

I am working on a series of jest test scripts, and to make the code a bit tighter, I am putting them in an array:
test('buttonPadding', function () {
const expectedResults = [
{ iconPosition: 'center', small: true, expectedResult: undefined },
{ iconPosition: 'center', small: false, expectedResult: undefined },
{ iconPosition: 'left', small: true, expectedResult: '10px 20px 10px 20px' },
{ iconPosition: 'left', small: false, expectedResult: '17px 42px 18px 42px' },
{ iconPosition: 'right', small: true, expectedResult: '10px 20px 10px 20px' },
{ iconPosition: 'right', small: false, expectedResult: '17px 42px 18px 42px' },
];
expectedResults.forEach(({ iconPosition, small, expectedResult }) => {
expect(buttonPadding({ iconPosition, small })).toEqual(expectedResult);
});
});
The downside is when an error occurs, it shows the expect(buttonPad... line as where the error occurred, but doesn't show what the parameters were that got passed into the tested function.
Is there something that can be passed to the expect() function that will allow you to output some type of log when an error occurs so I can see what made the test fail?
What I would like to know is what iconPosition and small were equal to to get the test to fail.
I can also suggest using describe.each or test.each like this:
describe.each(
[
['center', true, undefined],
['center', false, undefined],
['left', true, '10px 20px 10px 20px'],
['left', false, '17px 42px 18px 42px'],
['right', true, '10px 20px 10px 20px'],
['right', false, '17px 42px 18px 42px'],
]
)('with params (%p, %p)', (iconPosition, small, expectedResult) => {
it(`should return: ${expectedResult}`, () => {
expect(buttonPadding({ iconPosition, small })).toEqual(expectedResult);
})
});
example
Found a better way, and one where tests are more isolated by putting the foreach outside of the test()
[
{ iconPosition: 'center', small: true, expectedResult: undefined },
{ iconPosition: 'center', small: false, expectedResult: undefined },
{ iconPosition: 'left', small: true, expectedResult: '10px 20px 10px 20px' },
{ iconPosition: 'left', small: false, expectedResult: '17px 42px 18px 42px' },
{ iconPosition: 'right', small: true, expectedResult: '10px 20px 10px 20px' },
{ iconPosition: 'right', small: false, expectedResult: '17px 42px 18px 42px' },
].forEach( ({iconPosition, small, expectedResult}) => {
test(`buttonPadding with params (${iconPosition}, ${small}) => ${expectedResult}`, function () {
expect(buttonPadding({ iconPosition, small })).toEqual(expectedResult);
});
});
By passing the names into the test log it can show what was passed in and what the result should be when it fails.

jqGrid export to excel issue when loadonce option is setted to false

I have an ASP.net MVC solution and use jqGrid in it. To have a better performance I use loadonce: false as an option and it should be in this way, unfortunately It seems to be not supported by jqGrid because I cannot find any sign of that throughout my search.
$(document).ready(function () {
$("#jqGrid").jqGrid(
{
url: "/Student/GetStudents",
mtype: "GET",
datatype: "json",
contentType: "application/json; charset-utf-8",
jsonReader: {
root: "rows",
id: "StudentId",
repeatitems: false
},
colNames: ['StudentId', 'FirstName', 'LastName'],
colModel: [
{ label: 'StudentId', name: 'Id', key: true, width: 75 },
{ label: 'FirstName', name: 'FirstName', width: 150 },
{ label: 'LastName', name: 'LastName', width: 150 },
],
viewrecords: true,
loadonce: false,
width: '100%',
height: 'auto',
rowNum: 20,
rowList: [20, 30, 50],
sortable: true,
sortname: 'Id',
pager: "#jqGridPager",
autoencode: true,
scroll: false,
pgbuttons: true,
autowidth: true,
shrinkToFit: false,
forceFit: false,
gridview: false,
height: '100%',
scrollrows: true,
page: 1,
//pagerpos: 'center',
toppager: true,
recordpos: 'right',
multiselect: true,
multiboxonly: true,
direction: 'rtl',
ignoreCase: true,
caption: "",
rownumbers: true
});
$('#jqGrid').jqGrid('navGrid', '#jqGridPager', {
search: true,
searchtext: "Search",
edit: false,
add: false,
del: false,
excel: true,
refresh: false,
}, {}, {}, {}, {
closeOnEscape: true,
closeAfterSearch: true,
ignoreCase: true,
multipleSearch: false,
multipleGroup: false,
showQuery: false,
sopt: ['cn', 'eq', 'ne'],
defaultSearch: 'cn'
})
$('#jqGrid').jqGrid('navButtonAdd', '#jqGridPager', {
caption: "Export to Excel",
//buttonicon: "ui-icon-disk",
buttonicon: "ui-icon-folder-open",
onClickButton: function () {
exportToExcel();
},
});
});
function exportToExcel(data, e) {
exportExcelFile(data);
}
function exportExcelFile() {
debugger;
var data = $('#jqGrid')[0].addLocalData(true);
var ua = window.navigator.userAgent;
var msie = ua.indexOf("MSIE");
if (msie > 0 || !!navigator.userAgent.match(/Trident.*rv\:11\./)) {
frame1.document.open("txt/html", "replace");
frame1.document.write(setTableOfData(data));
frame1.document.close();
frame1.focus();
sa = frame1.document.execCommand("SaveAs", true, "text.xls");
} else
$('#jqGrid').jqGrid('exportToExcel', { fileName: "exportedExcel.xls", navigator: true });
}
function setTableOfData(data) {
var htmlString = '<table>';
var header = '<tr><td>StudentId</td><td>FirstName</td><td>LastName</td></tr>';
htmlString += header;
for (var i = 0; i < data.length; i++) {
var tag = '<tr><td>' + data[i].Id + '</td><td>' + data[i].FirstName + '</td><td>' + data[i].LastName + '</td></tr>';
htmlString += tag;
}
htmlString += '</table>';
return htmlString;
}
Finally, I forced to post all the filtering and other settings of the grid to the server and return a link to the client. Then with the given link I became able to download the excel file.
Info: you can not download a file with post(ajax) request.

ExtJS Advanced Fluid Border Layout

I need to create an advanced, fluid Border layout for our Report system.
The West pane would be split into 2 separate panes, top for the filter form, and the bottom for navigation.
The Center pane would be split into 3 separate panes, top for the primary data grid, and 2 bottom panes for sub report grids. I may at some point need 3 bottom panes, but I'm hoping to avoid that.
Here is an example of what I am looking for: http://dl.dropbox.com/u/298258/Amistaff/desiredLayout.png
What I have so far is definitely less than satisfactory.
http://dl.dropbox.com/u/298258/Amistaff/currentLayout.png
Here is the code:
var ReportForm = new Ext.FormPanel({
url: '',
frame: false,
border: false,
title: 'Filter Results',
width: 260,
labelWidth: 50,
padding: '10 0 0 5',
standardSubmit: true,
items: [
{
fieldLabel: 'Client',
hiddenName: 'ClientID',
mode: 'local',
store: frmClientStore,
displayField: 'CompanyName',
valueField: 'ClientID',
width: 150,
editable: true,
triggerAction: 'all',
xtype: 'combo'
}
],
buttons: [
{text:'Export',handler:function(){}},
{text:'Search',handler:function(){}},
{text:'Reset',handler:function(){}}
]
});
var ReportGrid = new Ext.grid.GridPanel({
id: 'ReportGrid',
width: '100%',
height: '50%',
viewConfig: {
forceFit: true
},
autoHeight: true,
loadMask: true,
stripeRows: true,
store: ReportStore,
margins: '5 5 5 5',
cm: ReportColumnModel
,bbar: new Ext.PagingToolbar
(
{
pageSize: 10,
store: ReportStore,
displayInfo: true,
displayMsg: 'Displaying results {0} - {1} of {2}'
}
)
});
var viewport = new Ext.Viewport({
layout: 'border',
items: [
{
region: 'west',
layout: 'vbox',
layoutConfig: {
align: 'stretch'
},
width: 260,
minSize: 175,
maxSize: 400,
margins: '5 5 5 5',
items: [
ReportForm,
{
region: 'south',
title: 'Superuser',
border: false,
xtype: 'tabpanel',
activeTab: 0,
items: [
{
title: 'General',
xtype: 'panel',
height: 200,
html: '',
},
{
title: 'Exams',
height: 200,
html: ''
}
]
}
]
},
new Ext.Panel({
region: 'center',
deferredRender: false,
layout: 'fit',
margins: '5 5 5 0',
items: [
ReportGrid,
new Ext.Panel({
region: 'south',
border: false,
height: '50%',
html: 'foo',
layout: 'fit',
items: [
new Ext.Panel({
region: 'west',
width: '50%',
border: false,
html: 'West'
}),
new Ext.Panel({
region: 'east',
width: '50%',
border: false,
html: 'East'
})
]
})
]
})
]
});
Thanks...
EDIT:
Many thanks to amol for the answer below. I have one additional question. If I collapse the form in the west region, how do I make it resize the navigation panel to fill the remaining space?
code -
var ReportForm = new Ext.FormPanel({
url: '',
frame: false,
border: false,
title: 'Filter Results',
width: 260,
labelWidth: 50,
padding: '10 0 0 5',
standardSubmit: true,
items: [
{
fieldLabel: 'Client',
hiddenName: 'ClientID',
mode: 'local',
//store: frmClientStore,
displayField: 'CompanyName',
valueField: 'ClientID',
width: 150,
editable: true,
triggerAction: 'all',
xtype: 'combo'
}
],
buttons: [
{text:'Export',handler:function(){}},
{text:'Search',handler:function(){}},
{text:'Reset',handler:function(){}}
]
});
var ReportGrid = new Ext.grid.GridPanel({
id: 'ReportGrid',
flex:1,
viewConfig: {
forceFit: true
},
loadMask: true,
stripeRows: true,
//store: ReportStore,
margins: '5 5 5 5',
cm: new Ext.grid.ColumnModel({
columns:[
{header:'A column', dataIndex:'afield'},
{header:'B column', dataIndex:'bfield'}
]
}),
store:new Ext.data.ArrayStore({
autoLoad:true,
fields:['afield', 'bfield'],
data:[['value 1','value 3'],['value 2', 'value4']]
}),
bbar: new Ext.PagingToolbar
(
{
pageSize: 10,
//store: ReportStore,
displayInfo: true,
displayMsg: 'Displaying results {0} - {1} of {2}'
}
)
});
var viewport = new Ext.Viewport({
layout: 'border',
items: [
{
region: 'west',
layout: 'vbox',
layoutConfig: {
align: 'stretch'
},
width: 260,
minSize: 175,
maxSize: 400,
margins: '5 5 5 5',
items: [
ReportForm,
{
region: 'south',
title: 'Superuser',
border: false,
xtype: 'tabpanel',
activeTab: 0,
items: [
{
title: 'General',
xtype: 'panel',
height: 200,
html: ''
},
{
title: 'Exams',
height: 200,
html: ''
}
]
}
]
},
new Ext.Panel({
region: 'center',
deferredRender: false,
layout: 'vbox',
layoutConfig:{align:'stretch'},
margins: '5 5 5 0',
items: [
ReportGrid,
{
border: false,
flex:1,
layout: 'hbox',
layoutConfig:{align:'stretch'},
defaults:{flex:1},
items: [
new Ext.Panel({
html: 'West'
}),
new Ext.Panel({
html: 'East'
})
]
}
]
})
]
});

Resources