Skip to content

Commit cd9b335

Browse files
matusdrobuliak66mrnicegyu11
authored andcommitted
✨ introduce /projects:search full search (ITISFoundation#6464)
1 parent eca803b commit cd9b335

File tree

7 files changed

+461
-40
lines changed

7 files changed

+461
-40
lines changed

api/specs/web-server/_projects_crud.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,10 @@
3232
from simcore_service_webserver._meta import API_VTAG
3333
from simcore_service_webserver.projects._common_models import ProjectPathParams
3434
from simcore_service_webserver.projects._crud_handlers import ProjectCreateParams
35-
from simcore_service_webserver.projects._crud_handlers_models import ProjectListParams
35+
from simcore_service_webserver.projects._crud_handlers_models import (
36+
ProjectListFullSearchParams,
37+
ProjectListParams,
38+
)
3639

3740
router = APIRouter(
3841
prefix=f"/{API_VTAG}",
@@ -137,6 +140,16 @@ async def clone_project(
137140
...
138141

139142

143+
@router.get(
144+
"/projects:search",
145+
response_model=Page[ProjectListItem],
146+
)
147+
async def list_projects_full_search(
148+
_params: Annotated[ProjectListFullSearchParams, Depends()],
149+
):
150+
...
151+
152+
140153
@router.get(
141154
"/projects/{project_id}/inactivity",
142155
response_model=Envelope[GetProjectInactivityResponse],

services/web/server/src/simcore_service_webserver/api/v0/openapi.yaml

Lines changed: 42 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3291,6 +3291,45 @@ paths:
32913291
application/json:
32923292
schema:
32933293
$ref: '#/components/schemas/Envelope_TaskGet_'
3294+
/v0/projects:search:
3295+
get:
3296+
tags:
3297+
- projects
3298+
summary: List Projects Full Search
3299+
operationId: list_projects_full_search
3300+
parameters:
3301+
- required: false
3302+
schema:
3303+
title: Limit
3304+
exclusiveMaximum: true
3305+
minimum: 1
3306+
type: integer
3307+
default: 20
3308+
maximum: 50
3309+
name: limit
3310+
in: query
3311+
- required: false
3312+
schema:
3313+
title: Offset
3314+
minimum: 0
3315+
type: integer
3316+
default: 0
3317+
name: offset
3318+
in: query
3319+
- required: false
3320+
schema:
3321+
title: Text
3322+
maxLength: 100
3323+
type: string
3324+
name: text
3325+
in: query
3326+
responses:
3327+
'200':
3328+
description: Successful Response
3329+
content:
3330+
application/json:
3331+
schema:
3332+
$ref: '#/components/schemas/Page_ProjectListItem_'
32943333
/v0/projects/{project_id}/inactivity:
32953334
get:
32963335
tags:
@@ -9148,18 +9187,6 @@ components:
91489187
title: Userid
91499188
type: string
91509189
description: the user that started the service
9151-
example:
9152-
published_port: 30000
9153-
entrypoint: /the/entry/point/is/here
9154-
service_uuid: 3fa85f64-5717-4562-b3fc-2c963f66afa6
9155-
service_key: simcore/services/comp/itis/sleeper
9156-
service_version: 1.2.3
9157-
service_host: jupyter_E1O2E-LAH
9158-
service_port: 8081
9159-
service_basepath: /x/E1O2E-LAH
9160-
service_state: pending
9161-
service_message: no suitable node (insufficient resources on 1 node)
9162-
user_id: 123
91639190
NodeGetIdle:
91649191
title: NodeGetIdle
91659192
required:
@@ -11601,13 +11628,14 @@ components:
1160111628
ServiceState:
1160211629
title: ServiceState
1160311630
enum:
11631+
- failed
1160411632
- pending
1160511633
- pulling
1160611634
- starting
1160711635
- running
11608-
- complete
11609-
- failed
1161011636
- stopping
11637+
- complete
11638+
- idle
1161111639
description: An enumeration.
1161211640
ServiceType:
1161311641
title: ServiceType

services/web/server/src/simcore_service_webserver/projects/_crud_api_read.py

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
66
"""
77

8-
98
from aiohttp import web
109
from models_library.access_rights import AccessRights
1110
from models_library.api_schemas_webserver._base import OutputSchema
@@ -143,6 +142,28 @@ async def list_projects( # pylint: disable=too-many-arguments
143142
return projects, total_number_projects
144143

145144

145+
async def list_projects_full_search(
146+
app,
147+
*,
148+
user_id: UserID,
149+
product_name: str,
150+
offset: NonNegativeInt,
151+
limit: int,
152+
text: str | None,
153+
) -> tuple[list[ProjectDict], int]:
154+
db = ProjectDBAPI.get_from_app_context(app)
155+
156+
total_number_projects, db_projects = await db.list_projects_full_search(
157+
user_id=user_id,
158+
product_name=product_name,
159+
text=text,
160+
offset=offset,
161+
limit=limit,
162+
)
163+
164+
return db_projects, total_number_projects
165+
166+
146167
async def get_project(
147168
request: web.Request,
148169
user_id: UserID,

services/web/server/src/simcore_service_webserver/projects/_crud_handlers.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
ProjectActiveParams,
5959
ProjectCreateHeaders,
6060
ProjectCreateParams,
61+
ProjectListFullSearchParams,
6162
ProjectListWithJsonStrParams,
6263
)
6364
from ._permalink_api import update_or_pop_permalink_in_project
@@ -226,6 +227,40 @@ async def list_projects(request: web.Request):
226227
)
227228

228229

230+
@routes.get(f"/{VTAG}/projects:search", name="list_projects_full_search")
231+
@login_required
232+
@permission_required("project.read")
233+
@_handle_projects_exceptions
234+
async def list_projects_full_search(request: web.Request):
235+
req_ctx = RequestContext.parse_obj(request)
236+
query_params: ProjectListFullSearchParams = parse_request_query_parameters_as(
237+
ProjectListFullSearchParams, request
238+
)
239+
240+
projects, total_number_of_projects = await _crud_api_read.list_projects_full_search(
241+
request.app,
242+
user_id=req_ctx.user_id,
243+
product_name=req_ctx.product_name,
244+
limit=query_params.limit,
245+
offset=query_params.offset,
246+
text=query_params.text,
247+
)
248+
249+
page = Page[ProjectDict].parse_obj(
250+
paginate_data(
251+
chunk=projects,
252+
request_url=request.url,
253+
total=total_number_of_projects,
254+
limit=query_params.limit,
255+
offset=query_params.offset,
256+
)
257+
)
258+
return web.Response(
259+
text=page.json(**RESPONSE_MODEL_POLICY),
260+
content_type=MIMETYPE_APPLICATION_JSON,
261+
)
262+
263+
229264
#
230265
# - Get https://google.aip.dev/131
231266
# - Get active project: Singleton per-session resources https://google.aip.dev/156

services/web/server/src/simcore_service_webserver/projects/_crud_handlers_models.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,10 @@
1212
from models_library.projects_nodes_io import NodeID
1313
from models_library.rest_ordering import OrderBy, OrderDirection
1414
from models_library.rest_pagination import PageQueryParameters
15-
from models_library.utils.common_validators import null_or_none_str_to_none_validator
15+
from models_library.utils.common_validators import (
16+
empty_str_to_none_pre_validator,
17+
null_or_none_str_to_none_validator,
18+
)
1619
from models_library.workspaces import WorkspaceID
1720
from pydantic import BaseModel, Extra, Field, Json, root_validator, validator
1821
from servicelib.common_headers import (
@@ -150,3 +153,16 @@ class Config:
150153

151154
class ProjectActiveParams(BaseModel):
152155
client_session_id: str
156+
157+
158+
class ProjectListFullSearchParams(PageQueryParameters):
159+
text: str | None = Field(
160+
default=None,
161+
description="Multi column full text search, across all folders and workspaces",
162+
max_length=100,
163+
example="My Project",
164+
)
165+
166+
_empty_is_none = validator("text", allow_reuse=True, pre=True)(
167+
empty_str_to_none_pre_validator
168+
)

0 commit comments

Comments
 (0)