diff --git a/.storybook/preview-head.html b/.storybook/preview-head.html deleted file mode 100644 index 965f8201c..000000000 --- a/.storybook/preview-head.html +++ /dev/null @@ -1,6 +0,0 @@ - - - diff --git a/src/__demo__/SingleValue.stories.js b/src/__demo__/SingleValue.stories.js index 1276c6134..2b382123f 100644 --- a/src/__demo__/SingleValue.stories.js +++ b/src/__demo__/SingleValue.stories.js @@ -1,4 +1,4 @@ -import React, { useState, useMemo, useRef, useEffect, useCallback } from 'react' +import React, { useState, useMemo, useRef, useEffect } from 'react' import { createVisualization } from '../index.js' const constainerStyleBase = { width: 800, @@ -636,7 +636,6 @@ export const Default = () => { const [dashboard, setDashboard] = useState(false) const [showIcon, setShowIcon] = useState(true) const [indicatorType, setIndicatorType] = useState('plain') - const [exportAsPdf, setExportAsPdf] = useState(true) const [width, setWidth] = useState(constainerStyleBase.width) const [height, setHeight] = useState(constainerStyleBase.height) const containerStyle = useMemo( @@ -682,39 +681,6 @@ export const Default = () => { }) } }, [containerStyle, dashboard, showIcon, indicatorType]) - const downloadOffline = useCallback(() => { - if (newChartRef.current) { - const currentBackgroundColor = - newChartRef.current.userOptions.chart.backgroundColor - - newChartRef.current.update({ - exporting: { - chartOptions: { - isPdfExport: exportAsPdf, - }, - }, - }) - newChartRef.current.exportChartLocal( - { - sourceHeight: 768, - sourceWidth: 1024, - scale: 1, - fallbackToExportServer: false, - filename: 'testOfflineDownload', - showExportInProgress: true, - type: exportAsPdf ? 'application/pdf' : 'image/png', - }, - { - chart: { - backgroundColor: - currentBackgroundColor === 'transparent' - ? '#ffffff' - : currentBackgroundColor, - }, - } - ) - } - }, [exportAsPdf]) return ( <> @@ -782,15 +748,6 @@ export const Default = () => { })} - -
diff --git a/src/visualizations/config/adapters/dhis_highcharts/events/loadCustomSVG/singleValue/index.js b/src/visualizations/config/adapters/dhis_highcharts/events/loadCustomSVG/singleValue/index.js index 84cc83e7d..268d2c547 100644 --- a/src/visualizations/config/adapters/dhis_highcharts/events/loadCustomSVG/singleValue/index.js +++ b/src/visualizations/config/adapters/dhis_highcharts/events/loadCustomSVG/singleValue/index.js @@ -7,7 +7,7 @@ import { DynamicStyles } from './styles.js' export default function loadSingleValueSVG() { const { formattedValue, icon, subText, fontColor } = this.userOptions.customSVGOptions - const dynamicStyles = new DynamicStyles(this.userOptions?.isPdfExport) + const dynamicStyles = new DynamicStyles() const valueElement = this.renderer .text(formattedValue) .attr('data-test', 'visualization-primary-value') diff --git a/src/visualizations/config/adapters/dhis_highcharts/events/loadCustomSVG/singleValue/styles.js b/src/visualizations/config/adapters/dhis_highcharts/events/loadCustomSVG/singleValue/styles.js index f1b944ee2..e7ec189fd 100644 --- a/src/visualizations/config/adapters/dhis_highcharts/events/loadCustomSVG/singleValue/styles.js +++ b/src/visualizations/config/adapters/dhis_highcharts/events/loadCustomSVG/singleValue/styles.js @@ -28,15 +28,14 @@ const spacings = [ export const MIN_SIDE_WHITESPACE = 4 export class DynamicStyles { - constructor(isPdfExport) { + constructor() { this.currentIndex = 0 - this.isPdfExport = isPdfExport } getStyle() { return { value: { ...valueStyles[this.currentIndex], - 'font-weight': this.isPdfExport ? 'normal' : '300', + 'font-weight': '300', }, subText: subTextStyles[this.currentIndex], spacing: spacings[this.currentIndex], diff --git a/src/visualizations/config/generators/highcharts/index.js b/src/visualizations/config/generators/highcharts/index.js index 3620e81f5..f087f06bd 100644 --- a/src/visualizations/config/generators/highcharts/index.js +++ b/src/visualizations/config/generators/highcharts/index.js @@ -3,20 +3,16 @@ import HM from 'highcharts/highcharts-more' import HB from 'highcharts/modules/boost' import HE from 'highcharts/modules/exporting' import HNDTD from 'highcharts/modules/no-data-to-display' -import HOE from 'highcharts/modules/offline-exporting' import HPF from 'highcharts/modules/pattern-fill' import HSG from 'highcharts/modules/solid-gauge' -import PEBFP from './pdfExportBugFixPlugin/index.js' // apply HM(H) HSG(H) HNDTD(H) HE(H) -HOE(H) HPF(H) HB(H) -PEBFP(H) /* Whitelist some additional SVG attributes here. Without this, * the PDF export for the SingleValue visualization breaks. */ diff --git a/src/visualizations/config/generators/highcharts/pdfExportBugFixPlugin/index.js b/src/visualizations/config/generators/highcharts/pdfExportBugFixPlugin/index.js deleted file mode 100644 index 7b4899cde..000000000 --- a/src/visualizations/config/generators/highcharts/pdfExportBugFixPlugin/index.js +++ /dev/null @@ -1,7 +0,0 @@ -import nonASCIIFontBugfix from './nonASCIIFont.js' -import textShadowBugFix from './textShadow.js' - -export default function (H) { - textShadowBugFix(H) - nonASCIIFontBugfix(H) -} diff --git a/src/visualizations/config/generators/highcharts/pdfExportBugFixPlugin/nonASCIIFont.js b/src/visualizations/config/generators/highcharts/pdfExportBugFixPlugin/nonASCIIFont.js deleted file mode 100644 index d2c8d9835..000000000 --- a/src/visualizations/config/generators/highcharts/pdfExportBugFixPlugin/nonASCIIFont.js +++ /dev/null @@ -1,9 +0,0 @@ -/* This is a workaround for https://github.com/highcharts/highcharts/issues/22008 - * We add some transparent text in a non-ASCII script to the chart to prevent - * the chart from being exported in a serif font */ - -export default function (H) { - H.addEvent(H.Chart, 'load', function () { - this.renderer.text('ыки', 20, 20).attr({ opacity: 0 }).add() - }) -} diff --git a/src/visualizations/config/generators/highcharts/pdfExportBugFixPlugin/textShadow.js b/src/visualizations/config/generators/highcharts/pdfExportBugFixPlugin/textShadow.js deleted file mode 100644 index 21a96e1a5..000000000 --- a/src/visualizations/config/generators/highcharts/pdfExportBugFixPlugin/textShadow.js +++ /dev/null @@ -1,308 +0,0 @@ -/* This plugin was provided by HighCharts support and resolves an issue with label - * text that has a white outline, such as the one we use for stacked bar charts. - * For example: "ANC: 1-4 visits by districts this year (stacked)" - * This issue has actually been resolved in HighCharts v11, so once we have upgraded - * to that version, this plugin can be removed. */ - -export default function (H) { - const { AST, defaultOptions, downloadURL } = H, - { ajax } = H.HttpUtilities, - doc = document, - win = window, - OfflineExporting = - H._modules['Extensions/OfflineExporting/OfflineExporting.js'], - { getScript, svgToPdf, imageToDataUrl, svgToDataUrl } = OfflineExporting - - H.wrap( - OfflineExporting, - 'downloadSVGLocal', - function (proceed, svg, options, failCallback, successCallback) { - var dummySVGContainer = doc.createElement('div'), - imageType = options.type || 'image/png', - filename = - (options.filename || 'chart') + - '.' + - (imageType === 'image/svg+xml' - ? 'svg' - : imageType.split('/')[1]), - scale = options.scale || 1 - var svgurl, - blob, - finallyHandler, - libURL = options.libURL || defaultOptions.exporting.libURL, - objectURLRevoke = true, - pdfFont = options.pdfFont - // Allow libURL to end with or without fordward slash - libURL = libURL.slice(-1) !== '/' ? libURL + '/' : libURL - /* - * Detect if we need to load TTF fonts for the PDF, then load them and - * proceed. - * - * @private - */ - var loadPdfFonts = function (svgElement, callback) { - var hasNonASCII = function (s) { - return ( - // eslint-disable-next-line no-control-regex - /[^\u0000-\u007F\u200B]+/.test(s) - ) - } - // Register an event in order to add the font once jsPDF is - // initialized - var addFont = function (variant, base64) { - win.jspdf.jsPDF.API.events.push([ - 'initialized', - function () { - this.addFileToVFS(variant, base64) - this.addFont(variant, 'HighchartsFont', variant) - if (!this.getFontList().HighchartsFont) { - this.setFont('HighchartsFont') - } - }, - ]) - } - // If there are no non-ASCII characters in the SVG, do not use - // bother downloading the font files - if (pdfFont && !hasNonASCII(svgElement.textContent || '')) { - pdfFont = void 0 - } - // Add new font if the URL is declared, #6417. - var variants = ['normal', 'italic', 'bold', 'bolditalic'] - // Shift the first element off the variants and add as a font. - // Then asynchronously trigger the next variant until calling the - // callback when the variants are empty. - var normalBase64 - var shiftAndLoadVariant = function () { - var variant = variants.shift() - // All variants shifted and possibly loaded, proceed - if (!variant) { - return callback() - } - var url = pdfFont && pdfFont[variant] - if (url) { - ajax({ - url: url, - responseType: 'blob', - success: function (data, xhr) { - var reader = new FileReader() - reader.onloadend = function () { - if (typeof this.result === 'string') { - var base64 = this.result.split(',')[1] - addFont(variant, base64) - if (variant === 'normal') { - normalBase64 = base64 - } - } - shiftAndLoadVariant() - } - reader.readAsDataURL(xhr.response) - }, - error: shiftAndLoadVariant, - }) - } else { - // For other variants, fall back to normal text weight/style - if (normalBase64) { - addFont(variant, normalBase64) - } - shiftAndLoadVariant() - } - } - shiftAndLoadVariant() - } - /* - * @private - */ - var downloadPDF = function () { - AST.setElementHTML(dummySVGContainer, svg) - var textElements = - dummySVGContainer.getElementsByTagName('text'), - // Copy style property to element from parents if it's not - // there. Searches up hierarchy until it finds prop, or hits the - // chart container. - setStylePropertyFromParents = function (el, propName) { - var curParent = el - while (curParent && curParent !== dummySVGContainer) { - if (curParent.style[propName]) { - el.style[propName] = curParent.style[propName] - break - } - curParent = curParent.parentNode - } - } - var titleElements, - outlineElements - // Workaround for the text styling. Making sure it does pick up - // settings for parent elements. - ;[].forEach.call(textElements, function (el) { - // Workaround for the text styling. making sure it does pick up - // the root element - ;['font-family', 'font-size'].forEach(function (property) { - setStylePropertyFromParents(el, property) - }) - el.style.fontFamily = - pdfFont && pdfFont.normal - ? // Custom PDF font - 'HighchartsFont' - : // Generic font (serif, sans-serif etc) - String( - el.style.fontFamily && - el.style.fontFamily.split(' ').splice(-1) - ) - // Workaround for plotband with width, removing title from text - // nodes - titleElements = el.getElementsByTagName('title') - ;[].forEach.call(titleElements, function (titleElement) { - el.removeChild(titleElement) - }) - - // Remove all .highcharts-text-outline elements, #17170 - outlineElements = el.getElementsByClassName( - 'highcharts-text-outline' - ) - while (outlineElements.length > 0) { - const outline = outlineElements[0] - if (outline.parentNode) { - outline.parentNode.removeChild(outline) - } - } - }) - var svgNode = dummySVGContainer.querySelector('svg') - if (svgNode) { - loadPdfFonts(svgNode, function () { - svgToPdf(svgNode, 0, function (pdfData) { - try { - downloadURL(pdfData, filename) - if (successCallback) { - successCallback() - } - } catch (e) { - failCallback(e) - } - }) - }) - } - } - // Initiate download depending on file type - if (imageType === 'image/svg+xml') { - // SVG download. In this case, we want to use Microsoft specific - // Blob if available - try { - if (typeof win.navigator.msSaveOrOpenBlob !== 'undefined') { - // eslint-disable-next-line no-undef - blob = new MSBlobBuilder() - blob.append(svg) - svgurl = blob.getBlob('image/svg+xml') - } else { - svgurl = svgToDataUrl(svg) - } - downloadURL(svgurl, filename) - if (successCallback) { - successCallback() - } - } catch (e) { - failCallback(e) - } - } else if (imageType === 'application/pdf') { - if (win.jspdf && win.jspdf.jsPDF) { - downloadPDF() - } else { - // Must load pdf libraries first. // Don't destroy the object - // URL yet since we are doing things asynchronously. A cleaner - // solution would be nice, but this will do for now. - objectURLRevoke = true - getScript(libURL + 'jspdf.js', function () { - getScript(libURL + 'svg2pdf.js', downloadPDF) - }) - } - } else { - // PNG/JPEG download - create bitmap from SVG - svgurl = svgToDataUrl(svg) - finallyHandler = function () { - try { - OfflineExporting.domurl.revokeObjectURL(svgurl) - } catch (e) { - // Ignore - } - } - // First, try to get PNG by rendering on canvas - imageToDataUrl( - svgurl, - imageType, - {}, - scale, - function (imageURL) { - // Success - try { - downloadURL(imageURL, filename) - if (successCallback) { - successCallback() - } - } catch (e) { - failCallback(e) - } - }, - function () { - // Failed due to tainted canvas - // Create new and untainted canvas - var canvas = doc.createElement('canvas'), - ctx = canvas.getContext('2d'), - imageWidth = - svg.match( - // eslint-disable-next-line no-useless-escape - /^]*width\s*=\s*\"?(\d+)\"?[^>]*>/ - )[1] * scale, - imageHeight = - svg.match( - // eslint-disable-next-line no-useless-escape - /^]*height\s*=\s*\"?(\d+)\"?[^>]*>/ - )[1] * scale, - downloadWithCanVG = function () { - var v = win.canvg.Canvg.fromString(ctx, svg) - v.start() - try { - downloadURL( - win.navigator.msSaveOrOpenBlob - ? canvas.msToBlob() - : canvas.toDataURL(imageType), - filename - ) - if (successCallback) { - successCallback() - } - } catch (e) { - failCallback(e) - } finally { - finallyHandler() - } - } - canvas.width = imageWidth - canvas.height = imageHeight - if (win.canvg) { - // Use preloaded canvg - downloadWithCanVG() - } else { - // Must load canVG first. // Don't destroy the object - // URL yet since we are doing things asynchronously. A - // cleaner solution would be nice, but this will do for - // now. - objectURLRevoke = true - getScript(libURL + 'canvg.js', function () { - downloadWithCanVG() - }) - } - }, - // No canvas support - failCallback, - // Failed to load image - failCallback, - // Finally - function () { - if (objectURLRevoke) { - finallyHandler() - } - } - ) - } - } - ) -}