Add terminal snippets feature with sidebar UI #377
Reference in New Issue
Block a user
Delete Branch "feature-snippets-in-ssh-tools"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary of Changes
Hello @LukeGus, I'm Gemini Code Assist1 ! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!
This PR introduces a comprehensive 'terminal snippets' feature, enabling users to manage and execute saved commands via a new sidebar UI. It includes full-stack implementation, from database schema and API endpoints to frontend components and internationalization.
Highlights
Backend API & Database:
snippetstable is added to the database schema (src/backend/database/db/index.ts,src/backend/database/db/schema.ts) to store user-specific command snippets (name, content, description, timestamps)./snippets) are implemented insrc/backend/database/routes/snippets.tsfor CRUD operations (create, read, update, delete) on snippets, including authentication and data access control.src/backend/database/database.ts) is updated to import and use these new snippet routes.Frontend UI & Logic:
Snippet,SnippetData) are defined insrc/types/index.tsfor type safety.SnippetsSidebar.tsx, is added (src/ui/Desktop/Apps/Terminal/SnippetsSidebar.tsx). This component provides the user interface for viewing, creating, editing, deleting, executing, and copying snippets.TopNavbar.tsxcomponent (src/ui/Desktop/Navigation/TopNavbar.tsx) is updated to include a new button to toggle theSnippetsSidebar. This button is enabled only when a terminal tab is active, and it integrates the functionality to send snippet content to the active terminal.getSnippets,createSnippet,updateSnippet,deleteSnippet) are added tosrc/ui/main-axios.tsto interact with the backend snippet endpoints.Internationalization:
src/locales/en/translation.jsonandsrc/locales/zh/translation.json.Using Gemini Code Assist
The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.
Invoking Gemini
You can request assistance from Gemini at any point by creating a comment using either
/gemini <command>or@gemini-code-assist <command>. Below is a summary of the supported commands on the current page./gemini review/gemini summary/gemini helpCustomization
To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a
.gemini/folder in the base of the repository. Detailed instructions can be found here.Limitations & Feedback
Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.
You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.
Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution. ↩︎
Code Review
This pull request introduces a new terminal snippets feature, complete with backend API endpoints, database schema updates, and a frontend sidebar UI. The implementation is well-structured and covers all necessary aspects of the feature. My review focuses on enhancing input validation on the backend for robustness, improving database query efficiency, and increasing type safety on the frontend for better maintainability.
@@ -0,0 +1,251 @@import express from "express";The route parameter
idis used withparseIntwithout validation. Ifidis not a string that can be parsed into a number (e.g., an empty string or non-numeric characters),parseIntwill returnNaN. This could lead to unexpected behavior or errors in the database query. You should validate thatidis a valid number before using it.This same validation should be applied to the
PUT /:idandDELETE /:idroutes as well.@@ -0,0 +167,4 @@if (updateData.content !== undefined)updateFields.content = updateData.content.trim();if (updateData.description !== undefined)updateFields.description = updateData.description?.trim() || null;The update endpoint allows setting
nameandcontentto empty strings, which is inconsistent with the creation endpoint that requires non-empty strings viaisNonEmptyString. You should add validation to ensurenameandcontentare not empty if they are being updated.Additionally, you can avoid using
anyforupdateFieldsby using a more specific type likePartial<typeof snippets.$inferInsert>for better type safety.@@ -0,0 +177,4 @@const updated = await db.select().from(snippets).where(eq(snippets.id, parseInt(id)));To improve efficiency, you can use Drizzle's
.returning()method on the update query. This will return the updated record in a single database call, avoiding the need for a separateselectquery.@@ -2158,0 +2197,4 @@} catch (error) {throw handleApiError(error, "delete snippet");}}To improve type safety and maintainability, you should use the specific
SnippetandSnippetDatatypes for the parameters and return values of these API functions instead ofany. You'll need to addSnippetandSnippetDatato your imports from../types/index.js.