Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inject css variables using nodejs module #522

Open
sebherrerabe opened this issue May 10, 2024 · 2 comments
Open

Inject css variables using nodejs module #522

sebherrerabe opened this issue May 10, 2024 · 2 comments
Labels

Comments

@sebherrerabe
Copy link

Hello,

My team and I are attempting to implement the export module to enable the downloading of our charts. However, we’re encountering an issue due to our extensive use of CSS variables, which your server doesn’t seem to accept as it doesn’t allow external resources.

I’ve begun setting up the export server Node.js module on our Express app. The image generation appears to be functioning well, but we’re still facing the same issue. We’re unable to inject the CSS variables. Here’s how we’ve implemented it:

module.exports = {
	downloadChart: async (req, res) => {
		const exportSettings = {
			export: {
				type: req.body.type,
				// this line is just for test purposes
				outfile: "./samples/module/" + req.body.filename + "." + "png",
				scale: req.body.scale
			},
			pool: {
				minWorkers: 1,
				maxWorkers: 1
			},
			payload: {
				svg: req.body.svg
			},
			customLogic: {
				allowCodeExecution: true,
				resources: {
					css: "here I'd like to inject our variables"
				}
			}
		};
		const options = exporter.setOptions(exportSettings);

		// Initialize a pool of workers
		await exporter.initPool(options);

		// Perform an export
		exporter.startExport(exportSettings, function(res, err) {
			console.log(res);
			// The export result is now in res.
			// It will be base64 encoded (res.data).
			// use fs to write the file
			fs.writeFile(exportSettings.export.outfile, res.data, "base64", function(err) {
				if (err) {
					console.error(err);
				}
			});

			// Kill the pool when we're done with it.
			exporter.killPool();
		});
		// send file
		res.status(200);
	}
};
@jszuminski jszuminski added the bug label May 16, 2024
@jszuminski
Copy link
Contributor

Thanks for reporting @sebherrerabe!

As a workaround, try exporting from a JSON config and not from an SVG payload. Then, the resources.css option should most likely be taken into account properly. If you try it out and it does not work, please share your chart's config as well as the CSS variables that you're setting so I could investigate this further.

@sebherrerabe
Copy link
Author

@jszuminski
Thanks for replying! In fact, I found the reason why the variables weren’t working. I think the documentation is wrong, at least for the export settings of the Node.js module. The property is not "customLogic", instead it’s "customCode". I was able to inject our CSS variables successfully.

Unfortunately, that wasn’t our only problem… Sadly, our HTML elements do not render as desired when exporting a chart (we use React). As you might’ve guessed, what we are trying to do is to use the Exporting module provided by you in the front and change the URL to the one pointing at our custom Express endpoint (where we import the export server module).

I believe the Exporting module in the front converts the whole chart into an SVG element but this does not support some features natively. This is a problem to be honest, because we use HTML almost everywhere (we have lots of Highcharts charts). For now, we are even questioning if we should use a library to just take screenshots in the browser.

Config in NodeJs now:

const exportSettings = {
    export: {
        type: req.body.type,
        // TODO: Define the actual directory where the files will be saved
        outfile: "./samples/module/" + randomName + "." + req.body.type.split("/")[1],
        scale: req.body.scale
    },
    pool: {
        minWorkers: 1,
        maxWorkers: 1
    },
    payload: {
        svg: req.body.svg
    },
    customCode: {
        allowCodeExecution: true,
        allowFileResources: true,
        resources: {
            // TODO: Find a way to import the css directly from the file system
            css: "@import 'http://localhost:3001/compiled/site.css';"
        }
    }
};

Config in the front:

/// ...imports
// we init the exporting module
Exporting(Highcharts);

const ChartComponent = (props: Props): JSX.Element => {
    // some logic
    const chartOptions = {
        exporting: {
            url: "/charts/download",
            allowHtml: true
        },
        plotOptions: {
            column: {
                borderRadius: 4,
                borderColor: "white",
                stacking: "normal",
                dataLabels: {
                    enabled: true,
                    align: "center",
                    useHTML: true,
                    style: {
                        color: "white",
                        textOutline: "none"
                    },
                    formatter: JSXFormatter<PointLabelObject>(({ point }) => {
                        if (checkIfSimpleColumn(point)) {
                            return null;
                        }
                        // THE FOLLOWING COMPONENT DOES NOT RENDER CORRECTLY
                        return (
                            <Badge variant={dataCollectionStatusData[point.series.userOptions.id].variant}>
                                {point.y !== point.total && <strong style={{ marginRight: 2 }}>{point.y}</strong>}
                                {point.series.name}
                            </Badge>
                        );
                    })
                }
                // ... other properties
            }
        }
    };

    return (
        <HighchartsReact
            highcharts={Highcharts}
            options={chartOptions}
        />
    );
};

Expected result:
image

Actual result:
image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants