Skip to content
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

✨ Trash folders #6642

Merged
merged 48 commits into from
Nov 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
5e682dd
split folders
pcrespov Oct 30, 2024
9f7436b
split handlers
pcrespov Oct 30, 2024
ff0e622
adds trash counterpart
pcrespov Oct 30, 2024
63cb1dc
trash folders API
pcrespov Oct 30, 2024
23eb5a9
exception handling
pcrespov Oct 30, 2024
f405fb4
uses in projects and renames
pcrespov Oct 30, 2024
ad0576e
doc
pcrespov Oct 30, 2024
49a0b64
doc
pcrespov Oct 30, 2024
5804a60
updates calls
pcrespov Oct 30, 2024
887c84e
rename
pcrespov Oct 30, 2024
54506b3
tests
pcrespov Oct 30, 2024
1d265f3
tests
pcrespov Oct 30, 2024
846980c
updates app_environemnt
pcrespov Nov 4, 2024
822aa88
adds trashed_at in folders
pcrespov Nov 4, 2024
8f45bd1
migration
pcrespov Nov 4, 2024
d7cda1a
minor
pcrespov Nov 4, 2024
1bc9544
connected trash in folders
pcrespov Nov 4, 2024
7af3ba7
updates OAS
pcrespov Nov 4, 2024
b0c08a3
services/webserver api version: 0.44.0 → 0.45.0
pcrespov Nov 4, 2024
33999a1
drafting tests
pcrespov Nov 4, 2024
5debfb5
simplified this version of the exception handling
pcrespov Nov 5, 2024
d506314
new import
pcrespov Nov 5, 2024
18e98c2
adapts tests
pcrespov Nov 5, 2024
c15a304
adds flags
pcrespov Nov 5, 2024
0223319
migration
pcrespov Nov 5, 2024
75dcb12
cleanup test_folders
pcrespov Nov 6, 2024
d929700
rm projects.trashed_explcitly. will used hidden
pcrespov Nov 6, 2024
53fcf21
cleanup
pcrespov Nov 6, 2024
8a518a5
updates folders
pcrespov Nov 6, 2024
d29d79f
patch project explicitly
pcrespov Nov 6, 2024
e8b482a
drafts implementation
pcrespov Nov 6, 2024
69236c2
simplified implementation and tests
pcrespov Nov 6, 2024
1e24c58
setup with folders and projects
pcrespov Nov 6, 2024
37067b8
tests pass
pcrespov Nov 6, 2024
a810e7f
doc
pcrespov Nov 6, 2024
9a3b4d8
fixes exception
pcrespov Nov 6, 2024
42e3f58
improves error handling
pcrespov Nov 6, 2024
547c349
minor
pcrespov Nov 6, 2024
1706b7f
@giancarloromeo review: rm constructor
pcrespov Nov 7, 2024
9c963ed
@sanderegg review: interfaces for batch/ update
pcrespov Nov 7, 2024
398b09a
@GitHK review: doc
pcrespov Nov 7, 2024
a27412a
new cols
pcrespov Nov 7, 2024
9dfad7b
@sanderegg review: rm defaults
pcrespov Nov 7, 2024
5685f6f
extra project col
pcrespov Nov 7, 2024
4f5407a
fixes explicits tests
pcrespov Nov 7, 2024
0b3e984
fixes tests
pcrespov Nov 7, 2024
d993713
updates tests
pcrespov Nov 7, 2024
01bf2ad
updates column fixture
pcrespov Nov 8, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions api/specs/web-server/_folders.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
from models_library.workspaces import WorkspaceID
from pydantic import Json
from simcore_service_webserver._meta import API_VTAG
from simcore_service_webserver.folders._folders_handlers import FoldersPathParams
from simcore_service_webserver.folders._models import FolderFilters, FoldersPathParams

router = APIRouter(
prefix=f"/{API_VTAG}",
Expand All @@ -30,8 +30,6 @@
],
)

### Folders


@router.post(
"/folders",
Expand All @@ -57,6 +55,10 @@ async def list_folders(
example='{"field": "name", "direction": "desc"}',
),
] = '{"field": "modified_at", "direction": "desc"}',
filters: Annotated[
Json | None,
Query(description=FolderFilters.schema_json(indent=1)),
] = None,
):
...

Expand Down
6 changes: 5 additions & 1 deletion api/specs/web-server/_projects_crud.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
from simcore_service_webserver.projects._common_models import ProjectPathParams
from simcore_service_webserver.projects._crud_handlers import ProjectCreateParams
from simcore_service_webserver.projects._crud_handlers_models import (
ProjectFilters,
ProjectListFullSearchParams,
ProjectListParams,
)
Expand Down Expand Up @@ -83,7 +84,10 @@ async def list_projects(
example='{"field": "last_change_date", "direction": "desc"}',
),
] = '{"field": "last_change_date", "direction": "desc"}',
filters: Annotated[Json | None, Query()] = None,
filters: Annotated[
Json | None,
Query(description=ProjectFilters.schema_json(indent=1)),
] = None,
):
...

Expand Down
41 changes: 39 additions & 2 deletions api/specs/web-server/_trash.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,14 @@

from fastapi import APIRouter, Depends, status
from simcore_service_webserver._meta import API_VTAG
from simcore_service_webserver.projects._trash_handlers import (
ProjectPathParams,
from simcore_service_webserver.folders._models import (
FoldersPathParams,
RemoveQueryParams,
)
from simcore_service_webserver.projects._trash_handlers import ProjectPathParams
from simcore_service_webserver.projects._trash_handlers import (
RemoveQueryParams as RemoveQueryParams_duplicated,
)

router = APIRouter(
prefix=f"/{API_VTAG}",
Expand Down Expand Up @@ -59,3 +63,36 @@ def untrash_project(
_p: Annotated[ProjectPathParams, Depends()],
):
...


_extra_tags = ["folders"]


@router.post(
"/folders/{folder_id}:trash",
tags=_extra_tags,
status_code=status.HTTP_204_NO_CONTENT,
responses={
status.HTTP_404_NOT_FOUND: {"description": "Not such a folder"},
status.HTTP_409_CONFLICT: {
"description": "One or more projects is in use and cannot be trashed"
},
status.HTTP_503_SERVICE_UNAVAILABLE: {"description": "Trash service error"},
},
)
def trash_folder(
_p: Annotated[FoldersPathParams, Depends()],
_q: Annotated[RemoveQueryParams_duplicated, Depends()],
):
...


@router.post(
"/folders/{folder_id}:untrash",
tags=_extra_tags,
status_code=status.HTTP_204_NO_CONTENT,
)
def untrash_folder(
_p: Annotated[FoldersPathParams, Depends()],
):
...
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class FolderGet(OutputSchema):
description: str
created_at: datetime
modified_at: datetime
trashed_at: datetime | None
owner: GroupID
my_access_rights: AccessRights
access_rights: dict[GroupID, AccessRights]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class FolderGet(OutputSchema):
name: str
created_at: datetime
modified_at: datetime
trashed_at: datetime | None
owner: GroupID
workspace_id: WorkspaceID | None
my_access_rights: AccessRights
Expand Down
4 changes: 4 additions & 0 deletions packages/models-library/src/models_library/folders.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ class FolderDB(BaseModel):
...,
description="Timestamp of last modification",
)
trashed_at: datetime | None = Field(
...,
)

user_id: UserID | None
workspace_id: WorkspaceID | None

Expand Down
1 change: 1 addition & 0 deletions packages/models-library/src/models_library/projects.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ class Project(BaseProjectModel):
default=None,
alias="trashedAt",
)
trashed_explicitly: bool = Field(default=False, alias="trashedExplicitly")

class Config:
description = "Document that stores metadata, pipeline and UI setup of a study"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
"""project and folder trash columns

Revision ID: 5ad02358751a
Revises: fce5d231e16d
Create Date: 2024-11-07 17:14:01.094583+00:00

"""
import sqlalchemy as sa
from alembic import op
from sqlalchemy.dialects import postgresql

