summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSunil Shetye2025-03-28 12:57:32 +0530
committerSunil Shetye2025-04-07 15:38:16 +0530
commit5180ed9cb4da5cb555aa8822abb681aea0d6a3d7 (patch)
tree4c14590a81392410cd8e3a75ad1df642be4c6d5e
parent08073c73fd18585a46266896c1e806aff05ca4ca (diff)
downloadCommon-Interface-Project-5180ed9cb4da5cb555aa8822abb681aea0d6a3d7.tar.gz
Common-Interface-Project-5180ed9cb4da5cb555aa8822abb681aea0d6a3d7.tar.bz2
Common-Interface-Project-5180ed9cb4da5cb555aa8822abb681aea0d6a3d7.zip
convert saveSchematic action/reducer to slice
-rw-r--r--blocks/eda-frontend/src/components/SchematicEditor/Header.js11
-rw-r--r--blocks/eda-frontend/src/components/SchematicEditor/Helper/ToolbarTools.js2
-rw-r--r--blocks/eda-frontend/src/components/SchematicEditor/PropertiesSidebar.js4
-rw-r--r--blocks/eda-frontend/src/components/SchematicEditor/SchematicToolbar.js22
-rw-r--r--blocks/eda-frontend/src/components/SchematicEditor/ToolbarExtension.js14
-rw-r--r--blocks/eda-frontend/src/pages/SchematicEditor.js18
-rw-r--r--blocks/eda-frontend/src/redux/actions/actions.js15
-rw-r--r--blocks/eda-frontend/src/redux/actions/index.js1
-rw-r--r--blocks/eda-frontend/src/redux/actions/saveSchematicActions.js241
-rw-r--r--blocks/eda-frontend/src/redux/reducers/index.js4
-rw-r--r--blocks/eda-frontend/src/redux/reducers/saveSchematicReducer.js95
-rw-r--r--blocks/eda-frontend/src/redux/saveSchematicSlice.js275
-rw-r--r--blocks/eda-frontend/src/redux/store.js2
13 files changed, 326 insertions, 378 deletions
diff --git a/blocks/eda-frontend/src/components/SchematicEditor/Header.js b/blocks/eda-frontend/src/components/SchematicEditor/Header.js
index b40987aa..04c17d8a 100644
--- a/blocks/eda-frontend/src/components/SchematicEditor/Header.js
+++ b/blocks/eda-frontend/src/components/SchematicEditor/Header.js
@@ -30,7 +30,8 @@ import { makeStyles } from '@material-ui/core/styles'
import { deepPurple } from '@material-ui/core/colors'
import logo from '../../static/favicon.ico'
-import { setTitle, setSchTitle, setSchShared } from '../../redux/actions/index'
+import { setTitle } from '../../redux/actions/index'
+import { setSchTitle, setSchShared } from '../../redux/saveSchematicSlice'
import { logout } from '../../redux/authSlice'
import { getDateTime as getDate, getUppercaseInitial } from '../../utils/GalleryUtils'
@@ -104,10 +105,10 @@ function Header () {
const classes = useStyles()
const isAuthenticated = useSelector(state => state.auth.isAuthenticated)
const user = useSelector(state => state.auth.user)
- const details = useSelector(state => state.saveSchematicReducer.details)
- const isSaved = useSelector(state => state.saveSchematicReducer.isSaved)
- const isShared = useSelector(state => state.saveSchematicReducer.isShared)
- const title = useSelector(state => state.saveSchematicReducer.title)
+ const details = useSelector(state => state.saveSchematic.details)
+ const isSaved = useSelector(state => state.saveSchematic.isSaved)
+ const isShared = useSelector(state => state.saveSchematic.isShared)
+ const title = useSelector(state => state.saveSchematic.title)
const [anchorEl, setAnchorEl] = useState(null)
const dispatch = useDispatch()
diff --git a/blocks/eda-frontend/src/components/SchematicEditor/Helper/ToolbarTools.js b/blocks/eda-frontend/src/components/SchematicEditor/Helper/ToolbarTools.js
index 71f14fad..c277950a 100644
--- a/blocks/eda-frontend/src/components/SchematicEditor/Helper/ToolbarTools.js
+++ b/blocks/eda-frontend/src/components/SchematicEditor/Helper/ToolbarTools.js
@@ -139,7 +139,7 @@ export function PrintPreview () {
header.style.lineHeight = (this.marginTop - 10) + 'px'
const footer = header.cloneNode(true)
- const title = store.getState().saveSchematicReducer.title
+ const title = store.getState().saveSchematic.title
mxUtils.write(header, title + ' - ' + process.env.REACT_APP_NAME + ' on Cloud')
header.style.borderBottom = '1px solid blue'
header.style.top = '0px'
diff --git a/blocks/eda-frontend/src/components/SchematicEditor/PropertiesSidebar.js b/blocks/eda-frontend/src/components/SchematicEditor/PropertiesSidebar.js
index baf6ed51..2752d38a 100644
--- a/blocks/eda-frontend/src/components/SchematicEditor/PropertiesSidebar.js
+++ b/blocks/eda-frontend/src/components/SchematicEditor/PropertiesSidebar.js
@@ -4,7 +4,7 @@ import { Hidden, List, ListItem, ListItemText, TextField, MenuItem, TextareaAuto
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 } from '../../redux/saveSchematicSlice'
import './Helper/SchematicEditor.css'
@@ -119,7 +119,7 @@ export default function PropertiesSidebar ({ gridRef, outlineRef }) {
const classes = useStyles()
const isOpen = useSelector(state => state.componentPropertiesReducer.isPropertiesWindowOpen)
- const description1 = useSelector(state => state.saveSchematicReducer.description)
+ const description1 = useSelector(state => state.saveSchematic.description)
const [description, setDescription] = useState(description1)
diff --git a/blocks/eda-frontend/src/components/SchematicEditor/SchematicToolbar.js b/blocks/eda-frontend/src/components/SchematicEditor/SchematicToolbar.js
index 1d36dd61..fabd47c3 100644
--- a/blocks/eda-frontend/src/components/SchematicEditor/SchematicToolbar.js
+++ b/blocks/eda-frontend/src/components/SchematicEditor/SchematicToolbar.js
@@ -1,5 +1,5 @@
/* eslint new-cap: ["error", {"newIsCapExceptionPattern": "^mx"}] */
-import React, { useState } from 'react'
+import React, { useEffect, useState } from 'react'
import PropTypes from 'prop-types'
import { Canvg } from 'canvg'
import {
@@ -31,9 +31,10 @@ import beautify from 'xml-beautifier'
import mxGraphFactory from 'mxgraph'
import { NetlistModal, HelpScreen, ImageExportDialog, OpenSchDialog, ScriptScreen } from './ToolbarExtension'
-import { editorZoomIn, editorZoomOut, editorZoomAct, deleteComp, PrintPreview, Rotate, editorUndo, editorRedo, saveXml, ClearGrid } from './Helper/ToolbarTools'
+import { editorZoomIn, editorZoomOut, editorZoomAct, deleteComp, PrintPreview, Rotate, editorUndo, editorRedo, saveXml, ClearGrid, renderGalleryXML } from './Helper/ToolbarTools'
import { useSelector, useDispatch } from 'react-redux'
-import { toggleSimulate, closeCompProperties, setSchXmlData, saveSchematic, openLocalSch, setLoadingDiagram } from '../../redux/actions/index'
+import { toggleSimulate, closeCompProperties } from '../../redux/actions/index'
+import { setSchXmlData, saveSchematic, openLocalSch, setLoadingDiagram } from '../../redux/saveSchematicSlice'
import api from '../../utils/Api'
import { transformXcos, saveToFile } from '../../utils/GalleryUtils'
@@ -96,10 +97,11 @@ SimpleSnackbar.propTypes = {
export default function SchematicToolbar ({ mobileClose, gridRef }) {
const classes = useStyles()
const isAuthenticated = useSelector(state => state.auth.isAuthenticated)
- const description = useSelector(state => state.saveSchematicReducer.description)
- const title2 = useSelector(state => state.saveSchematicReducer.title)
+ const description = useSelector(state => state.saveSchematic.description)
+ const xmlData = useSelector(state => state.saveSchematic.xmlData)
+ const title2 = useSelector(state => state.saveSchematic.title)
- const scriptDump = useSelector(state => state.saveSchematicReducer.scriptDump)
+ const scriptDump = useSelector(state => state.saveSchematic.scriptDump)
const dispatch = useDispatch()
const isMobile = useMediaQuery('(max-width:600px)')
@@ -158,6 +160,12 @@ export default function SchematicToolbar ({ mobileClose, gridRef }) {
setSnacOpen(false)
}
+ useEffect(() => {
+ if (xmlData) {
+ renderGalleryXML(xmlData)
+ }
+ }, [xmlData])
+
// Image Export of Schematic Diagram
async function exportImage (type) {
try {
@@ -296,7 +304,7 @@ export default function SchematicToolbar ({ mobileClose, gridRef }) {
dispatch(setSchXmlData(xml))
exportImage('PNG')
.then(res => {
- dispatch(saveSchematic(title2, description, xml, res, scriptDump))
+ dispatch(saveSchematic({ title: title2, description, xml, base64: res, scriptDump }))
setMessage('Saved Successfully')
})
.catch(err => {
diff --git a/blocks/eda-frontend/src/components/SchematicEditor/ToolbarExtension.js b/blocks/eda-frontend/src/components/SchematicEditor/ToolbarExtension.js
index b2fdb5ef..3e79ae4a 100644
--- a/blocks/eda-frontend/src/components/SchematicEditor/ToolbarExtension.js
+++ b/blocks/eda-frontend/src/components/SchematicEditor/ToolbarExtension.js
@@ -36,11 +36,12 @@ import {
import { makeStyles } from '@material-ui/core/styles'
import CloseIcon from '@material-ui/icons/Close'
import { useSelector, useDispatch } from 'react-redux'
-import { fetchSchematic, fetchDiagram, setSchScriptDump } from '../../redux/actions/index'
+import { fetchSchematic, fetchDiagram, setSchScriptDump } from '../../redux/saveSchematicSlice'
import { fetchSchematics, fetchGallery } from '../../redux/dashboardSlice'
import { setScriptTaskId } from '../../redux/simulationSlice'
import { blue } from '@material-ui/core/colors'
import { getDateTime as getDate, getUppercaseInitial, saveToFile } from '../../utils/GalleryUtils'
+import { renderGalleryXML } from './Helper/ToolbarTools'
import api from '../../utils/Api'
const Transition = forwardRef(function Transition (props, ref) {
@@ -338,7 +339,7 @@ HelpScreen.propTypes = {
}
export function ScriptScreen ({ isOpen, onClose }) {
- const scriptDump = useSelector(state => state.saveSchematicReducer.scriptDump)
+ const scriptDump = useSelector(state => state.saveSchematic.scriptDump)
const title = useSelector(state => state.netlistReducer.title)
const dispatch = useDispatch()
const scriptHandler = (e) => {
@@ -522,11 +523,12 @@ export function OpenSchDialog (props) {
const { open, close, openLocal } = props
const [isLocal, setisLocal] = useState(true)
const [isGallery, setisGallery] = useState(false)
- const details = useSelector(state => state.saveSchematicReducer.details)
+ const details = useSelector(state => state.saveSchematic.details)
const isAuthenticated = useSelector(state => state.auth.isAuthenticated)
const user = useSelector(state => state.auth.user)
const schematics = useSelector(state => state.dashboard.schematics)
const GallerySchSample = useSelector(state => state.dashboard.gallery)
+ const xmlData = useSelector(state => state.schematicEditor.xmlData)
const dispatch = useDispatch()
@@ -534,6 +536,12 @@ export function OpenSchDialog (props) {
dispatch(fetchGallery())
}, [])
+ useEffect(() => {
+ if (xmlData) {
+ renderGalleryXML(xmlData)
+ }
+ }, [xmlData])
+
const title = 'Open ' + process.env.REACT_APP_DIAGRAM_NAME
const typography1 = "You don't have any saved " + process.env.REACT_APP_SMALL_DIAGRAMS_NAME + '...'
return (
diff --git a/blocks/eda-frontend/src/pages/SchematicEditor.js b/blocks/eda-frontend/src/pages/SchematicEditor.js
index 61b078aa..72e39a6b 100644
--- a/blocks/eda-frontend/src/pages/SchematicEditor.js
+++ b/blocks/eda-frontend/src/pages/SchematicEditor.js
@@ -1,4 +1,4 @@
-// Main Layout for Schemaic Editor page.
+// Main Layout for Schematic Editor page.
import React, { useEffect, useRef, useState } from 'react'
import PropTypes from 'prop-types'
import { TailSpin } from 'react-loader-spinner'
@@ -13,8 +13,9 @@ import SchematicToolbar from '../components/SchematicEditor/SchematicToolbar'
import RightSidebar from '../components/SchematicEditor/RightSidebar'
import PropertiesSidebar from '../components/SchematicEditor/PropertiesSidebar'
import LoadGrid from '../components/SchematicEditor/Helper/ComponentDrag'
+import { renderGalleryXML } from '../components/SchematicEditor/Helper/ToolbarTools'
import '../components/SchematicEditor/Helper/SchematicEditor.css'
-import { fetchDiagram, fetchSchematic } from '../redux/actions/index'
+import { fetchDiagram, fetchSchematic } from '../redux/saveSchematicSlice'
import { useDispatch, useSelector } from 'react-redux'
const useStyles = makeStyles((theme) => ({
@@ -34,13 +35,20 @@ export default function SchematicEditor (props) {
const outlineRef = useRef()
const dispatch = useDispatch()
const [mobileOpen, setMobileOpen] = useState(false)
- const isLoading = useSelector(state => state.saveSchematicReducer.isLoading)
+ const isLoading = useSelector(state => state.saveSchematic.isLoading)
+ const xmlData = useSelector(state => state.saveSchematic.xmlData)
const handleDrawerToggle = () => {
setMobileOpen(!mobileOpen)
}
useEffect(() => {
+ if (xmlData) {
+ renderGalleryXML(xmlData)
+ }
+ }, [xmlData])
+
+ useEffect(() => {
document.title = process.env.REACT_APP_DIAGRAM_NAME + ' Editor - ' + process.env.REACT_APP_NAME
const container = gridRef.current
const sidebar = compRef.current
@@ -52,11 +60,11 @@ export default function SchematicEditor (props) {
const cktid = query.get('id')
if (cktid.substring(0, 7) === 'gallery') {
- // Loading Gallery schemaic.
+ // Loading Gallery schematic.
dispatch(fetchDiagram(cktid))
} else {
- // Loading User on-cloud saved schemaic.
+ // Loading User on-cloud saved schematic.
dispatch(fetchSchematic(cktid))
}
}
diff --git a/blocks/eda-frontend/src/redux/actions/actions.js b/blocks/eda-frontend/src/redux/actions/actions.js
index 87267226..56d69b00 100644
--- a/blocks/eda-frontend/src/redux/actions/actions.js
+++ b/blocks/eda-frontend/src/redux/actions/actions.js
@@ -16,18 +16,3 @@ export const CLOSE_COMP_PROPERTIES = 'CLOSE_COMP_PROPERTIES'
export const SET_NETLIST = 'SET_NETLIST'
export const SET_TITLE = 'SET_TITLE'
export const SET_MODEL = 'SET_MODEL'
-
-// Actions for saving scheamtics and loading saved, gallery and local schematics.
-export const LOADING_DIAGRAM = 'LOADING_DIAGRAM'
-export const SAVE_SCHEMATICS = 'SAVE_SCHEMATICS'
-export const SET_SCH_SAVED = 'SET_SCH_SAVED'
-export const SET_SCH_TITLE = 'SET_SCH_TITLE'
-export const SET_SCH_DESCRIPTION = 'SET_SCH_DESCRIPTION'
-export const SET_SCH_XML_DATA = 'SET_SCH_XML_DATA'
-export const SET_SCH_SHARED = 'SET_SCH_SHARED'
-export const CLEAR_DETAILS = 'CLEAR_DETAILS'
-export const LOAD_GALLERY = 'LOAD_GALLERY'
-export const SET_SCH_SCRIPT_DUMP = 'SET_SCH_SCRIPT_DUMP'
-
-// Action for fetching on-cloud saved schematics for authenticated user to display in dashboard
-export const FETCH_DIAGRAM = 'FETCH_DIAGRAM'
diff --git a/blocks/eda-frontend/src/redux/actions/index.js b/blocks/eda-frontend/src/redux/actions/index.js
index bd55df33..dcfac0f0 100644
--- a/blocks/eda-frontend/src/redux/actions/index.js
+++ b/blocks/eda-frontend/src/redux/actions/index.js
@@ -2,4 +2,3 @@
export * from './schematicEditorActions'
export * from './componentPropertiesActions'
export * from './netlistActions'
-export * from './saveSchematicActions'
diff --git a/blocks/eda-frontend/src/redux/actions/saveSchematicActions.js b/blocks/eda-frontend/src/redux/actions/saveSchematicActions.js
deleted file mode 100644
index b4ae9466..00000000
--- a/blocks/eda-frontend/src/redux/actions/saveSchematicActions.js
+++ /dev/null
@@ -1,241 +0,0 @@
-import * as actions from './actions'
-import queryString from 'query-string'
-import api from '../../utils/Api'
-import { renderGalleryXML } from '../../components/SchematicEditor/Helper/ToolbarTools'
-import { setTitle } from './index'
-import { transformXcos } from '../../utils/GalleryUtils'
-
-export const setLoadingDiagram = (isLoading) => (dispatch) => {
- dispatch({
- type: actions.LOADING_DIAGRAM,
- payload: {
- isLoading
- }
- })
-}
-
-export const setSchTitle = (title) => (dispatch) => {
- dispatch({
- type: actions.SET_SCH_TITLE,
- payload: {
- title
- }
- })
-}
-
-export const setSchDescription = (description) => (dispatch) => {
- dispatch({
- type: actions.SET_SCH_DESCRIPTION,
- payload: {
- description
- }
- })
-}
-
-export const setSchXmlData = (xmlData) => (dispatch) => {
- dispatch({
- type: actions.SET_SCH_XML_DATA,
- payload: {
- xmlData
- }
- })
-}
-
-export const setSchScriptDump = (scriptDump) => (dispatch) => {
- dispatch({
- type: actions.SET_SCH_SCRIPT_DUMP,
- payload: {
- scriptDump
- }
- })
-}
-
-// Api call to save new schematic or updating saved schematic.
-export const saveSchematic = (title, description, xml, base64, scriptDump) => (dispatch, getState) => {
- const body = {
- data_dump: xml,
- base64_image: base64,
- name: title,
- description,
- script_dump: scriptDump
- }
-
- // Get token from localstorage
- const token = getState().auth.token
- const details = getState().saveSchematicReducer.details
- const isSaved = getState().saveSchematicReducer.isSaved
-
- // add headers
- const config = {
- headers: {
- 'Content-Type': 'application/x-www-form-urlencoded'
- }
- }
-
- // If token available add to headers
- if (token) {
- config.headers.Authorization = `Token ${token}`
- }
-
- if (isSaved) {
- // Updating saved schemaic
- api.post('save/diagram/' + details.save_id, queryString.stringify(body), config)
- .then(
- (res) => {
- dispatch({
- type: actions.SET_SCH_SAVED,
- payload: res.data
- })
- }
- )
- .catch((err) => { console.error(err) })
- } else {
- // saving new schematic
- api.post('save/diagram', queryString.stringify(body), config)
- .then(
- (res) => {
- dispatch({
- type: actions.SET_SCH_SAVED,
- payload: res.data
- })
- }
- )
- .catch((err) => { console.error(err) })
- }
-}
-
-// Action for Loading on-cloud saved schematics
-export const fetchSchematic = (saveId) => (dispatch, getState) => {
- // Get token from localstorage
- const token = getState().auth.token
-
- // add headers
- const config = {
- headers: {
- 'Content-Type': 'application/x-www-form-urlencoded'
- }
- }
-
- // If token available add to headers
- if (token) {
- config.headers.Authorization = `Token ${token}`
- }
-
- api.get('save/diagram/' + saveId, config)
- .then(
- (res) => {
- dispatch({
- type: actions.SET_SCH_SAVED,
- payload: res.data
- })
- dispatch(setSchTitle(res.data.name))
- dispatch(setSchDescription(res.data.description))
- dispatch(setSchXmlData(res.data.data_dump))
- dispatch(setSchScriptDump(res.data.script_dump))
- renderGalleryXML(res.data.data_dump)
- }
- )
- .catch((err) => { console.error(err) })
-}
-
-export const fetchDiagram = (saveId) => (dispatch) => {
- api.get('save/gallery/' + saveId)
- .then(
- (res) => {
- dispatch(loadGallery(res.data))
- }
- )
- .catch((err) => { console.error(err) })
-}
-
-export const setSchShared = (share) => (dispatch, getState) => {
- // Get token from localstorage
- const token = getState().auth.token
- const details = getState().saveSchematicReducer.details
-
- // add headers
- const config = {
- headers: {
- 'Content-Type': 'application/json'
- }
- }
-
- // If token available add to headers
- if (token) {
- config.headers.Authorization = `Token ${token}`
- }
-
- let isShared
- if (share === true) {
- isShared = 'on'
- } else {
- isShared = 'off'
- }
-
- api.post('save/' + details.save_id + '/sharing/' + isShared, {}, config)
- .then(
- (res) => {
- dispatch({
- type: actions.SET_SCH_SHARED,
- payload: res.data
- })
- }
- )
- .catch((err) => { console.error(err) })
-}
-
-// Action for Loading Gallery schematics
-export const loadGallery = (data) => async (dispatch) => {
- if (!data) {
- console.error(`No gallery schematic found with save_id: ${data}`)
- return
- }
-
- dispatch(setLoadingDiagram(true))
-
- try {
- // Check if the data is xcos or xml
- const parser = new DOMParser()
- const xmlDoc = parser.parseFromString(data.data_dump, 'application/xml')
- const isXcos = xmlDoc.getElementsByTagName('XcosDiagram').length > 0
-
- const handleGalleryLoad = (data, dataDump) => {
- dispatch({
- type: actions.LOAD_GALLERY,
- payload: { ...data, data_dump: dataDump }
- })
- dispatch(setTitle('* ' + data.name))
- dispatch(setSchTitle(data.name))
- dispatch(setSchDescription(data.description))
- dispatch(setSchXmlData(dataDump))
- dispatch(setSchScriptDump(data.script_dump))
- renderGalleryXML(dataDump)
- }
-
- if (isXcos) {
- const transformedXml = await transformXcos(xmlDoc)
- const dataDump = new XMLSerializer().serializeToString(transformedXml)
- handleGalleryLoad(data, dataDump)
- } else {
- handleGalleryLoad(data, data.data_dump)
- }
- } catch (error) {
- console.error('Error loading gallery:', error)
- } finally {
- dispatch(setLoadingDiagram(false))
- window.loadGalleryComplete = true
- }
-}
-
-// Action for Loading local exported schematics
-export const openLocalSch = (obj) => (dispatch) => {
- const data = obj
-
- dispatch({ type: actions.CLEAR_DETAILS })
- dispatch(setTitle('* ' + data.title))
- dispatch(setSchTitle(data.title))
- dispatch(setSchDescription(data.description))
- dispatch(setSchXmlData(data.data_dump))
- dispatch(setSchScriptDump(data.script_dump))
- renderGalleryXML(data.data_dump)
-}
diff --git a/blocks/eda-frontend/src/redux/reducers/index.js b/blocks/eda-frontend/src/redux/reducers/index.js
index e8474bb2..bb3fc882 100644
--- a/blocks/eda-frontend/src/redux/reducers/index.js
+++ b/blocks/eda-frontend/src/redux/reducers/index.js
@@ -2,10 +2,8 @@ import { combineReducers } from 'redux'
import schematicEditorReducer from './schematicEditorReducer'
import componentPropertiesReducer from './componentPropertiesReducer'
import netlistReducer from './netlistReducer'
-import saveSchematicReducer from './saveSchematicReducer'
export default combineReducers({
schematicEditorReducer,
componentPropertiesReducer,
- netlistReducer,
- saveSchematicReducer
+ netlistReducer
})
diff --git a/blocks/eda-frontend/src/redux/reducers/saveSchematicReducer.js b/blocks/eda-frontend/src/redux/reducers/saveSchematicReducer.js
deleted file mode 100644
index 3aa288f5..00000000
--- a/blocks/eda-frontend/src/redux/reducers/saveSchematicReducer.js
+++ /dev/null
@@ -1,95 +0,0 @@
-import * as actions from '../actions/actions'
-
-const initialState = {
- title: 'Untitled',
- description: '',
- xmlData: null,
- details: {},
- isLoading: false,
- isSaved: null,
- isShared: null
-}
-
-export default function saveSchematicReducer (state = initialState, action) {
- switch (action.type) {
- case actions.LOADING_DIAGRAM: {
- return {
- ...state,
- isLoading: action.payload.isLoading
- }
- }
-
- case actions.SET_SCH_SAVED: {
- return {
- ...state,
- isSaved: true,
- isShared: action.payload.shared,
- details: action.payload
- }
- }
-
- case actions.SET_SCH_SHARED: {
- return {
- ...state,
- isShared: true,
- details: action.payload
- }
- }
-
- case actions.CLEAR_DETAILS: {
- return {
- ...state,
- isSaved: null,
- isShared: null,
- details: {}
- }
- }
-
- case actions.LOAD_GALLERY: {
- return {
- ...state,
- isSaved: null,
- isShared: null,
- details: action.payload
- }
- }
-
- case actions.FETCH_DIAGRAM: {
- return {
- ...state,
- data: action.payload
- }
- }
-
- case actions.SET_SCH_TITLE: {
- return {
- ...state,
- title: action.payload.title
- }
- }
-
- case actions.SET_SCH_DESCRIPTION: {
- return {
- ...state,
- description: action.payload.description
- }
- }
-
- case actions.SET_SCH_XML_DATA: {
- return {
- ...state,
- xmlData: action.payload.xmlData
- }
- }
-
- case actions.SET_SCH_SCRIPT_DUMP: {
- return {
- ...state,
- scriptDump: action.payload.scriptDump
- }
- }
-
- default:
- return state
- }
-}
diff --git a/blocks/eda-frontend/src/redux/saveSchematicSlice.js b/blocks/eda-frontend/src/redux/saveSchematicSlice.js
new file mode 100644
index 00000000..639e130b
--- /dev/null
+++ b/blocks/eda-frontend/src/redux/saveSchematicSlice.js
@@ -0,0 +1,275 @@
+import { createSlice, createAsyncThunk } from '@reduxjs/toolkit'
+
+import api from '../utils/Api'
+import { transformXcos } from '../utils/GalleryUtils'
+
+const initialState = {
+ title: 'Untitled',
+ description: '',
+ xmlData: null,
+ scriptDump: '',
+ details: {},
+ isLoading: false,
+ isSaved: null,
+ isShared: null
+}
+
+// Api call to save new schematic or updating saved schematic.
+export const saveSchematic = createAsyncThunk(
+ 'saveSchematic/saveSchematic',
+ async ({ title, description, xml, base64, scriptDump }, { getState, rejectWithValue }) => {
+ // Get token from localstorage
+ const token = getState().auth.token
+ if (!token) return rejectWithValue('No token found')
+ const isSaved = getState().saveSchematic.isSaved
+ const details = getState().saveSchematic.details
+
+ // add headers
+ const config = {
+ headers: {
+ 'Content-Type': 'application/json',
+ Authorization: `Token ${token}`
+ }
+ }
+
+ const body = {
+ data_dump: xml,
+ base64_image: base64,
+ name: title,
+ description,
+ script_dump: scriptDump
+ }
+
+ try {
+ const url = `save/diagram${isSaved ? `/${details.save_id}` : ''}`
+ const res = await api.post(url, body, config)
+ if (res.status === 200) {
+ return res.data
+ }
+
+ return rejectWithValue(res.data || 'Failed to save schematic')
+ } catch (err) {
+ console.log(err)
+ const res = err.response
+ return rejectWithValue(res?.data || 'Failed to save schematic')
+ }
+ })
+
+// Action for Loading on-cloud saved schematics
+export const fetchSchematic = createAsyncThunk(
+ 'saveSchematic/fetchSchematic',
+ async (saveId, { getState, rejectWithValue }) => {
+ // Get token from localstorage
+ const token = getState().auth.token
+ if (!token) return rejectWithValue('No token found')
+
+ // add headers
+ const config = {
+ headers: {
+ 'Content-Type': 'application/json',
+ Authorization: `Token ${token}`
+ }
+ }
+
+ try {
+ const res = await api.get(`save/diagram/${saveId}`, config)
+ if (res.status === 200) {
+ return res.data
+ }
+
+ return rejectWithValue(res.data || 'Failed to load schematic')
+ } catch (err) {
+ console.log(err)
+ const res = err.response
+ return rejectWithValue(res?.data || 'Failed to load schematic')
+ }
+ })
+
+// Action for Loading on-cloud saved schematics
+export const fetchDiagram = createAsyncThunk(
+ 'saveSchematic/fetchDiagram',
+ async (saveId, { rejectWithValue }) => {
+ try {
+ const res = await api.get(`save/gallery/${saveId}`)
+ if (res.status === 200) {
+ res.data.data_dump = await loadGallery(res.data)()
+ return res.data
+ }
+
+ return rejectWithValue(res.data || 'Failed to load diagram')
+ } catch (err) {
+ console.log(err)
+ const res = err.response
+ return rejectWithValue(res?.data || 'Failed to load diagram')
+ }
+ })
+
+export const setSchShared = createAsyncThunk(
+ 'saveSchematic/setSchShared',
+ async (share, { getState, rejectWithValue }) => {
+ // Get token from localstorage
+ const token = getState().auth.token
+ if (!token) return rejectWithValue('No token found')
+
+ const details = getState().saveSchematic.details
+
+ // add headers
+ const config = {
+ headers: {
+ 'Content-Type': 'application/json',
+ Authorization: `Token ${token}`
+ }
+ }
+
+ const isShared = share ? 'on' : 'off'
+
+ try {
+ const res = await api.get(`save/${details.save_id}/sharing/${isShared}`, config)
+ if (res.status === 200) {
+ return res.data
+ }
+
+ return rejectWithValue(res.data || 'Failed to share schematic')
+ } catch (err) {
+ console.log(err)
+ const res = err.response
+ return rejectWithValue(res?.data || 'Failed to share schematic')
+ }
+ })
+
+// Action for Loading local exported schematics
+export const openLocalSch = createAsyncThunk(
+ 'saveSchematic/openLocalSch',
+ async (data) => {
+ return data
+ })
+
+// Action for Loading Gallery diagrams
+const loadGallery = (data) => async () => {
+ if (!data) {
+ console.error('No diagram found')
+ return
+ }
+
+ try {
+ // Check if the data is xcos or xml
+ const parser = new DOMParser()
+ let dataDump = data.data_dump
+ const xmlDoc = parser.parseFromString(dataDump, 'application/xml')
+ const isXcos = xmlDoc.getElementsByTagName('XcosDiagram').length > 0
+ if (isXcos) {
+ dataDump = new XMLSerializer().serializeToString(await transformXcos(xmlDoc))
+ }
+ return dataDump
+ } catch (error) {
+ console.error('Error loading gallery:', error)
+ } finally {
+ window.loadGalleryComplete = true
+ }
+}
+
+const saveSchematicSlice = createSlice({
+ name: 'saveSchematic',
+ initialState,
+ reducers: {
+ setLoadingDiagram: (state, action) => {
+ state.isLoading = action.payload
+ },
+ setSchTitle: (state, action) => {
+ state.title = action.payload
+ },
+ setSchDescription: (state, action) => {
+ state.description = action.payload
+ },
+ setSchXmlData: (state, action) => {
+ state.xmlData = action.payload
+ },
+ setSchScriptDump: (state, action) => {
+ state.scriptDump = action.payload
+ }
+ },
+ extraReducers: (builder) => {
+ builder
+ .addCase(saveSchematic.pending, (state) => {
+ state.isLoading = true
+ })
+ .addCase(saveSchematic.fulfilled, (state, action) => {
+ state.isLoading = false
+ state.details = action.payload
+ state.isSaved = true
+ state.isShared = action.payload.shared
+ })
+ .addCase(saveSchematic.rejected, (state) => {
+ state.isLoading = false
+ })
+ .addCase(fetchSchematic.pending, (state) => {
+ state.isLoading = true
+ })
+ .addCase(fetchSchematic.fulfilled, (state, action) => {
+ state.isLoading = false
+ state.details = action.payload
+ state.description = action.payload.description
+ state.isSaved = true
+ state.isShared = action.payload.shared
+ state.title = action.payload.name
+ state.xmlData = action.payload.data_dump
+ state.scriptDump = action.payload.script_dump
+ })
+ .addCase(fetchSchematic.rejected, (state) => {
+ state.isLoading = false
+ })
+ .addCase(fetchDiagram.pending, (state) => {
+ state.isLoading = true
+ })
+ .addCase(fetchDiagram.fulfilled, (state, action) => {
+ state.isLoading = false
+ state.details = action.payload
+ state.description = action.payload.description
+ state.isSaved = false
+ state.isShared = false
+ state.title = action.payload.name
+ state.xmlData = action.payload.data_dump
+ state.scriptDump = action.payload.script_dump
+ })
+ .addCase(fetchDiagram.rejected, (state) => {
+ state.isLoading = false
+ })
+ .addCase(setSchShared.pending, (state) => {
+ state.isLoading = true
+ })
+ .addCase(setSchShared.fulfilled, (state, action) => {
+ state.isLoading = false
+ state.details = action.payload
+ state.isShared = action.payload.shared
+ })
+ .addCase(setSchShared.rejected, (state) => {
+ state.isLoading = false
+ })
+ .addCase(openLocalSch.pending, (state) => {
+ state.isLoading = true
+ })
+ .addCase(openLocalSch.fulfilled, (state, action) => {
+ state.isLoading = false
+ state.details = action.payload
+ state.description = action.payload.description
+ state.isSaved = true
+ state.isShared = action.payload.shared
+ state.title = action.payload.name
+ state.xmlData = action.payload.data_dump
+ state.scriptDump = action.payload.script_dump
+ })
+ .addCase(openLocalSch.rejected, (state) => {
+ state.isLoading = false
+ })
+ }
+})
+
+export const {
+ setLoadingDiagram,
+ setSchTitle,
+ setSchDescription,
+ setSchXmlData,
+ setSchScriptDump
+} = saveSchematicSlice.actions
+
+export default saveSchematicSlice.reducer
diff --git a/blocks/eda-frontend/src/redux/store.js b/blocks/eda-frontend/src/redux/store.js
index 4e16a2a1..c504f79d 100644
--- a/blocks/eda-frontend/src/redux/store.js
+++ b/blocks/eda-frontend/src/redux/store.js
@@ -1,12 +1,14 @@
import { configureStore } from '@reduxjs/toolkit'
import authReducer from './authSlice'
import dashboardReducer from './dashboardSlice'
+import saveSchematicReducer from './saveSchematicSlice'
import simulationReducer from './simulationSlice'
const store = configureStore({
reducer: {
auth: authReducer,
dashboard: dashboardReducer,
+ saveSchematic: saveSchematicReducer,
simulation: simulationReducer
},
middleware: (getDefaultMiddleware) => getDefaultMiddleware()