html2canvas failing to capture Google static map - reactjs

I'm creating a booking reference for the user to download after successfully making a booking. It looks like this in the browser:
However, after using html2canvas to get a screenshot of the component in React, I get this:
I suspect the issue has to do with the fact that the static map's use is protected by an API key, causing issues to render the image in an external view.
This is the callback that fires on hitting the share button, which for now just downloads the png (which is then converted to pdf using jsPDF):
const share = () => {
const input = document.getElementById("trip-summary");
if (input === null) return;
html2canvas(input!).then((canvas) => {
var image = canvas
.toDataURL("image/png")
.replace("image/png", "image/octet-stream");
const pdf = new jsPDF();
// #ts-ignore
pdf.addImage(image, "PNG", 0, 0);
pdf.save("download.pdf");
});
};

It looks like an external source of content. You should set the allowTaint option to true.
html2canvas(input, { allowTaint: true }).then(...);

Just wanted to add to the answer above.
It achieves exactly what I want, but you just need to set useCORS to true in the options as well
html2canvas(input!, { allowTaint: true, useCORS: true }).then(...)
, otherwise you'll get
Uncaught SecurityError: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported.

Related

Cloudinary cannot read property of new

Currently, I'm implementing cloudinary in a react app using cloudinary-react.
For this project, I was given this code which I've added to my API helper file. However, I am getting errors when I try to use it:
export const resolveSimpleCloudinaryUrl = id => {
return cloudinary.Cloudinary.new({
use_root_path: true,
private_cdn: true,
cloud_name: 'mycloudname',
secure: true,
}).url(id);
};
The first error states:
'cloudinary' is not defined
For the cloudinary error, I created a variable using the cloudinary base URL:
export const resolveSimpleCloudinaryUrl = id => {
let cloudinary = `https://res.cloudinary.com/`;
//remaining code...
This removes the first error, but now I get a new error:
Unhandled Rejection (TypeError): Cannot read property 'new' of undefined
What is the proper way to implement this? I haven't been able to figure this out yet. I haven't found anything in the documentation specific to what I've been given. Thank you in advance

Set retry with dropzone-react-component when upload fails

In my project I'm using React-Dropzone-Component (https://github.com/felixrieseberg/React-Dropzone-Component) based on Dropzone.js.
I'm using this component because I'm developing a SharePoint webpart and there is already an example based on this solution on Microsoft PnP GitHub repository.
Anyway, the upload is working fine, but sometimes, mainly when I keep a web page opened for a couple of minutes doing nothing, I receive an error trying to upload new files. I retry an upload and it fails returning Server responded with (0) code error. I also see on Google Chrome console an ERR_CONNECTION_RESET error. If I try to upload 5 files in second instance, I get error on first 2-3 and then the remaining files works fine. Weird.
I've already investigated my network, but there are no failures. I've also tried with 3 different networks and I've received the same error.
I've also updated the component with the latest Dropzone.js (5.7.2).
This is my code:
let componentConfig = {
iconFiletypes: this.props.fileTypes.split(','),
showFiletypeIcon: true,
postUrl: _context.pageContext.web.absoluteUrl,
autoProcessQueue: true
};
var djsConfig = {
headers: {
"X-RequestDigest": digest1
},
addRemoveLinks:false
};
let myDropzone;
let eventHandlers = {
// This one receives the dropzone object as the first parameter
// and can be used to additional work with the dropzone.js
// object
init: function(dz){
myDropzone=dz;
},
sending: async function (file, xhr) {
var fileName = file.name;
fileName = fileName.replace(/[&\/\\#,+()$~%='":*?<>{}]/g, "");
if (file.size <= 10485760) {
// small upload
await web.getFolderByServerRelativeUrl("/test/"+_listName).files.add(fileName, file, true).then(_ => console.log("Ok!"));
} else {
// large upload
await web.getFolderByServerRelativeUrl("/test/"+_listName).files.addChunked(fileName, file, data => {}, true).then(_ => console.log("Ok!"));
}
},
error:function(file,error,xhr){
file.status = myDropzone.ADDED;
myDropzone.removeFile(file);
myDropzone.enqueueFile(file);
}
};
<DropzoneComponent eventHandlers={eventHandlers} djsConfig={djsConfig} config={componentConfig}>
<div className="dz-message icon ion-upload">Drop files here to upload</div>
</DropzoneComponent>
If I can't prevent this ERR_CONNECTION_RESET error, I would like to set up an automatic retry for these files. The code I've posted above is not working fine or it returns "Uncaught Error: This file can't be queued because it has already been processed or was rejected.".
Is there a solution or a good way to set up a retry?

Get Stream IO React Native UnFollowing option not available

I am using Get Stream Io react native in my project https://github.com/GetStream/react-native-activity-feed
I see there is a functionality in the library of following a particular user, whereas the opposite is not available i.e. how to unfollow a user.
Please point me in the right direction on how to achieve this in react native
Our library doesn't include the logic for following/unfollowing. It has a button that allows you to set it up yourself though. Which is the FollowButton you're talking about. You could do something like this:
<FollowButton
followed={async () => {
// check if you're following the user
const following = await your_timeline_feed.following({filter: ['user:user_42'] })
if (following) {
return true;
}
return false;
}} // renders the button as "following"
clicked={async () => {
// your logic for following/unfollowing
await your_timeline_feed.follow('user', 'user_42');
}}
/>
Read more here:
https://getstream.github.io/react-native-activity-feed/#!/FollowButton
https://getstream.io/docs/following/?language=js

Uploading an image to Azure Blob Storage using React

I want to upload an image to Azure Blob Storage using React.
I've tried a lot of examples and none of them work.
The one that seemed the best was this one but still didn't manage to get it working on React.
What I'm trying right now is to use the createContainerIfNotExists method just to test and the error is Cannot read property createBlobServiceWithSas of undefined
My code is the following:
import AzureStorage from 'azure-storage';
const account = {
name: 'x',
sas: 'x',
};
const blobUri = `https://${account.name}.blob.core.windows.net`;
const blobService = AzureStorage.Blob.createBlobServiceWithSas(blobUri, account.sas);
export const createContainer = () => {
blobService.createContainerIfNotExists('test', (error, container) => {
if (error) {
// Handle create container error
} else {
console.log(container.name);
}
});
};
export default createContainer;
According to my research, because you develop A React application, we can not use the createBlockBlobFromBrowserFile method. We just can use the method in the browser. For more details, please refer to the document.
According to the situation, I suggest you use the other method(such as uploadStreamToBlockBlob) to upload image with V10 sdk. For more details, please refer to https://learn.microsoft.com/en-us/javascript/api/#azure/storage-blob/?view=azure-node-latest

html2canvas dynamically rendered div

I am trying to use html2canvas (http://html2canvas.hertzen.com) to take a screenshot of my page that contains a google maps view, but I am running into an issue where the resulting screenshot is white, except for the marker. What (possibly) complicates the issue is that I am (trying to) creating a React application.
I use this code to take the screenshot:
takeScreenshot = () => {
let googleMapsView = document.querySelector('.google-map');
html2canvas(googleMapsView).then((canvas) => {
let imgData = canvas.toDataURL('image/png');
console.log(imgData);
});
}
This is the page I'm trying to take a screenshot of:
The code above generates the following image:
As you can see, it generates the screenshot and captures the marker and the bottom "Map Data ©2018 Google" however, the resulting screenshot is still blank.
In the documentation on their Github, I see an option to preload here: https://github.com/niklasvh/html2canvas/wiki/Documentation#preload-content
However, this seems to have been removed from the library since the 0.5.0 beta version - they're now in 1.0.0 alpha, so going back that far to such an outdated library is not really an option.
How can I tell html2canvas to wait for the GMaps component to be rendered, before taking the screenshot?
You need to add param useCORS to use it with google maps, in your case:
takeScreenshot = () => {
let googleMapsView = document.querySelector('.google-map');
html2canvas(googleMapsView, {useCORS: true}).then((canvas) => {
let imgData = canvas.toDataURL('image/png');
console.log(imgData);
});
}
Have you tried to put your code inside the google map listener
google.maps.event.addListenerOnce(map, 'idle', function(){
// do something only the first time the map is loaded
takeScreenshot = () => {
let googleMapsView = document.querySelector('.google-map');
html2canvas(googleMapsView).then((canvas) => {
let imgData = canvas.toDataURL('image/png');
console.log(imgData);
});
}
});
See also the events section in the Google Maps Reference.

Resources