# revision identifiers, used by Alembic.
revision = "5ad02358751a"
down_revision = "fce5d231e16d"
branch_labels = None
depends_on = None


def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column(
"folders_v2",
sa.Column(
"trashed_at",
sa.DateTime(timezone=True),
nullable=True,
comment="The date and time when the folder was marked as trashed.Null if the folder has not been trashed [default].",
),
)
op.add_column(
"folders_v2",
sa.Column(
"trashed_explicitly",
sa.Boolean(),
server_default=sa.text("false"),
nullable=False,
comment="Indicates whether the folder was explicitly trashed by the user (true) or inherited its trashed status from a parent (false) [default].",
),
)
op.add_column(
"projects",
sa.Column(
"trashed_explicitly",
sa.Boolean(),
server_default=sa.text("false"),
nullable=False,
comment="Indicates whether the project was explicitly trashed by the user (true) or inherited its trashed status from a parent (false) [default].",
),
)
op.alter_column(
"projects",
"trashed_at",
existing_type=postgresql.TIMESTAMP(timezone=True),
comment="The date and time when the project was marked as trashed. Null if the project has not been trashed [default].",
existing_nullable=True,
)
# ### end Alembic commands ###


def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.alter_column(
"projects",
"trashed_at",
existing_type=postgresql.TIMESTAMP(timezone=True),
comment=None,
existing_comment="The date and time when the project was marked as trashed. Null if the project has not been trashed [default].",
existing_nullable=True,
)
op.drop_column("projects", "trashed_explicitly")
op.drop_column("folders_v2", "trashed_explicitly")
op.drop_column("folders_v2", "trashed_at")
# ### end Alembic commands ###
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import sqlalchemy as sa
from sqlalchemy.sql import expression

from ._common import column_created_datetime, column_modified_datetime
from .base import metadata
Expand Down Expand Up @@ -74,4 +75,19 @@
),
column_created_datetime(timezone=True),
column_modified_datetime(timezone=True),
sa.Column(
"trashed_at",
sa.DateTime(timezone=True),
nullable=True,
comment="The date and time when the folder was marked as trashed."
"Null if the folder has not been trashed [default].",
),
sa.Column(
"trashed_explicitly",
sa.Boolean,
nullable=False,
server_default=expression.false(),
comment="Indicates whether the folder was explicitly trashed by the user (true)"
" or inherited its trashed status from a parent (false) [default].",
),
)
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import sqlalchemy as sa
from sqlalchemy.dialects.postgresql import ARRAY, JSONB
from sqlalchemy.sql import func
from sqlalchemy.sql import expression, func

from .base import metadata

Expand Down Expand Up @@ -145,7 +145,16 @@ class ProjectType(enum.Enum):
"trashed_at",
sa.DateTime(timezone=True),
nullable=True,
doc="Timestamp indicating when the project was marked as trashed, or null otherwise.",
comment="The date and time when the project was marked as trashed. "
"Null if the project has not been trashed [default].",
),
sa.Column(
"trashed_explicitly",
sa.Boolean,
nullable=False,
server_default=expression.false(),
comment="Indicates whether the project was explicitly trashed by the user (true)"
" or inherited its trashed status from a parent (false) [default].",
pcrespov marked this conversation as resolved.
Show resolved Hide resolved
),
sa.Column(
"workspace_id",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -186,5 +186,5 @@ async def assert_get_same_project(
data, error = await assert_status(resp, expected)

if not error:
assert data == project
assert data == {k: project[k] for k in data}
return data
2 changes: 1 addition & 1 deletion services/web/server/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.44.0
0.45.0
2 changes: 1 addition & 1 deletion services/web/server/setup.cfg
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[bumpversion]
current_version = 0.44.0
current_version = 0.45.0
commit = True
message = services/webserver api version: {current_version} → {new_version}
tag = False
Expand Down
Loading
Loading