From 8351327c8953aaa66b4c597745c523d320785660 Mon Sep 17 00:00:00 2001 From: raymond1242 Date: Tue, 12 Sep 2023 08:11:04 -0500 Subject: [PATCH 1/3] Serach by project name query and api call to that query --- estela-api/api/views/project.py | 23 +++++ estela-api/docs/api.yaml | 30 +++++++ .../src/pages/ProjectListPage/index.tsx | 90 +++++++++++++++++-- .../services/api/generated-api/apis/ApiApi.ts | 45 ++++++++++ 4 files changed, 181 insertions(+), 7 deletions(-) diff --git a/estela-api/api/views/project.py b/estela-api/api/views/project.py index fa7aaf81..b8550cbc 100644 --- a/estela-api/api/views/project.py +++ b/estela-api/api/views/project.py @@ -59,6 +59,29 @@ def get_queryset(self): else self.request.user.project_set.filter(deleted=False) ) + @swagger_auto_schema( + methods=["GET"], + manual_parameters=[ + openapi.Parameter( + "search", + openapi.IN_QUERY, + description="Search for a project by name.", + type=openapi.TYPE_STRING, + required=False, + ) + ], + responses={status.HTTP_200_OK: ProjectSerializer(many=True)}, + ) + @action(methods=["GET"], detail=False) + def search(self, request, *args, **kwargs): + search = request.query_params.get("search", None) + projects = self.get_queryset() + if search: + projects = projects.filter(name__icontains=search) + + serializer = ProjectSerializer(projects, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + def perform_create(self, serializer): instance = serializer.save() instance.users.add( diff --git a/estela-api/docs/api.yaml b/estela-api/docs/api.yaml index dcfaef48..00baca1e 100644 --- a/estela-api/docs/api.yaml +++ b/estela-api/docs/api.yaml @@ -437,6 +437,36 @@ paths: tags: - api parameters: [] + /api/projects/search: + get: + operationId: api_projects_search + description: '' + parameters: + - name: page + in: query + description: A page number within the paginated result set. + required: false + type: integer + - name: page_size + in: query + description: Number of results to return per page. + required: false + type: integer + - name: search + in: query + description: Search for a project by name. + required: false + type: string + responses: + '200': + description: '' + schema: + type: array + items: + $ref: '#/definitions/Project' + tags: + - api + parameters: [] /api/projects/{pid}: get: operationId: api_projects_read diff --git a/estela-web/src/pages/ProjectListPage/index.tsx b/estela-web/src/pages/ProjectListPage/index.tsx index 95b1becf..f2532805 100644 --- a/estela-web/src/pages/ProjectListPage/index.tsx +++ b/estela-web/src/pages/ProjectListPage/index.tsx @@ -9,7 +9,14 @@ import Bug from "../../assets/icons/bug.svg"; import FolderDotted from "../../assets/icons/folderDotted.svg"; import WelcomeProjects from "../../assets/images/welcomeProjects.svg"; import history from "../../history"; -import { ApiProjectsListRequest, ApiProjectsCreateRequest, Project, ProjectCategoryEnum } from "../../services/api"; +import { + ApiProjectsListRequest, + ApiProjectsCreateRequest, + ApiProjectsSearchRequest, + InlineResponse2002, + Project, + ProjectCategoryEnum, +} from "../../services/api"; import { incorrectDataNotification, Spin, PaginationItem } from "../../shared"; import { UserContext, UserContextProps } from "../../context/UserContext"; @@ -32,6 +39,7 @@ interface ProjectsPageState { loaded: boolean; count: number; current: number; + query: string; modalNewProject: boolean; modalWelcome: boolean; newProjectName: string; @@ -48,6 +56,7 @@ export class ProjectListPage extends Component { loaded: false, count: 0, current: 0, + query: "", modalNewProject: false, modalWelcome: false, newProjectName: "", @@ -182,8 +191,12 @@ export class ProjectListPage extends Component { return { data: data.results, count: data.count, current: page }; } - onPageChange = async (page: number): Promise => { - this.setState({ loaded: false }); + + getProject = async (page: number) => { + const requestParams: ApiProjectsListRequest = { page, pageSize: this.PAGE_SIZE }; + this.apiService.apiProjectsList(requestParams).then((response: InlineResponse2002) => { + console.log(response) + }) const data = await this.getProjects(page); const projectData: ProjectList[] = data.data.map((project: Project, id: number) => { return { @@ -203,10 +216,54 @@ export class ProjectListPage extends Component { loaded: true, modalWelcome: data.count === 0, }); + } + + updateFilteredProjects = async (query: string): Promise => { + const requestParams: ApiProjectsSearchRequest = { search: query }; + this.apiService.apiProjectsSearch(requestParams).then((response: Project[]) => { + console.log(response) + }) + } + + onPageChange = async (page: number): Promise => { + this.setState({ loaded: false }); + this.getProject(page); + // const data = await this.getProjects(page); + // const projectData: ProjectList[] = data.data.map((project: Project, id: number) => { + // return { + // name: project.name, + // pid: project.pid, + // framework: project.framework, + // role: + // project.users?.find((user) => user.user?.username === AuthService.getUserUsername())?.permission || + // "ADMIN", + // key: id, + // }; + // }); + // this.setState({ + // projects: [...projectData], + // count: data.count, + // current: data.current, + // loaded: true, + // modalWelcome: data.count === 0, + // }); }; + onQueryChange = (event: React.ChangeEvent): void => { + const { + target: { value, name }, + } = event; + if (name === "query") { + this.setState({ query: value }); + this.updateFilteredProjects(value); + } + if (value === "") { + // Get all projects + } + } + render(): JSX.Element { - const { projects, count, current, loaded, modalNewProject, modalWelcome, newProjectName, newProjectCategory } = + const { projects, count, current, loaded, modalNewProject, modalWelcome, newProjectName, newProjectCategory, query } = this.state; return ( <> @@ -307,9 +364,28 @@ export class ProjectListPage extends Component { - - -

MY PROJECTS

+ + {/* */} +

MY PROJECTS

+
+ + + {/*

MY PROJECTS

*/} + - +
@@ -476,27 +470,31 @@ export class ProjectListPage extends Component {
- - - - + {loadedProjects ? ( + +
+ + + ) : ( + + )} {this.totalProjects === 0 && ( diff --git a/estela-web/src/services/api/generated-api/.openapi-generator/FILES b/estela-web/src/services/api/generated-api/.openapi-generator/FILES index 21451ac3..07a4efe4 100644 --- a/estela-web/src/services/api/generated-api/.openapi-generator/FILES +++ b/estela-web/src/services/api/generated-api/.openapi-generator/FILES @@ -33,6 +33,7 @@ models/ProjectActivity.ts models/ProjectCronJob.ts models/ProjectDetail.ts models/ProjectJob.ts +models/ProjectSearch.ts models/ProjectStats.ts models/ProjectUpdate.ts models/ProjectUsage.ts diff --git a/estela-web/src/services/api/generated-api/apis/ApiApi.ts b/estela-web/src/services/api/generated-api/apis/ApiApi.ts index 7f0fe1a0..e1694535 100644 --- a/estela-web/src/services/api/generated-api/apis/ApiApi.ts +++ b/estela-web/src/services/api/generated-api/apis/ApiApi.ts @@ -84,6 +84,9 @@ import { ProjectJob, ProjectJobFromJSON, ProjectJobToJSON, + ProjectSearch, + ProjectSearchFromJSON, + ProjectSearchToJSON, ProjectStats, ProjectStatsFromJSON, ProjectStatsToJSON, @@ -1695,7 +1698,7 @@ export class ApiApi extends runtime.BaseAPI { /** */ - async apiProjectsSearchRaw(requestParameters: ApiProjectsSearchRequest): Promise>> { + async apiProjectsSearchRaw(requestParameters: ApiProjectsSearchRequest): Promise> { const queryParameters: any = {}; if (requestParameters.page !== undefined) { @@ -1722,12 +1725,12 @@ export class ApiApi extends runtime.BaseAPI { query: queryParameters, }); - return new runtime.JSONApiResponse(response, (jsonValue) => jsonValue.map(ProjectFromJSON)); + return new runtime.JSONApiResponse(response, (jsonValue) => ProjectSearchFromJSON(jsonValue)); } /** */ - async apiProjectsSearch(requestParameters: ApiProjectsSearchRequest): Promise> { + async apiProjectsSearch(requestParameters: ApiProjectsSearchRequest): Promise { const response = await this.apiProjectsSearchRaw(requestParameters); return await response.value(); } diff --git a/estela-web/src/services/api/generated-api/models/ProjectSearch.ts b/estela-web/src/services/api/generated-api/models/ProjectSearch.ts new file mode 100644 index 00000000..d2c1301d --- /dev/null +++ b/estela-web/src/services/api/generated-api/models/ProjectSearch.ts @@ -0,0 +1,72 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * estela API v1.0 Documentation + * estela API Swagger Specification + * + * The version of the OpenAPI document: v1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +import { + Project, + ProjectFromJSON, + ProjectFromJSONTyped, + ProjectToJSON, +} from './'; + +/** + * + * @export + * @interface ProjectSearch + */ +export interface ProjectSearch { + /** + * Project search results. + * @type {Array} + * @memberof ProjectSearch + */ + results: Array; + /** + * Project search results count. + * @type {number} + * @memberof ProjectSearch + */ + count: number; +} + +export function ProjectSearchFromJSON(json: any): ProjectSearch { + return ProjectSearchFromJSONTyped(json, false); +} + +export function ProjectSearchFromJSONTyped(json: any, ignoreDiscriminator: boolean): ProjectSearch { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'results': ((json['results'] as Array).map(ProjectFromJSON)), + 'count': json['count'], + }; +} + +export function ProjectSearchToJSON(value?: ProjectSearch | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'results': ((value.results as Array).map(ProjectToJSON)), + 'count': value.count, + }; +} + + diff --git a/estela-web/src/services/api/generated-api/models/index.ts b/estela-web/src/services/api/generated-api/models/index.ts index 9f4329b1..8c985cc1 100644 --- a/estela-web/src/services/api/generated-api/models/index.ts +++ b/estela-web/src/services/api/generated-api/models/index.ts @@ -29,6 +29,7 @@ export * from './ProjectActivity'; export * from './ProjectCronJob'; export * from './ProjectDetail'; export * from './ProjectJob'; +export * from './ProjectSearch'; export * from './ProjectStats'; export * from './ProjectUpdate'; export * from './ProjectUsage';