diff --git a/ArduinoFrontend/package-lock.json b/ArduinoFrontend/package-lock.json index 078f2a20e..3baea0774 100644 --- a/ArduinoFrontend/package-lock.json +++ b/ArduinoFrontend/package-lock.json @@ -1532,6 +1532,7 @@ "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", "dev": true, + "optional": true, "requires": { "delegates": "^1.0.0", "readable-stream": "^2.0.6" @@ -2676,6 +2677,11 @@ "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", "dev": true }, + "chroma-js": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/chroma-js/-/chroma-js-1.4.1.tgz", + "integrity": "sha512-jTwQiT859RTFN/vIf7s+Vl/Z2LcMrvMv3WUFmd/4u76AdlFC0NTNgqEEFPcRiHmAswPsMiQEDZLM8vX8qXpZNQ==" + }, "chrome-trace-event": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz", @@ -2984,7 +2990,8 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", - "dev": true + "dev": true, + "optional": true }, "constants-browserify": { "version": "1.0.0", @@ -3505,7 +3512,8 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", - "dev": true + "dev": true, + "optional": true }, "depd": { "version": "1.1.2", @@ -4848,12 +4856,14 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, + "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -4874,7 +4884,8 @@ "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "console-control-strings": { "version": "1.1.0", @@ -5025,6 +5036,7 @@ "version": "3.0.4", "bundled": true, "dev": true, + "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -5032,12 +5044,14 @@ "minimist": { "version": "1.2.5", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "minipass": { "version": "2.9.0", "bundled": true, "dev": true, + "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -5056,6 +5070,7 @@ "version": "0.5.3", "bundled": true, "dev": true, + "optional": true, "requires": { "minimist": "^1.2.5" } @@ -5117,7 +5132,8 @@ "npm-normalize-package-bin": { "version": "1.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "npm-packlist": { "version": "1.4.8", @@ -5158,6 +5174,7 @@ "version": "1.4.0", "bundled": true, "dev": true, + "optional": true, "requires": { "wrappy": "1" } @@ -5235,7 +5252,8 @@ "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "safer-buffer": { "version": "2.1.2", @@ -5335,12 +5353,14 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "yallist": { "version": "3.1.1", "bundled": true, - "dev": true + "dev": true, + "optional": true } } }, @@ -5349,6 +5369,7 @@ "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", "dev": true, + "optional": true, "requires": { "graceful-fs": "^4.1.2", "inherits": "~2.0.0", @@ -5367,6 +5388,7 @@ "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", "dev": true, + "optional": true, "requires": { "aproba": "^1.0.3", "console-control-strings": "^1.0.0", @@ -5410,7 +5432,8 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", - "dev": true + "dev": true, + "optional": true }, "get-stream": { "version": "3.0.0", @@ -5626,7 +5649,8 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", - "dev": true + "dev": true, + "optional": true }, "has-value": { "version": "1.0.0", @@ -6470,7 +6494,8 @@ "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", - "dev": true + "dev": true, + "optional": true }, "is-windows": { "version": "1.0.2", @@ -7160,6 +7185,7 @@ "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", "dev": true, + "optional": true, "requires": { "graceful-fs": "^4.1.2", "parse-json": "^2.2.0", @@ -7172,7 +7198,8 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true + "dev": true, + "optional": true } } }, @@ -7204,10 +7231,17 @@ } }, "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "lodash-transpose": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/lodash-transpose/-/lodash-transpose-0.2.1.tgz", + "integrity": "sha1-bNVTiutzuzsMvhAVBLBfCOiMg0k=", + "requires": { + "lodash": "^4.12.0" + } }, "lodash.clonedeep": { "version": "4.5.0", @@ -7405,7 +7439,8 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", - "dev": true + "dev": true, + "optional": true }, "map-stream": { "version": "0.1.0", @@ -8098,6 +8133,7 @@ "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", "dev": true, + "optional": true, "requires": { "are-we-there-yet": "~1.1.2", "console-control-strings": "~1.1.0", @@ -8576,6 +8612,7 @@ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", "dev": true, + "optional": true, "requires": { "error-ex": "^1.2.0" } @@ -9390,18 +9427,18 @@ }, "dependencies": { "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", "dev": true, "requires": { - "ms": "^2.1.1" + "ms": "2.1.2" } }, "mime": { - "version": "2.4.6", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.6.tgz", - "integrity": "sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.2.tgz", + "integrity": "sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==", "dev": true }, "ms": { @@ -9545,6 +9582,7 @@ "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", "dev": true, + "optional": true, "requires": { "load-json-file": "^1.0.0", "normalize-package-data": "^2.3.2", @@ -9556,6 +9594,7 @@ "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", "dev": true, + "optional": true, "requires": { "graceful-fs": "^4.1.2", "pify": "^2.0.0", @@ -9566,7 +9605,8 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true + "dev": true, + "optional": true } } }, @@ -9575,6 +9615,7 @@ "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", "dev": true, + "optional": true, "requires": { "find-up": "^1.0.0", "read-pkg": "^1.0.0" @@ -9585,6 +9626,7 @@ "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", "dev": true, + "optional": true, "requires": { "path-exists": "^2.0.0", "pinkie-promise": "^2.0.0" @@ -9595,6 +9637,7 @@ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", "dev": true, + "optional": true, "requires": { "pinkie-promise": "^2.0.0" } @@ -11089,6 +11132,7 @@ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", "dev": true, + "optional": true, "requires": { "is-utf8": "^0.2.0" } @@ -12075,7 +12119,8 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true + "dev": true, + "optional": true }, "readdirp": { "version": "3.4.0", @@ -12589,6 +12634,7 @@ "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", "dev": true, + "optional": true, "requires": { "string-width": "^1.0.2 || 2" } diff --git a/eda-frontend/src/components/Dashboard/SchematicCard.js b/eda-frontend/src/components/Dashboard/SchematicCard.js index 0ef5086cc..b9375cd0b 100644 --- a/eda-frontend/src/components/Dashboard/SchematicCard.js +++ b/eda-frontend/src/components/Dashboard/SchematicCard.js @@ -1,5 +1,5 @@ -import React from 'react' -import PropTypes from 'prop-types' +import React from "react" +import PropTypes from "prop-types" import { Button, Typography, @@ -25,7 +25,7 @@ import MuiAlert from '@material-ui/lab/Alert' const useStyles = makeStyles((theme) => ({ media: { height: 0, - paddingTop: '56.25%' // 16:9 + paddingTop: "56.25%", // 16:9 }, rating: { marginTop: theme.spacing(1), @@ -47,66 +47,83 @@ function SimpleSnackbar({ open, close, sch }) { return ( - - - - - } + + + + + } > - {'Delete ' + sch.name + ' ?'} + {"Delete " + sch.name + " ?"} - ) + ); } SimpleSnackbar.propTypes = { open: PropTypes.bool, close: PropTypes.func, - sch: PropTypes.object -} + sch: PropTypes.object, +}; // Display schematic updated status (e.g : updated 2 hours ago...) function timeSince(jsonDate) { var json = jsonDate - var date = new Date(json) + var date = new Date(json); - var seconds = Math.floor((new Date() - date) / 1000) + var seconds = Math.floor((new Date() - date) / 1000); - var interval = Math.floor(seconds / 31536000) + var interval = Math.floor(seconds / 31536000); if (interval > 1) { - return interval + ' years' + return interval + " years"; } - interval = Math.floor(seconds / 2592000) + interval = Math.floor(seconds / 2592000); if (interval > 1) { - return interval + ' months' + return interval + " months"; } - interval = Math.floor(seconds / 86400) + interval = Math.floor(seconds / 86400); if (interval > 1) { - return interval + ' days' + return interval + " days"; } - interval = Math.floor(seconds / 3600) + interval = Math.floor(seconds / 3600); if (interval > 1) { - return interval + ' hours' + return interval + " hours"; } - interval = Math.floor(seconds / 60) + interval = Math.floor(seconds / 60); if (interval > 1) { - return interval + ' minutes' + return interval + " minutes"; } - return Math.floor(seconds) + ' seconds' + return Math.floor(seconds) + " seconds"; } // Display schematic created date (e.g : Created On 29 Jun 2020) @@ -123,14 +140,14 @@ export default function SchematicCard({ sch }) { const classes = useStyles() // To handel delete schematic snackbar - const [snacOpen, setSnacOpen] = React.useState(false) + const [snacOpen, setSnacOpen] = React.useState(false); const handleSnacClick = () => { setSnacOpen(true) } const handleSnacClose = (event, reason) => { - if (reason === 'clickaway') { - return + if (reason === "clickaway") { + return; } setSnacOpen(false) } @@ -148,7 +165,7 @@ export default function SchematicCard({ sch }) { + { handleSnacClick() }} @@ -187,18 +204,22 @@ export default function SchematicCard({ sch }) { {/* Display share status */} - + - ) + ); } SchematicCard.propTypes = { diff --git a/eda-frontend/src/components/SchematicEditor/PropertiesSidebar.js b/eda-frontend/src/components/SchematicEditor/PropertiesSidebar.js index 4b3800f20..7daaa6fbe 100644 --- a/eda-frontend/src/components/SchematicEditor/PropertiesSidebar.js +++ b/eda-frontend/src/components/SchematicEditor/PropertiesSidebar.js @@ -1,10 +1,14 @@ import React from 'react' import PropTypes from 'prop-types' -import { Hidden, List, ListItem, ListItemText, TextField, MenuItem, TextareaAutosize } from '@material-ui/core' +import { Hidden, List, ListItem, ListItemText, TextField, MenuItem, TextareaAutosize, IconButton, Collapse, Dialog, DialogTitle, DialogContent, Button } from '@material-ui/core' +import CreateNewFolderOutlinedIcon from "@material-ui/icons/CreateNewFolderOutlined" import { makeStyles } from '@material-ui/core/styles' import ComponentProperties from './ComponentProperties' import { useSelector, useDispatch } from 'react-redux' -import { setSchDescription } from '../../redux/actions/index' +import { setSchDescription,saveSchematic } from '../../redux/actions/index' +import api from "../../utils/Api" +import VersionComponent from "./VersionComponent" +import Canvg from "canvg"; import './Helper/SchematicEditor.css' @@ -115,13 +119,66 @@ GridProperties.propTypes = { gridRef: PropTypes.object.isRequired } -export default function PropertiesSidebar ({ gridRef, outlineRef }) { +export default function PropertiesSidebar({ gridRef, outlineRef }) { const classes = useStyles() const isOpen = useSelector(state => state.componentPropertiesReducer.isPropertiesWindowOpen) const schSave = useSelector(state => state.saveSchematicReducer) const [description, setDescription] = React.useState(schSave.description) + const [versions, setVersions] = React.useState(null) + const [branchOpen,setBranchOpen] = React.useState(null) + const [branchName,setBranchName] = React.useState("") + const [dialogOpen,setDialogOpen] = React.useState(false) + + React.useEffect(() => { + const config = { + headers: { + "Content-Type": "application/x-www-form-urlencoded", + }, + }; + const token = localStorage.getItem("esim_token") + // If token available add to headers + if (token) { + config.headers.Authorization = `Token ${token}` + } + if (window.location.href.split("?id=")[1]&&!window.location.href.split("?id=")[1].includes('gallery')) { + api + .get( + "save/versions/" + + window.location.href.split("?id=")[1].substring(0, 36), + config + ) + .then((resp) => { + console.log(resp.data); + var versionsAccordingFreq={} + resp.data.forEach((value) => { + var d = new Date(value.save_time) + value.date = + d.getDate() + "/" + d.getMonth() + "/" + d.getFullYear(); + value.time = d.getHours() + ":" + d.getMinutes(); + if (d.getMinutes() < 10) { + value.time = d.getHours() + ":0" + d.getMinutes(); + } + versionsAccordingFreq[value.branch]?versionsAccordingFreq[value.branch].push(value):versionsAccordingFreq[value.branch]=[value] + }); + setVersions(Object.entries(versionsAccordingFreq).reverse()) + var temp=[]; + for(var i=0;i svg").cloneNode(true); + svg.removeAttribute("style"); + svg.setAttribute("width", gridRef.current.scrollWidth); + svg.setAttribute("height", gridRef.current.scrollHeight); + const canvas = document.createElement("canvas"); + canvas.width = gridRef.current.scrollWidth; + canvas.height = gridRef.current.scrollHeight; + canvas.style.width = canvas.width + "px"; + canvas.style.height = canvas.height + "px"; + var images = svg.getElementsByTagName("image"); + for (var image of images) { + const data = await fetch(image.getAttribute("xlink:href")).then((v) => { + return v.text(); + }); + image.removeAttribute("xlink:href"); + image.setAttribute( + "href", + "data:image/svg+xml;base64," + window.btoa(data) + ); + } + var ctx = canvas.getContext("2d"); + ctx.mozImageSmoothingEnabled = true; + ctx.webkitImageSmoothingEnabled = true; + ctx.msImageSmoothingEnabled = true; + ctx.imageSmoothingEnabled = true; + const pixelRatio = window.devicePixelRatio || 1; + ctx.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0); + return new Promise((resolve) => { + if (type === "SVG") { + var svgdata = new XMLSerializer().serializeToString(svg); + resolve('' + svgdata); + return; + } + var v = Canvg.fromString(ctx, svg.outerHTML); + v.render().then(() => { + var image = ""; + if (type === "JPG") { + const imgdata = ctx.getImageData(0, 0, canvas.width, canvas.height); + for (let i = 0; i < imgdata.data.length; i += 4) { + if (imgdata.data[i + 3] === 0) { + imgdata.data[i] = 255; + imgdata.data[i + 1] = 255; + imgdata.data[i + 2] = 255; + imgdata.data[i + 3] = 255; + } + } + ctx.putImageData(imgdata, 0, 0); + image = canvas.toDataURL("image/jpeg", 1.0); + } else { + if (type === "PNG") { + image = canvas.toDataURL("image/png"); + } + } + resolve(image); + }); + }); + } + + const handleBranch = (branchName) => { + setDialogOpen(false) + exportImage("PNG").then((res) => { + dispatch(saveSchematic(schSave.title,schSave.description,schSave.xmlData,res,true,branchName,setVersions,versions)) + }) + setBranchName("") + } + + const handleClick = (index) => { + console.log(index) + var left=branchOpen.slice(0,index) + var right=branchOpen.slice(index+1) + var temp=!branchOpen[index] + left.push(temp) + left=left.concat(right) + console.log(left) + setBranchOpen(left) + } + + const handleBranchName = (e) => { + setBranchName(e.target.value) + } + + const handleDialogOpen = () => { + setDialogOpen(true) + } + + const handleDialogClose = () => { + setBranchName("") + setDialogOpen(false) + } + return ( <> @@ -160,8 +308,76 @@ export default function PropertiesSidebar ({ gridRef, outlineRef }) { - + + +

History

+ + + + + Create new Variation + + +
+ + +
+
+
+ {(versions&&branchOpen) ? + <> + {versions.map((branch,index) => { + return ( + <> + handleClick(index)}> + + + + { + branch[1].map((version) => + + ) + } + + + + ) + } + ) + } + + : No History Available + } +
) } diff --git a/eda-frontend/src/components/SchematicEditor/SchematicToolbar.js b/eda-frontend/src/components/SchematicEditor/SchematicToolbar.js index 710179e04..f7407dfbe 100644 --- a/eda-frontend/src/components/SchematicEditor/SchematicToolbar.js +++ b/eda-frontend/src/components/SchematicEditor/SchematicToolbar.js @@ -34,33 +34,33 @@ import CreateProject from '../Project/CreateProject' const useStyles = makeStyles((theme) => ({ menuButton: { - marginLeft: 'auto', + marginLeft: "auto", marginRight: theme.spacing(0), padding: theme.spacing(1), - [theme.breakpoints.up('lg')]: { - display: 'none' - } + [theme.breakpoints.up("lg")]: { + display: "none", + }, }, tools: { padding: theme.spacing(1), margin: theme.spacing(0, 0.5), - color: '#262626' + color: "#262626", }, pipe: { - fontSize: '1.45rem', - color: '#d6c4c2', - margin: theme.spacing(0, 1.5) - } -})) + fontSize: "1.45rem", + color: "#d6c4c2", + margin: theme.spacing(0, 1.5), + }, +})); // Notification snackbar to give alert messages -function SimpleSnackbar ({ open, close, message }) { +function SimpleSnackbar({ open, close, message }) { return (
- + } />
- ) + ); } SimpleSnackbar.propTypes = { open: PropTypes.bool, close: PropTypes.func, - message: PropTypes.string -} + message: PropTypes.string, +}; -export default function SchematicToolbar ({ mobileClose, gridRef }) { - const classes = useStyles() - const netfile = useSelector(state => state.netlistReducer) - const auth = useSelector(state => state.authReducer) - const schSave = useSelector(state => state.saveSchematicReducer) +export default function SchematicToolbar({ mobileClose, gridRef }) { + const classes = useStyles(); + const netfile = useSelector((state) => state.netlistReducer); + const auth = useSelector((state) => state.authReducer); + const schSave = useSelector((state) => state.saveSchematicReducer); - const dispatch = useDispatch() + const dispatch = useDispatch(); // Netlist Modal Control - const [open, setOpen] = React.useState(false) - const [netlist, genNetlist] = React.useState('') + const [open, setOpen] = React.useState(false); + const [netlist, genNetlist] = React.useState("") + + const handleSave = (version, newSave,save_id) => { + if (!newSave) { + window.location = "#/editor?id=" + window.location.href.split("id=")[1].substr(0, 36) + "&version=" + version + "&branch=" + window.location.href.split("branch=")[1].substr(0) + window.location.reload() + } + else { + window.location = "#/editor?id=" + save_id + "&version=" + version + "&branch=master" + window.location.reload() + } + } const handleClickOpen = () => { - var compNetlist = GenerateNetList() - var netlist = netfile.title + '\n\n' + - compNetlist.models + '\n' + - compNetlist.main + '\n' + - netfile.controlLine + '\n' + - netfile.controlBlock + '\n' - genNetlist(netlist) - setOpen(true) - } + var compNetlist = GenerateNetList(); + var netlist = + netfile.title + + "\n\n" + + compNetlist.models + + "\n" + + compNetlist.main + + "\n" + + netfile.controlLine + + "\n" + + netfile.controlBlock + + "\n"; + genNetlist(netlist); + setOpen(true); + }; const handleClose = () => { - setOpen(false) - } + setOpen(false); + }; // Control Help dialog window - const [helpOpen, setHelpOpen] = React.useState(false) + const [helpOpen, setHelpOpen] = React.useState(false); const handleHelpOpen = () => { - setHelpOpen(true) - } + setHelpOpen(true); + }; const handleHelpClose = () => { - setHelpOpen(false) - } + setHelpOpen(false); + }; // Handel Delete component const handleDeleteComp = () => { - DeleteComp() - dispatch(closeCompProperties()) - } + DeleteComp(); + dispatch(closeCompProperties()); + }; // Handel Notification Snackbar - const [snacOpen, setSnacOpen] = React.useState(false) - const [message, setMessage] = React.useState('') + const [snacOpen, setSnacOpen] = React.useState(false); + const [message, setMessage] = React.useState(""); const handleSnacClick = () => { - setSnacOpen(true) - } + setSnacOpen(true); + }; const handleSnacClose = (event, reason) => { - if (reason === 'clickaway') { - return + if (reason === "clickaway") { + return; } - setSnacOpen(false) - } + setSnacOpen(false); + }; // Image Export of Schematic Diagram - async function exportImage (type) { - const svg = document.querySelector('#divGrid > svg').cloneNode(true) - svg.removeAttribute('style') - svg.setAttribute('width', gridRef.current.scrollWidth) - svg.setAttribute('height', gridRef.current.scrollHeight) - const canvas = document.createElement('canvas') - canvas.width = gridRef.current.scrollWidth - canvas.height = gridRef.current.scrollHeight - canvas.style.width = canvas.width + 'px' - canvas.style.height = canvas.height + 'px' - var images = svg.getElementsByTagName('image') + async function exportImage(type) { + const svg = document.querySelector("#divGrid > svg").cloneNode(true); + svg.removeAttribute("style"); + svg.setAttribute("width", gridRef.current.scrollWidth); + svg.setAttribute("height", gridRef.current.scrollHeight); + const canvas = document.createElement("canvas"); + canvas.width = gridRef.current.scrollWidth; + canvas.height = gridRef.current.scrollHeight; + canvas.style.width = canvas.width + "px"; + canvas.style.height = canvas.height + "px"; + var images = svg.getElementsByTagName("image"); for (var image of images) { - const data = await fetch(image.getAttribute('xlink:href')).then((v) => { - return v.text() - }) - image.removeAttribute('xlink:href') + const data = await fetch(image.getAttribute("xlink:href")).then((v) => { + return v.text(); + }); + image.removeAttribute("xlink:href"); image.setAttribute( - 'href', - 'data:image/svg+xml;base64,' + window.btoa(data) - ) + "href", + "data:image/svg+xml;base64," + window.btoa(data) + ); } - var ctx = canvas.getContext('2d') - ctx.mozImageSmoothingEnabled = true - ctx.webkitImageSmoothingEnabled = true - ctx.msImageSmoothingEnabled = true - ctx.imageSmoothingEnabled = true - const pixelRatio = window.devicePixelRatio || 1 - ctx.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0) - return new Promise(resolve => { - if (type === 'SVG') { - var svgdata = new XMLSerializer().serializeToString(svg) - resolve('' + svgdata) - return + var ctx = canvas.getContext("2d"); + ctx.mozImageSmoothingEnabled = true; + ctx.webkitImageSmoothingEnabled = true; + ctx.msImageSmoothingEnabled = true; + ctx.imageSmoothingEnabled = true; + const pixelRatio = window.devicePixelRatio || 1; + ctx.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0); + return new Promise((resolve) => { + if (type === "SVG") { + var svgdata = new XMLSerializer().serializeToString(svg); + resolve('' + svgdata); + return; } - var v = Canvg.fromString(ctx, svg.outerHTML) + var v = Canvg.fromString(ctx, svg.outerHTML); v.render().then(() => { - var image = '' - if (type === 'JPG') { - const imgdata = ctx.getImageData(0, 0, canvas.width, canvas.height) + var image = ""; + if (type === "JPG") { + const imgdata = ctx.getImageData(0, 0, canvas.width, canvas.height); for (let i = 0; i < imgdata.data.length; i += 4) { if (imgdata.data[i + 3] === 0) { - imgdata.data[i] = 255 - imgdata.data[i + 1] = 255 - imgdata.data[i + 2] = 255 - imgdata.data[i + 3] = 255 + imgdata.data[i] = 255; + imgdata.data[i + 1] = 255; + imgdata.data[i + 2] = 255; + imgdata.data[i + 3] = 255; } } - ctx.putImageData(imgdata, 0, 0) - image = canvas.toDataURL('image/jpeg', 1.0) + ctx.putImageData(imgdata, 0, 0); + image = canvas.toDataURL("image/jpeg", 1.0); } else { - if (type === 'PNG') { - image = canvas.toDataURL('image/png') + if (type === "PNG") { + image = canvas.toDataURL("image/png"); } } - resolve(image) - }) - }) + resolve(image); + }); + }); } // Download JPEG, PNG exported Image - function downloadImage (data, type) { - var evt = new MouseEvent('click', { + function downloadImage(data, type) { + var evt = new MouseEvent("click", { view: window, bubbles: false, - cancelable: true - }) - var a = document.createElement('a') - const ext = (type === 'PNG') ? '.png' : '.jpg' - a.setAttribute('download', schSave.title + '_eSim_on_cloud' + ext) - a.setAttribute('href', data) - a.setAttribute('target', '_blank') - a.dispatchEvent(evt) + cancelable: true, + }); + var a = document.createElement("a"); + const ext = type === "PNG" ? ".png" : ".jpg"; + a.setAttribute("download", schSave.title + "_eSim_on_cloud" + ext); + a.setAttribute("href", data); + a.setAttribute("target", "_blank"); + a.dispatchEvent(evt); } // Download SVG image - function downloadText (data, options) { - const blob = new Blob(data, options) - const evt = new MouseEvent('click', { + function downloadText(data, options) { + const blob = new Blob(data, options); + const evt = new MouseEvent("click", { view: window, bubbles: false, - cancelable: true - }) - const a = document.createElement('a') - a.setAttribute('download', schSave.title + '_eSim_on_cloud.svg') - a.href = URL.createObjectURL(blob) - a.target = '_blank' - a.setAttribute('target', '_blank') - a.dispatchEvent(evt) + cancelable: true, + }); + const a = document.createElement("a"); + a.setAttribute("download", schSave.title + "_eSim_on_cloud.svg"); + a.href = URL.createObjectURL(blob); + a.target = "_blank"; + a.setAttribute("target", "_blank"); + a.dispatchEvent(evt); } - const [imgopen, setImgOpen] = React.useState(false) + const [imgopen, setImgOpen] = React.useState(false); const handleImgClickOpen = () => { - setImgOpen(true) - } + setImgOpen(true); + }; const handleImgClose = (value) => { - setImgOpen(false) - if (value === 'SVG') { - exportImage('SVG') - .then(v => { - downloadText([v], { - type: 'data:image/svg+xml;charset=utf-8;' - }) - }) - } else if (value === 'PNG') { - exportImage('PNG') - .then(v => { - downloadImage(v, 'PNG') - }) - } else if (value === 'JPG') { - exportImage('JPG') - .then(v => { - downloadImage(v, 'JPG') - }) + setImgOpen(false); + if (value === "SVG") { + exportImage("SVG").then((v) => { + downloadText([v], { + type: "data:image/svg+xml;charset=utf-8;", + }); + }); + } else if (value === "PNG") { + exportImage("PNG").then((v) => { + downloadImage(v, "PNG"); + }); + } else if (value === "JPG") { + exportImage("JPG").then((v) => { + downloadImage(v, "JPG"); + }); } - } + }; // Handel Save Schematic onCloud const handelSchSave = () => { if (auth.isAuthenticated !== true) { - setMessage('You are not Logged In') - handleSnacClick() + setMessage("You are not Logged In"); + handleSnacClick(); } else { - var xml = Save() - dispatch(setSchXmlData(xml)) - var title = schSave.title - var description = schSave.description - exportImage('PNG') - .then(res => { - dispatch(saveSchematic(title, description, xml, res)) - }) - setMessage('Saved Successfully') - handleSnacClick() + var xml = Save(); + dispatch(setSchXmlData(xml)); + var title = schSave.title; + var description = schSave.description; + exportImage("PNG").then((res) => { + dispatch(saveSchematic(title, description, xml, res, false, null, handleSave)); + }); + setMessage("Saved Successfully"); + handleSnacClick(); } - } + }; // Save Schematics Locally const handelLocalSchSave = () => { - var saveLocalData = {} - saveLocalData.data_dump = Save() - saveLocalData.title = schSave.title - saveLocalData.description = schSave.description - var json = JSON.stringify(saveLocalData) - const blob = new Blob([json], { type: 'octet/stream' }) - const evt = new MouseEvent('click', { + var saveLocalData = {}; + saveLocalData.data_dump = Save(); + saveLocalData.title = schSave.title; + saveLocalData.description = schSave.description; + var json = JSON.stringify(saveLocalData); + const blob = new Blob([json], { type: "octet/stream" }); + const evt = new MouseEvent("click", { view: window, bubbles: false, - cancelable: true - }) - const a = document.createElement('a') - a.setAttribute('download', schSave.title + '_eSim_on_cloud.json') - a.href = URL.createObjectURL(blob) - a.target = '_blank' - a.setAttribute('target', '_blank') - a.dispatchEvent(evt) - } + cancelable: true, + }); + const a = document.createElement("a"); + a.setAttribute("download", schSave.title + "_eSim_on_cloud.json"); + a.href = URL.createObjectURL(blob); + a.target = "_blank"; + a.setAttribute("target", "_blank"); + a.dispatchEvent(evt); + }; // Open Locally Saved Schematic const handelLocalSchOpen = () => { - var obj = {} - const fileSelector = document.createElement('input') - fileSelector.setAttribute('type', 'file') - fileSelector.setAttribute('accept', 'application/JSON') - fileSelector.click() - fileSelector.addEventListener('change', function (event) { - var reader = new FileReader() - var filename = event.target.files[0].name - if (filename.slice(filename.length - 4) === 'json') { - reader.onload = onReaderLoad - reader.readAsText(event.target.files[0]) + var obj = {}; + const fileSelector = document.createElement("input"); + fileSelector.setAttribute("type", "file"); + fileSelector.setAttribute("accept", "application/JSON"); + fileSelector.click(); + fileSelector.addEventListener("change", function (event) { + var reader = new FileReader(); + var filename = event.target.files[0].name; + if (filename.slice(filename.length - 4) === "json") { + reader.onload = onReaderLoad; + reader.readAsText(event.target.files[0]); } else { - setMessage('Unsupported file type error ! Select valid file.') - handleSnacClick() + setMessage("Unsupported file type error ! Select valid file."); + handleSnacClick(); } - }) + }); const onReaderLoad = function (event) { - obj = JSON.parse(event.target.result) - if (obj.data_dump === undefined || obj.title === undefined || obj.description === undefined) { - setMessage('Unsupported file error !') - handleSnacClick() + obj = JSON.parse(event.target.result); + if ( + obj.data_dump === undefined || + obj.title === undefined || + obj.description === undefined + ) { + setMessage("Unsupported file error !"); + handleSnacClick(); } else { - dispatch(openLocalSch(obj)) + dispatch(openLocalSch(obj)); } - } - } + }; + }; // Control Help dialog window open and close - const [schOpen, setSchOpen] = React.useState(false) + const [schOpen, setSchOpen] = React.useState(false); const handleSchDialOpen = () => { - setSchOpen(true) - } + setSchOpen(true); + }; const handleSchDialClose = () => { - setSchOpen(false) - } + setSchOpen(false); + }; const [libsOpen, setlibsOpen] = React.useState(false) @@ -355,55 +377,112 @@ export default function SchematicToolbar ({ mobileClose, gridRef }) { return ( <> - + - + - + - + - + | - + - + - + | - { dispatch(toggleSimulate()) }}> + { + dispatch(toggleSimulate()); + }} + > - + - + @@ -416,60 +495,105 @@ export default function SchematicToolbar ({ mobileClose, gridRef }) { | - + - + - + | - + - + - + | - + - + - + | - ) + ); } SchematicToolbar.propTypes = { mobileClose: PropTypes.func, - gridRef: PropTypes.object.isRequired -} + gridRef: PropTypes.object.isRequired, +}; diff --git a/eda-frontend/src/components/SchematicEditor/VersionComponent.js b/eda-frontend/src/components/SchematicEditor/VersionComponent.js new file mode 100644 index 000000000..0cc38ba07 --- /dev/null +++ b/eda-frontend/src/components/SchematicEditor/VersionComponent.js @@ -0,0 +1,34 @@ +import React from "react" +import Button from "@material-ui/core/Button" +import { Link as RouterLink } from "react-router-dom" + +export default function VersionComponent({ + name, + date, + time, + save_id, + version, + branch +}) { + const handleClick = (e) => { + e.preventDefault() + window.location = "#/editor?id=" + save_id + "&version=" + version + "&branch=" + branch + window.location.reload() + } + return ( + <> +