Skip to content

Commit

Permalink
Merge pull request #279 from VineetBala-AOT/develop
Browse files Browse the repository at this point in the history
Add search and filter functionality to the home page for staff
  • Loading branch information
VineetBala-AOT authored Feb 4, 2025
2 parents f1b9595 + ff6e267 commit de80eaa
Show file tree
Hide file tree
Showing 8 changed files with 50 additions and 20 deletions.
24 changes: 16 additions & 8 deletions submit-api/src/submit_api/models/queries/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
# limitations under the License.
"""Model to handle all complex operations related to User."""

from sqlalchemy import or_
from submit_api.models import AccountProject, Project, db
from submit_api.models.account_project_search_options import AccountProjectSearchOptions
from submit_api.models.package import Package
Expand All @@ -33,11 +34,13 @@ def get_projects_by_proponent_id(cls, proponent_id: int):
return query.all()

@classmethod
def get_projects_by_account_id(cls, account_id: int, search_options: AccountProjectSearchOptions = None):
def get_filtered_projects(cls, account_id: int = None, search_options: AccountProjectSearchOptions = None):
"""Find projects by account_id with optional search and pagination."""
query = db.session.query(AccountProject).filter(
AccountProject.account_id == account_id,
).join(AccountProject.project)
query = db.session.query(AccountProject).join(AccountProject.project)

# Apply account_id filter only if provided
if account_id is not None:
query = query.filter(AccountProject.account_id == account_id)

