How to use "google-charts-node" npm package with dynamic parameters - node-modules

I am trying to create charts using "google-charts-node" npm via REST api but getting this error everytime when I try to pass dynamic data from request body in the drawChart function but it works fine when I passed static parameters
Here is my code
const GoogleChartsNode = require('google-charts-node');
const express=require('express')
const body_parser=require('body-parser')
const fs = require('fs');
const app=express()
app.use(body_parser.json());
async function drawChart(body) {
var arr=[]
arr=body.chartData
console.log(arr)
var data = google.visualization.arrayToDataTable(arr);
var options = {
title: 'Revenue of C2C 2020',
chartArea: { width: '50%' },
hAxis: {
title: 'Revenue',
minValue: 0,
},
vAxis: {
title: 'Products',
},
};
var chart = new google.visualization.BarChart(container);
chart.draw(data, options);
}
const Img= async(body) => {
const image = await GoogleChartsNode.render(drawChart(body), {
width: 400,
height: 300,
});
return image
}
var bodyData
const getDataFirst=(data,callback)=>{
console.log('func',data)
callback(data)
}
app.post('/drawcharts', async (req,res)=>{
bodyData=req.body
getDataFirst(bodyData,async(data)=>{
console.log('callback',data)
const v= await Img(data)
console.log(v)
})
And getting this error
(node:9608) UnhandledPromiseRejectionWarning: ReferenceError: google is not defined
at drawChart (C:\Users\C2C04\Desktop\Charts\test.js:16:17)

Related

How to use React useContext with leaflet routing machine and react leaflet?

I'm trying to use a useContext hook inside a react-leaflet controlComponent but I have an error when my context fires the update function.
I use a react-leaflet controlComponent because of leaflet routing machine. I think the code + the error are better than word:
MainBoard.tsx
export const CartographyContext: React.Context<CartographyContextType> = React.createContext<CartographyContextType>({ positions: [] });
...
const routeSummaryValueContext = React.useMemo(
() => ({ routeSummary, setRouteSummary }),
[routeSummary]
);
const elevationProfileValueContext = React.useMemo(
() => ({ elevationProfile, setElevationProfile }),
[elevationProfile]
);
........
<CartographyContext.Provider value={{ positions, elevationProfileValueContext, routeSummaryValueContext, positionsValueContext, addPosition, changePosition }}>
.........
<RoutingMachine
orsOptions={{
....
}} />
..........
</CartographyContext.Provider>
RoutingMachine.tsx:
const CreateRoutineMachineLayer = (props: any) => {
const geoService = new GeoLocalisationService();
const cartographyContext: CartographyContextType = React.useContext<CartographyContextType>(CartographyContext);
const [routes, setRoutes] = React.useState<any[]>();
React.useEffect(() => {
if (routes) {
//The line which cause the error
cartographyContext.elevationProfileValueContext.setElevationProfile(geoService.getElevationProfile(decodePolyline(routes[0].geometry, true)));
const summary: RouteSummary = {
ascent: routes[0].routeSummary.ascent,
descent: routes[0].routeSummary.descent,
distance: routes[0].routeSummary.distance,
estimatedDuration: routes[0].routeSummary.duration
}
cartographyContext.routeSummaryValueContext.setRouteSummary(summary);
}
}, [routes]);
const { orsOptions } = props;
const instance = L.Routing.control({
router: new OpenRouteRouter(orsOptions),
lineOptions: {
styles: [{ color: "#3933ff", weight: 4 }],
extendToWaypoints: true,
missingRouteTolerance: 0
},
routeWhileDragging: true,
autoRoute: true,
geocoder: new geocoder.Geocoder(),
}).on('routesfound', (e) => {
setRoutes(e.routes);
});
useMapEvents({
click: (e: L.LeafletMouseEvent) => {
if (instance.getWaypoints().length === 2 && instance.getWaypoints()[0].latLng == null) {
instance.spliceWaypoints(0, 1, new L.Routing.Waypoint(e.latlng, null, {}));
} else if (instance.getWaypoints().length === 2 && instance.getWaypoints()[1].latLng == null) {
instance.spliceWaypoints(1, 1, new L.Routing.Waypoint(e.latlng, null, {}));
} else {
instance.spliceWaypoints(instance.getWaypoints().length, 0, new L.Routing.Waypoint(e.latlng, null, {}));
}
}
});
return instance;
};
const RoutingMachine = createControlComponent(CreateRoutineMachineLayer);
error :
g: React has detected a change in the order of Hooks called by ForwardRef(LeafComponent). This will lead to bugs and errors if not fixed. For more information, read the Rules of Hooks: https://reactjs.org/link/rules-of-hooks
Previous render Next render
------------------------------------------------------
1. useContext useContext
2. useRef useRef
3. useContext useRef
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
..............
Uncaught Error: Rendered fewer hooks than expected. This may be caused by an accidental early return statement.
I clearly doing something wrong here but I haven't found yet.
Thank you
Kind regards
Ok I found the good implementation :
const RoutingMachine: React.FC<RoutingMachineProps> = (props) => {
//const RoutineMachine = (props: any) => {
const geoService = new GeoLocalisationService();
const cartographyContext: CartographyContextType = React.useContext<CartographyContextType>(CartographyContext);
const [instance, setInstance] = React.useState<any>();
const [alreadyDisplayed, setAlreadyDisplayed] = React.useState(false);
const { orsOptions } = props;
const map = useMap();
//const instance = L.Routing.control({
React.useEffect(() => {
const instance = L.Routing.control({
router: new OpenRouteRouter(orsOptions),
lineOptions: {
styles: [{ color: "#3933ff", weight: 4 }],
extendToWaypoints: true,
missingRouteTolerance: 0
},
routeWhileDragging: true,
autoRoute: true,
geocoder: (L.Control as any).Geocoder.google({
apiKey: GOOGLE.googleMapApiKey,
}),
}).on('routesfound', (e) => {
const routes = e.routes;
cartographyContext.setElevationProfile(geoService.getElevationProfile(decodePolyline(routes[0].geometry, true)));
const summary: RouteSummary = {
ascent: routes[0].routeSummary.ascent,
descent: routes[0].routeSummary.descent,
distance: routes[0].routeSummary.distance,
estimatedDuration: routes[0].routeSummary.duration
}
cartographyContext.setRouteSummary(summary);
})
setInstance(instance);
instance.addTo(map);
}, []);
useMapEvents({
click: (e: L.LeafletMouseEvent) => {
if (instance) {
if (instance.getWaypoints().length === 2 && instance.getWaypoints()[0].latLng == null) {
instance.spliceWaypoints(0, 1, new L.Routing.Waypoint(e.latlng, null, {}));
} else if (instance.getWaypoints().length === 2 && instance.getWaypoints()[1].latLng == null) {
instance.spliceWaypoints(1, 1, new L.Routing.Waypoint(e.latlng, null, {}));
} else {
instance.spliceWaypoints(instance.getWaypoints().length, 0, new L.Routing.Waypoint(e.latlng, null, {}));
}
}
}
});
return null;
};
export default RoutingMachine;

Visual regression in Cypress

I am doing a visual regression :
code: plugins/indexts
on('task', {
graphicsMatch: ({ img1Path, img2Path, diffImgPath }) => {
const img1 = PNG.sync.read(fs.readFileSync(img1Path));
const img2 = PNG.sync.read(fs.readFileSync(img2Path));
const { width, height } = img1;
const diff = new PNG({ width, height });
let pixelCount = pixelmatch(img1.data, img2.data, diff.data);
fs.writeFileSync(diffImgPath, PNG.sync.write(diff));
return pixelCount;
},
});
stepdef:
And('I capture the screenshot of {string}', (editorDocument: string) => {
cy.wait(5000);
cy.captureScreen(editorDocument).as('generatedFileName');
});
Then(
'the generated pdf is as expected {string} and {string}',
(nameOfFeatureFile: string, editorScreenshot: string) => {
filesApi.comparePixelDiff(
nameOfFeatureFile,
editorScreenshot,
Cypress.currentTest.title,
);
},
);
API's:
comparePixelDiff(
nameOfFeaturefile: string,
actualFileName: string,
expectedFileName: string,
) {
cy.get('#generatedFileName').then((receivedFileName) => {
const sourceFilePath = `${FilesApi.screesnShotsFolder}${FilesApi.visualTestingFeaturesFolder}/${nameOfFeaturefile}/${actualFileName}${FilesApi.graphicExt}`;
const expectedFilePath = `${FilesApi.expectedExportsFolder}${expectedFileName}${FilesApi.graphicExt}`;
const diffFilePath = `${FilesApi.actualExportsFolder}${actualFileName}-${FilesApi.graphicsDiffSufix}${FilesApi.graphicExt}`;
cy.task('graphicsMatch', {
img1Path: sourceFilePath,
img2Path: expectedFilePath,
diffImgPath: diffFilePath,
}).then((pixelsDiff) => {});
});
}
}
i am using pixelmatch here,i have used viewport as 1280x720 in json file locally it works fine but fails on CI as the resolution of screenshot is not persistent
i have even tried cy.viewport(1280, 720) before capturescreenshot it didnt work as well.
How do i fix this issue, please help.

How to work with pdf files on back4app parse server

i have been exploring back4app parse server. i am tiered of finding documentation for pdf files. I am trying to generate some pdf files on back4app parse server from its cloud function.i do not see any documentation for it. will some one guide me to find it and little enlightment will be highly appreciated.
edit:
pdf creator library out there ask for output path but in back4app we don't have early access to path. we create new file passing it data and then save it to object. how do we achieve the order.
I some how managed get it done, thank you #Davi macedo. but there is some problem, i created pdf locally(root) cloud code,deleting it each time is envitable . this could be problem for more requests.
can someone improve little bit. would be great.
Here is my code.
I have used pdf-creator-node for creating pdf.
var pdf = require("pdf-creator-node");
var fs = require("fs")
var path = require('path')
const pdf2base64 = require('pdf-to-base64');
Parse.Cloud.define("pdf", async (req) => {
//creating pdf
// var html = fs.readFileSync("template.html", "utf8");
var html = fs.readFileSync(path.resolve(__dirname, 'template.html'), {
encoding: 'utf-8' });
var options = {
format: "A3",
orientation: "portrait",
border: "10mm",
header: {
height: "45mm",
contents: '<div style="text-align: center;">Author: Shyam Hajare</div>'
},
footer: {
height: "28mm",
contents: {
first: 'Cover page',
2: 'Second page', // Any page number is working. 1-based index
default: '<span style="color: #444;">{{page}}</span>/<span>{{pages}}</span>', // fallback value
last: 'Last Page'
}
}
};
var users = [
{
name: "Shyam",
age: "26",
},
{
name: "Navjot",
age: "26",
},
{
name: "Vitthal",
age: "26",
},
];
var document = {
html: html,
data: {
users: users,
},
path: path.resolve(__dirname, './pdfs', 'my_file.pdf'),//using path is necessary
type: "",
};
return pdf
.create(document, options)
.then((res) => {
return pdf2base64(path.resolve(__dirname, "/usr/src/app/data/cloud /pdfs/my_file.pdf")) //this path /usr/src/app/data/cloud/pdfs still mystery to me.
.then(
(response) => {
// console.log(response); //cGF0aC90by9maWxlLmpwZw==
const saveFiles = async () => {
//creating file
const parseFile = new Parse.File('pdfFile.pdf',{base64:response});
// console.log(parseFile)
//saving file
const responseFile = await parseFile.save();
const Document = Parse.Object.extend('Document');
const document = new Document();
//saving it to object.
document.set('document', responseFile);
await document.save();
}
saveFiles();
}
)
.catch(
(error) => {
console.log(error); //Exepection error....
}
)
console.log(res);
})
.catch((error) => {
console.error(error);
});
});

Recieved this error: Error: Too many re-renders. React limits the number of renders to prevent an infinite loop

I've a stepper form, that insert data using GraphQL/Apollo and React, of two different places.
Here are the code:
export function ProjectStep({classes, nextStep}) {
const {loading, error, data} = useUserQuery();
const organizationsArray = _.get(data, "user.organizations");
const [projectName, setProjectName] = useState("");
const [organization, setOrganization] = useState("");
const [createProject, appMutationResponse] = useappInsertMutation();
const [createToken, tokenMutationResponse] = usetokenInsertMutation();
const submitForm = () => {
const variables = {name: projectName, orgId: organization, description: ""};
createProject({variables});
};
const submitToken = () => {
const variables = {
enable: true,
lastUsed: Date.now().toString(),
appId: appMutationResponse.data.appInsert.id,
orgId: appMutationResponse.data.appInsert.orgId,
};
createToken({variables});
};
if (appMutationResponse.data) {
submitToken();
}
}
The first insert is on:
const submitForm = () => {
const variables = {name: projectName, orgId: organization, description: ""};
createProject({variables});
};
The second insert is on:
const submitToken = () => {
const variables = {
enable: true,
lastUsed: Date.now().toString(),
appId: appMutationResponse.data.appInsert.id,
orgId: appMutationResponse.data.appInsert.orgId,
};
createToken({variables});
};
These events are called in a button:
<Button variant="contained" color="primary" type='button' onClick={submitForm}>
Next
</Button>
But, when i click on the button, i got this error:
Error: Too many re-renders. React limits the number of renders to prevent an infinite loop.
When a go to my database, i see that 50 tokens are saved using this part of the code in a single call:
const submitToken = () => {
const variables = {
enable: true,
lastUsed: Date.now().toString(),
appId: appMutationResponse.data.appInsert.id,
orgId: appMutationResponse.data.appInsert.orgId,
};
createToken({variables});
};
I think that because i'm using a hook, i got a response and that response bring that error to me, the question is, why i'm saving and receiving in a single call, 50 tokens?
You have written below code directly in render, so when the appMutationResponse.data is available if calls the submitToken function which triggers a re-render and then the function is called again causing an infinite loop.
if (appMutationResponse.data) {
submitToken();
}
The solution is to put this code in useEffect and run it on data change
useEffect(() => {
if (appMutationResponse.data) {
submitToken();
}
}, [appMutationResponse.data])

Graphql-js subscriptions unit tests not working as expected

I have written integration tests for graphql-js subscriptions, which are showing weird behavior.
My graphq-js subscription works perfectly in GraphiQL. But when the same subscriptions is called from unit test, it fails.
Ggraphql-Js object, with resolve function and subscribe function
return {
type: outputType,
args: {
input: {type: new GraphQLNonNull(inputType)},
},
resolve(payload, args, context, info) {
const clientSubscriptionId = (payload) ? payload.subscriptionId : null;
const object = (payload) ? payload.object : null;
var where = null;
var type = null;
var target = null;
if (object) {
where = (payload) ? payload.object.where : null;
type = (payload) ? payload.object.type : null;
target = (payload) ? payload.object.target : null;
}
return Promise.resolve(subscribeAndGetPayload(payload, args, context, info))
.then(payload => ({
clientSubscriptionId, where, type, target, object: payload.data,
}));
},
subscribe: withFilter(
() => pubSub.asyncIterator(modelName),
(payload, variables, context, info) => {
const subscriptionPayload = {
clientSubscriptionId: variables.input.clientSubscriptionId,
remove: variables.input.remove,
create: variables.input.create,
update: variables.input.update,
opts: variables.input.options,
};
subscriptionPayload.model = model;
try {
pubSub.subscribe(info.fieldName, null, subscriptionPayload);
} catch (ex) {
console.log(ex);
}
return true;
}
),
};
Subscription query
subscription {
Customer(input: {create: true, clientSubscriptionId: 112}) {
customer {
id
name
age
}
}
}
Mutation query
mutation {
Customer {
CustomerCreate (input:{data:{name:"Atif 50", age:50}}) {
obj {
id
name
}
}
}
}
Integration Test
'use strict';
const ws = require('ws');
const { SubscriptionClient } = require('subscriptions-transport-ws');
const { ApolloClient } = require('apollo-client');
const { HttpLink } = require('apollo-link-http');
const { InMemoryCache } = require('apollo-cache-inmemory');
const Promise = require('bluebird');
const expect = require('chai').expect;
const chai = require('chai').use(require('chai-http'));
const server = require('../server/server');
const gql = require('graphql-tag');
let apollo;
let networkInterface;
const GRAPHQL_ENDPOINT = 'ws://localhost:5000/subscriptions';
describe('Subscription', () => {
before(async () => {
networkInterface = new SubscriptionClient(
GRAPHQL_ENDPOINT, { reconnect: true }, ws);
apollo = new ApolloClient({
networkInterface ,
link: new HttpLink({ uri: 'http://localhost:3000/graphql' }),
cache: new InMemoryCache()
});
});
after(done => {
networkInterface.close() ;
});
it('subscription', async () => {
const client = () => apollo;
// SUBSCRIBE and make a promise
const subscriptionPromise = new Promise((resolve, reject) => {
client().subscribe({
query: gql`
subscription {
Customer(input: {create: true,
clientSubscriptionId: 112,
options: {where: {age: 50}}}) {
customer {
name
}
}
}
`
}).subscribe({
next: resolve,
error: reject
});
});
let execGraphQL;
// MUTATE
await execGraphQL(
`mutation {
Customer {
CustomerCreate (input:{data:{name:"Atif 21", age:50}}) {
obj {
id
name
}
}
}
}`
);
// ASSERT SUBSCRIPTION RECEIVED EVENT
expect(await subscriptionPromise).to.deep.equal({});
});
});
Issue Here
When test in run, payload in the resolve function contains global data, where as it should contain the subscription payload. So the code breaks.

Resources