Skip to content

Commit b03711f

Browse files
committed
mv preview to nodes_api
1 parent 2b67314 commit b03711f

File tree

3 files changed

+123
-121
lines changed

3 files changed

+123
-121
lines changed

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

Lines changed: 122 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,31 @@
11
import datetime
2+
import logging
3+
import mimetypes
4+
import urllib.parse
25
from typing import Final
36

47
from aiohttp import web
58
from models_library.projects import ProjectID
9+
from models_library.projects_nodes import Node, NodeID
10+
from models_library.projects_nodes_io import SimCoreFileLink
611
from models_library.users import UserID
7-
from pydantic import NonNegativeFloat, NonNegativeInt
12+
from pydantic import (
13+
BaseModel,
14+
Field,
15+
HttpUrl,
16+
NonNegativeFloat,
17+
NonNegativeInt,
18+
ValidationError,
19+
parse_obj_as,
20+
root_validator,
21+
)
822

23+
from .._constants import APP_SETTINGS_KEY, RQT_USERID_KEY
924
from ..application_settings import get_settings
25+
from ..storage.api import get_download_link
1026
from .exceptions import ProjectStartsTooManyDynamicNodes
1127

28+
_logger = logging.getLogger(__name__)
1229
_NODE_START_INTERVAL_S: Final[datetime.timedelta] = datetime.timedelta(seconds=15)
1330

1431

@@ -43,3 +60,107 @@ def get_total_project_dynamic_nodes_creation_interval(
4360
director-v2. Note: these calls are sent one after the other.
4461
"""
4562
return max_nodes * _NODE_START_INTERVAL_S.total_seconds()
63+
64+
65+
#
66+
# PREVIEWS
67+
#
68+
69+
70+
class NodeScreenshot(BaseModel):
71+
thumbnail_url: HttpUrl
72+
file_url: HttpUrl
73+
mimetype: str | None = Field(
74+
default=None,
75+
description="File's media type or None if unknown. SEE https://www.iana.org/assignments/media-types/media-types.xhtml",
76+
example="image/jpeg",
77+
)
78+
79+
@root_validator(pre=True)
80+
@classmethod
81+
def guess_mimetype_if_undefined(cls, values):
82+
mimetype = values.get("mimetype")
83+
84+
if mimetype is None:
85+
file_url = values["file_url"]
86+
assert file_url # nosec
87+
88+
_type, _encoding = mimetypes.guess_type(file_url)
89+
# NOTE: mimetypes.guess_type works differently in our image, therefore made it nullable if
90+
# cannot guess type
91+
# SEE https://github.com/ITISFoundation/osparc-simcore/issues/4385
92+
values["mimetype"] = _type
93+
94+
return values
95+
96+
97+
async def fake_screenshots_factory(
98+
request: web.Request, node_id: NodeID, node: Node
99+
) -> list[NodeScreenshot]:
100+
"""
101+
ONLY for testing purposes
102+
103+
"""
104+
assert request.app[APP_SETTINGS_KEY].WEBSERVER_DEV_FEATURES_ENABLED # nosec
105+
screenshots = []
106+
107+
if (
108+
"file-picker" in node.key
109+
and "fake" in node.label.lower()
110+
and node.outputs is not None
111+
):
112+
# Example of file that can be added in file-picker:
113+
# Example https://github.com/Ybalrid/Ogre_glTF/raw/6a59adf2f04253a3afb9459549803ab297932e8d/Media/Monster.glb
114+
try:
115+
user_id = request[RQT_USERID_KEY]
116+
text = urllib.parse.quote(node.label)
117+
118+
assert node.outputs is not None # nosec
119+
120+
filelink = parse_obj_as(SimCoreFileLink, node.outputs["outFile"])
121+
122+
file_url = await get_download_link(request.app, user_id, filelink)
123+
screenshots.append(
124+
NodeScreenshot(
125+
thumbnail_url=f"https://placehold.co/170x120?text={text}",
126+
file_url=file_url,
127+
)
128+
)
129+
except (KeyError, ValidationError) as err:
130+
_logger.debug(
131+
"Failed to create link from file-picker %s: %s",
132+
node.json(indent=1),
133+
err,
134+
)
135+
136+
elif node.key.startswith("simcore/services/dynamic"):
137+
# For dynamic services, just create fake images
138+
139+
# References:
140+
# - https://github.com/Ybalrid/Ogre_glTF
141+
# - https://placehold.co/
142+
# - https://picsum.photos/
143+
#
144+
count = int(str(node_id.int)[0])
145+
text = urllib.parse.quote(node.label)
146+
147+
screenshots = [
148+
*(
149+
NodeScreenshot(
150+
thumbnail_url=f"https://picsum.photos/seed/{node_id.int + n}/170/120",
151+
file_url=f"https://picsum.photos/seed/{node_id.int + n}/500",
152+
mimetype="image/jpeg",
153+
)
154+
for n in range(count)
155+
),
156+
*(
157+
NodeScreenshot(
158+
thumbnail_url=f"https://placehold.co/170x120?text={text}",
159+
file_url=f"https://placehold.co/500x500?text={text}",
160+
mimetype="image/svg+xml",
161+
)
162+
for n in range(count)
163+
),
164+
]
165+
166+
return screenshots

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
from ..utils_aiohttp import envelope_json_response
4848
from . import projects_api
4949
from ._handlers_crud import ProjectPathParams, RequestContext
50-
from ._nodes_previews_api import NodeScreenshot, fake_screenshots_factory
50+
from ._nodes_api import NodeScreenshot, fake_screenshots_factory
5151
from .db import ProjectDBAPI
5252
from .exceptions import (
5353
NodeNotFoundError,

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

Lines changed: 0 additions & 119 deletions
This file was deleted.

0 commit comments

Comments
 (0)