From f4699d8485751ed01e730e9734cc5212c68f2587 Mon Sep 17 00:00:00 2001 From: Rugz007 Date: Thu, 22 Jul 2021 14:45:03 +0530 Subject: [PATCH] Basic Implementation of Simulation parameters done --- .../src/components/Project/CreateProject.js | 219 ++++++--- .../Project/ProjectSimulationParameters.js | 435 ++++++++++++++++++ .../SchematicEditor/SimulationProperties.js | 16 +- eda-frontend/src/pages/ProjectPage.js | 299 ++++++------ .../src/redux/actions/projectActions.js | 1 - esim-cloud-backend/publishAPI/models.py | 40 ++ esim-cloud-backend/publishAPI/serializers.py | 46 +- esim-cloud-backend/publishAPI/views.py | 83 +++- 8 files changed, 905 insertions(+), 234 deletions(-) create mode 100644 eda-frontend/src/components/Project/ProjectSimulationParameters.js diff --git a/eda-frontend/src/components/Project/CreateProject.js b/eda-frontend/src/components/Project/CreateProject.js index c12c992a8..f7d8382fa 100644 --- a/eda-frontend/src/components/Project/CreateProject.js +++ b/eda-frontend/src/components/Project/CreateProject.js @@ -1,5 +1,5 @@ /* eslint-disable camelcase */ -import React, { useState, useEffect } from 'react' +import React, { useState, useEffect, useRef } from 'react' import { Button, Toolbar, @@ -21,9 +21,10 @@ import { DialogActions, DialogContent, DialogContentText, - DialogTitle + DialogTitle, } from '@material-ui/core' +import { Multiselect } from 'multiselect-react-dropdown' import CloseIcon from '@material-ui/icons/Close' import PostAddIcon from '@material-ui/icons/PostAdd' import KeyboardArrowUpIcon from '@material-ui/icons/KeyboardArrowUp' @@ -34,6 +35,7 @@ import { useDispatch, useSelector } from 'react-redux' import { changeStatus, createProject, deleteProject, getStatus } from '../../redux/actions' import api from '../../utils/Api' import ProjectTimeline from './ProjectTimeline' +import ProjectSimulationParameters from './ProjectSimulationParameters' const useStyles = makeStyles((theme) => ({ appBar: { @@ -49,7 +51,7 @@ const useStyles = makeStyles((theme) => ({ }, paper: { padding: theme.spacing(2), - textAlign: 'center', + textAlign: 'left', color: '#fff' }, formControl: { @@ -62,11 +64,11 @@ const useStyles = makeStyles((theme) => ({ } })) -const Transition = React.forwardRef(function Transition (props, ref) { +const Transition = React.forwardRef(function Transition(props, ref) { return }) -function CreateProject () { +function CreateProject() { const [open, setOpen] = useState(false) const classes = useStyles() const dispatch = useDispatch() @@ -90,9 +92,38 @@ function CreateProject () { const [fields, setFields] = useState([{ name: 'Procedure', text: '' }, { name: 'Observation', text: '' }, { name: 'Conclusion', text: '' }]) const [changed, setChanged] = useState(0) const [deleteDialogue, setDeleteDialogue] = useState(false) + const [dcSweepcontrolLine, setDcSweepControlLine] = useState({ + parameter: '', + sweepType: 'Linear', + start: '', + stop: '', + step: '', + parameter2: '', + start2: '', + stop2: '', + step2: '' + }) + const [transientAnalysisControlLine, setTransientAnalysisControlLine] = useState({ + start: '', + stop: '', + step: '', + skipInitial: false + }) + const [acAnalysisControlLine, setAcAnalysisControlLine] = useState({ + input: 'dec', + start: '', + stop: '', + pointsBydecade: '' + }) + + const [tfAnalysisControlLine, setTfAnalysisControlLine] = useState({ + outputNodes: false, + outputVoltageSource: '', + inputVoltageSource: '' + }) + const [selectedSimulation, setSelectedSimulation] = useState('') useEffect(() => { - console.log(project.details?.project_id) if (open && project.details?.project_id) { dispatch(getStatus(project.details?.project_id)) setStatus(project.details?.status_name) @@ -100,6 +131,18 @@ function CreateProject () { if (project.details) { setDetails({ title: project.details.title, description: project.details.description, active_version: project.details.active_version, active_branch: project.details.active_branch }) setFields(project.details.fields) + if (project.details.dc_sweep) { + setDcSweepControlLine(project.details.dc_sweep) + } + if (project.details.transient_analysis) { + setTransientAnalysisControlLine(project.details.transient_analysis) + } + if (project.details.tf_analysis) { + setTfAnalysisControlLine(project.details.tf_analysis) + } + if (project.details.ac_analysis) { + setAcAnalysisControlLine(project.details.ac_analysis) + } } if (!project.details) { setDetails({ @@ -224,21 +267,20 @@ function CreateProject () { setOpen(!open) } const createPub = () => { - dispatch(createProject(save_id, [details, fields])) + dispatch(createProject(save_id, [details, fields, '', dcSweepcontrolLine, transientAnalysisControlLine, acAnalysisControlLine, tfAnalysisControlLine])) } const clickChange = () => { - console.log(changed) if (changed === 1) { - dispatch(createProject(save_id, [details, fields, ''])) + dispatch(createProject(save_id, [details, fields, '', dcSweepcontrolLine, transientAnalysisControlLine, acAnalysisControlLine, tfAnalysisControlLine])) } else if (changed === 2) { if (status !== project.details.status_name) { dispatch(changeStatus(project.details.project_id, status, '')) } } else if (changed === 3) { if (status !== project.details.status_name) { - dispatch(createProject(save_id, [details, fields, status])) + dispatch(createProject(save_id, [details, fields, status, dcSweepcontrolLine, transientAnalysisControlLine, acAnalysisControlLine, tfAnalysisControlLine])) } else { - dispatch(createProject(save_id, [details, fields, ''])) + dispatch(createProject(save_id, [details, fields, '', dcSweepcontrolLine, transientAnalysisControlLine, acAnalysisControlLine, tfAnalysisControlLine])) } } setChanged(0) @@ -291,6 +333,9 @@ function CreateProject () { setDeleteDialogue(!deleteDialogue) setOpen(false) } + useEffect(() => { + console.log(selectedSimulation) + }, [selectedSimulation]) return (
{(window.location.href.split('?id=')[1] && auth.user?.username === owner) && @@ -340,26 +385,28 @@ function CreateProject () { alignItems="flex-start" > + {project.details &&

Status of the project: {project.details.status_name}

Active Version: {activeName} of variation {project.details.active_branch} saved on {activeSaveDate} at {activeSaveTime} hours

{project.details.history && project.details.history.slice(0).reverse()[0]?.reviewer_notes &&

Reviewer Notes: {project.details.history.slice(0).reverse()[0]?.reviewer_notes}

}
} +

Project Details

{versions != null && - ((project.details && project.details.can_edit) || !project.details) && - Select the version you want to use for your project. - - } + ((project.details && project.details.can_edit) || !project.details) && + Select the version you want to use for your project. + + } {fields && fields.map((item, index) => - ( - <> -
- {((project.details && project.details.can_edit) || !project.details) && + ( + <> +
+ {((project.details && project.details.can_edit) || !project.details) && <> onRemove(index)}> @@ -409,37 +456,65 @@ function CreateProject () { } } - - - - ))} + + + + ))}
{((project.states && project.details) || !project.details) && } +

Simulation Parameters

+
+ + Select simulation mode parameters to enter: + + +
+ {project.details && <>{ project.states &&
@@ -453,9 +528,9 @@ function CreateProject () { value={status} > {project.states.map((item, index) => - ( - {item} - ))} + ( + {item} + ))} {project.details.status_name}
@@ -488,19 +563,19 @@ function CreateProject () {
- - - -

History of this Project

- {(project.details?.history && project.details?.history[0]) - ? <> - - - :

No history of this project.

- } -
-
-
} + + + +

History of this Project

+ {(project.details?.history && project.details?.history[0]) + ? <> + + + :

No history of this project.

+ } +
+
+
} {!project.details && } - + + + Simulate Circuit + + {project.details && } + + + + Report this project + + + + + + + + + +

Circuit Diagram: + {auth.isAuthenticated && } + {auth.isAuthenticated && } + + +

+ + setSnackbarOpen(false)} > - Simulate Circuit - - - -
- - Report this project - - - - - - - - - -

Circuit Diagram: - {auth.isAuthenticated && } - {auth.isAuthenticated && } - - -

- - setSnackbarOpen(false)} - > - setSnackbarOpen(false)} severity="success"> - Successfully made a copy! - - - - - -
- - - - - -
-
- - - - - -
-
- - - - - -
-
-
- - -
-
-
-
-
- - + setSnackbarOpen(false)} severity="success"> + Successfully made a copy! + + + + + +
+ + + + + +
+
+ + + + + +
+
+ + + + + +
+
+
+ + +
+
+
+
+
+ + - - - -

History of this Project

- {project.details?.history[0] - ? - :

No history of this project.

- } -
-
+ + + +

History of this Project

+ {project.details?.history[0] + ? + :

No history of this project.

+ } +
+
+
-
- - } - - : <> - {statusChanged ? <>Status Changed. Wait for it to get back to the status where it is visible for you. : <>Not Authorized} - } + + } + + : <> + {statusChanged ? <>Status Changed. Wait for it to get back to the status where it is visible for you. : <>Not Authorized} + } +
) } diff --git a/eda-frontend/src/redux/actions/projectActions.js b/eda-frontend/src/redux/actions/projectActions.js index 7b8ebfe80..12e68be7c 100644 --- a/eda-frontend/src/redux/actions/projectActions.js +++ b/eda-frontend/src/redux/actions/projectActions.js @@ -17,7 +17,6 @@ export const createProject = (save_id, details) => (dispatch, getState) => { if (token) { config.headers.Authorization = `Token ${token}` } - api.post(`/publish/project/${save_id}`, details, config) .then( (res) => { diff --git a/esim-cloud-backend/publishAPI/models.py b/esim-cloud-backend/publishAPI/models.py index f142a066f..d8038eed9 100644 --- a/esim-cloud-backend/publishAPI/models.py +++ b/esim-cloud-backend/publishAPI/models.py @@ -45,6 +45,14 @@ class Project(models.Model): is_reported = models.BooleanField(default=False, null=True) active_branch = models.CharField(max_length=20, null=True) active_version = models.CharField(max_length=20, null=True) + dc_sweep = models.OneToOneField( + to='DCSweepParameters', on_delete=models.CASCADE, null=True) + transient_analysis = models.OneToOneField( + to='TransientAnalysisParameters', on_delete=models.CASCADE, null=True) + tf_analysis = models.OneToOneField( + to='TFAnalysisParameters', on_delete=models.CASCADE, null=True) + ac_analysis = models.OneToOneField( + to='ACAnalysisParameters', on_delete=models.CASCADE, null=True) def __str__(self): return self.title @@ -80,3 +88,35 @@ class Report(models.Model): get_user_model(), on_delete=models.CASCADE, related_name='reporter', null=True) # noqa approved = models.BooleanField(default=None, null=True) + + +class DCSweepParameters(models.Model): + parameter = models.CharField(max_length=200, null=True) + sweepType = models.CharField(max_length=200, null=False, default='Linear') + start = models.CharField(max_length=200, null=True) + stop = models.CharField(max_length=200, null=True) + step = models.CharField(max_length=200, null=True) + parameter2 = models.CharField(max_length=200, null=True) + start2 = models.CharField(max_length=200, null=True) + stop2 = models.CharField(max_length=200, null=True) + step2 = models.CharField(max_length=200, null=True) + + +class TransientAnalysisParameters(models.Model): + start = models.CharField(max_length=200, null=True) + stop = models.CharField(max_length=200, null=True) + step = models.CharField(max_length=200, null=True) + skipInitial = models.BooleanField(default=False) + + +class ACAnalysisParameters(models.Model): + input = models.CharField(max_length=200, default='dec') + stop = models.CharField(max_length=200, null=True) + start = models.CharField(max_length=200, null=True) + pointsBydecade = models.CharField(max_length=200, null=True) + + +class TFAnalysisParameters(models.Model): + outputNodes = models.BooleanField(default=False) + outputVoltageSource = models.CharField(max_length=200, null=True) + inputVoltageSource = models.CharField(max_length=200, null=True) diff --git a/esim-cloud-backend/publishAPI/serializers.py b/esim-cloud-backend/publishAPI/serializers.py index b85dbdcee..43e7a714b 100644 --- a/esim-cloud-backend/publishAPI/serializers.py +++ b/esim-cloud-backend/publishAPI/serializers.py @@ -1,6 +1,7 @@ +from django.db import models from django.db.models import fields from rest_framework import serializers -from .models import CircuitTag, Project, Report, TransitionHistory, Field +from .models import * from django.core.files.base import ContentFile import base64 import six @@ -9,6 +10,33 @@ from saveAPI.serializers import StateSaveSerializer from workflowAPI.models import Transition +class DCSweepSerializer(serializers.ModelSerializer): + class Meta: + model = DCSweepParameters + fields='__all__' + def create(self, validated_data): + return DCSweepParameters.objects.create(**validated_data) + def update(self, instance, validated_data): + return super().update(instance, validated_data) +class TransientAnalysisSerializer(serializers.ModelSerializer): + class Meta: + model = TransientAnalysisParameters + fields='__all__' + + + +class ACAnalysisSerializer(serializers.ModelSerializer): + class Meta: + model = ACAnalysisParameters + fields='__all__' + + + +class TFAnalysisSerializer(serializers.ModelSerializer): + class Meta: + model = TFAnalysisParameters + fields='__all__' + class Base64ImageField(serializers.ImageField): @@ -72,7 +100,10 @@ class ProjectSerializer(serializers.ModelSerializer): fields = FieldSerializer(many=True) save_id = serializers.SerializerMethodField() active_save = serializers.SerializerMethodField() - + dc_sweep = DCSweepSerializer() + transient_analysis = TransientAnalysisSerializer() + tf_analysis = TFAnalysisSerializer() + ac_analysis = ACAnalysisSerializer() class Meta: model = Project fields = ('project_id', @@ -85,9 +116,12 @@ class Meta: 'active_branch', 'active_version', 'save_id', - 'active_save' + 'active_save', + 'dc_sweep', + 'transient_analysis', + 'tf_analysis', + 'ac_analysis', ) - def get_save_id(self, obj): return obj.statesave_set.first().save_id @@ -98,6 +132,8 @@ def get_active_save(self, obj): version=obj.active_version)).data + + class ReportSerializer(serializers.ModelSerializer): class Meta: model = Report @@ -109,3 +145,5 @@ class ReportDescriptionSerializer(serializers.ModelSerializer): class Meta: model = Report fields = ('description',) + + diff --git a/esim-cloud-backend/publishAPI/views.py b/esim-cloud-backend/publishAPI/views.py index 4cd962496..0748d2a66 100644 --- a/esim-cloud-backend/publishAPI/views.py +++ b/esim-cloud-backend/publishAPI/views.py @@ -1,11 +1,11 @@ from rest_framework import permissions -from publishAPI.serializers import CircuitTagSerializer, ProjectSerializer, \ - TransitionHistorySerializer # noqa +from publishAPI.serializers import CircuitTagSerializer, ProjectSerializer, \ + TransitionHistorySerializer, DCSweepSerializer, TransientAnalysisSerializer, ACAnalysisSerializer, TFAnalysisSerializer # noqa from rest_framework.permissions import DjangoModelPermissionsOrAnonReadOnly, \ AllowAny, DjangoModelPermissions # noqa from rest_framework.parsers import JSONParser, MultiPartParser from workflowAPI.models import Permission -from publishAPI.models import CircuitTag, Project, Field, TransitionHistory +from publishAPI.models import ACAnalysisParameters, CircuitTag, DCSweepParameters, Project, Field, TFAnalysisParameters, TransientAnalysisParameters, TransitionHistory from rest_framework.permissions import DjangoModelPermissionsOrAnonReadOnly, \ IsAuthenticated, AllowAny, \ DjangoModelPermissions # noqa @@ -97,7 +97,43 @@ def post(self, request, circuit_id): ['description'], author=active_state_save.owner, is_arduino=active_state_save.is_arduino, active_branch=request.data[0]['active_branch'], - active_version=request.data[0]['active_version']) + active_version=request.data[0]['active_version'], + ) + dc_sweep = DCSweepParameters(parameter=request.data[3]['parameter'], + sweepType=request.data[3]['sweepType'], + start=request.data[3]['start'], + stop=request.data[3]['stop'], + step=request.data[3]['step'], + parameter2=request.data[3]['parameter2'], + start2=request.data[3]['start2'], + step2=request.data[3]['step2'], + stop2=request.data[3]['stop2'], + ) + transient_analysis = TransientAnalysisParameters( + start=request.data[4]['start'], + stop=request.data[4]['stop'], + step=request.data[4]['step'], + skipInitial=request.data[4]['skipInitial'], + ) + ac_analysis = ACAnalysisParameters( + input=request.data[5]['input'], + stop=request.data[5]['stop'], + start=request.data[5]['start'], + pointsBydecade=request.data[5]['pointsBydecade'], + ) + tf_analysis = TFAnalysisParameters( + outputNodes=request.data[6]['outputNodes'], + outputVoltageSource=request.data[6]['outputVoltageSource'], + inputVoltageSource=request.data[6]['inputVoltageSource'], + ) + dc_sweep.save() + ac_analysis.save() + tf_analysis.save() + transient_analysis.save() + project.dc_sweep = dc_sweep + project.transient_analysis = transient_analysis + project.ac_analysis = ac_analysis + project.tf_analysis = tf_analysis project.save() for field in request.data[1]: field = Field(name=field['name'], text=field['text']) @@ -145,6 +181,41 @@ def post(self, request, circuit_id): 'active_branch'] active_state_save.project.active_version = request.data[0][ 'active_version'] + dc_sweep = DCSweepParameters(parameter=request.data[3]['parameter'], + sweepType=request.data[3]['sweepType'], + start=request.data[3]['start'], + stop=request.data[3]['stop'], + step=request.data[3]['step'], + parameter2=request.data[3]['parameter2'], + start2=request.data[3]['start2'], + step2=request.data[3]['step2'], + stop2=request.data[3]['stop2'], + ) + transient_analysis = TransientAnalysisParameters( + start=request.data[4]['start'], + stop=request.data[4]['stop'], + step=request.data[4]['step'], + skipInitial=request.data[4]['skipInitial'], + ) + ac_analysis = ACAnalysisParameters( + input=request.data[5]['input'], + stop=request.data[5]['stop'], + start=request.data[5]['start'], + pointsBydecade=request.data[5]['pointsBydecade'], + ) + tf_analysis = TFAnalysisParameters( + outputNodes=request.data[6]['outputNodes'], + outputVoltageSource=request.data[6]['outputVoltageSource'], + inputVoltageSource=request.data[6]['inputVoltageSource'], + ) + dc_sweep.save() + ac_analysis.save() + tf_analysis.save() + transient_analysis.save() + active_state_save.project.dc_sweep = dc_sweep + active_state_save.project.transient_analysis = transient_analysis + active_state_save.project.ac_analysis = ac_analysis + active_state_save.project.tf_analysis = tf_analysis active_state_save.project.save() if request.data[2] != '': ChangeStatus(self, request.data[2], active_state_save.project) @@ -182,8 +253,8 @@ def delete(self, request, circuit_id): return Response({'error': 'No circuit there'}, status=status.HTTP_404_NOT_FOUND) if project.author == self.request.user and Permission.objects.filter( - role__in=self.request.user.groups.all(), - del_own_states=project.state).exists(): + role__in=self.request.user.groups.all(), + del_own_states=project.state).exists(): project.delete() return Response({'done': True}) else: