TradingView widget, advanced chart, not showing in React - reactjs

I am trying to implement the Advanced chart widget of TradingView in my web application, that is created in React/Javascript, using primereact. I have tried several options before, and the only thing that worked so far was by importing the TradingViewEmbed from "react-tradingview-embed". Unfortunately it only worked with the old version "1.0.2", that has the old advertisement bar in it and also the banner below.
In order to remove those and implement it the way TradingView states I have done the below:
import React, { useEffect } from "react";
import './market-data.css';
const MarketData = () => {
const useScript = url => {
useEffect(() => {
const script = document.createElement('script');
script.src = url;
script.async = true;
document.body.appendChild(script);
return () => {
document.body.removeChild(script);
}
}, [url]);
};
return (
<div className="tradingview-widget-container">
{useScript('https://s3.tradingview.com/tv.js')}
<div id="tradingview_dc023"></div>
<div className="tradingview-widget-copyright"></div>
<script type="text/javascript" nonce>
{
new window.TradingView.widget(
{
autosize: true,
symbol: "FX_IDC:EURUSD",
timezone: "Europe/Amsterdam",
theme: "dark",
style: "2",
enable_publishing: false,
hide_top_toolbar: false,
hide_legend: false,
withdateranges: true,
range: "1D",
hide_side_toolbar: true,
allow_symbol_change: true,
save_image: false,
watchlist: [
"FX_IDC:EURUSD",
"FX_IDC:EURGBP",
"FX_IDC:EURJPY"
],
details: true,
hotlist: false,
calendar: true,
studies: [],
height: "100%",
width: "100%",
container_id: "tradingview_dc023"
})
}
</script>
</div>
)
}
export default MarketData;
Looking at the inspect of the web application it looks fine to me, but the chart/widget is just not showing.
tv.js is loaded:
tv.js
script is loaded and shows the way TradingView states on its website:
script
Could anybody please help and direct me in the right way of fixing this?

Related

How to remove title, share button, youtube logo from videojs

I'm using videojs to render youtube videos.
But I can't remove the video title, share button or youtube logo.
My videojs config:
React.useEffect(() => {
if (videoNode.current) {
const playerInstance = videojs(videoNode.current, {
...initialOptions,
...options,
BlockYoutubeButton: false,
});
setPlayer(playerInstance);
}
}, [videoNode?.current, options]);
Options:
const videoJsOptions = {
...optionsPlayer,
playing: true,
sources: [
{
type: "video/youtube",
src: optionsPlayer.urlVideoTY
? optionsPlayer.urlVideoTY
: "https://www.youtube.com/watch?v=hzqmRq56X8o",
},
],
techOrder: ["youtube"],
};
can someone help me to remove the buttons?
Thank you very much
I've already tried adding the css to override the class and adding diplay:none, but I can't access the iframe either.
I already tried to add the parameter: controls: false and controlBar: false in the videojs options, but it didn't work either

How to refresh powerbi-client-react component once token has expired?

