Merge pull request #3395 from ethereum/sol2uml-download-matomo
Add download Button and Matomo Integration to Sol2Uml pluginpull/5370/head
commit
94b5eec640
@ -0,0 +1,4 @@ |
||||
{ |
||||
"solUml.pngDownload": "Download as PNG", |
||||
"solUml.pdfDownload": "Download as PDF" |
||||
} |
@ -0,0 +1,4 @@ |
||||
{ |
||||
"solUml.PngDownload": "sfg", |
||||
"solUml.PdfDownload": "sdf" |
||||
} |
@ -0,0 +1,143 @@ |
||||
import { CustomTooltip } from '@remix-ui/helper' |
||||
import React, { Fragment, Ref } from 'react' |
||||
import { Dropdown } from 'react-bootstrap' |
||||
import { UmlFileType } from '../utilities/UmlDownloadStrategy' |
||||
|
||||
const _paq = (window._paq = window._paq || []) |
||||
|
||||
export const Markup = React.forwardRef( |
||||
( |
||||
{ |
||||
children, |
||||
onClick, |
||||
icon, |
||||
className = "", |
||||
}: { |
||||
children: React.ReactNode |
||||
onClick: (e) => void |
||||
icon: string |
||||
className: string |
||||
}, |
||||
ref: Ref<HTMLButtonElement> |
||||
) => ( |
||||
<button |
||||
ref={ref} |
||||
onClick={(e) => { |
||||
e.preventDefault() |
||||
onClick(e) |
||||
}} |
||||
className={className.replace("dropdown-toggle", "")} |
||||
> |
||||
<i className={icon}></i> |
||||
</button> |
||||
) |
||||
) |
||||
|
||||
export const UmlCustomMenu = React.forwardRef( |
||||
( |
||||
{ |
||||
children, |
||||
style, |
||||
className, |
||||
"aria-labelledby": labeledBy, |
||||
}: { |
||||
children: React.ReactNode |
||||
style?: React.CSSProperties |
||||
className: string |
||||
"aria-labelledby"?: string |
||||
}, |
||||
ref: Ref<HTMLDivElement> |
||||
) => { |
||||
const height = window.innerHeight * 0.6 |
||||
return ( |
||||
<div |
||||
ref={ref} |
||||
style={style} |
||||
className={className} |
||||
aria-labelledby={labeledBy} |
||||
> |
||||
<ul |
||||
className="overflow-auto list-unstyled mb-0" |
||||
style={{ maxHeight: height + "px" }} |
||||
> |
||||
{children} |
||||
</ul> |
||||
</div> |
||||
) |
||||
} |
||||
) |
||||
|
||||
interface UmlDownloadProps { |
||||
download: (fileType: UmlFileType) => void |
||||
} |
||||
|
||||
export default function UmlDownload(props: UmlDownloadProps) { |
||||
return ( |
||||
<Fragment> |
||||
<Dropdown id="solUmlMenuDropdown"> |
||||
<Dropdown.Toggle |
||||
icon="far fa-arrow-to-bottom uml-btn-icon" |
||||
as={Markup} |
||||
className="badge badge-info remixui_no-shadow p-2 rounded-circle mr-2" |
||||
></Dropdown.Toggle> |
||||
<Dropdown.Menu as={UmlCustomMenu} className="custom-dropdown-items"> |
||||
<Dropdown.Item |
||||
onClick={() => { |
||||
_paq.push([ |
||||
"trackEvent", |
||||
"solidityumlgen", |
||||
"download", |
||||
"downloadAsPng", |
||||
]); |
||||
props.download("png") |
||||
}} |
||||
> |
||||
<CustomTooltip |
||||
placement="left-start" |
||||
tooltipId="solUmlgenDownloadAsPngTooltip" |
||||
tooltipClasses="text-nowrap" |
||||
tooltipText={"Download UML diagram as a PNG file"} |
||||
> |
||||
<div data-id="umlPngDownload"> |
||||
<span |
||||
id="umlPngDownloadBtn" |
||||
data-id="umlPngDownload" |
||||
className="far fa-image pl-2" |
||||
></span> |
||||
<span className="pl-1">Download as PNG</span> |
||||
</div> |
||||
</CustomTooltip> |
||||
</Dropdown.Item> |
||||
<Dropdown.Divider /> |
||||
<Dropdown.Item |
||||
onClick={() => { |
||||
_paq.push([ |
||||
"trackEvent", |
||||
"solUmlgen", |
||||
"download", |
||||
"downloadAsPdf", |
||||
]); |
||||
props.download("pdf") |
||||
}} |
||||
> |
||||
<CustomTooltip |
||||
placement="left-start" |
||||
tooltipId="solUmlgenDownloadAsPdfTooltip" |
||||
tooltipClasses="text-nowrap" |
||||
tooltipText={"Download UML diagram as a PDF file"} |
||||
> |
||||
<div data-id="umlPdfDownload"> |
||||
<span |
||||
id="umlPdfDownloadBtn" |
||||
data-id="umlPdfDownload" |
||||
className="far fa-file-pdf pl-2" |
||||
></span> |
||||
<span className="pl-2">Download as PDF</span> |
||||
</div> |
||||
</CustomTooltip> |
||||
</Dropdown.Item> |
||||
</Dropdown.Menu> |
||||
</Dropdown> |
||||
</Fragment> |
||||
) |
||||
} |
@ -0,0 +1,86 @@ |
||||
interface IUmlDownloadStrategy { |
||||
download (uml: string, fileName: string): void |
||||
} |
||||
|
||||
export type UmlFileType = 'pdf' | 'png' |
||||
|
||||
class PdfUmlDownloadStrategy implements IUmlDownloadStrategy { |
||||
|
||||
public download (uml: string, fileName: string): void { |
||||
const svg = new Blob([uml], { type: 'image/svg+xml;charset=utf-8' }) |
||||
const Url = window.URL || window.webkitURL |
||||
const url = Url.createObjectURL(svg) |
||||
const img = document.createElement('img') |
||||
let doc |
||||
img.onload = async () => { |
||||
const canvas = document.createElement('canvas') |
||||
canvas.width = img.naturalWidth |
||||
canvas.height = img.naturalHeight |
||||
const ctx = canvas.getContext('2d') |
||||
const scale = window.devicePixelRatio*1 |
||||
canvas.style.width = `${Math.round(img.naturalWidth/scale)}`.concat('px') |
||||
canvas.style.height = `${Math.round(img.naturalHeight/scale)}`.concat('px') |
||||
canvas.style.margin = '0' |
||||
canvas.style.padding = '0' |
||||
ctx.scale(window.devicePixelRatio, window.devicePixelRatio) |
||||
ctx.drawImage(img, 0, 0, Math.round(img.naturalWidth/scale), Math.round(img.naturalHeight/scale)) |
||||
if (doc === null || doc === undefined) { |
||||
const { default: jsPDF } = await import('jspdf') |
||||
doc = new jsPDF('landscape', 'px', [img.naturalHeight, img.naturalWidth], true) |
||||
} |
||||
const pageWidth = doc.internal.pageSize.getWidth() |
||||
const pageHeight = doc.internal.pageSize.getHeight() |
||||
doc.addImage(canvas.toDataURL('image/png',0.5), 'PNG', 0, 0, pageWidth, pageHeight) |
||||
doc.save(fileName.split('/')[1].split('.')[0].concat('.pdf')) |
||||
} |
||||
img.src = url |
||||
doc = null |
||||
} |
||||
} |
||||
|
||||
class ImageUmlDownloadStrategy implements IUmlDownloadStrategy { |
||||
public download (uml: string, fileName: string): void { |
||||
const svg = new Blob([uml], { type: 'image/svg+xml;charset=utf-8' }) |
||||
const Url = window.URL || window.webkitURL |
||||
const url = Url.createObjectURL(svg) |
||||
const img = document.createElement('img') |
||||
img.onload = () => { |
||||
const canvas = document.createElement('canvas') |
||||
canvas.width = img.naturalWidth |
||||
canvas.height = img.naturalHeight |
||||
const ctx = canvas.getContext('2d') |
||||
const scale = window.devicePixelRatio*1 |
||||
canvas.style.width = `${Math.round(img.naturalWidth/scale)}`.concat('px') |
||||
canvas.style.height = `${Math.round(img.naturalHeight/scale)}`.concat('px') |
||||
canvas.style.margin = '0' |
||||
canvas.style.padding = '0' |
||||
ctx.scale(window.devicePixelRatio, window.devicePixelRatio) |
||||
ctx.drawImage(img, 0, 0, Math.round(img.naturalWidth/scale), Math.round(img.naturalHeight/scale)) |
||||
const png = canvas.toDataURL('image/png') |
||||
const a = document.createElement('a') |
||||
a.download = fileName.split('/')[1].split('.')[0].concat('.png') |
||||
a.href = png |
||||
a.click() |
||||
} |
||||
img.src = url |
||||
} |
||||
} |
||||
|
||||
export class UmlDownloadContext { |
||||
private strategy: IUmlDownloadStrategy |
||||
|
||||
private setStrategy (strategy: IUmlDownloadStrategy): void { |
||||
this.strategy = strategy |
||||
} |
||||
|
||||
public download (uml: string, fileName: string, fileType: UmlFileType ): void { |
||||
if (fileType === 'pdf') { |
||||
this.setStrategy(new PdfUmlDownloadStrategy()) |
||||
} else if (fileType === 'png') { |
||||
this.setStrategy(new ImageUmlDownloadStrategy()) |
||||
} else { |
||||
throw new Error('Invalid file type') |
||||
} |
||||
this.strategy.download(uml, fileName) |
||||
} |
||||
} |
Loading…
Reference in new issue