-
Notifications
You must be signed in to change notification settings - Fork 201
Added Feat #332 Search project by name #340
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -47,6 +47,10 @@ export const projectService = { | |
| queryParts.push(`created:${filters.created}`); | ||
| } | ||
|
|
||
| if(filters.repoName) { | ||
| const trimmedRepoName = filters.repoName.trim(); | ||
| queryParts.push(`${trimmedRepoName} in:name`) | ||
| } | ||
|
Comment on lines
+50
to
+53
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. User-supplied This is the injection point for the concern raised in the router's schema validation comment. If input sanitization is added at the schema level (as suggested in Ensure the upstream schema validation restricts 🤖 Prompt for AI Agents |
||
| // Default fields to filter contributor friendly repos | ||
| queryParts.push(`is:organization`); | ||
| queryParts.push(`is:public`); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -25,7 +25,7 @@ export default function FiltersContainer() { | |
|
|
||
| const { toggleShowFilters } = useFilterStore(); | ||
| const { setRenderProjects } = useRenderProjects(); | ||
| const { filters, resetFilters } = useFilterInputStore(); | ||
| const { filters, resetFilters, updateFilters } = useFilterInputStore(); | ||
| const { setData, eraseData } = useProjectsData(); | ||
| const { setProjectsNotFound } = useProjectsNotFoundStore(); | ||
| const getProjects = useGetProjects(); | ||
|
|
@@ -80,6 +80,16 @@ export default function FiltersContainer() { | |
| {/* Filter Content */} | ||
| <div className="flex-1 overflow-y-auto py-4"> | ||
| <Accordion type="multiple" className="space-y-2"> | ||
| <div className="w-full px-6 flex justify-center h-10"> | ||
| <input | ||
| type="text" | ||
| placeholder="Enter repository name" | ||
| className="w-full rounded-md outline-none focus:outline-2 focus:outline-ox-purple px-2" | ||
| onChange={(e) => { | ||
| updateFilters({repoName: e.target.value}) | ||
| }} | ||
| /> | ||
| </div> | ||
|
Comment on lines
+83
to
+92
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Uncontrolled input won't clear on reset, lacks accessibility and dark-theme styling. Several issues with this input:
Proposed fixYou'll need to wire the input value to a state variable. One approach is to read - <div className="w-full px-6 flex justify-center h-10">
- <input
- type="text"
- placeholder="Enter repository name"
- className="w-full rounded-md outline-none focus:outline-2 focus:outline-ox-purple px-2"
- onChange={(e) => {
- updateFilters({repoName: e.target.value})
- }}
- />
- </div>
+ <div className="w-full px-6 flex justify-center h-10">
+ <input
+ type="text"
+ placeholder="Enter repository name"
+ aria-label="Search by repository name"
+ value={(filters as Record<string, string>).repoName ?? ""}
+ className="w-full rounded-md bg-[`#141418`] text-white border border-[`#28282c`] outline-none focus:outline-2 focus:outline-ox-purple px-2 placeholder:text-zinc-500"
+ onChange={(e) => {
+ updateFilters({repoName: e.target.value})
+ }}
+ />
+ </div>As per coding guidelines: "Prefer controlled components over uncontrolled", "Include proper aria labels for accessibility", and "NEVER use hardcoded hex values directly in components; ALWAYS reference colors from the design token system using Tailwind classes" — consider using semantic color tokens (e.g., 🤖 Prompt for AI Agents |
||
| <Filter | ||
| filterName="Tech stack" | ||
| filters={[ | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -94,6 +94,7 @@ const userInputValues: UserFilterObjProps = { | |||||
| // Competition: "High", | ||||||
| // Stage: "Very early", | ||||||
| // Activity: "Normal", | ||||||
| // repoName: "name" | ||||||
| // }; | ||||||
|
|
||||||
| // API INPUT EXAMPLE | ||||||
|
|
@@ -104,6 +105,7 @@ const userInputValues: UserFilterObjProps = { | |||||
| // forks: { min: "50", max: "1000" }, | ||||||
| // pushed: ">=2024-12-08", | ||||||
| // created: ">=2024-12-12", | ||||||
| // reponame: "name" | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Typo in comment: The comment example uses lowercase -// reponame: "name"
+// repoName: "name"📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||
| // }; | ||||||
|
|
||||||
| export const convertUserInputToApiInput = ( | ||||||
|
|
@@ -133,7 +135,9 @@ export const convertUserInputToApiInput = ( | |||||
| if (filter.Stage) { | ||||||
| data.created = userInputValues.Stage[filter.Stage as keyof StageProps]; | ||||||
| } | ||||||
|
|
||||||
| if(filter.repoName) { | ||||||
| data.repoName = filter.repoName.trim() | ||||||
| } | ||||||
| return data as FilterProps; | ||||||
| }; | ||||||
|
|
||||||
|
|
||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -20,4 +20,5 @@ export type FilterProps = { | |
| forks?: ForkRange; | ||
| pushed?: string; | ||
| created?: string; | ||
| repoName?: string | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider adding length validation and sanitization to
repoName.The
repoNamestring is passed directly into the GitHub search query (seeproject.service.tsLine 52:`${trimmedRepoName} in:name`). A user could inject GitHub search qualifiers (e.g.,"stars:>1000 is:private") to manipulate search results beyond the intended name filter.Proposed fix
The regex restricts input to valid GitHub repository name characters, preventing injection of search qualifiers like
stars:,is:, etc.📝 Committable suggestion
🤖 Prompt for AI Agents