I try to have a response on my request GraphQL.
I tried many things but currently I have always the Sequence response, and no the Buckets response (belongs To relation).
I have 2 tables :
Sequence [id | is_active]
Bucket [id | fk_language_id | fk_sequence_id | is_active]
model/sequence.js
'use strict';
module.exports = (sequelize, DataTypes) => {
// define sequence
const Sequence = sequelize.define('sequence', {
is_active: {type: DataTypes.BOOLEAN}
});
Sequence.associate = function (models) {
models.Sequence.hasMany(models.Bucket, {
foreignKey: 'fk_sequence_id'
});
return Sequence;
};
model/bucket.js
'use strict';
module.exports = (sequelize, DataTypes) => {
const Bucket = sequelize.define('bucket', {
code : {type: DataTypes.STRING},
is_active: {type: DataTypes.BOOLEAN}
});
Bucket.associate = function (models) {
models.Bucket.belongsTo(models.Language, {
foreignKey: 'fk_language_id',
});
models.Bucket.belongsTo(models.Sequence, {
foreignKey: 'fk_sequence_id',
});
};
return Bucket;
};
schema.js
# Sequence
type Sequence {
id: Int!,
code: String,
buckets: [Bucket],
is_active: Boolean
}
# Bucket
type Bucket {
id: Int!,
code: String
blocks: [Block]
is_active: Boolean
}
# SequenceInput
input SequenceInput {
buckets: [BucketInput],
is_active: Boolean
}
# BucketInput
input BucketInput {
code: String,
fk_language_id: Int,
fk_sequence_id: Int,
is_active: Boolean
}
type Query {
sequences: [Sequence]
sequence(id: Int): Sequence
buckets: [Bucket]
bucket(id: Int): Bucket
}
type Mutation {
createSequence(input: SequenceInput): Sequence,
}
Request GraphQL
mutation {
createSequence(input: {
is_active: false,
buckets: [
{fk_language_id: 2, code: "Test"}
]
}) {
is_active,
buckets {
id,
code
}
}
}
But I have this result, the Buckets doesn't load :
{
"data": {
"createSequence": {
"is_active": false,
"buckets": []
}
}
}
my mutation :
...
Sequence : {
buckets(sequence) {
return models.Bucket.findAll({
where: {id: sequence.id}
});
},
...
},
...
Mutation : {
createSequence(_, {input}) {
let sequenceId = 0;
// Create Sequence
return models.Sequence.create(input)
.then((sequence) => {
sequenceId = sequence.id;
console.log('sequence created');
// Create Bucket
// Foreach on buckets
return Promise.map(input.buckets, function (bucket) {
bucket.fk_sequence_id = sequenceId;
console.log('bucket created');
return models.Bucket.create(bucket);
})
})
.then(() => {
console.log('load created', sequenceId);
return models.Sequence.findOne({
where : {id: sequenceId},
include: [
{
model: models.Bucket,
where: { fk_sequence_id: sequenceId }
}
]
}).then((response) => {
console.log(response);
return response;
})
});
},
}
The final console.log show many informations...
sequence {
dataValues:
{ id: 416,
is_active: false,
created_at: 2019-03-29T20:33:56.196Z,
updated_at: 2019-03-29T20:33:56.196Z,
buckets: [ [Object] ] },
_previousDataValues:
{ id: 416,
is_active: false,
created_at: 2019-03-29T20:33:56.196Z,
updated_at: 2019-03-29T20:33:56.196Z,
buckets: [ [Object] ] },
_changed: {},
_modelOptions:
{ timestamps: true,
validate: {},
freezeTableName: true,
underscored: false,
paranoid: false,
rejectOnEmpty: false,
whereCollection: { id: 416 },
schema: null,
schemaDelimiter: '',
defaultScope: {},
scopes: {},
indexes: [],
name: { plural: 'sequences', singular: 'sequence' },
omitNull: false,
createdAt: 'created_at',
updatedAt: 'updated_at',
sequelize:
Sequelize {
options: [Object],
config: [Object],
dialect: [Object],
queryInterface: [Object],
models: [Object],
modelManager: [Object],
connectionManager: [Object],
importCache: [Object],
test: [Object] },
hooks: {} },
_options:
{ isNewRecord: false,
_schema: null,
_schemaDelimiter: '',
include: [ [Object] ],
includeNames: [ 'buckets' ],
includeMap: { buckets: [Object] },
includeValidated: true,
attributes: [ 'id', 'is_active', 'created_at', 'updated_at' ],
raw: true },
isNewRecord: false,
buckets:
[ bucket {
dataValues: [Object],
_previousDataValues: [Object],
_changed: {},
_modelOptions: [Object],
_options: [Object],
isNewRecord: false } ] }
Your mutation resolver returns a Promise, which resolves into a Model instance. The promise in question is returned on this line:
return models.Sequence.create(input)
.
As such, the server will wait until that promise is resolved before passing the value forward. Other actions were also waiting on that promise, but they were not the promises returned, so they will not be waited for.
All you have to do is wait for all of your operations to finish before resolving your promise.
createSequence: async (parent, { input }) => {
const sequence = await models.Sequence.create({
is_active: input.is_active
})
if (!input.buckets) return sequence
// You may have to modify your Sequence.buckets resolver to avoid fetching buckets again.
sequence.buckets = await Promise.all(input.buckets.map(bucket => {
// You can avoid these if checks by implementing stricter input types.
// e.g. buckets: [BucketInput!]!
if (!bucket) return null
return models.Bucket.create({
...bucket,
fk_sequence_id: sequence.id
})
}))
return sequence
}
Also, make sure your Sequence.buckets resolver isn't overwriting buckets with faulty data. The resolver you've provided will try to match bucket primary keys with a sequence primary key instead of matching the correct foreign keys with a primary key.
Here's a resolver that will work:
buckets: (parent) => (
parent.buckets // This line may conflict with some of your code and cause problems.
|| models.Bucket.findAll({
where: {fk_sequence_id: parent.id}
})
)
i am using highcharts-export-server for export charts and send it to Email in PDF format
while i am trying to export that in localy it was working fine, but on live server when i am trying to export all the charts data-labels disappear.
this is the image from which was exporting from live server.
and here is the image which was exporting locally.
Here is my Code
exports.getPieChartImg = (seriesData, xOrLength, innersize, showLegend, width, height) => {
var chartOpts = {
chart: {
type: 'pie',
width: width,
height: height,
},
plotOptions: {
pie: {
innerSize: innersize || 80,
depth: 25,
allowPointSelect: true,
dataLabels: {
enabled: false,
format: '<b>{point.name}</b>: {point.percentage:.2f} %'
},
showInLegend: showLegend || false,
},
series: {
stacking: 'normal',
dataLabels: {
enabled: true,
color: '#6f6f6f',
format: '{point.percentage:.2f}',
crop: false,
overflow: "none",
},
pointWidth: 30,
}
},
legend: {
labelFormat: '<b>{name}</b> ({percentage:.2f})%',
useHTML: true,
},
series: [{
data: seriesData
}]
};
var exportSettings = generateExportSettings(chartOpts, 'Pie');
return generateBase64Chart(exportSettings)
}
function generateExportSettings(chartOpts, constr) {
return {
// b64: true,
instr: JSON.stringify(chartOpts),
noDownload: true,
constr,
globalOptions: {
colors: ['#3BB9DA', '#0F89A8', '#0B8F8B', '#1DB1AD', '#68E3DF', '#FFB469', '#F58B1F', '#D16900', '#FC3C3C', '#FF6666', '#FC8D8D', '#FCC0C0'],
lang: {
thousandsSep: ','
}
},
scale: false,
styledMode: false,
type: "image/png",
width: false,
};
}
function generateBase64Chart(exportSettings) {
return new Promise((resolve, reject) => {
highchartsExporter.export(exportSettings, function (err, res) {
if (err) {
return reject({
code: '1',
err,
msg: 'Error in stock chart',
exportSettings
})
}
return resolve({
code: '0',
msg: 'success',
data: 'data:image/png;base64,' + res.data,
})
});
})
}
remove node_module and reInstall it again.
and if not installed libfontconfig then install 'sudo apt-get install libfontconfig'
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.
how to work on add row, edit, del the row in jqgrid? how to invoke editurl??
my code is below... jqgrid.php page.
var $mygrid= jQuery("#list").jqGrid({
url:'example.php',
datatype: 'xml',
mtype: 'GET',
colNames:['Seq','Name', 'ID','Pass','Mail','Note'],
colModel :[
{name:'seq',index:'seq', width:55, resizable:false, editable:true, editoptions:{readonly:true,size:10}},
{name:'name',index:'name', width:90,resizable:false, editable:true, editoptions:{readonly:false,size:10}},
{name:'id',index:'id', width:80, align:'right', editable:true, editoptions:{readonly:false,size:10}},
{name:'pass',index:'pass', width:80, align:'right', sortable:false, editable:true, editoptions:{readonly:false,size:10}},
{name:'mail',index:'mail', width:80,align:'right', sortable:false, editable:true, editoptions:{readonly:false,size:10}},
{name:'id',index:'id', width:150, sortable:false} ],
pager: jQuery('#pager'),
rowNum:10,
rowList:[10,20,30,50],
sortname: 'seq',
sortorder: "Asc",
width: 1000,
height: 230,
viewrecords: true,
multiselect: true,
editable: true,
toolbar: [true,"top"],
multikey: "ctrlKey",
editurl:'add.php',
caption: 'staff'
});
$("#list").jqGrid('navGrid', '#pager', {
edit: true,
add: true,
del: true,
search: false,
refresh:false
})
});
And example.php code is
enter code here <?php
$dbhost = 'localhost';
$dbuser = 'test';
$dbpassword = 'test';
$database = 'cs_test';
$page = $_GET['page'];
// get how many rows we want to have into the grid - rowNum parameter in the grid
$limit = $_GET['rows'];
// get index row - i.e. user click to sort. At first time sortname parameter -
// after that the index from colModel
$sidx = $_GET['sidx'];
// sorting order - at first time sortorder
$sord = $_GET['sord'];
// if we not pass at first time index use the first column for the index or what you want
if(!$sidx) $sidx =1;
// connect to the MySQL database server
$db = mysql_connect($dbhost, $dbuser, $dbpassword) or die("Connection Error: " . mysql_error());
// select the database
mysql_select_db($database) or die("Error conecting to db.");
// calculate the number of rows for the query. We need this to paging the result
$result = mysql_query("SELECT COUNT(*) AS count FROM TM_Staff");
$row = mysql_fetch_array($result,MYSQL_ASSOC);
$count = $row['count'];
// calculation of total pages for the query
if( $count > 0 ) {
$total_pages = ceil($count/$limit);
//$total_pages = 20;
} else {
$total_pages = 0;
}
if ($page > $total_pages) $page=$total_pages;
$start = $limit*$page - $limit;
if($start<0) $start = 0;
// the actual query for the grid data
$SQL = "SELECT seq,name,id,pass,mail,ins_dt from TM_Staff ORDER BY $sidx $sord LIMIT $start,$limit";
$result = mysql_query( $SQL ) or die("Couldn t execute query.".mysql_error());
if ( stristr($_SERVER["HTTP_ACCEPT"],"application/xhtml+xml") ) {
header("Content-type: application/xhtml+xml;charset=utf-8");
} else {
header("Content-type: text/xml;charset=utf-8");
}
echo "<?xml version='1.0' encoding='utf-8'?>";
echo "<rows>";
echo "<page>".$page."</page>";
echo "<total>".$total_pages."</total>";
echo "<records>".$count."</records>";
// be sure to put text data in CDATA
while($row = mysql_fetch_array($result,MYSQL_ASSOC)) {
echo "<row id='". $row[seq]."'>";
echo "<cell>". $row[seq]."</cell>";
echo "<cell>". $row[name]."</cell>";
echo "<cell>". $row[id]."</cell>";
echo "<cell>". $row[pass]."</cell>";
echo "<cell>". $row[mail]."</cell>";
echo "<cell><![CDATA[". $row[id]."]]></cell>";
echo "</row>";
}
echo "</rows>";
?>
plz help me, im in trouble...
var lastSel;
$(function () {
$("#grid").jqGrid({
colNames: ['Name', 'Address', 'Contact', 'Pan Number', 'Registration Number', 'Email Address', 'File'],
colModel: [
{ name: 'Name', index: 'Name', sortable: true, align: 'left', title: false, width: 200, editable: true, edittype: 'text', editrules: { required: true }, formoptions: { elmprefix: '* ' }, searchoptions: { sopt: ['eq', 'ne', 'bw', 'bn', 'ew', 'en', 'cn', 'nc']} },
{ name: 'Address', index: 'Address', sortable: true, title: false, align: 'left', width: 220, editable: true, edittype: 'text', editrules: { required: true }, formoptions: { elmprefix: '* ' }, searchoptions: { sopt: ['eq', 'ne', 'bw', 'bn', 'ew', 'en', 'cn', 'nc']} },
{ name: 'Contact', index: 'Contact', sortable: true, title: false, align: 'left', width: 200, editable: true, edittype: 'text', editrules: { required: true }, formoptions: { elmprefix: '* ' }, searchoptions: { sopt: ['eq', 'ne', 'bw', 'bn', 'ew', 'en', 'cn', 'nc']} },
{ name: 'PanNumber', index: 'PanNumber', sortable: true, title: false, align: 'left', width: 200, editable: true, edittype: 'text', editrules: { required: true }, formoptions: { elmprefix: '* ' }, searchoptions: { sopt: ['eq', 'ne', 'bw', 'bn', 'ew', 'en', 'cn', 'nc']} },
{ name: 'ServiceTaxRegistrationNo', index: 'ServiceTaxRegistrationNo', title: false, sortable: true, align: 'left', width: 240, editable: true, edittype: 'text', editrules: { required: true }, formoptions: { elmprefix: '* ' }, searchoptions: { sopt: ['eq', 'ne', 'bw', 'bn', 'ew', 'en', 'cn', 'nc']} },
{ name: 'Email', index: 'Email', sortable: true, align: 'left', title: false, width: 190, editable: true, edittype: 'text', editrules: { required: true, email: true }, formoptions: { elmprefix: '* ' }, search: false },
{ name: 'FilePath', index: 'FilePath', sortable: false, title: false, align: 'left', editable: true, edittype: 'file', width: 190, allowedExtensions: ['jpg', 'jpeg', 'png', 'gif'],
search: false, editoptions: {
enctype: "multipart/form-data"
}
},
],
pager: jQuery("#pager"),
sortname: 'Name',
rowNum: 10,
rowList: [10, 20, 25],
sortOrder: "",
height: 225,
viewrecords: true,
rownumbers: true,
caption: "Companies",
width: 950,
imgpath: '/Content/themes/smoothness/images',
url: "/Master/GetCompanies",
editurl: "/Master/PerformCompanyCRUDAction",
datatype: "json",
mtype: "GET",
onCellSelect: function (rowid, iCol, aData) {
if (rowid && rowid !== lastSel) {
if (lastSel) {
$("#" + lastSel).removeClass('state-active');
$("#" + lastSel).addClass('ui-widget-content');
}
$("#" + rowid).removeClass('ui-widget-content');
$("#" + rowid).addClass('state-active');
lastSel = rowid;
}
}
});
jQuery("#grid").jqGrid('navGrid', '#pager',
{ edit: true, add: true, del: true, search: true, refresh: true },
{ closeOnEscape: true, reloadAfterSubmit: true, modal: true,
beforeShowForm: function (formid) {
$("#pData, #nData").hide();
},
onInitializeForm: function (formid) {
$(formid).attr('method', 'POST');
$(formid).attr('action', '');
$(formid).attr('enctype', 'multipart/form-data');
},
test: function () {
var filenam = $("#FilePath").val();
},
afterSubmit: function (response, postdata) {
$.ajaxFileUpload({
url: '/Master/CompanyFileUpload?CompanyId=' + postdata.id,
secureuri: false,
data: postdata,
cache: false,
contentType: 'multipart/form-data',
processData: false,
type: 'POST',
fileElementId: 'FilePath',
dataType: 'json',
success: function (data, status) {
// $('#notificationDiv').text("Bank Updated Successfully!");
}
});
return true;
},
closeAfterEdit: true, left: 200, top: 50, width: 500,
afterShowForm: function (formid) {
$('#Contact').numeric({ allow: "," });
},
afterComplete: function (response, postdata, formid) {
if (response.responseText == "true") {
$("#notificationDivSuccess").delay(0).fadeIn("slow");
$('#notificationDivSuccess').text("Record Updated Successfully!");
$("#notificationDivSuccess").delay(2500).fadeOut("slow");
$('#notificationDivFail').text("");
}
else {
$("#notificationDivFail").delay(0).fadeIn("slow");
$('#notificationDivFail').text("Record Already Exist!");
$("#notificationDivFail").delay(2500).fadeOut("slow");
$('#notificationDivSuccess').text("");
}
}
},
{ closeOnEscape: true, reloadAfterSubmit: true,
closeAfterAdd: true, left: 200, top: 50, width: 500,
onInitializeForm: function (formid) {
$(formid).attr('method', 'POST');
$(formid).attr('action', '');
$(formid).attr('enctype', 'multipart/form-data');
},
afterShowForm: function (formid) {
$('#Contact').numeric({ allow: "," });
},
afterSubmit: function (response, postdata) {
// var data = $.parseJSON(response.responseText);
// bid = data.id;
// pageNo = data.page;
//debugger;
var Id = response.responseText;
$.ajaxFileUpload({
url: '/Master/CompanyFileUpload?CompanyId=' + Id,
secureuri: false,
data: postdata,
cache: false,
contentType: 'multipart/form-data',
processData: false,
type: 'POST',
fileElementId: 'FilePath',
dataType: 'json',
success: function (data, status) {
// $('#notificationDiv').text("Bank Added Successfully!");
}
});
return true;
}
,
afterComplete: function (response, postdata, formid) {
if (response.responseText != "") {
if (response.responseText == "false") {
$("#notificationDivFail").delay(0).fadeIn("slow");
$('#notificationDivFail').text("Record Already Exist!");
$("#notificationDivFail").delay(2500).fadeOut("slow");
$('#notificationDivSuccess').text("");
}
else {
$("#notificationDivSuccess").delay(0).fadeIn("slow");
$('#notificationDivSuccess').text("New Record Added Successfully!");
$("#notificationDivSuccess").delay(2500).fadeOut("slow");
$('#notificationDivFail').text("");
}
}
else {
}
}
},
{ closeOnEscape: true, reloadAfterSubmit: true, left: 300, top: 80, width: 220,
afterComplete: function (response, postdata, formid) {
if (response.responseText == "true") {
$("#notificationDivSuccess").delay(0).fadeIn("slow");
$('#notificationDivSuccess').text("Record Deleted Successfully!");
$("#notificationDivSuccess").delay(2500).fadeOut("slow");
$('#notificationDivFail').text("");
}
else {
$("#notificationDivFail").delay(0).fadeIn("slow");
$('#notificationDivFail').text("The selected record can not be deleted, Please delete associated record first");
$("#notificationDivFail").delay(2500).fadeOut("slow");
$('#notificationDivSuccess').text("");
}
}
},
{ closeAfterSearch: true, closeOnEscape: true, left: 200, top: 50, enableClear: true,
onClose: function () {
var postdata = $("#grid").jqGrid('getGridParam', 'postData');
postdata._search = false;
postdata.searchString = "";
$("#grid").trigger('reloadGrid');
return true;
}
});
});
In edit.php you have to put it like this:
if($_POST['oper']=='add')
{
... ... ...
}
else if($_POST['oper']=='edit')
{
... ... ...
}
else if($_POST['oper']=='del')
{
... ... ...
}
If you want to see what you are getting, use: print_r($_REQUEST);
var $mygrid= jQuery("#list").jqGrid({
url:'example.php',
editurl: 'edit.php',
datatype: 'xml',
mtype: 'GET',
colNames:['Seq','Name', 'ID','Pass','Mail','Note'],
colModel :[
{name:'seq',index:'seq', width:55, resizable:false, editable:true, editoptions:{readonly:true,size:10}},
{name:'name',index:'name', width:90,resizable:false, editable:true, editoptions:{readonly:false,size:10}},
{name:'id',index:'id', width:80, align:'right', editable:true, editoptions:{readonly:false,size:10}},
{name:'pass',index:'pass', width:80, align:'right', sortable:false, editable:true, editoptions:{readonly:false,size:10}},
{name:'mail',index:'mail', width:80,align:'right', sortable:false, editable:true, editoptions:{readonly:false,size:10}},
{name:'id',index:'id', width:150, sortable:false} ],
pager: jQuery('#pager'),
rowNum:10,
rowList:[10,20,30,50],
sortname: 'seq',
sortorder: "Asc",
width: 1000,
height: 230,
viewrecords: true,
multiselect: true,
editable: true,
toolbar: [true,"top"],
multikey: "ctrlKey",
caption: 'staff'
});
$("#list").jqGrid('navGrid', '#pager', {
edit: true,
add: true,
del: true,
search: false,
refresh:false
})
In edit.php
if($_GET['oper']=='add')
{
... ... ...
}
if($_GET['oper']=='edit')
{
... ... ...
}
if($_GET['oper']=='del')
{
... ... ...
}
I really like the idea of PHPjq however the code they are "selling" does not have any of the best practices to prevent SQL injection. so buy their code and add the proper sql escape wrappers or write your own .... be safe not lazy.