I am testing a react web app where I can display reports from Power BI. I am using powerbi-client-react to embed the reports. However, I face an issue when I load the component with an expired token, I get this error: Content not available screenshot.
So whenever that happens, I catch it with the error event handler, get a new token and update the powerbi report accessToken. However, it doesn't seem to reload/refresh the embed when I set the new accessToken in react. It only displays the screenshot above.
Error log screenshot.
Is there a way to force refresh the embed component with the new access token? or is my approach not correct? Any mistakes pointer would be appreciated.
import React from 'react';
import {models} from 'powerbi-client';
import {PowerBIEmbed} from 'powerbi-client-react';
// Bootstrap config
let embedConfigTest = {
type: 'report', // Supported types: report, dashboard, tile, visual and qna
id: reportId,
embedUrl: powerBIEmbedURL,
accessToken: null,
tokenType: models.TokenType.Embed,
pageView: 'fitToWidth',
settings: {
panes: {
filters: {
expanded: false,
visible: false,
},
},
background: models.BackgroundType.Transparent,
},
};
const PowerBiReport = ({graphName, ...props}) => {
let [embedToken, setEmbedToken] = React.useState();
let [embedConfig, setEmbedConfig] = React.useState(embedConfigTest);
React.useEffect(
() => {
setEmbedToken(EXPIRED_TOKEN);
setEmbedConfig({
...embedConfig,
accessToken: EXPIRED_TOKEN, // Initiate with known expired token
});
},
[graphName]
);
const changeSettings = (newToken) => {
setEmbedConfig({
...embedConfig,
accessToken: newToken,
});
};
// Map of event handlers to be applied to the embedding report
const eventHandlersMap = new Map([
[
'loaded',
function() {
console.log('Report has loaded');
},
],
[
'rendered',
function() {
console.log('Report has rendered');
},
],
[
'error',
async function(event, embed) {
if (event) {
console.error(event.detail);
console.log(embed);
// Simulate getting a new token and update
setEmbedToken(NEW_TOKEN);
changeSettings(NEW_TOKEN);
}
},
],
]);
return (
<PowerBIEmbed
embedConfig={embedConfig}
eventHandlers={eventHandlersMap}
cssClassName={'report-style-class'}
/>
);
};
export default PowerBiReport;
Thanks #vtCode. Here is a sample but the refresh can only happen in 15 secs interval.
import { PowerBIEmbed } from "powerbi-client-react";
export default function PowerBiContainer({ embeddedToken }) {
const [report, setReport] = useState(null);
useEffect(() => {
if (report == null) return;
report.refresh();
}, [report, embeddedToken]);
return (
<PowerBIEmbed
embedConfig={{ ...embedConfig, accessToken: embeddedToken }}
getEmbeddedComponent={(embeddedReport) => setReport(embeddedReport)};
/>
);
}
Alternatively, you can add the React "key" attribute which remounts the component when embededToken changes
<PowerBIEmbed key={embeddedToken}
embedConfig={{ ...embedConfig, accessToken: embeddedToken }}
/>
I ended up solving this issue, although not so beautiful.
I checked the powerbi-client wiki as it has dependency on it and found out that you could use embed.reload() in the embed object I get from the error function.
For some reason (I could not find out why), the error handler gets triggered twice, so to avoid refreshing the token twice, I had to create a dialog notifying the user that the token had expired and whenever that dialog is closed, I reload the powerbi report.
Exact wiki reference:
Overriding Error Experience
Reload a report
Update embed token

How to customize default export option in material-table

I am using material-table and I want to remove the default CSV & PDF export option.
I would like to have only an excel option.
How can I change the menu ?
Thank you
For custom CSV and PDF, you should define options
options={{
exportButton: {
csv: true,
pdf: true,
}
}}
and for the handlers should be defined more options
options={{
exportButton: {
csv: true,
pdf: true,
},
exportCsv: (data, columns) => console.log(data, columns, '<== CSV'),
exportPdf: (data, columns) => console.log(data, columns, '<== PDF'),
}}
in the handler function for the CSV you can use filefy package
import { CsvBuilder } from 'filefy';
and for PDF you can use jspdf and jspdf-autotable packages
import jsPDF from 'jspdf';
import 'jspdf-autotable';
also handler examples
exportCsv: (data, columns) => {
const columnTitles = columns
.map(columnDef => columnDef.title);
const csvData = data.map(rowData =>
columns.map(columnDef => rowData[columnDef.field]),
);
const builder = new CsvBuilder(`data.csv`)
.setColumns(columnTitles)
.addRows(csvData)
.exportFile();
return builder;
}
exportPdf: (data, columns) => {
const doc = new jsPDF();
const columnTitles = columns
.map(columnDef => columnDef.title);
const pdfData = data.map(rowData =>
columns.map(columnDef => rowData[columnDef.field]),
);
doc.autoTable({
head: [columnTitles],
body: pdfData,
});
doc.save(`data.pdf`);
}
Defining options on the MT component like this will allow you to show/hide each option:
options={{
// ..other options
exportButton: {
csv: true,
pdf: false
}
}}
Also, you could use localization settings to rename the label of each option like this:
localization={{
toolbar: {
exportCSVName: "Export some Excel format",
exportPDFName: "Export as pdf!!"
}
}}
It looks like the official docs are a bit outdated, so I found the answer to what you were looking for on these threads in GitHub:
exportButton
localization
Working sandbox here. Good luck!

react-chartjs-2 does not show line until window is resized