# Apply search filters if provided
if search_options and any(bool(search_option) for search_option in search_options.__dict__.values()):
Expand All @@ -52,7 +55,7 @@ def filter_by_search_criteria(cls, project_query, search_options: AccountProject
package_query = db.session.query(Package)

if search_options.search_text:
package_query = cls._filter_by_submission_name(package_query, search_options.search_text)
package_query = cls._filter_by_search_text(package_query, search_options.search_text)
if search_options.status:
package_query = cls._filter_by_submission_status(package_query, search_options.status)
if search_options.submitted_on_start or search_options.submitted_on_end:
Expand All @@ -65,14 +68,19 @@ def filter_by_search_criteria(cls, project_query, search_options: AccountProject

project_query = project_query.join(Package).filter(
Package.id.in_(filtered_package_ids)).options(
db.contains_eager(AccountProject.packages))
db.contains_eager(AccountProject._packages))

return project_query

@classmethod
def _filter_by_submission_name(cls, query, search_text):
def _filter_by_search_text(cls, query, search_text):
"""Filter by search text across package name."""
return query.filter(Package.name.ilike(f"%{search_text}%"))
return query.filter(
or_(
Package.name.ilike(f"%{search_text}%"),
Project.name.ilike(f"%{search_text}%")
)
)

@classmethod
def _filter_by_submission_status(cls, query, statuses):
Expand Down
17 changes: 16 additions & 1 deletion submit-api/src/submit_api/resources/staff/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,13 @@
"""API endpoints for managing a project resource."""

from http import HTTPStatus
from flask import request

from flask_restx import Namespace, Resource, cors

from submit_api.auth import auth
from submit_api.models.account_project_search_options import AccountProjectSearchOptions
from submit_api.models.package import PackageStatus
from submit_api.resources.apihelper import Api as ApiHelper
from submit_api.schemas.project import StaffAccountProjectSchema
from submit_api.services.project_service import ProjectService
Expand Down Expand Up @@ -52,7 +55,19 @@ class AccountProjects(Resource):
@cors.crossdomain(origin="*")
def get():
"""Get all account projects."""
account_projects = ProjectService.get_all_account_projects()
args = request.args
search_text = args.get('search_text')
submitted_on_start = args.get('submitted_on_start')
submitted_on_end = args.get('submitted_on_end')
status = list(map(PackageStatus, args.getlist('status[]')))
search_options = AccountProjectSearchOptions(
search_text=search_text,
submitted_on_start=submitted_on_start,
submitted_on_end=submitted_on_end,
status=status,
)

account_projects = ProjectService.get_all_account_projects(search_options)
return StaffAccountProjectSchema(many=True).dump(account_projects), HTTPStatus.OK


Expand Down
6 changes: 3 additions & 3 deletions submit-api/src/submit_api/services/project_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ def get_account_project_by_id(cls, account_project_id):
@classmethod
def get_projects_by_account_id(cls, account_id, search_options: AccountProjectSearchOptions):
"""Get projects by account id."""
return ProjectQueries.get_projects_by_account_id(account_id, search_options)
return ProjectQueries.get_filtered_projects(account_id, search_options)

@classmethod
def get_projects_by_proponent_id(cls, proponent_id):
Expand All @@ -35,9 +35,9 @@ def bulk_add_projects(cls, account_id: int, project_ids: list):
return projects

@classmethod
def get_all_account_projects(cls):
def get_all_account_projects(cls, search_options: AccountProjectSearchOptions):
"""Get projects by proponent id."""
return AccountProjectModel.get_all()
return ProjectQueries.get_filtered_projects(None, search_options)

@classmethod
def get_all_account_projects_with_latest_packages(cls):
Expand Down
4 changes: 2 additions & 2 deletions submit-web/src/components/Filters/ProjectFilters.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { useProjectFilters } from "./projectFilterStore";
import DateSubmittedFromFilter from "./DateSubmittedFromFilter";
import DateSubmittedToFilter from "./DateSubmittedToFilter";

function ProjectFilters() {
function ProjectFilters({userType}: {userType: string;}) {
const { resetFilters } = useProjectFilters();

return (
Expand All @@ -17,7 +17,7 @@ function ProjectFilters() {
sx={{ maxWidth: "1448px", justifyContent: "space-between" }}
>
<Grid item xs={2.5}>
<SearchFilter />
<SearchFilter userType={userType}/>
</Grid>
<Grid item xs={3.5}>
<StatusFilter />
Expand Down
11 changes: 8 additions & 3 deletions submit-web/src/components/Filters/SearchFilter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ import { InputAdornment, IconButton, TextField } from "@mui/material";
import { Search, Clear } from "@mui/icons-material";
import { useProjectFilters } from "./projectFilterStore";
import { BCDesignTokens } from "epic.theme";
import { USER_TYPE } from "@/models/User";

export const SearchFilter = () => {
export const SearchFilter = ({userType}: {userType: string;}) => {
const { filters, setFilters } = useProjectFilters();
const [searchText, setSearchText] = useState(filters.search_text);

Expand All @@ -27,13 +28,17 @@ export const SearchFilter = () => {
<TextField
fullWidth
variant="outlined"
placeholder="Search Submissions"
placeholder={userType === USER_TYPE.PROPONENT
? "Search Submissions" : "Search Projects/Submissions by Name"}
value={searchText}
onChange={handleChange}
onKeyDown={handleKeyDown}
InputProps={{
startAdornment: (
<InputAdornment position="start">
<InputAdornment
position="start"
sx={{ width: "auto", minWidth: "unset", mx: 0 }}
>
<Search htmlColor={BCDesignTokens.typographyColorPlaceholder} />
</InputAdornment>
),
Expand Down
2 changes: 1 addition & 1 deletion submit-web/src/components/Filters/StatusFilter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ function StatusFilter() {
(status) => status.value,
),
});
} else if (value.length <= 2) {
} else if (value.length <= 3) {
setFilters({ status: value });
}
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { notify } from "@/components/Shared/Snackbar/snackbarStore";
import { PageGrid } from "@/components/Shared/PageGrid";
import ProjectFilters from "@/components/Filters/ProjectFilters";
import { useProjectFilters } from "@/components/Filters/projectFilterStore";
import { USER_TYPE } from "@/models/User";

export const Route = createFileRoute(
"/proponent/_proponentLayout/projects/",
Expand Down Expand Up @@ -42,7 +43,7 @@ export function ProjectsPage() {
return (
<PageGrid>
<Grid item xs={12}>
<ProjectFilters />
<ProjectFilters userType={USER_TYPE.PROPONENT}/>
<If condition={isProjectsLoading}>
<Then>
<ProjectsSkeleton />
Expand Down
3 changes: 2 additions & 1 deletion submit-web/src/routes/staff/_staffLayout/projects/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { Grid } from "@mui/material";
import { createFileRoute, Navigate } from "@tanstack/react-router";
import { useEffect } from "react";
import { Else, If, Then } from "react-if";
import { USER_TYPE } from "@/models/User";

export const Route = createFileRoute("/staff/_staffLayout/projects/")({
component: ProjectsPage,
Expand Down Expand Up @@ -37,7 +38,7 @@ function ProjectsPage() {
return (
<PageGrid>
<Grid item xs={12}>
<ProjectFilters />
<ProjectFilters userType={USER_TYPE.STAFF}/>
<If condition={isProjectsLoading}>
<Then>
<ProjectsSkeleton />
Expand Down

0 comments on commit de80eaa

Please sign in to comment.