From 4cb44fe73d2bd4aa4f94db67af73ae44a51627c4 Mon Sep 17 00:00:00 2001 From: Arnabdaz <96580571+Arnabdaz@users.noreply.github.com> Date: Sun, 18 Jun 2023 01:27:20 +0530 Subject: [PATCH 01/22] feat(gsoc): fix tabbar issue, project loading, updating, circuit delete, circuit name change, circuit switching, etc issues Signed-off-by: Arnabdaz <96580571+Arnabdaz@users.noreply.github.com> --- src/assets/constants/Navbar/USER_DATA.json | 57 +++++- src/components/DialogBox/ProjectNameSet.vue | 21 +++ .../DialogBox/ProjectNameSetHelper.ts | 48 +++++ .../DialogBox/SetDetailsOnCreate.vue | 0 src/components/Dropdown/DropDown.vue | 28 ++- src/components/MessageBox/messageBox.vue | 16 +- src/components/Navbar/Navbar.vue | 14 +- src/components/Navbar/User/User.vue | 33 ++-- .../ModuleProperty/ModuleProperty.vue | 2 +- .../ProjectProperty/ProjectProperty.vue | 167 ++++++++++++++++-- src/components/TabsBar/TabsBar.vue | 102 +++++++---- src/globalVariables.ts | 2 + src/pages/simulator.vue | 27 ++- src/pages/simulatorHandler.vue | 94 ++++++++++ src/router/index.ts | 23 ++- src/simulator/spec/data.spec.js | 4 +- src/simulator/src/circuit.js | 56 ++++-- src/simulator/src/data/load.js | 25 ++- src/simulator/src/data/save.js | 96 +++++++--- src/simulator/src/setup.js | 51 ++++-- src/store/SimulatorStore/state.ts | 26 ++- src/store/authStore.ts | 47 +++++ src/store/projectStore.ts | 64 +++++++ vite.config.ts | 16 ++ 24 files changed, 847 insertions(+), 172 deletions(-) create mode 100644 src/components/DialogBox/ProjectNameSet.vue create mode 100644 src/components/DialogBox/ProjectNameSetHelper.ts create mode 100644 src/components/DialogBox/SetDetailsOnCreate.vue create mode 100644 src/pages/simulatorHandler.vue create mode 100644 src/store/authStore.ts create mode 100644 src/store/projectStore.ts diff --git a/src/assets/constants/Navbar/USER_DATA.json b/src/assets/constants/Navbar/USER_DATA.json index cc2db7cd..4d317d1e 100644 --- a/src/assets/constants/Navbar/USER_DATA.json +++ b/src/assets/constants/Navbar/USER_DATA.json @@ -3,18 +3,69 @@ "id": "1", "item": "dashboard", "itemid": "", - "attributes": [] + "attributes": [ + { + "name": "href", + "value": "/users/${:id}" + }, + { + "name": "role", + "value": "button" + }, + { + "name": "aria-haspopup", + "value": "true" + }, + { + "name": "aria-expanded", + "value": "false" + } + ] }, { "id": "2", "item": "my_groups", "itemid": "", - "attributes": [] + "attributes": [ + { + "name": "href", + "value": "/users/${:id}/groups" + }, + { + "name": "role", + "value": "button" + }, + { + "name": "aria-haspopup", + "value": "true" + }, + { + "name": "aria-expanded", + "value": "false" + } + ] }, { "id": "3", "item": "notifications", "itemid": "", - "attributes": [] + "attributes": [ + { + "name": "href", + "value": "/users/${:id}/notifications" + }, + { + "name": "role", + "value": "button" + }, + { + "name": "aria-haspopup", + "value": "true" + }, + { + "name": "aria-expanded", + "value": "false" + } + ] } ] diff --git a/src/components/DialogBox/ProjectNameSet.vue b/src/components/DialogBox/ProjectNameSet.vue new file mode 100644 index 00000000..38cfc23d --- /dev/null +++ b/src/components/DialogBox/ProjectNameSet.vue @@ -0,0 +1,21 @@ + + + + + diff --git a/src/components/DialogBox/ProjectNameSetHelper.ts b/src/components/DialogBox/ProjectNameSetHelper.ts new file mode 100644 index 00000000..f415eeb6 --- /dev/null +++ b/src/components/DialogBox/ProjectNameSetHelper.ts @@ -0,0 +1,48 @@ +import { useProjectStore, projectStoreType } from '#/store/projectStore' + +let resolvePromise: (value?: string) => void // will be used to store the resolve function of the Promise + +export const confirmName = (selectedOption: string): void => { + const projectStore: projectStoreType = useProjectStore() + projectStore.CreateProjectHelper.changeProjectName = false + if (selectedOption === 'save') { + resolvePromise(projectStore.CreateProjectHelper.inputList[0].val) + } else { + resolvePromise(undefined) + } +} + +export const provideProjectName = async (): Promise => { + const projectStore: projectStoreType = useProjectStore() + projectStore.CreateProjectHelper.changeProjectName = true + projectStore.CreateProjectHelper.isPersistent = true + projectStore.CreateProjectHelper.messageText = + 'Provide a name for the project' + projectStore.CreateProjectHelper.buttonList = [ + { + text: 'Save', + emitOption: 'save', + }, + { + text: 'Cancel', + emitOption: 'cancel', + }, + ] + projectStore.CreateProjectHelper.inputList = [ + { + text: 'Project Name:', + val: '', + placeholder: 'Untitled', + id: 'projectName', + class: 'inputField', + style: '', + type: 'text', + }, + ] + + const projectName = await new Promise((resolve) => { + resolvePromise = resolve + }) + + return projectName +} diff --git a/src/components/DialogBox/SetDetailsOnCreate.vue b/src/components/DialogBox/SetDetailsOnCreate.vue new file mode 100644 index 00000000..e69de29b diff --git a/src/components/Dropdown/DropDown.vue b/src/components/Dropdown/DropDown.vue index d83890e7..0d4823cd 100644 --- a/src/components/Dropdown/DropDown.vue +++ b/src/components/Dropdown/DropDown.vue @@ -10,6 +10,14 @@ : '' " style="white-space: pre-line" + v-bind=" + Object.fromEntries( + listItem.attributes.map((attr) => [ + attr.name, + attr.value.replace('${:id}', userId), + ]) + ) + " > {{ $t('simulator.nav.' + dropDownHeader + '.' + listItem.item) @@ -18,7 +26,12 @@
  • - + {{ $t('simulator.nav.sign_out') }}
  • @@ -26,11 +39,22 @@ diff --git a/src/components/MessageBox/messageBox.vue b/src/components/MessageBox/messageBox.vue index 041a6662..ca35542d 100644 --- a/src/components/MessageBox/messageBox.vue +++ b/src/components/MessageBox/messageBox.vue @@ -55,8 +55,19 @@ import { onUpdated } from '@vue/runtime-core' const props = defineProps({ messageText: { type: String, default: '' }, isPersistent: { type: Boolean, default: false }, - buttonList: { type: Array, default: () => [] }, - inputList: { type: Array, default: () => [] }, + buttonList: { type: Array<{ + text: string + emitOption: string + }>, default: () => [] }, + inputList: { type: Array<{ + text: string + val: string + placeholder: string + id: string + class: string + style: string + type: string + }>, default: () => [] }, inputClass: { type: String, default: '' }, circuitItem: { type: Object, default: () => ({}) }, tableHeader: { type: Array, default: () => [] }, @@ -65,5 +76,4 @@ const props = defineProps({ const emit = defineEmits(['buttonClick']) - diff --git a/src/components/Navbar/Navbar.vue b/src/components/Navbar/Navbar.vue index 4f82162f..caeec961 100644 --- a/src/components/Navbar/Navbar.vue +++ b/src/components/Navbar/Navbar.vue @@ -10,12 +10,9 @@ id="projectName" class="projectName noSelect defaultCursor font-weight-bold" > - Untitled + {{ projectStore.getProjectName }} - + @@ -26,17 +23,18 @@ import QuickButton from '@/Navbar/QuickButton/QuickButton.vue' import User from '@/Navbar/User/User.vue' import NavbarLinks from '@/Navbar/NavbarLinks/NavbarLinks.vue' -import navbarData from '#/assets/constants/Navbar/NAVBAR_DATA' -import userDropdownItems from '#/assets/constants/Navbar/USER_DATA' +import navbarData from '#/assets/constants/Navbar/NAVBAR_DATA.json' +import userDropdownItems from '#/assets/constants/Navbar/USER_DATA.json' import Logo from '@/Logo/Logo.vue' import Hamburger from '@/Navbar/Hamburger/Hamburger.vue' import { ref, onMounted } from 'vue' +import { useProjectStore } from '#/store/projectStore' const navbarLogo = ref('logo') const minWidthToShowSidebar = ref(992) -const isUserSignedIn = ref(false) const showSidebar = ref(false) +const projectStore = useProjectStore() showSidebar.value = window.innerWidth < minWidthToShowSidebar.value ? true : false onMounted(() => { diff --git a/src/components/Navbar/User/User.vue b/src/components/Navbar/User/User.vue index 3831f913..839dae5e 100644 --- a/src/components/Navbar/User/User.vue +++ b/src/components/Navbar/User/User.vue @@ -1,7 +1,7 @@ diff --git a/src/components/Panels/PropertiesPanel/ModuleProperty/ModuleProperty.vue b/src/components/Panels/PropertiesPanel/ModuleProperty/ModuleProperty.vue index 5ea5aeca..92d0c9aa 100644 --- a/src/components/Panels/PropertiesPanel/ModuleProperty/ModuleProperty.vue +++ b/src/components/Panels/PropertiesPanel/ModuleProperty/ModuleProperty.vue @@ -29,7 +29,7 @@ import PanelHeader from '#/components/Panels/Shared/PanelHeader.vue' import HelpButton from '#/components/Panels/Shared/HelpButton.vue' import ElementProperty from '#/components/Panels/PropertiesPanel/ModuleProperty/ElementProperty/ElementProperty.vue' import ProjectProperty from '#/components/Panels/PropertiesPanel/ModuleProperty/ProjectProperty/ProjectProperty.vue' -import SubcircuitPropert from '#/components/Panels/PropertiesPanel/ModuleProperty/SubcircuitProperty/SubcircuitProperty.vue' +import SubcircuitProperty from '#/components/Panels/PropertiesPanel/ModuleProperty/SubcircuitProperty/SubcircuitProperty.vue' import { ref, toRefs } from '@vue/reactivity' import { onMounted } from '@vue/runtime-core' diff --git a/src/components/Panels/PropertiesPanel/ModuleProperty/ProjectProperty/ProjectProperty.vue b/src/components/Panels/PropertiesPanel/ModuleProperty/ProjectProperty/ProjectProperty.vue index 209253c8..3c4970ac 100644 --- a/src/components/Panels/PropertiesPanel/ModuleProperty/ProjectProperty/ProjectProperty.vue +++ b/src/components/Panels/PropertiesPanel/ModuleProperty/ProjectProperty/ProjectProperty.vue @@ -1,13 +1,14 @@ + + diff --git a/src/components/TabsBar/TabsBar.vue b/src/components/TabsBar/TabsBar.vue index 18d251f2..989d2008 100644 --- a/src/components/TabsBar/TabsBar.vue +++ b/src/components/TabsBar/TabsBar.vue @@ -20,17 +20,17 @@ :key="element.id" style="" class="circuits toolbarButton" - :class="tabsbarClasses(element.id)" + :class="element.focussed ? 'current' : ''" draggable="true" @click="switchCircuit(element.id)" > - {{ truncateString(scopeList[element.id].name, 18) }} + {{ truncateString(element.name, 18) }} mdi-close @@ -57,8 +57,7 @@ diff --git a/src/pages/simulatorHandler.vue b/src/pages/simulatorHandler.vue new file mode 100644 index 00000000..9a2c0d02 --- /dev/null +++ b/src/pages/simulatorHandler.vue @@ -0,0 +1,94 @@ + + + diff --git a/src/router/index.ts b/src/router/index.ts index 7f788992..21d4cd28 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -1,15 +1,26 @@ import { createRouter, createWebHistory } from 'vue-router' -import simulator from '../pages/simulator.vue' +// import simulator from '../pages/simulator.vue' +import simulatorHandler from '../pages/simulatorHandler.vue' const routes = [ - { - path: '/', - redirect: '/simulatorvue', // @TODO: update later back to /simulator - }, + // { + // path: '/', + // redirect: '/simulatorvue', // @TODO: update later back to /simulator + // }, { path: '/simulatorvue', // @TODO: update later back to /simulator name: 'simulator', - component: simulator, + // component: simulator, + component: simulatorHandler, + children: [ + { + path: 'edit/:projectId', + name: 'simulator-edit', + // component: simulator, + component: simulatorHandler, + props: true, + }, + ], }, ] const router = createRouter({ diff --git a/src/simulator/spec/data.spec.js b/src/simulator/spec/data.spec.js index f5afc76f..4ac49e23 100644 --- a/src/simulator/spec/data.spec.js +++ b/src/simulator/spec/data.spec.js @@ -23,7 +23,7 @@ import createSaveAsImgPrompt from '../src/data/saveImage' jest.mock('codemirror') describe('data dir working', () => { - CodeMirror.fromTextArea.mockReturnValueOnce({ setValue: (text) => {} }) + CodeMirror.fromTextArea.mockReturnValueOnce({ setValue: (text) => { } }) window.confirm = jest.fn(() => true) setup() @@ -79,7 +79,7 @@ describe('data dir working', () => { test('save updated circuit_data', () => { // save project - window.__logix_project_id = decoderCircuitData.projectId + window.logixProjectId = decoderCircuitData.projectId expect(() => save()).not.toThrow() }) diff --git a/src/simulator/src/circuit.js b/src/simulator/src/circuit.js index dd7f84cb..4dca029f 100644 --- a/src/simulator/src/circuit.js +++ b/src/simulator/src/circuit.js @@ -40,7 +40,6 @@ import { updateTestbenchUI } from './testbench' import { SimulatorStore } from '#/store/SimulatorStore/SimulatorStore' import { toRef, toRefs } from 'vue' - export const circuitProperty = { toggleLayoutMode, setProjectName, @@ -54,7 +53,10 @@ export const circuitProperty = { export var scopeList = {} export function resetScopeList() { + const simulatorStore = SimulatorStore() + const { circuit_list } = toRefs(simulatorStore) scopeList = {} + circuit_list.value = [] } /** * Function used to change the current focusedCircuit @@ -65,6 +67,11 @@ export function resetScopeList() { * @category circuit */ export function switchCircuit(id) { + // TODO: fix tomorrow + const simulatorStore = SimulatorStore() + const { circuit_list } = toRefs(simulatorStore) + const { activeCircuit } = toRefs(simulatorStore) + if (layoutModeGet()) { toggleLayoutMode() } @@ -75,7 +82,10 @@ export function switchCircuit(id) { // globalScope.fixLayout(); scheduleBackup() if (id === globalScope.id) return - $(`.circuits`).removeClass('current') + // $(`.circuits`).removeClass('current') + circuit_list.value.forEach((circuit) => + circuit.focussed ? (circuit.focussed = false) : null + ) simulationArea.lastSelected = undefined simulationArea.multipleObjectSelections = [] simulationArea.copyList = [] @@ -84,7 +94,13 @@ export function switchCircuit(id) { verilogModeSet(true) } if (globalScope.isVisible()) { - $(`#${id}`).addClass('current') + // $(`#${id}`).addClass('current') + const index = circuit_list.value.findIndex( + (circuit) => circuit.id == id + ) // TODO: add strict equality after typescript + circuit_list.value[index].focussed = true + activeCircuit.value.id = globalScope.id + activeCircuit.value.name = globalScope.name } updateSimulationSet(true) updateSubcircuitSet(true) @@ -107,7 +123,6 @@ export function getDependenciesList(scopeId) { let scope = scopeList[scopeId] if (scope == undefined) scope = scopeList[globalScope.id] - let dependencies = '' for (id in scopeList) { if (id != scope.id && scopeList[id].checkDependency(scope.id)) { @@ -129,6 +144,8 @@ export function getDependenciesList(scopeId) { * @category circuit */ export function deleteCurrentCircuit(scopeId = globalScope.id) { + const simulatorStore = SimulatorStore() + const { circuit_list } = toRefs(simulatorStore) let scope = scopeList[scopeId] if (scope == undefined) scope = scopeList[globalScope.id] @@ -137,11 +154,17 @@ export function deleteCurrentCircuit(scopeId = globalScope.id) { for (var id in scope.verilogMetadata.subCircuitScopeIds) delete scopeList[id] } - $(`#${scope.id}`).remove() + // $(`#${scope.id}`).remove() + const index = circuit_list.value.findIndex( + (circuit) => circuit.id === scope.id + ) + circuit_list.value.splice(index, 1) delete scopeList[scope.id] - switchCircuit(Object.keys(scopeList)[0]) + if (scope.id == globalScope.id) { + switchCircuit(Object.keys(scopeList)[0]) + } + showMessage('Circuit was successfully closed') } - /** * Wrapper function around newCircuit to be called from + button on UI */ @@ -165,13 +188,14 @@ export function createNewCircuitScope(name = 'Untitled-Circuit') { export function newCircuit(name, id, isVerilog = false, isVerilogMain = false) { const simulatorStore = SimulatorStore() const { circuit_list } = toRefs(simulatorStore) + const { activeCircuit } = toRefs(simulatorStore) if (layoutModeGet()) { toggleLayoutMode() } if (verilogModeGet()) { verilogModeSet(false) } - name = name || prompt('Enter circuit name:', 'Untitled-Circuit') + name = name || 'Untitled-Circuit' name = stripTags(name) if (!name) return const scope = new Scope(name) @@ -179,6 +203,7 @@ export function newCircuit(name, id, isVerilog = false, isVerilogMain = false) { scopeList[scope.id] = scope let currCircuit = { id: scope.id, + name: scope.name, // fix for tab name issue - vue - to be reviewed @devartstar } circuit_list.value.push(currCircuit) @@ -187,7 +212,12 @@ export function newCircuit(name, id, isVerilog = false, isVerilogMain = false) { scope.verilogMetadata.isMainCircuit = isVerilogMain } globalScope = scope - $('.circuits').removeClass('current') + // $('.circuits').removeClass('current') + circuit_list.value.forEach((circuit) => (circuit.focussed = false)) + circuit_list.value[circuit_list.value.length - 1].focussed = true + activeCircuit.value.id = scope.id + activeCircuit.value.name = scope.name + if (!isVerilog || isVerilogMain) { if (embed) { // added calss - embed-tab using vue logic @@ -229,7 +259,6 @@ export function newCircuit(name, id, isVerilog = false, isVerilogMain = false) { } dots(false) } - return scope } @@ -240,10 +269,15 @@ export function newCircuit(name, id, isVerilog = false, isVerilogMain = false) { * @category circuit */ export function changeCircuitName(name, id = globalScope.id) { + const simulatorStore = SimulatorStore() + const { circuit_list } = toRefs(simulatorStore) + // const { activeCircuit } = toRefs(simulatorStore) name = name || 'Untitled' name = stripTags(name) - $(`#${id} .circuitName`).html(`${truncateString(name, 18)}`) scopeList[id].name = name + const index = circuit_list.value.findIndex((circuit) => circuit.id === id) + circuit_list.value[index].name = name + // activeCircuit.value.name = name // add later if necessary at current stage not important handled by projectProperty on switching circuit } /** diff --git a/src/simulator/src/data/load.js b/src/simulator/src/data/load.js index b23ce050..f9d7b89b 100644 --- a/src/simulator/src/data/load.js +++ b/src/simulator/src/data/load.js @@ -19,7 +19,8 @@ import modules from '../modules' import { oppositeDirection } from '../canvasApi' import plotArea from '../plotArea' import { updateTestbenchUI, TestbenchData } from '../testbench' - +import { SimulatorStore } from '#/store/SimulatorStore/SimulatorStore' +import { toRefs } from 'vue' /** * Backward compatibility - needs to be deprecated * @param {CircuitElement} obj - the object to be rectified @@ -203,6 +204,9 @@ export function loadScope(scope, data) { */ export default function load(data) { // If project is new and no data is there, then just set project name + const simulatorStore = SimulatorStore() + const { circuit_list } = toRefs(simulatorStore) + if (!data) { setProjectName(__projectName) return @@ -213,7 +217,7 @@ export default function load(data) { globalScope = undefined resetScopeList() // Remove default scope - $('.circuits').remove() // Delete default scope + // $('.circuits').remove() // Delete default scope // Load all according to the dependency order for (let i = 0; i < data.scopes.length; i++) { @@ -264,16 +268,19 @@ export default function load(data) { // Reorder tabs according to the saved order if (data.orderedTabs) { - var unorderedTabs = $('.circuits').detach() - var plusButton = $('#tabsBar').children().detach() - for (const tab of data.orderedTabs) { - $('#tabsBar').append(unorderedTabs.filter(`#${tab}`)) - } - $('#tabsBar').append(plusButton) + // var unorderedTabs = $('.circuits').detach() + // var plusButton = $('#tabsBar').children().detach() + // for (const tab of data.orderedTabs) { + // $('#tabsBar').append(unorderedTabs.filter(`#${tab}`)) + // } + // $('#tabsBar').append(plusButton) + circuit_list.value.sort((a, b) => { + return data.orderedTabs.indexOf(String(a.id)) - data.orderedTabs.indexOf(String(b.id)); + }) } // Switch to last focussedCircuit - if (data.focussedCircuit) switchCircuit(data.focussedCircuit) + if (data.focussedCircuit) switchCircuit(String(data.focussedCircuit)) // Update the testbench UI updateTestbenchUI() diff --git a/src/simulator/src/data/save.js b/src/simulator/src/data/save.js index b04a1ee8..7462a42a 100644 --- a/src/simulator/src/data/save.js +++ b/src/simulator/src/data/save.js @@ -12,8 +12,11 @@ import { layoutModeGet, toggleLayoutMode } from '../layoutMode' import { verilogModeGet } from '../Verilog2CV' import domtoimage from 'dom-to-image' import '../../vendor/canvas2svg' +import { useProjectStore } from '#/store/projectStore' +// import provideProjectName from '#/components/DialogBox/save.vue' +import { provideProjectName } from '#/components/DialogBox/ProjectNameSetHelper' -var projectName = undefined +// var projectName = undefined /** * Function to set the name of project. @@ -21,13 +24,15 @@ var projectName = undefined * @category data */ export function setProjectName(name) { + const projectStore = useProjectStore() if (name == undefined) { - $('#projectName').html('Untitled') + // $('#projectName').html('Untitled') return } name = stripTags(name) - projectName = name - $('#projectName').html(name) + // projectName = name + // $('#projectName').html(name) + projectStore.setProjectName(name) } /** @@ -36,9 +41,10 @@ export function setProjectName(name) { * @category data */ export function getProjectName() { - return projectName + const projectStore = useProjectStore() + if (projectStore.getProjectNameDefined) return projectStore.getProjectName + else return undefined } - /** * Helper function to save canvas as image based on image type * @param {string} name -name of the circuit @@ -57,7 +63,7 @@ function downloadAsImg(name, imgType) { * Returns the order of tabs in the project */ export function getTabsOrder() { - var tabs = $('#tabsBar').children().not('button') + var tabs = document.getElementById('tabsBar').firstChild.children var order = [] for (let i = 0; i < tabs.length; i++) { order.push(tabs[i].id) @@ -71,12 +77,12 @@ export function getTabsOrder() { * @return {JSON} * @category data */ -export function generateSaveData(name) { +export async function generateSaveData(name) { data = {} // Prompts for name, defaults to Untitled name = - getProjectName() || name || prompt('Enter Project Name:') || 'Untitled' + getProjectName() || name || (await provideProjectName()) || 'Untitled' data.name = stripTags(name) setProjectName(data.name) @@ -342,13 +348,13 @@ export default async function save() { projectSavedSet(true) + const data = await generateSaveData() $('.loadingIcon').fadeIn() - const data = generateSaveData() const projectName = getProjectName() var imageData = await generateImageForOnline() - if (!userSignedIn) { + if (!window.isUserLoggedIn) { // user not signed in, save locally temporarily and force user to sign in localStorage.setItem('recover_login', data) // Asking user whether they want to login. @@ -360,7 +366,7 @@ export default async function save() { window.location.href = '/users/sign_in' else $('.loadingIcon').fadeOut() // eslint-disable-next-line camelcase - } else if (__logix_project_id == '0') { + } else if (logixProjectId == '0') { // Create new project - this part needs to be improved and optimised const form = $('
    ', { action: '/simulator/create_data', @@ -400,35 +406,67 @@ export default async function save() { form.submit() } else { // updates project - this part needs to be improved and optimised - $.ajax({ - url: '/simulator/update_data', - type: 'POST', - contentType: 'application/json', - beforeSend(xhr) { - xhr.setRequestHeader( - 'X-CSRF-Token', - $('meta[name="csrf-token"]').attr('content') - ) + // $.ajax({ + // url: '/api/v1/simulator/update', + // type: 'PATCH', + // contentType: 'application/json', + // beforeSend(xhr) { + // xhr.setRequestHeader( + // 'X-CSRF-Token', + // $('meta[name="csrf-token"]').attr('content') + // ) + // }, + // data: JSON.stringify({ + // data, + // id: logixProjectId, + // image: imageData, + // name: projectName, + // }), + // success(response) { + // showMessage( + // `We have saved your project: ${projectName} in our servers.` + // ) + // $('.loadingIcon').fadeOut() + // localStorage.removeItem('recover') + // }, + // failure(err) { + // showMessage( + // "There was an error, we couldn't save to our servers" + // ) + // $('.loadingIcon').fadeOut() + // }, + // }) + // function getCookie(name) { + // const value = `; ${document.cookie}`; + // const parts = value.split(`; ${name}=`); + // if (parts.length === 2) return parts.pop().split(';').shift(); + // } + + fetch('/api/v1/simulator/update', { + method: 'PATCH', + headers: { + 'Content-Type': 'application/json', + 'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content'), + Authorization: `Token`, }, - data: JSON.stringify({ + body: JSON.stringify({ data, - id: __logix_project_id, + id: logixProjectId, image: imageData, name: projectName, }), - success(response) { + }).then((response) => { + if (response.ok) { showMessage( `We have saved your project: ${projectName} in our servers.` ) - $('.loadingIcon').fadeOut() localStorage.removeItem('recover') - }, - failure(err) { + } else { showMessage( "There was an error, we couldn't save to our servers" ) - $('.loadingIcon').fadeOut() - }, + } + $('.loadingIcon').fadeOut() }) } diff --git a/src/simulator/src/setup.js b/src/simulator/src/setup.js index 90af19a3..275f24af 100644 --- a/src/simulator/src/setup.js +++ b/src/simulator/src/setup.js @@ -120,6 +120,29 @@ function setupElementLists() { window.renderOrder = [...moduleList.slice().reverse(), 'wires', 'allNodes'] // Order of render } +async function fetchProjectData(projectId) { + try { + const response = await fetch(`/api/v1/simulator/${projectId}/data`, { + method: 'GET', + headers: { + Accept: 'application/json', + } + }) + if (response.ok) { + const data = await response.json() + await load(data) + await simulationArea.changeClockTime(data.timePeriod || 500) + $('.loadingIcon').fadeOut() + } else { + throw new Error('API call failed') + } + } catch (error) { + console.error(error) + alert('Error: Could not load.') + $('.loadingIcon').fadeOut() + } +} + /** * The first function to be called to setup the whole simulator * @category setup @@ -141,26 +164,16 @@ export function setup() { // Load project data after 1 second - needs to be improved, delay needs to be eliminated setTimeout(() => { - let __logix_project_id = 0 - if (__logix_project_id != 0) { + // let __logix_project_id + if (!window.logixProjectId) { + // __logix_project_id = window.logixProjectId + window.logixProjectId = 0 + } + // else { __logix_project_id = 0 } + if (logixProjectId != 0) { $('.loadingIcon').fadeIn() - $.ajax({ - url: `/simulator/get_data/${__logix_project_id}`, - type: 'GET', - success(response) { - var data = response - if (data) { - load(data) - simulationArea.changeClockTime(data.timePeriod || 500) - } - $('.loadingIcon').fadeOut() - }, - failure() { - alert('Error: could not load ') - $('.loadingIcon').fadeOut() - }, - }) - } else if (localStorage.getItem('recover_login') && userSignedIn) { + fetchProjectData(logixProjectId) + } else if (localStorage.getItem('recover_login') && isUserLoggedIn) { // Restore unsaved data and save var data = JSON.parse(localStorage.getItem('recover_login')) load(data) diff --git a/src/store/SimulatorStore/state.ts b/src/store/SimulatorStore/state.ts index 30d1b3ca..12e2f594 100644 --- a/src/store/SimulatorStore/state.ts +++ b/src/store/SimulatorStore/state.ts @@ -3,9 +3,27 @@ import { defineStore } from 'pinia' // use camel case variable names export interface State { title: string - circuit_list: [] - dialogBox: Object - createCircuit: Object + activeCircuit: + | Object + | { + id: number | string + name: string + } + circuit_list: Array + dialogBox: { + create_circuit: boolean + delete_circuit: boolean + combinationalanalysis_dialog: boolean + hex_bin_dec_converter_dialog: boolean + saveimage_dialog: boolean + theme_dialog: boolean + customshortcut_dialog: boolean + insertsubcircuit_dialog: boolean + exportverilog_dialog: boolean + save_project_dialog: boolean + open_project_dialog: boolean + } + createCircuit: Object | { circuitName: string } combinationalAnalysis: Object } @@ -15,9 +33,11 @@ export const useState = defineStore({ state: (): State => { return { title: 'Welcome to CircuitVerse Simulator', + activeCircuit: {}, circuit_list: [], dialogBox: { create_circuit: false, + delete_circuit: false, combinationalanalysis_dialog: false, hex_bin_dec_converter_dialog: false, saveimage_dialog: false, diff --git a/src/store/authStore.ts b/src/store/authStore.ts new file mode 100644 index 00000000..1f30a0e4 --- /dev/null +++ b/src/store/authStore.ts @@ -0,0 +1,47 @@ +import { defineStore } from 'pinia' + +interface UserInfo { + isLoggedIn: boolean + id: string + attributes: { + name: string + locale: string + admin: boolean + } +} +export const useAuthStore = defineStore({ + id: 'authStore', + state: () => ({ + isLoggedIn: false, + userId: '', + username: '', + locale: 'en', + isAdmin: false, + }), + actions: { + setUserInfo(userInfo: UserInfo): void { + this.isLoggedIn = true + this.userId = userInfo.id ?? '' + this.username = userInfo.attributes.name ?? '' + this.locale = userInfo.attributes.locale ?? 'en' + this.isAdmin = userInfo.attributes.admin + }, + }, + getters: { + getIsLoggedIn(): boolean { + return this.isLoggedIn + }, + getUserId(): string { + return this.userId + }, + getUsername(): string { + return this.username + }, + getLocale(): string { + return this.locale + }, + getIsAdmin(): boolean { + return this.isAdmin + }, + }, +}) diff --git a/src/store/projectStore.ts b/src/store/projectStore.ts new file mode 100644 index 00000000..1f428a88 --- /dev/null +++ b/src/store/projectStore.ts @@ -0,0 +1,64 @@ +import { defineStore } from 'pinia' + +export interface projectStoreType { + project: { + // id: number //use later if needed + name: string + nameDefined: boolean + } + CreateProjectHelper: { + changeProjectName: boolean + resolvePromise: null | ((value?: string) => void) + messageText: string + isPersistent: boolean + buttonList: Array<{ + text: string + emitOption: string + }> + inputList: Array<{ + text: string + val: string + placeholder: string + id: string + class: string + style: string + type: string + }> + } +} + +export const useProjectStore = defineStore({ + id: 'projectStore', + state: () => ({ + project: { + // id: 0, //use later if needed + name: 'Untitled', + nameDefined: false, + }, + CreateProjectHelper: { + changeProjectName: false, + resolvePromise: null, + messageText: '', + isPersistent: false, + buttonList: [], + inputList: [], + }, + }), + actions: { + setProjectName(projectName: string): void { + this.project.name = projectName + this.project.nameDefined = true + }, + setProjectNameDefined(defined: boolean = true): void { + this.project.nameDefined = defined + }, + }, + getters: { + getProjectName(): string { + return this.project.name + }, + getProjectNameDefined(): boolean { + return this.project.nameDefined + }, + }, +}) diff --git a/vite.config.ts b/vite.config.ts index 85415f7d..e0e20c37 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -6,6 +6,8 @@ import vueI18n from '@intlify/vite-plugin-vue-i18n' // https://github.com/vuetifyjs/vuetify-loader/tree/next/packages/vite-plugin import vuetify from 'vite-plugin-vuetify' +const proxyUrl: string = 'http://localhost:3000' + // https://vitejs.dev/config/ export default defineConfig({ plugins: [ @@ -33,4 +35,18 @@ export default defineConfig({ assetsDir: 'assets', chunkSizeWarningLimit: 1600, }, + server: { + port: 4000, + proxy: { + // ...(process.env.NODE_ENV === 'development' && { + '^/(?!(simulatorvue)).*': { + target: proxyUrl, + changeOrigin: true, + headers: { + origin: proxyUrl, + }, + }, + // }), + }, + }, }) From 29667434ac96c2da50a4fc309dfbce8de82666d1 Mon Sep 17 00:00:00 2001 From: Arnabdaz <96580571+Arnabdaz@users.noreply.github.com> Date: Sun, 18 Jun 2023 22:20:08 +0530 Subject: [PATCH 02/22] fix(netlify-build): add / to check netlify build fixes Signed-off-by: Arnabdaz <96580571+Arnabdaz@users.noreply.github.com> --- src/router/index.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/router/index.ts b/src/router/index.ts index 21d4cd28..6659082b 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -3,10 +3,10 @@ import { createRouter, createWebHistory } from 'vue-router' import simulatorHandler from '../pages/simulatorHandler.vue' const routes = [ - // { - // path: '/', - // redirect: '/simulatorvue', // @TODO: update later back to /simulator - // }, + { + path: '/', + redirect: '/simulatorvue', // @TODO: update later back to /simulator + }, { path: '/simulatorvue', // @TODO: update later back to /simulator name: 'simulator', From 7048947128b863710c28fd834a2b3a78f3c50295 Mon Sep 17 00:00:00 2001 From: Arnabdaz <96580571+Arnabdaz@users.noreply.github.com> Date: Sun, 18 Jun 2023 22:30:35 +0530 Subject: [PATCH 03/22] feat(netlify): add _redirects to fix routing issues with netlify deployment Signed-off-by: Arnabdaz <96580571+Arnabdaz@users.noreply.github.com> --- public/_redirects | 1 + 1 file changed, 1 insertion(+) create mode 100644 public/_redirects diff --git a/public/_redirects b/public/_redirects new file mode 100644 index 00000000..50a46335 --- /dev/null +++ b/public/_redirects @@ -0,0 +1 @@ +/* /index.html 200 \ No newline at end of file From 39aa9c68f0c7b32b02af65ac0676575b6ecc5da9 Mon Sep 17 00:00:00 2001 From: Arnabdaz <96580571+Arnabdaz@users.noreply.github.com> Date: Sun, 18 Jun 2023 22:39:43 +0530 Subject: [PATCH 04/22] fix(netlify): update netlify.toml to get _redirects to correct directory after build Signed-off-by: Arnabdaz <96580571+Arnabdaz@users.noreply.github.com> --- netlify.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/netlify.toml b/netlify.toml index 8f1f882e..273dac43 100644 --- a/netlify.toml +++ b/netlify.toml @@ -1,2 +1,2 @@ [build] - command = "npm run build && mkdir -p ./dist && cp -r ../public/* ./dist/ && mv ./dist/simulatorvue/index.html ./dist/" + command = "npm run build && mkdir -p ./dist && cp -r ../public/* ./dist/ && mv ./dist/simulatorvue/index.html ./dist/ && mv ./dist/simulatorvue/_redirects ./dist/" From 39b3bb5f3b03effc25f5e5660a0d06aa3a120595 Mon Sep 17 00:00:00 2001 From: Arnabdaz <96580571+Arnabdaz@users.noreply.github.com> Date: Sun, 18 Jun 2023 23:16:06 +0530 Subject: [PATCH 05/22] fix(netlify): move redirects to neltify.toml Signed-off-by: Arnabdaz <96580571+Arnabdaz@users.noreply.github.com> --- netlify.toml | 7 ++++++- public/_redirects | 1 - 2 files changed, 6 insertions(+), 2 deletions(-) delete mode 100644 public/_redirects diff --git a/netlify.toml b/netlify.toml index 273dac43..ba7e0217 100644 --- a/netlify.toml +++ b/netlify.toml @@ -1,2 +1,7 @@ [build] - command = "npm run build && mkdir -p ./dist && cp -r ../public/* ./dist/ && mv ./dist/simulatorvue/index.html ./dist/ && mv ./dist/simulatorvue/_redirects ./dist/" + command = "npm run build && mkdir -p ./dist && cp -r ../public/* ./dist/ && mv ./dist/simulatorvue/index.html ./dist/" + +[[redirects]] + from = "/simulatorvue/*" + to = "/index.html" + status = 200 diff --git a/public/_redirects b/public/_redirects deleted file mode 100644 index 50a46335..00000000 --- a/public/_redirects +++ /dev/null @@ -1 +0,0 @@ -/* /index.html 200 \ No newline at end of file From da44f65d5025be62822a4eb2962f988dbd3497a6 Mon Sep 17 00:00:00 2001 From: Arnabdaz <96580571+Arnabdaz@users.noreply.github.com> Date: Mon, 19 Jun 2023 20:19:01 +0530 Subject: [PATCH 06/22] feat(gsoc): update types for store and naming error fixes Signed-off-by: Arnabdaz <96580571+Arnabdaz@users.noreply.github.com> --- src/components/DialogBox/ProjectNameSet.vue | 4 +-- .../DialogBox/ProjectNameSetHelper.ts | 6 ++-- src/pages/simulatorHandler.vue | 35 ++++++++++--------- src/store/authStore.ts | 14 ++++++-- src/store/projectStore.ts | 4 +-- 5 files changed, 37 insertions(+), 26 deletions(-) diff --git a/src/components/DialogBox/ProjectNameSet.vue b/src/components/DialogBox/ProjectNameSet.vue index 38cfc23d..1cb4d288 100644 --- a/src/components/DialogBox/ProjectNameSet.vue +++ b/src/components/DialogBox/ProjectNameSet.vue @@ -12,10 +12,10 @@ diff --git a/src/components/DialogBox/ProjectNameSetHelper.ts b/src/components/DialogBox/ProjectNameSetHelper.ts index f415eeb6..3e068a73 100644 --- a/src/components/DialogBox/ProjectNameSetHelper.ts +++ b/src/components/DialogBox/ProjectNameSetHelper.ts @@ -1,9 +1,9 @@ -import { useProjectStore, projectStoreType } from '#/store/projectStore' +import { useProjectStore } from '#/store/projectStore' let resolvePromise: (value?: string) => void // will be used to store the resolve function of the Promise export const confirmName = (selectedOption: string): void => { - const projectStore: projectStoreType = useProjectStore() + const projectStore = useProjectStore() projectStore.CreateProjectHelper.changeProjectName = false if (selectedOption === 'save') { resolvePromise(projectStore.CreateProjectHelper.inputList[0].val) @@ -13,7 +13,7 @@ export const confirmName = (selectedOption: string): void => { } export const provideProjectName = async (): Promise => { - const projectStore: projectStoreType = useProjectStore() + const projectStore = useProjectStore() projectStore.CreateProjectHelper.changeProjectName = true projectStore.CreateProjectHelper.isPersistent = true projectStore.CreateProjectHelper.messageText = diff --git a/src/pages/simulatorHandler.vue b/src/pages/simulatorHandler.vue index 9a2c0d02..b321860d 100644 --- a/src/pages/simulatorHandler.vue +++ b/src/pages/simulatorHandler.vue @@ -1,11 +1,11 @@ + +