I'm having this weird bug with my React app with the react-chartjs-2. Chart data does not show correctly until I resize window. Tested on Firefox and Chrome, same result. Data is there, but I don't know if the data is loaded after the render or something. Please, I am student and not an expert, so please explain in detail if you know the solution for my problem. Thank you!
Youtube video of my bug
import React, {Component} from 'react';
import {Line} from 'react-chartjs-2';
const options = {
title: {
display: true,
text: "Chart Title"
},
scales: {
yAxes: [
{
ticks: {
suggestedMin: 20,
suggestedMax: 50
}
}
]
}
};
const legend = {
display: true,
position: "bottom",
labels: {
fontColor: "#323130",
fontSize: 14
}
};
class SensorChart extends Component {
constructor(props) {
super(props);
this.chartReference = React.createRef()
this.state = {
data : {
labels: props.labels,
datasets: [
{
label: "Humidity",
borderColor: "rgb(9,0,192)",
data: props.humidity
},
{
label: "Temperature",
borderColor: "red",
data: props.temperature
}
]
}
}
}
componentDidMount() {
console.log(this.state.data.datasets[0].data)
console.log(this.state.data.datasets[1].data)
}
render() {
return (
<div>
<h5>Line Example</h5>
<Line ref={this.chartReference} data={this.state.data} legend={legend} options={options}/>
</div>
);
}
}
export default SensorChart;
import React from 'react';
import Icon from '#mdi/react'
import {mdiThermometer, mdiWaterPercent, mdiCalendarRange} from '#mdi/js';
import './SensorData.css';
import SensorChart from "./SensorChart";
function SensorData() {
const [humi, setHumi] = React.useState("");
const [temp, setTemp] = React.useState("");
const [date, setDate] = React.useState("");
const [labels] = React.useState([]);
const [humidity] = React.useState([]);
const [temperature] = React.useState([]);
function fetchData() {
fetch('https://myAPIurl/datalist/100')
.then(response => response.json())
.then(responseData => {
setDate(responseData[0].stringTime);
setHumi(responseData[0].humidity);
setTemp(responseData[0].temperature);
for (let i = 0; i < 100; i++) {
labels.push(responseData[i].stringTime)
humidity.push(responseData[i].humidity)
temperature.push(responseData[i].temperature)
}
})
}
React.useEffect(() => {
fetchData();
}, []);
return (
<div className="App">
<h1>Sensor data</h1>
<h3><Icon path={mdiWaterPercent}/> Humidity: {humi}%</h3>
<h3><Icon path={mdiThermometer}/>Temperature: {temp}°C</h3>
<h3><Icon path={mdiCalendarRange}/>Time: {date}</h3>
<div className="Chart">
<SensorChart labels={labels} humidity={humidity} temperature={temperature}/>
</div>
</div>
);
}
export default SensorData;
Console logs after site is loaded
console.log(this.state.data.datasets[0].data)
console.log(this.state.data.datasets[1].data)
_chartjs: {…}, push: ƒ, pop: ƒ, shift: ƒ, splice: ƒ, …]0: 371: 372: 353: 354: 355: 366: 387: 388: 409: 4110: 4711: 4312: 4013: 3714: 3615: 3516: 3717: 3618: 3619: 3620: 3621: 3622: 3623: 3624: 3625: 3626: 3627: 3628: 3629: 3630: 3631: 3632: 3633: 3634: 3635: 3736: 3737: 3738: 3739: 3840: 3841: 3842: 3843: 3844: 3845: 3846: 3947: 3948: 3949: 4050: 4151: 4152: 4153: 4154: 4255: 4356: 4357: 4458: 4459: 4360: 3961: 4062: 3963: 3864: 3765: 3666: 3667: 3768: 3769: 3770: 3771: 3672: 3673: 3574: 3575: 3676: 3577: 3678: 3679: 3580: 3681: 3782: 3783: 3784: 3885: 3886: 3887: 3888: 3789: 3890: 3891: 3792: 3793: 3794: 3795: 3796: 3797: 3798: 3799: 37length: 100_chartjs: {listeners: Array(1)}push: ƒ ()pop: ƒ ()shift: ƒ ()splice: ƒ ()unshift: ƒ ()__proto__: Array(0)
SensorChart.js:61 [_chartjs: {…}, push: ƒ, pop: ƒ, shift: ƒ, splice: ƒ, …]0: 24.31: 24.32: 24.33: 24.24: 24.15: 23.86: 22.87: 22.98: 23.59: 2410: 24.811: 24.812: 24.713: 24.514: 24.515: 24.516: 24.617: 24.518: 24.519: 24.520: 24.421: 24.422: 24.423: 24.424: 24.525: 24.426: 24.427: 24.428: 24.429: 24.430: 24.431: 24.432: 24.433: 24.434: 24.335: 24.436: 24.437: 24.538: 24.539: 24.540: 24.541: 24.442: 24.543: 24.544: 24.545: 24.546: 24.547: 24.448: 24.349: 24.450: 24.451: 24.452: 24.453: 24.554: 24.555: 24.556: 24.557: 24.558: 24.559: 24.560: 24.561: 24.562: 24.563: 24.564: 24.565: 24.566: 24.567: 24.468: 24.469: 24.470: 24.471: 24.472: 24.373: 24.374: 24.375: 24.376: 24.377: 24.378: 24.379: 24.380: 24.381: 24.482: 24.483: 24.384: 24.385: 24.386: 24.387: 24.388: 24.389: 24.490: 24.291: 24.392: 24.293: 24.294: 24.295: 24.296: 24.197: 24.198: 24.299: 24.1length: 100_chartjs: {listeners: Array(1)}push: ƒ ()pop: ƒ ()shift: ƒ ()splice: ƒ ()unshift: ƒ ()__proto__: Array(0)
For everyone who is still ending up here, this seems to be an actively tracked issue at the moment since about 2017 on their GitHub Repo (#90). Although the issue is closed at the moment (2021-Apr-01), it is obviously still a problem for a lot of users as it has received comments on GitHub itself quite recently as well as here on Stack Overflow.
Previously listed solutions:
Redraw:
Apparently including the redraw prop on the React-ChartJS-2 component call is supposed to force a redraw of the data:
return (
<Line data={chartData} options={options} title="My Chart" ref={chartRef} redraw />
)
Sadly, this did nothing for me...
useEffect():
By tying the charts actual data into a useState() hook, it will trigger a component reload every time you change the data, which if you plan it right can also include initial data load.
const [chartData, setChartData] = useState(null);
// Data Fetch
useEffect(() => {
//...Async fetch my data from source and update state
});
// Attempt at triggering update whenever datasets change:
useEffect(() => {
if (chartData !== null) {
chartRef.current.chartInstance.update({
preservation: true,
});
}
}, [chartData]);
// Nested component to trigger rerender of only the graph for performance
const Graph = () => {
return (
<>
{chartData ? (
<Line data={chartData} options={options} title="My Chart" ref={chartRef} redraw />
) : null}
</>
);
};
return (
<Graph />
)
Sadly (again), this also did nothing...
Conclusion:
This appears to be a bug with how ChartJS was ported to React, meaning this appears to be an issue with the actual React-ChartJS-2 package.
TL;DR
Its a known issue on the React-ChartJS-2 GitHub (#90). Normal approaches do not work currently. Stay tuned there for updates.
After a few tinkering about I finally managed to get the Line graph to re-render when the data is received.
You may need to make use of both useState and useEffect, how I got around it is by updating the state to hold the datasets when data received has changed
const [data, setData] = React.useState<any>({ datasets: [{ data: [] }] });
And the useEffect with the data sets and labels as the dependencies
React.useEffect(() => {
setData({
labels: label,
datasets: [
{
data: datavals,
borderColor: "#59F5FF",
backgroundColor: "none",
pointBackgroundColor: "#59F5FF",
pointBorderWidth: 5,
pointHoverRadius: 10,
tension: 0.4
}
]
});
}, [label, datavals]);
then further down in the Line component
return <Line data={data} />;

electron-react-boilerplate :sub window on clicking a button

i have a doubt that how the reactjs file can be loaded into a new window on
clicking a button in electron-react-boilerplate.
const handleVideoCall=()=>{
const remote=require('electron').remote;
const BrowserWindow=remote.BrowserWindow;
const win = new BrowserWindow({
height: 600,
width: 800,
});
win.loadFile(fileName);
}
handleVideoCall is the method which is called on clicking the button.
FileName is the reactjs file that i needed to open.
As there is no documentation from react-electron-boilerplate i was stuck with this. Any help is appreciable.
i got the answer i think that this will be helpful for lot of peoples as there are no documentation for electron-react-boilerplate.
Make the nodeIntegration to true or preload js.
const handleVideoCallNew = async number => {
const remote=require('electron').remote;
const BrowserWindow=remote.BrowserWindow;
const win = new BrowserWindow({
height: 600,
width: 800,
frame:false,
webPreferences: {
nodeIntegration: true,
}
});
win.loadURL(`file://${__dirname}/app.html#/login`);
}
And on the router file
<Route path="/login" component={Login} />
By using this code we can open the reactjs file and route to login. The app.html is main file which is loaded in main.dev.js in electron-react-boilerplate code. The hashing is simplest method to open the reactjs file.
As the loadURL in electron only loads urls and htmls files we can't open js files. So open the main app.html and hash using routes.
Just create a react videoCall Component then create a window and load a url with query params like this,
const videoCallWidow = new BrowserWindow({
height: 600,
width: 800,
webPreferences: {
nodeIntegration: true,
webSecurity: false,
},
})
videoCallWidow.loadURL(
url.format({
pathname: path.join(__dirname, '../build/index.html'),
protocol: 'file:',
slashes: true,
query: {
page: 'videoCall',
},
})
)
after that, In your index.js file you will get query params so on that you can put a condition to load videoCall Component or app component .
ReactDOM.render(
locationPath === 'videoCall' ? <videoCallComponent /> : <App />,
document.getElementById('root')
)

Resources