Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
125 changes: 119 additions & 6 deletions app/backend/api/routers/project_router.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
ProjectImportIn, ProtocolWizardExecuteResponse,
ProtocolWizardExecuteRequest)
from app.backend.api.services.project_service import ProjectService
from app.backend.models.project_model import ExternalViewerLaunchRequest
from app.backend.models.protocol_model import (
ProtocolRequest,
ProtocolRenameIn,
Expand Down Expand Up @@ -515,16 +516,36 @@ def renameProtocol(
)

try:
newName = getattr(payload, "name", None)
if not newName or not str(newName).strip():
newName = getattr(payload, "runName", None)
newComment = getattr(payload, "comment", "")

if newName is None:
return JSONResponse(
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
content={"status": 1,
"errors": ["Missing name"],
"workflow": []},
content={
"status": 1,
"errors": ["Missing name"],
"workflow": [],
},
)

service.renameProtocol(protocolId, str(newName).strip())
newNameText = str(newName)

if newNameText != "" and not newNameText.strip():
return JSONResponse(
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
content={
"status": 1,
"errors": ["Missing name"],
"workflow": [],
},
)

service.renameProtocol(
protocolId,
newNameText.strip(),
str(newComment or "").strip(),
)
service.syncProjectGraphAfterMutation(
mapper,
projectId,
Expand Down Expand Up @@ -2628,6 +2649,98 @@ def getMetadataTableWindow(
resp.headers["Vary"] = "Authorization"
return resp

# ======================================================================
# ANALYZE RESULTS: EXTERNAL VIEWERS
# ======================================================================

@router.get(
"/{projectId}/protocols/{protocolId}/outputs/{outputName}/external-viewers",
response_model=Any,
status_code=status.HTTP_200_OK,
)
def listExternalViewers(
projectId: int,
protocolId: int,
outputName: str,
objectId: Optional[str] = Query(None),
objectKind: Optional[str] = Query(None),
currentUser=Depends(getCurrentUser),
mapper: PostgresqlFlatMapper = Depends(getMapper),
service: ProjectService = Depends(getProjectService),
):
project = service.getProjectById(
mapper,
projectId,
currentUser,
refresh=False,
checkPid=False,
)
if not project:
raise HTTPException(status_code=404, detail="Project not found")

try:
viewers = service.listExternalViewers(
protocolId=protocolId,
outputName=outputName,
objectId=objectId,
objectKind=objectKind,
)
return {"viewers": viewers}
except HTTPException:
raise
except Exception as e:
logger.exception("Error in listExternalViewers: %s", e)
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"Failed to list external viewers: {e}",
)


@router.post(
"/{projectId}/protocols/{protocolId}/outputs/{outputName}/external-viewers/{viewerId}/launch",
response_model=Any,
status_code=status.HTTP_200_OK,
)
def launchExternalViewer(
projectId: int,
protocolId: int,
outputName: str,
viewerId: str,
payload: Optional[ExternalViewerLaunchRequest] = Body(default=None),
currentUser=Depends(getCurrentUser),
mapper: PostgresqlFlatMapper = Depends(getMapper),
service: ProjectService = Depends(getProjectService),
):
project = service.getProjectById(
mapper,
projectId,
currentUser,
refresh=False,
checkPid=False,
)
if not project:
raise HTTPException(status_code=404, detail="Project not found")

payload = payload or ExternalViewerLaunchRequest()

try:
return service.launchExternalViewer(
protocolId=protocolId,
outputName=outputName,
viewerId=viewerId,
objectId=payload.objectId,
objectKind=payload.objectKind,
params=payload.params or {},
)
except HTTPException:
raise
except Exception as e:
logger.exception("Error in launchExternalViewer: %s", e)
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"Failed to launch external viewer: {e}",
)

# ======================================================================
# PROTOCOL TAGS
# ======================================================================
Expand Down
10 changes: 10 additions & 0 deletions app/backend/api/services/plugin_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

from app.backend.api.services.plugin_task_log import appendPluginTaskLog, writePluginTaskStep
from app.utils.scipion_helper import serializeToJson
from app.backend.resources import getPluginCategoryIds, getPluginCategoryData

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -77,6 +78,15 @@ def getPlugins(self, forceRefresh: bool = False) -> List[Dict[str, Any]]:

serializedPlugin = serializeToJson(pluginObj)
serializedPlugin["fullLogo"] = self._buildFullLogo(serializedPlugin)
pipName = str(serializedPlugin.get("pipName") or pluginKey).strip()
categories = getPluginCategoryIds(pipName)
serializedPlugin["categories"] = categories
serializedPlugin["categoryData"] = getPluginCategoryData(pipName)

# if 'tomography' not in categories:
# continue
# serializedPlugin["categories"] = ['tomography']
# serializedPlugin["categoryData"] = [{'description': 'Tomograms, tilt series and subtomogram workflows', 'id': 'tomography', 'title': 'Tomography'}]

isInstalled = False
try:
Expand Down
Loading
Loading