Week 3 & 4 - CircuitVerse@GSOC'23
Hi everyone this is my Second blog for GSoC@CircuitVerse
In weeks 3 and 4, I faced numerous bugs affecting my project planning. Despite challenges, I adapted and resolved issues. In this post, I'll share updates and how I overcame obstacles.
During the third week, a power outage due to severe weather hindered my project. However, I recovered by working extra hours, ensuring continued progress.
Change in planning
As the content of this entire blog will be somewhat different, I will be writing the whole blog as a story to provide context for the changes more easily, rather than solely focusing on technical aspects.
In week 2, I had a task that involved creating new API endpoints and connecting them to the Vue simulator. The connection process was relatively simple; The flow of the API and simulator loading in edit mode should be as below diagram:
ignore the API endpoints defined in the diagram as they were changed later
As anticipated, the task involved implementing the logic to determine whether a user has access to edit the circuit when opened in edit mode, and if not, simply load a blank simulator. This part functioned well, and the rest of the implementation, such as loading and updating circuit data from the server, was as straightforward as adding the new API endpoints with fetch and ES6 JavaScript. However, the main issue arose shortly after implementing the circuit data loading API.
The main issue:
The main issue surfaced when loading a newly created circuit led to tab errors, hindering all tabs from loading except for the project's default circuit. After addressing minor issues during debugging, it was found that a truncate function received an undefined parameter. The solution entailed storing the name in the Pinia store, specifically within the circuit_list Array.
With fixing this I supposed things were fixed and I can move to the next part but multiple bugs kept occurring with the tabs bar on circuit data loading such as:
Tabs not switching in order according to the loaded data,
Tabs not switching upon circuit deletion,
Tabs not being highlighted when active,
The last active tab not being selected, instead, the main tab is selected,
Different tab(s) are highlighted upon clicking a tab
Tabs from simulator state not getting removed upon deletion or scope reset
One by one, as these issues occurred, I began addressing them. However, even after resolving all of them, problems persisted with tab deletion and the tab ID not being sent with the update data request. Consequently, I decided to stop using the hybrid approach of JavaScript variables and Pinia store for managing tabs. Instead, I opted to move the entire tab data handling process to the Pinia store.
This turned out to be an excellent decision. The following day, I transferred all tab-related data handling to the Simulator store. As a result, tabs could now be rearranged without using DOM manipulation, and deleting and switching tabs became much easier to manage using the store. Ultimately, I replaced all tab data handling with the Pinia store and eliminated all tab-related DOM manipulation. Most Importantly I was able to easily fix a very old unresolved issue #23 which removed the use of setInterval being called every 100ms to check the change in the active circuit.
After fixing the active circuit issue and ensuring the simulator could load and update circuit data, I proceeded to implement the project creation API while addressing circuit deletion errors and issues with new circuit creation from context and navbar menus. Issues: #55 #61 #68 #62
DeleteCircuit.vue:
The delete circuit logic and the creation of new circuits were divided between tabsbar.vue and circuit.js. The issue with deleting circuits occurred because the conditions were only defined in tabsbar.vue and not in propertypanel.vue. Initially, I considered adding the delete condition logic to propertypanel but to avoid code repetition and adhere to the DRY principle, I created a separate DeleteCircuit.vue component containing all circuit deletion logic.
PromptComponent.vue:
Next, I addressed the issue of new circuit creation. Rather than having a unique component and exporting the logic from circuit.js and load.js, I chose to replace the prompt component, which was used for obtaining the new circuit name, with a Vue dialog box. By utilizing async-await, we can make the code wait just as it does for prompt(). With this change, I successfully fixed all the "create new circuit" options, ensuring that they consistently display the dialog box instead of the prompt.
I created the component to replace prompt() in the codebase, and successfully replaced the "enter new project name" prompt, with plans to replace all future prompts as well.
ConfirmComponent.vue:
Similar to promptComponent.vue to replace the confirm() and alert() I created a general component to get user selection form choices provided.
it consists of three functions
confirmSingleOption(messageText): used to replace alert()
confirmOption(messageText): used to replace confirm()
confirmMultiOption(messageText, buttonArray): to get user choice where the choice can be set with button array.
All the alert() and confirm() were already replaced with this component.
Create New Project:
Now that the major bugs have been fixed, we can move forward with implementing the new project creation API into our simulator. Previously, a form was used to update the project data and make a request. Once the request was successful, the user was redirected to the project details edit page to update the project details. Since our goal is to make the Vue simulator independent of the main repository and have it only work with API requests, I created a new, fully JSON-based API to create new projects from the simulator during week 2.
UpdateProjectDetail.vue:
Thus, we implemented the new API using fetch, and we were now able to create new projects from the Vue simulator. However, there was still one issue to be resolved. As we made the POST request, we received JSON containing the created project information, but the user needs to be able to update the project details as they create a new project. To address this, we created a new UpdateProjectDetail.vue component, which opens a dialog box containing all the options for updating the project details if project creation is successful.
TextEditor.vue:
As the edit project details box needed a WYSIWYG editor I tried to find a working editor in the form of a vue3 component but was unable to find one working with our project as there were hardly any actively maintained editors for vue3. Ultimately, I decided to use the Tiptap editor, as it was compatible with Vue 3. Since it wasn't a simple plug-and-play solution and required extensive configuration, I created a new component for the editor and added all the essential functionality.
In the future, if a better editor is found, it can easily replace the current one, as it has been implemented as a separate component in the project. On the other hand, as it is a maintained package we can keep using it and also enable other features in the editor.
PR #170 https://github.com/CircuitVerse/cv-frontend-vue/pull/170 contains all the changes described above.
Import and Export as .cv file:
ExportProject.vue:
In this file, I implemented the project Export as .cv file functionality. it uses the generateSaveData() and download() functions defined in save.js to first create the circuit data as JSON string and then download it in the browser.
ImportProject.vue:
This was a bit tricky, as it involved obtaining the file, reading it, verifying its contents, and then loading the project from the file's JSON data. Most of all, Vuetify did not have a fully functional file import component with file dragging functionality, so I had to resort to a somewhat hacky method. As I wanted to solve it with only vue instead DOM manipulation or pure JavaScript. To handle this, I wrapped the dropping zone with a v-cloak and added @drop.prevent
and @dragover.prevent
to call the below function:
function addDropFile(e: DragEvent) {
if (e.dataTransfer?.files[0]) {
const droppedFile = e.dataTransfer?.files[0]
file.value[0] = droppedFile
}
}
Now, with this implementation, users can either select a file from the file manager or drag and drop it into the drop zone. Next, I added all the necessary functionalities, such as reading the file with FileReader()
, verifying the correct format of the JSON in the .cv file, and ultimately loading the circuit using the load() function.
PR #171 https://github.com/CircuitVerse/cv-frontend-vue/pull/171 Contains the import and export-related changes.
UserMenu Revamp
UserMenu.vue
With the need to add more options to the user menu, such as locale switching and future additions, the old user menu was not ideal in terms of incorporating complex features and providing a good UI/UX experience. To address this issue, I revamped the user menu to adopt the new GitHub user menu style. This not only makes it easier to include more complex features like locale switching but also significantly improves the UI/UX.
Other changes:
other than the above changes I did a lot of other changes for which you can check out my prs in the cv-frontend-vue repo. I am also working on the Quickmenu and issue report component and embed simulator implementation for which pr would be created after discussion with mentors.
I appreciate everyone who read this article till the end. Happy coding!
Subscribe to my newsletter
Read articles from Arnab Das directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by