From 40239cb35b536e03e8344bf53ef2b6906e185956 Mon Sep 17 00:00:00 2001 From: Mantvydas Deltuva Date: Wed, 11 Sep 2024 23:31:13 +0300 Subject: [PATCH 1/7] MDE/PKFE-30 implemented http requests for toolbar buttons --- .../toolbarGroupButtons/applyGroupButtons.tsx | 40 ++++++------- .../downloadGroupButtons.tsx | 57 ++++++++++--------- .../toolbarGroupButtons/mergeGroupButtons.tsx | 46 +++++++-------- .../src/features/editor/utils/helpers.tsx | 17 ++++++ .../src/features/editor/utils/index.ts | 2 +- .../src/types/constants/endpoints.ts | 9 +++ 6 files changed, 100 insertions(+), 71 deletions(-) diff --git a/app/front-end/src/features/editor/components/toolbarView/toolbarGroupButtons/applyGroupButtons.tsx b/app/front-end/src/features/editor/components/toolbarView/toolbarGroupButtons/applyGroupButtons.tsx index c099c10..4f6229d 100644 --- a/app/front-end/src/features/editor/components/toolbarView/toolbarGroupButtons/applyGroupButtons.tsx +++ b/app/front-end/src/features/editor/components/toolbarView/toolbarGroupButtons/applyGroupButtons.tsx @@ -1,6 +1,9 @@ import { ToolbarGroupItem, ToolbarGroupItemProps } from '@/features/editor/components/toolbarView'; -import { useToolbarContext } from '@/features/editor/hooks'; +import { useToolbarContext, useWorkspaceContext } from '@/features/editor/hooks'; +import { findUniqueFileName, generateTimestamp } from '@/features/editor/utils'; import { useStatusContext } from '@/hooks'; +import { axios } from '@/lib'; +import { Endpoints } from '@/types'; import { Deblur as DeblurIcon } from '@mui/icons-material'; import { useCallback, useMemo } from 'react'; @@ -8,6 +11,7 @@ export interface ApplyGroupButtonsProps {} export const ApplyGroupButtons: React.FC = () => { const { blockedStateUpdate } = useStatusContext(); + const { fileTree } = useWorkspaceContext(); const { saveTo, override, applyTo, applyErrorStateUpdate } = useToolbarContext(); const applySpliceAiClick = useCallback(async () => { @@ -19,16 +23,15 @@ export const ApplyGroupButtons: React.FC = () => { blockedStateUpdate(true); try { - console.log( - 'Clicked Apply SpliceAI Button! Params:\n saveTo:', - saveTo, - '\n override:', - override, - '\n applyTo:', - applyTo - ); + const timestamp = generateTimestamp(); + const savePath = saveTo !== '/' ? saveTo : findUniqueFileName(fileTree, `spliceai_${timestamp}.csv`); - await new Promise((resolve) => setTimeout(resolve, 1000)); // TODO: remove this line + await axios.get(`${Endpoints.WORKSPACE_APPLY}/spliceai/${savePath}`, { + params: { + override, + applyTo, + }, + }); } catch (error) { console.error('Error applying SpliceAI:', error); } finally { @@ -45,16 +48,15 @@ export const ApplyGroupButtons: React.FC = () => { blockedStateUpdate(true); try { - console.log( - 'Clicked Merge LOVD & ClinVar Button! Params:\n saveTo:', - saveTo, - '\n override:', - override, - '\n applyTo:', - applyTo - ); + const timestamp = generateTimestamp(); + const savePath = saveTo !== '/' ? saveTo : findUniqueFileName(fileTree, `cadd_${timestamp}.csv`); - await new Promise((resolve) => setTimeout(resolve, 1000)); // TODO: remove this line + await axios.get(`${Endpoints.WORKSPACE_APPLY}/cadd/${savePath}`, { + params: { + override, + applyTo, + }, + }); } catch (error) { console.error('Error applying CADD:', error); } finally { diff --git a/app/front-end/src/features/editor/components/toolbarView/toolbarGroupButtons/downloadGroupButtons.tsx b/app/front-end/src/features/editor/components/toolbarView/toolbarGroupButtons/downloadGroupButtons.tsx index 39a4133..0a420f9 100644 --- a/app/front-end/src/features/editor/components/toolbarView/toolbarGroupButtons/downloadGroupButtons.tsx +++ b/app/front-end/src/features/editor/components/toolbarView/toolbarGroupButtons/downloadGroupButtons.tsx @@ -1,6 +1,9 @@ import { ToolbarGroupItem, ToolbarGroupItemProps } from '@/features/editor/components/toolbarView'; -import { useToolbarContext } from '@/features/editor/hooks'; +import { useToolbarContext, useWorkspaceContext } from '@/features/editor/hooks'; +import { findUniqueFileName, generateTimestamp } from '@/features/editor/utils'; import { useStatusContext } from '@/hooks'; +import { axios } from '@/lib'; +import { Endpoints } from '@/types'; import { Download as DownloadIcon } from '@mui/icons-material'; import { useCallback, useMemo } from 'react'; @@ -8,22 +11,22 @@ export interface DownloadGroupButtonsProps {} export const DownloadGroupButtons: React.FC = () => { const { blockedStateUpdate } = useStatusContext(); + const { fileTree } = useWorkspaceContext(); const { saveTo, override, gene } = useToolbarContext(); const handleDownloadLovdClick = useCallback(async () => { blockedStateUpdate(true); try { - console.log( - 'Clicked Download Lovd Button! Params:\n saveTo:', - saveTo, - '\n override:', - override, - '\n gene:', - gene - ); + const timestamp = generateTimestamp(); + const savePath = saveTo !== '/' ? saveTo : findUniqueFileName(fileTree, `lovd_${timestamp}.csv`); - await new Promise((resolve) => setTimeout(resolve, 1000)); // TODO: remove this line + await axios.get(`${Endpoints.WORKSPACE_DOWNLOAD}/lovd/${savePath}`, { + params: { + override, + gene, + }, + }); } catch (error) { console.error('Error downloading LOVD file:', error); } finally { @@ -35,16 +38,15 @@ export const DownloadGroupButtons: React.FC = () => { blockedStateUpdate(true); try { - console.log( - 'Clicked Download Clinvar Button! Params:\n saveTo:', - saveTo, - '\n override:', - override, - '\n gene:', - gene - ); + const timestamp = generateTimestamp(); + const savePath = saveTo !== '/' ? saveTo : findUniqueFileName(fileTree, `clinvar_${timestamp}.csv`); - await new Promise((resolve) => setTimeout(resolve, 1000)); // TODO: remove this line + await axios.get(`${Endpoints.WORKSPACE_DOWNLOAD}/clinvar/${savePath}`, { + params: { + override, + gene, + }, + }); } catch (error) { console.error('Error downloading ClinVar file:', error); } finally { @@ -56,16 +58,15 @@ export const DownloadGroupButtons: React.FC = () => { blockedStateUpdate(true); try { - console.log( - 'Clicked Download Gnomad Button! Params:\n saveTo:', - saveTo, - '\n override:', - override, - '\n gene:', - gene - ); + const timestamp = generateTimestamp(); + const savePath = saveTo !== '/' ? saveTo : findUniqueFileName(fileTree, `gnomad_${timestamp}.csv`); - await new Promise((resolve) => setTimeout(resolve, 1000)); // TODO: remove this line + await axios.get(`${Endpoints.WORKSPACE_DOWNLOAD}/gnomad/${savePath}`, { + params: { + override, + gene, + }, + }); } catch (error) { console.error('Error downloading gnomAD file:', error); } finally { diff --git a/app/front-end/src/features/editor/components/toolbarView/toolbarGroupButtons/mergeGroupButtons.tsx b/app/front-end/src/features/editor/components/toolbarView/toolbarGroupButtons/mergeGroupButtons.tsx index f7f585f..784314e 100644 --- a/app/front-end/src/features/editor/components/toolbarView/toolbarGroupButtons/mergeGroupButtons.tsx +++ b/app/front-end/src/features/editor/components/toolbarView/toolbarGroupButtons/mergeGroupButtons.tsx @@ -1,6 +1,9 @@ import { ToolbarGroupItem, ToolbarGroupItemProps } from '@/features/editor/components/toolbarView'; -import { useToolbarContext } from '@/features/editor/hooks'; +import { useToolbarContext, useWorkspaceContext } from '@/features/editor/hooks'; +import { findUniqueFileName, generateTimestamp } from '@/features/editor/utils'; import { useStatusContext } from '@/hooks'; +import { axios } from '@/lib'; +import { Endpoints } from '@/types'; import { MergeType as MergeTypeIcon } from '@mui/icons-material'; import { useCallback, useMemo } from 'react'; @@ -8,6 +11,7 @@ export interface MergeGroupButtonsProps {} export const MergeGroupButtons: React.FC = () => { const { blockedStateUpdate } = useStatusContext(); + const { fileTree } = useWorkspaceContext(); const { saveTo, override, @@ -29,18 +33,16 @@ export const MergeGroupButtons: React.FC = () => { blockedStateUpdate(true); try { - console.log( - 'Clicked Merge LOVD & gnomAD Button! Params:\n saveTo:', - saveTo, - '\n override:', - override, - '\n lovd:', - lovdFile, - '\n gnomad:', - gnomadFile - ); + const timestamp = generateTimestamp(); + const savePath = saveTo !== '/' ? saveTo : findUniqueFileName(fileTree, `lovd_gnomad_${timestamp}.csv`); - await new Promise((resolve) => setTimeout(resolve, 1000)); // TODO: remove this line + await axios.get(`${Endpoints.WORKSPACE_MERGE}/lovd_gnomad/${savePath}`, { + params: { + override, + lovdFile, + gnomadFile, + }, + }); } catch (error) { console.error('Error merging LOVD & gnomAD files:', error); } finally { @@ -58,18 +60,16 @@ export const MergeGroupButtons: React.FC = () => { blockedStateUpdate(true); try { - console.log( - 'Clicked Merge LOVD & ClinVar Button! Params:\n saveTo:', - saveTo, - '\n override:', - override, - '\n lovd:', - lovdFile, - '\n clinvar:', - clinvarFile - ); + const timestamp = generateTimestamp(); + const savePath = saveTo !== '/' ? saveTo : findUniqueFileName(fileTree, `lovd_clinvar_${timestamp}.csv`); - await new Promise((resolve) => setTimeout(resolve, 1000)); // TODO: remove this line + await axios.get(`${Endpoints.WORKSPACE_MERGE}/lovd_clinvar/${savePath}`, { + params: { + override, + lovdFile, + clinvarFile, + }, + }); } catch (error) { console.error('Error merging LOVD & ClinVar files:', error); } finally { diff --git a/app/front-end/src/features/editor/utils/helpers.tsx b/app/front-end/src/features/editor/utils/helpers.tsx index c0263bb..e988e6e 100644 --- a/app/front-end/src/features/editor/utils/helpers.tsx +++ b/app/front-end/src/features/editor/utils/helpers.tsx @@ -90,3 +90,20 @@ export const getWorkspaceArray = (fileTreeView: TreeViewBaseItem { + const now = new Date(); + return ( + now.getFullYear() + + '-' + + String(now.getMonth() + 1).padStart(2, '0') + // Months are zero-indexed + '-' + + String(now.getDate()).padStart(2, '0') + + '_' + + String(now.getHours()).padStart(2, '0') + + ':' + + String(now.getMinutes()).padStart(2, '0') + + ':' + + String(now.getSeconds()).padStart(2, '0') + ); +}; diff --git a/app/front-end/src/features/editor/utils/index.ts b/app/front-end/src/features/editor/utils/index.ts index acd3fe7..e8b1ca1 100644 --- a/app/front-end/src/features/editor/utils/index.ts +++ b/app/front-end/src/features/editor/utils/index.ts @@ -1 +1 @@ -export { doesFileExist, findUniqueFileName, getFileExtension, getIconFromFileType, isExpandable, getWorkspaceArray } from './helpers'; +export { doesFileExist, findUniqueFileName, getFileExtension, getIconFromFileType, isExpandable, getWorkspaceArray, generateTimestamp } from './helpers'; diff --git a/app/front-end/src/types/constants/endpoints.ts b/app/front-end/src/types/constants/endpoints.ts index 689abad..8c3ce82 100644 --- a/app/front-end/src/types/constants/endpoints.ts +++ b/app/front-end/src/types/constants/endpoints.ts @@ -20,6 +20,12 @@ * @property {string} WORKSPACE_CREATE - The endpoint path for creating new items in the workspace. * @property {string} WORKSPACE_RENAME - The endpoint path for renaming items in the workspace. * @property {string} WORKSPACE_DELETE - The endpoint path for deleting items in the workspace. + * @property {string} WORKSPACE_AGGREGATE - The endpoint path for aggregating workspace items. + * @property {string} WORKSPACE_IMPORT - The endpoint path for importing workspace items. + * @property {string} WORKSPACE_EXPORT - The endpoint path for exporting workspace items. + * @property {string} WORKSPACE_DOWNLOAD - The endpoint path for downloading workspace items. + * @property {string} WORKSPACE_MERGE - The endpoint path for merging workspace items. + * @property {string} WORKSPACE_APPLY - The endpoint path for applying workspace items. * * @example * // Example usage of the Endpoints object @@ -40,4 +46,7 @@ export const Endpoints = { WORKSPACE_AGGREGATE: `/workspace/aggregate`, WORKSPACE_IMPORT: `/workspace/import`, WORKSPACE_EXPORT: `/workspace/export`, + WORKSPACE_DOWNLOAD: `/workspace/download`, + WORKSPACE_MERGE: `/workspace/merge`, + WORKSPACE_APPLY: `/workspace/apply`, }; From a7c767ffd051bcb8c2036e7ccdd91dd1357bbe1c Mon Sep 17 00:00:00 2001 From: Mantvydas Deltuva Date: Wed, 11 Sep 2024 23:32:21 +0300 Subject: [PATCH 2/7] MDE/PKFE-30 implemented download route --- app/back-end/src/constants.py | 3 + .../src/routes/workspace_download_route.py | 369 ++++++++++++++++++ 2 files changed, 372 insertions(+) create mode 100644 app/back-end/src/routes/workspace_download_route.py diff --git a/app/back-end/src/constants.py b/app/back-end/src/constants.py index 20bf7f8..955b4cd 100644 --- a/app/back-end/src/constants.py +++ b/app/back-end/src/constants.py @@ -35,6 +35,9 @@ WORKSPACE_AGGREGATE_ROUTE = "/workspace/aggregate" WORKSPACE_IMPORT_ROUTE = "/workspace/import" WORKSPACE_EXPORT_ROUTE = "/workspace/export" +WORKSPACE_DOWNLOAD_ROUTE = "/workspace/download" +WORKSPACE_MERGE_ROUTE = "/workspace/merge" +WORKSPACE_APPLY_ROUTE = "/workspace/apply" # Events CONSOLE_FEEDBACK_EVENT = "console_feedback" diff --git a/app/back-end/src/routes/workspace_download_route.py b/app/back-end/src/routes/workspace_download_route.py new file mode 100644 index 0000000..8541b58 --- /dev/null +++ b/app/back-end/src/routes/workspace_download_route.py @@ -0,0 +1,369 @@ +""" +Workspace download route module. +This module defines routes for downloading data from external sources +and saving it to the user's workspace. +""" + +# pylint: disable=import-error + +import os +import time # TODO: Remove this import once the download logic is implemented +from flask import Blueprint, request, jsonify + +from src.setup.extensions import logger +from src.utils.helpers import socketio_emit_to_user_session +from src.utils.exceptions import UnexpectedError +from src.constants import ( + WORKSPACE_DOWNLOAD_ROUTE, + WORKSPACE_DIR, + CONSOLE_FEEDBACK_EVENT, + WORKSPACE_UPDATE_FEEDBACK_EVENT, +) + +workspace_download_route_bp = Blueprint("workspace_download_route", __name__) + + +@workspace_download_route_bp.route( + f"{WORKSPACE_DOWNLOAD_ROUTE}/lovd/", methods=["GET"] +) +def get_workspace_download_lovd(relative_path): + """ + Download LOVD data for a specific gene and save it to the user's workspace. + """ + + # Check if 'uuid' and 'sid' are provided in the headers + if "uuid" not in request.headers or "sid" not in request.headers: + return jsonify({"error": "UUID and SID headers are required"}), 400 + + uuid = request.headers.get("uuid") + sid = request.headers.get("sid") + + # Check if 'override' and 'gene' are provided + if "override" not in request.args or "gene" not in request.args: + return jsonify({"error": "'override' and 'gene' parameters are required"}), 400 + + # Explanation about the parameters: + # - destination_path: string + # - The path to the destination file (where to save it) in the user's workspace + # Destination file can either be a new file or an existing file, check its existence + # - override: boolean + # - If true, the existing destination file should be overridden + # - If false, the existing destination file should not be overridden and download + # content should be appended + # - gene: string + # - Determines the gene to be downloaded from LOVD (e.g. 'eys') + + destination_path = os.path.join(WORKSPACE_DIR, uuid, relative_path) + override = request.args.get("override") + gene = request.args.get("gene") + + try: + # Emit a feedback to the user's console + socketio_emit_to_user_session( + CONSOLE_FEEDBACK_EVENT, + { + "type": "info", + "message": f"Downloading LOVD data for gene '{gene}' to '{relative_path}' with " + + f"override: `{override}'...", + }, + uuid, + sid, + ) + + # + # TODO: Implement LOVD data download and save logic using defined parameters + # [destination_path, override, gene] + # + + # TODO: Remove this sleep statement once the download logic is implemented + time.sleep(1) # Simulate a delay for the download process + + # Emit a feedback to the user's console + socketio_emit_to_user_session( + CONSOLE_FEEDBACK_EVENT, + {"type": "succ", "message": f"LOVD file '{relative_path}' was saved successfully."}, + uuid, + sid, + ) + + socketio_emit_to_user_session( + WORKSPACE_UPDATE_FEEDBACK_EVENT, + {"status": "updated"}, + uuid, + sid, + ) + + except FileNotFoundError as e: + logger.error("FileNotFoundError: %s while downloading LOVD %s", e, destination_path) + # Emit a feedback to the user's console + socketio_emit_to_user_session( + CONSOLE_FEEDBACK_EVENT, + { + "type": "errr", + "message": f"FileNotFoundError: {e} while downloading LOVD {destination_path}", + }, + uuid, + sid, + ) + return jsonify({"error": "Requested file not found"}), 404 + except PermissionError as e: + logger.error("PermissionError: %s while downloading LOVD %s", e, destination_path) + # Emit a feedback to the user's console + socketio_emit_to_user_session( + CONSOLE_FEEDBACK_EVENT, + { + "type": "errr", + "message": f"PermissionError: {e} while downloading LOVD {destination_path}", + }, + uuid, + sid, + ) + return jsonify({"error": "Permission denied"}), 403 + except UnexpectedError as e: + logger.error("UnexpectedError: %s while downloading LOVD %s", e.message, destination_path) + # Emit a feedback to the user's console + socketio_emit_to_user_session( + CONSOLE_FEEDBACK_EVENT, + { + "type": "errr", + "message": f"UnexpectedError: {e.message} while downloading LOVD " + + f"{destination_path}", + }, + uuid, + sid, + ) + return jsonify({"error": "An internal error occurred"}), 500 + + return jsonify({"message": "LOVD data downloaded successful"}), 200 + + +@workspace_download_route_bp.route( + f"{WORKSPACE_DOWNLOAD_ROUTE}/clinvar/", methods=["GET"] +) +def get_workspace_download_clinvar(relative_path): + """ + Download ClinVar data for a specific gene and save it to the user's workspace. + """ + + # Check if 'uuid' and 'sid' are provided in the headers + if "uuid" not in request.headers or "sid" not in request.headers: + return jsonify({"error": "UUID and SID headers are required"}), 400 + + uuid = request.headers.get("uuid") + sid = request.headers.get("sid") + + # Check if 'override' and 'gene' are provided + if "override" not in request.args or "gene" not in request.args: + return jsonify({"error": "'override' and 'gene' parameters are required"}), 400 + + # Explanation about the parameters: + # - destination_path: string + # - The path to the destination file (where to save it) in the user's workspace + # Destination file can either be a new file or an existing file, check its existence + # - override: boolean + # - If true, the existing destination file should be overridden + # - If false, the existing destination file should not be overridden and download + # content should be appended + # - gene: string + # - Determines the gene to be downloaded from LOVD (e.g. 'eys') + + destination_path = os.path.join(WORKSPACE_DIR, uuid, relative_path) + override = request.args.get("override") + gene = request.args.get( + "gene", + ) + + try: + # Emit a feedback to the user's console + socketio_emit_to_user_session( + CONSOLE_FEEDBACK_EVENT, + { + "type": "info", + "message": f"Downloading ClinVar data for gene '{gene}' to '{relative_path}' with " + + f"override: `{override}'...", + }, + uuid, + sid, + ) + + # + # TODO: Implement ClinVar data download and save logic using defined parameters + # [destination_path, override, gene] + # + + # TODO: Remove this sleep statement once the download logic is implemented + time.sleep(1) # Simulate a delay for the download process + + # Emit a feedback to the user's console + socketio_emit_to_user_session( + CONSOLE_FEEDBACK_EVENT, + {"type": "succ", "message": f"ClinVar file '{relative_path}' was saved successfully."}, + uuid, + sid, + ) + + socketio_emit_to_user_session( + WORKSPACE_UPDATE_FEEDBACK_EVENT, + {"status": "updated"}, + uuid, + sid, + ) + + except FileNotFoundError as e: + logger.error("FileNotFoundError: %s while downloading ClinVar %s", e, destination_path) + # Emit a feedback to the user's console + socketio_emit_to_user_session( + CONSOLE_FEEDBACK_EVENT, + { + "type": "errr", + "message": f"FileNotFoundError: {e} while downloading ClinVar {destination_path}", + }, + uuid, + sid, + ) + return jsonify({"error": "Requested file not found"}), 404 + except PermissionError as e: + logger.error("PermissionError: %s while downloading ClinVar %s", e, destination_path) + # Emit a feedback to the user's console + socketio_emit_to_user_session( + CONSOLE_FEEDBACK_EVENT, + { + "type": "errr", + "message": f"PermissionError: {e} while downloading ClinVar {destination_path}", + }, + uuid, + sid, + ) + return jsonify({"error": "Permission denied"}), 403 + except UnexpectedError as e: + logger.error( + "UnexpectedError: %s while downloading ClinVar %s", e.message, destination_path + ) + # Emit a feedback to the user's console + socketio_emit_to_user_session( + CONSOLE_FEEDBACK_EVENT, + { + "type": "errr", + "message": f"UnexpectedError: {e.message} while downloading ClinVar " + + f"{destination_path}", + }, + uuid, + sid, + ) + return jsonify({"error": "An internal error occurred"}), 500 + + return jsonify({"message": "CliVar data downloaded successful"}), 200 + + +@workspace_download_route_bp.route( + f"{WORKSPACE_DOWNLOAD_ROUTE}/gnomad/", methods=["GET"] +) +def get_workspace_download_gnomad(relative_path): + """ + Download gnomAD data for a specific gene and save it to the user's workspace. + """ + + # Check if 'uuid' and 'sid' are provided in the headers + if "uuid" not in request.headers or "sid" not in request.headers: + return jsonify({"error": "UUID and SID headers are required"}), 400 + + uuid = request.headers.get("uuid") + sid = request.headers.get("sid") + + # Check if 'override' and 'gene' are provided + if "override" not in request.args or "gene" not in request.args: + return jsonify({"error": "'override' and 'gene' parameters are required"}), 400 + + # Explanation about the parameters: + # - destination_path: string + # - The path to the destination file (where to save it) in the user's workspace + # Destination file can either be a new file or an existing file, check its existence + # - override: boolean + # - If true, the existing destination file should be overridden + # - If false, the existing destination file should not be overridden and download + # content should be appended + # - gene: string + # - Determines the gene to be downloaded from LOVD (e.g. 'eys') + + destination_path = os.path.join(WORKSPACE_DIR, uuid, relative_path) + override = request.args.get("override") + gene = request.args.get("gene") + + try: + # Emit a feedback to the user's console + socketio_emit_to_user_session( + CONSOLE_FEEDBACK_EVENT, + { + "type": "info", + "message": f"Downloading gnomAD data for gene '{gene}' to '{relative_path}' with " + + f"override: `{override}'...", + }, + uuid, + sid, + ) + + # + # TODO: Implement gnomAD data download and save logic using defined parameters + # [destination_path, override, gene] + # + + # TODO: Remove this sleep statement once the download logic is implemented + time.sleep(1) # Simulate a delay for the download process + + # Emit a feedback to the user's console + socketio_emit_to_user_session( + CONSOLE_FEEDBACK_EVENT, + {"type": "succ", "message": f"gnomAD file '{relative_path}' was saved successfully."}, + uuid, + sid, + ) + + socketio_emit_to_user_session( + WORKSPACE_UPDATE_FEEDBACK_EVENT, + {"status": "updated"}, + uuid, + sid, + ) + + except FileNotFoundError as e: + logger.error("FileNotFoundError: %s while downloading gnomAD %s", e, destination_path) + # Emit a feedback to the user's console + socketio_emit_to_user_session( + CONSOLE_FEEDBACK_EVENT, + { + "type": "errr", + "message": f"FileNotFoundError: {e} while downloading gnomAD {destination_path}", + }, + uuid, + sid, + ) + return jsonify({"error": "Requested file not found"}), 404 + except PermissionError as e: + logger.error("PermissionError: %s while downloading gnomAD %s", e, destination_path) + # Emit a feedback to the user's console + socketio_emit_to_user_session( + CONSOLE_FEEDBACK_EVENT, + { + "type": "errr", + "message": f"PermissionError: {e} while downloading gnomAD {destination_path}", + }, + uuid, + sid, + ) + return jsonify({"error": "Permission denied"}), 403 + except UnexpectedError as e: + logger.error("UnexpectedError: %s while downloading gnomAD %s", e.message, destination_path) + # Emit a feedback to the user's console + socketio_emit_to_user_session( + CONSOLE_FEEDBACK_EVENT, + { + "type": "errr", + "message": f"UnexpectedError: {e.message} while downloading gnomAD " + + f"{destination_path}", + }, + uuid, + sid, + ) + return jsonify({"error": "An internal error occurred"}), 500 + + return jsonify({"message": "gnomAD data downloaded successful"}), 200 From 582349e83046cbd50859fc52ff38630e8db5c99a Mon Sep 17 00:00:00 2001 From: Mantvydas Deltuva Date: Wed, 11 Sep 2024 23:32:36 +0300 Subject: [PATCH 3/7] MDE/PKFE-30 implemented merge route --- .../src/routes/workspace_merge_route.py | 284 ++++++++++++++++++ 1 file changed, 284 insertions(+) create mode 100644 app/back-end/src/routes/workspace_merge_route.py diff --git a/app/back-end/src/routes/workspace_merge_route.py b/app/back-end/src/routes/workspace_merge_route.py new file mode 100644 index 0000000..150d958 --- /dev/null +++ b/app/back-end/src/routes/workspace_merge_route.py @@ -0,0 +1,284 @@ +""" +Workspace merge route module. +This module defines routes for merging data from different sources and saving the merged data to +the user's workspace. +""" + +# pylint: disable=import-error + +import os +import time # TODO: Remove this import once the merge logic is implemented +from flask import Blueprint, request, jsonify + +from src.setup.extensions import logger +from src.utils.helpers import socketio_emit_to_user_session +from src.utils.exceptions import UnexpectedError +from src.constants import ( + WORKSPACE_MERGE_ROUTE, + WORKSPACE_DIR, + CONSOLE_FEEDBACK_EVENT, + WORKSPACE_UPDATE_FEEDBACK_EVENT, +) + +workspace_merge_route_bp = Blueprint("workspace_merge_route", __name__) + + +@workspace_merge_route_bp.route( + f"{WORKSPACE_MERGE_ROUTE}/lovd_gnomad/", methods=["GET"] +) +def get_workspace_merge_lovd_gnomad(relative_path): + """ + Route to merge LOVD and gnomAD data and save the merged data to the workspace. + """ + + # Check if 'uuid' and 'sid' are provided in the headers + if "uuid" not in request.headers or "sid" not in request.headers: + return jsonify({"error": "UUID and SID headers are required"}), 400 + + uuid = request.headers.get("uuid") + sid = request.headers.get("sid") + + # Check if 'override', 'lovdFile' and 'gnomadFile' are provided + if ( + "override" not in request.args + or "lovdFile" not in request.args + or "gnomadFile" not in request.args + ): + return ( + jsonify({"error": "'override', 'lovdFile' and 'gnomadFile' parameters are required"}), + 400, + ) + + # Explanation about the parameters: + # - destination_path: string + # - The path to the destination file (where to save it) in the user's workspace + # Destination file can either be a new file or an existing file, check its existence + # - override: boolean + # - If true, the existing destination file should be overridden + # - If false, the existing destination file should not be overridden and merged + # content should be appended + # - lovd_file: string + # - The path to the LOVD file to be used in merge + # - gnomad_file: string + # - The path to the gnomAD file to be used in merge + + destination_path = os.path.join(WORKSPACE_DIR, uuid, relative_path) + override = request.args.get("override") + lovd_file = os.path.join(WORKSPACE_DIR, uuid, request.args.get("lovdFile")) + gnomad_file = os.path.join(WORKSPACE_DIR, uuid, request.args.get("gnomadFile")) + + try: + # Emit a feedback to the user's console + socketio_emit_to_user_session( + CONSOLE_FEEDBACK_EVENT, + { + "type": "info", + "message": f"Merging LOVD and gnomAD data to '{relative_path}' with " + + f"override: `{override}'...", + }, + uuid, + sid, + ) + + # + # TODO: Implement LOVD and gnomAD data merge and save logic using defined parameters + # [destination_path, override, lovd_file, gnomad_file] + # + + # TODO: Remove this sleep statement once the merge logic is implemented + time.sleep(1) # Simulate a delay for the merge process + + # Emit a feedback to the user's console + socketio_emit_to_user_session( + CONSOLE_FEEDBACK_EVENT, + { + "type": "succ", + "message": f"LOVD and gnomAD merge to '{relative_path}' was successful.", + }, + uuid, + sid, + ) + + socketio_emit_to_user_session( + WORKSPACE_UPDATE_FEEDBACK_EVENT, + {"status": "updated"}, + uuid, + sid, + ) + + except FileNotFoundError as e: + logger.error("FileNotFoundError: %s while merging LOVD and gnomAD %s", e, destination_path) + # Emit a feedback to the user's console + socketio_emit_to_user_session( + CONSOLE_FEEDBACK_EVENT, + { + "type": "errr", + "message": f"FileNotFoundError: {e} while merging LOVD and gnomAD " + + f"{destination_path}", + }, + uuid, + sid, + ) + return jsonify({"error": "Requested file not found"}), 404 + except PermissionError as e: + logger.error("PermissionError: %s while merging LOVD and gnomAD %s", e, destination_path) + # Emit a feedback to the user's console + socketio_emit_to_user_session( + CONSOLE_FEEDBACK_EVENT, + { + "type": "errr", + "message": f"PermissionError: {e} while merging LOVD and gnomAD {destination_path}", + }, + uuid, + sid, + ) + return jsonify({"error": "Permission denied"}), 403 + except UnexpectedError as e: + logger.error( + "UnexpectedError: %s while merging LOVD and gnomAD %s", e.message, destination_path + ) + # Emit a feedback to the user's console + socketio_emit_to_user_session( + CONSOLE_FEEDBACK_EVENT, + { + "type": "errr", + "message": f"UnexpectedError: {e.message} while merging LOVD and gnomAD " + + f"{destination_path}", + }, + uuid, + sid, + ) + return jsonify({"error": "An internal error occurred"}), 500 + + return jsonify({"message": "LOVD and gnomAD data merge successful"}), 200 + + +@workspace_merge_route_bp.route( + f"{WORKSPACE_MERGE_ROUTE}/lovd_clinvar/", methods=["GET"] +) +def get_workspace_merge_lovd_clinvar(relative_path): + """ + Route to merge LOVD and ClinVar data and save the merged data to the workspace. + """ + + # Check if 'uuid' and 'sid' are provided in the headers + if "uuid" not in request.headers or "sid" not in request.headers: + return jsonify({"error": "UUID and SID headers are required"}), 400 + + uuid = request.headers.get("uuid") + sid = request.headers.get("sid") + + # Check if 'override', 'lovdFile' and 'gnomadFile' are provided + if ( + "override" not in request.args + or "lovdFile" not in request.args + or "clinvarFile" not in request.args + ): + return ( + jsonify({"error": "'override', 'lovdFile' and 'clinvarFile' parameters are required"}), + 400, + ) + + # Explanation about the parameters: + # - destination_path: string + # - The path to the destination file (where to save it) in the user's workspace + # Destination file can either be a new file or an existing file, check its existence + # - override: boolean + # - If true, the existing destination file should be overridden + # - If false, the existing destination file should not be overridden and merged + # content should be appended + # - lovd_file: string + # - The path to the LOVD file to be used in merge + # - clinvar_file: string + # - The path to the ClinVar file to be used in merge + + destination_path = os.path.join(WORKSPACE_DIR, uuid, relative_path) + override = request.args.get("override") + lovd_file = os.path.join(WORKSPACE_DIR, uuid, request.args.get("lovdFile")) + clinvar_file = os.path.join(WORKSPACE_DIR, uuid, request.args.get("clinvarFile")) + + try: + # Emit a feedback to the user's console + socketio_emit_to_user_session( + CONSOLE_FEEDBACK_EVENT, + { + "type": "info", + "message": f"Merging LOVD and ClinVar data to '{relative_path}' with " + + f"override: `{override}'...", + }, + uuid, + sid, + ) + + # + # TODO: Implement LOVD and ClinVar data merge and save logic using defined parameters + # [destination_path, override, lovd_file, clinvar_file] + # + + # TODO: Remove this sleep statement once the merge logic is implemented + time.sleep(1) # Simulate a delay for the merge process + + # Emit a feedback to the user's console + socketio_emit_to_user_session( + CONSOLE_FEEDBACK_EVENT, + { + "type": "succ", + "message": f"LOVD and ClinVar merge to '{relative_path}' was successful.", + }, + uuid, + sid, + ) + + socketio_emit_to_user_session( + WORKSPACE_UPDATE_FEEDBACK_EVENT, + {"status": "updated"}, + uuid, + sid, + ) + + except FileNotFoundError as e: + logger.error("FileNotFoundError: %s while merging LOVD and ClinVar %s", e, destination_path) + # Emit a feedback to the user's console + socketio_emit_to_user_session( + CONSOLE_FEEDBACK_EVENT, + { + "type": "errr", + "message": f"FileNotFoundError: {e} while merging LOVD and ClinVar " + + f"{destination_path}", + }, + uuid, + sid, + ) + return jsonify({"error": "Requested file not found"}), 404 + except PermissionError as e: + logger.error("PermissionError: %s while merging LOVD and ClinVar %s", e, destination_path) + # Emit a feedback to the user's console + socketio_emit_to_user_session( + CONSOLE_FEEDBACK_EVENT, + { + "type": "errr", + "message": f"PermissionError: {e} while merging LOVD and ClinVar " + + f"{destination_path}", + }, + uuid, + sid, + ) + return jsonify({"error": "Permission denied"}), 403 + except UnexpectedError as e: + logger.error( + "UnexpectedError: %s while merging LOVD and ClinVar %s", e.message, destination_path + ) + # Emit a feedback to the user's console + socketio_emit_to_user_session( + CONSOLE_FEEDBACK_EVENT, + { + "type": "errr", + "message": f"UnexpectedError: {e.message} while merging LOVD and ClinVar " + + f"{destination_path}", + }, + uuid, + sid, + ) + return jsonify({"error": "An internal error occurred"}), 500 + + return jsonify({"message": "LOVD and ClinVar data merge successful"}), 200 From 333a1db16502b8e4a2f91e7778df28bea610b7d0 Mon Sep 17 00:00:00 2001 From: Mantvydas Deltuva Date: Wed, 11 Sep 2024 23:33:02 +0300 Subject: [PATCH 4/7] MDE/PKFE-30 implemented apply route --- .../src/routes/workspace_apply_route.py | 276 ++++++++++++++++++ 1 file changed, 276 insertions(+) create mode 100644 app/back-end/src/routes/workspace_apply_route.py diff --git a/app/back-end/src/routes/workspace_apply_route.py b/app/back-end/src/routes/workspace_apply_route.py new file mode 100644 index 0000000..5ec68ab --- /dev/null +++ b/app/back-end/src/routes/workspace_apply_route.py @@ -0,0 +1,276 @@ +""" +Workspace apply route module. +This module defines routes for applying algorithms to files and saving the results to the user's +workspace. +""" + +# pylint: disable=import-error + +import os +import time # TODO: Remove this import once the apply logic is implemented +from flask import Blueprint, request, jsonify + +from src.setup.extensions import logger +from src.utils.helpers import socketio_emit_to_user_session +from src.utils.exceptions import UnexpectedError +from src.constants import ( + WORKSPACE_APPLY_ROUTE, + WORKSPACE_DIR, + CONSOLE_FEEDBACK_EVENT, + WORKSPACE_UPDATE_FEEDBACK_EVENT, +) + +workspace_apply_route_bp = Blueprint("workspace_apply_route", __name__) + + +@workspace_apply_route_bp.route( + f"{WORKSPACE_APPLY_ROUTE}/spliceai/", methods=["GET"] +) +def get_workspace_apply_spliceai(relative_path): + """ + Route to apply the SpliceAI algorithm to a file and save the result to the workspace. + """ + + # Check if 'uuid' and 'sid' are provided in the headers + if "uuid" not in request.headers or "sid" not in request.headers: + return jsonify({"error": "UUID and SID headers are required"}), 400 + + uuid = request.headers.get("uuid") + sid = request.headers.get("sid") + + # Check if 'override' and 'applyTo' are provided + if "override" not in request.args or "applyTo" not in request.args: + return ( + jsonify({"error": "'override', and 'applyTo' parameters are required"}), + 400, + ) + + # Explanation about the parameters: + # - destination_path: string + # - The path to the destination file (where to save it) in the user's workspace + # Destination file can either be a new file or an existing file, check its existence + # - override: boolean + # - If true, the existing destination file should be overridden + # - If false, the existing destination file should not be overridden and merged + # content should be appended + # - apply_to: string + # - The path to the file to which the SpliceAI algorithm should be applied + # Destination file can be the same file so ensure correct handling + + destination_path = os.path.join(WORKSPACE_DIR, uuid, relative_path) + override = request.args.get("override") + apply_to = os.path.join(WORKSPACE_DIR, uuid, request.args.get("applyTo")) + + try: + # Emit a feedback to the user's console + socketio_emit_to_user_session( + CONSOLE_FEEDBACK_EVENT, + { + "type": "info", + "message": f"Applying SpliceAI algorithm to '{relative_path}' with " + + f"override: `{override}'...", + }, + uuid, + sid, + ) + + # + # TODO: Implement SpliceAI algorithm apply and save logic using defined parameters + # [destination_path, override, apply_to] + # + + # TODO: Remove this sleep statement once the apply logic is implemented + time.sleep(1) # Simulate a delay for the apply process + + # Emit a feedback to the user's console + socketio_emit_to_user_session( + CONSOLE_FEEDBACK_EVENT, + { + "type": "succ", + "message": f"SpliceAI algorithm was successfully applied to '{relative_path}'.", + }, + uuid, + sid, + ) + + socketio_emit_to_user_session( + WORKSPACE_UPDATE_FEEDBACK_EVENT, + {"status": "updated"}, + uuid, + sid, + ) + + except FileNotFoundError as e: + logger.error( + "FileNotFoundError: %s while applying SpliceAI algorithm %s", e, destination_path + ) + # Emit a feedback to the user's console + socketio_emit_to_user_session( + CONSOLE_FEEDBACK_EVENT, + { + "type": "errr", + "message": f"FileNotFoundError: {e} while SpliceAI applying algorithm " + + f"{destination_path}", + }, + uuid, + sid, + ) + return jsonify({"error": "Requested file not found"}), 404 + except PermissionError as e: + logger.error( + "PermissionError: %s while applying SpliceAI algorithm %s", e, destination_path + ) + # Emit a feedback to the user's console + socketio_emit_to_user_session( + CONSOLE_FEEDBACK_EVENT, + { + "type": "errr", + "message": f"PermissionError: {e} while SpliceAI applying algorithm " + + f"{destination_path}", + }, + uuid, + sid, + ) + return jsonify({"error": "Permission denied"}), 403 + except UnexpectedError as e: + logger.error( + "UnexpectedError: %s while applying SpliceAI algorithm %s", e.message, destination_path + ) + # Emit a feedback to the user's console + socketio_emit_to_user_session( + CONSOLE_FEEDBACK_EVENT, + { + "type": "errr", + "message": f"UnexpectedError: {e.message} while applying SpliceAI algorithm " + + f"{destination_path}", + }, + uuid, + sid, + ) + return jsonify({"error": "An internal error occurred"}), 500 + + return jsonify({"message": "SpliceAI algorithm was successfully applied"}), 200 + + +@workspace_apply_route_bp.route( + f"{WORKSPACE_APPLY_ROUTE}/cadd/", methods=["GET"] +) +def get_workspace_apply_cadd(relative_path): + """ + Route to apply the CADD algorithm to a file and save the result to the workspace. + """ + + # Check if 'uuid' and 'sid' are provided in the headers + if "uuid" not in request.headers or "sid" not in request.headers: + return jsonify({"error": "UUID and SID headers are required"}), 400 + + uuid = request.headers.get("uuid") + sid = request.headers.get("sid") + + # Check if 'override' and 'applyTo' are provided + if "override" not in request.args or "applyTo" not in request.args: + return ( + jsonify({"error": "'override', and 'applyTo' parameters are required"}), + 400, + ) + + # Explanation about the parameters: + # - destination_path: string + # - The path to the destination file (where to save it) in the user's workspace + # Destination file can either be a new file or an existing file, check its existence + # - override: boolean + # - If true, the existing destination file should be overridden + # - If false, the existing destination file should not be overridden and merged + # content should be appended + # - apply_to: string + # - The path to the file to which the CADD algorithm should be applied + # Destination file can be the same file so ensure correct handling + + destination_path = os.path.join(WORKSPACE_DIR, uuid, relative_path) + override = request.args.get("override") + apply_to = os.path.join(WORKSPACE_DIR, uuid, request.args.get("applyTo")) + + try: + # Emit a feedback to the user's console + socketio_emit_to_user_session( + CONSOLE_FEEDBACK_EVENT, + { + "type": "info", + "message": f"Applying CADD algorithm to '{relative_path}' with " + + f"override: `{override}'...", + }, + uuid, + sid, + ) + + # + # TODO: Implement CADD algorithm apply and save logic using defined parameters + # [destination_path, override, apply_to] + # + + # TODO: Remove this sleep statement once the apply logic is implemented + time.sleep(1) # Simulate a delay for the apply process + + # Emit a feedback to the user's console + socketio_emit_to_user_session( + CONSOLE_FEEDBACK_EVENT, + { + "type": "succ", + "message": f"CADD algorithm was successfully applied to '{relative_path}'.", + }, + uuid, + sid, + ) + + socketio_emit_to_user_session( + WORKSPACE_UPDATE_FEEDBACK_EVENT, + {"status": "updated"}, + uuid, + sid, + ) + + except FileNotFoundError as e: + logger.error("FileNotFoundError: %s while applying CADD algorithm %s", e, destination_path) + # Emit a feedback to the user's console + socketio_emit_to_user_session( + CONSOLE_FEEDBACK_EVENT, + { + "type": "errr", + "message": f"FileNotFoundError: {e} while applying CADD algorithm " + + f"{destination_path}", + }, + uuid, + sid, + ) + return jsonify({"error": "Requested file not found"}), 404 + except PermissionError as e: + logger.error("PermissionError: %s while applying CADD algorithm %s", e, destination_path) + # Emit a feedback to the user's console + socketio_emit_to_user_session( + CONSOLE_FEEDBACK_EVENT, + { + "type": "errr", + "message": f"PermissionError: {e} while applying CADD algorithm {destination_path}", + }, + uuid, + sid, + ) + return jsonify({"error": "Permission denied"}), 403 + except UnexpectedError as e: + logger.error( + "UnexpectedError: %s while applying CADD algorithm %s", e.message, destination_path + ) + # Emit a feedback to the user's console + socketio_emit_to_user_session( + CONSOLE_FEEDBACK_EVENT, + { + "type": "errr", + "message": f"UnexpectedError: {e.message} while applying CADD algorithm " + + f"{destination_path}", + }, + uuid, + sid, + ) + return jsonify({"error": "An internal error occurred"}), 500 + + return jsonify({"message": "CADD algorithm was successfully applied"}), 200 From a1f743cfc503be04c4c3d572829b741969dc244d Mon Sep 17 00:00:00 2001 From: Mantvydas Deltuva Date: Wed, 11 Sep 2024 23:33:21 +0300 Subject: [PATCH 5/7] MDE/PKFE-30 added routing to router --- app/back-end/src/setup/router.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/back-end/src/setup/router.py b/app/back-end/src/setup/router.py index 102e080..3088ba6 100644 --- a/app/back-end/src/setup/router.py +++ b/app/back-end/src/setup/router.py @@ -19,6 +19,9 @@ from src.routes.workspace_aggregate_route import workspace_aggregate_route_bp from src.routes.workspace_export_route import workspace_export_route_bp from src.routes.workspace_import_route import workspace_import_route_bp +from src.routes.workspace_download_route import workspace_download_route_bp +from src.routes.workspace_merge_route import workspace_merge_route_bp +from src.routes.workspace_apply_route import workspace_apply_route_bp def router(prefix): @@ -37,6 +40,9 @@ def router(prefix): router_bp = Blueprint("router", __name__, url_prefix=prefix) # Register API routes with the main router blueprint + router_bp.register_blueprint(workspace_apply_route_bp) + router_bp.register_blueprint(workspace_merge_route_bp) + router_bp.register_blueprint(workspace_download_route_bp) router_bp.register_blueprint(workspace_export_route_bp) router_bp.register_blueprint(workspace_import_route_bp) router_bp.register_blueprint(workspace_aggregate_route_bp) From 3cf9a0e8a1c80f8e6d9c298f4610cc2740b95c12 Mon Sep 17 00:00:00 2001 From: Mantvydas Deltuva Date: Wed, 11 Sep 2024 23:33:57 +0300 Subject: [PATCH 6/7] MDE/PKFE-30 temp ui fix regarding toolbar params override field --- .../toolbarView/toolbarGroupParams/applyGroupParams.tsx | 2 +- .../toolbarView/toolbarGroupParams/downloadGroupParams.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/front-end/src/features/editor/components/toolbarView/toolbarGroupParams/applyGroupParams.tsx b/app/front-end/src/features/editor/components/toolbarView/toolbarGroupParams/applyGroupParams.tsx index 9617c80..89c43ca 100644 --- a/app/front-end/src/features/editor/components/toolbarView/toolbarGroupParams/applyGroupParams.tsx +++ b/app/front-end/src/features/editor/components/toolbarView/toolbarGroupParams/applyGroupParams.tsx @@ -111,7 +111,7 @@ export const ApplyGroupParams: React.FC = () => { - + = () => { - + Date: Thu, 12 Sep 2024 01:11:12 +0300 Subject: [PATCH 7/7] MDE/PKFE-30 typos changes --- app/back-end/src/routes/workspace_apply_route.py | 10 +++++----- app/back-end/src/routes/workspace_download_route.py | 12 ++++++------ app/back-end/src/routes/workspace_merge_route.py | 4 ++-- app/front-end/src/features/editor/utils/helpers.tsx | 6 +++--- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/app/back-end/src/routes/workspace_apply_route.py b/app/back-end/src/routes/workspace_apply_route.py index 5ec68ab..b88025d 100644 --- a/app/back-end/src/routes/workspace_apply_route.py +++ b/app/back-end/src/routes/workspace_apply_route.py @@ -68,7 +68,7 @@ def get_workspace_apply_spliceai(relative_path): { "type": "info", "message": f"Applying SpliceAI algorithm to '{relative_path}' with " - + f"override: `{override}'...", + + f"override: '{override}'...", }, uuid, sid, @@ -109,7 +109,7 @@ def get_workspace_apply_spliceai(relative_path): CONSOLE_FEEDBACK_EVENT, { "type": "errr", - "message": f"FileNotFoundError: {e} while SpliceAI applying algorithm " + "message": f"FileNotFoundError: {e} while applying SpliceAI algorithm" + f"{destination_path}", }, uuid, @@ -125,7 +125,7 @@ def get_workspace_apply_spliceai(relative_path): CONSOLE_FEEDBACK_EVENT, { "type": "errr", - "message": f"PermissionError: {e} while SpliceAI applying algorithm " + "message": f"PermissionError: {e} while applying SpliceAI algorithm" + f"{destination_path}", }, uuid, @@ -141,7 +141,7 @@ def get_workspace_apply_spliceai(relative_path): CONSOLE_FEEDBACK_EVENT, { "type": "errr", - "message": f"UnexpectedError: {e.message} while applying SpliceAI algorithm " + "message": f"UnexpectedError: {e.message} while applying SpliceAI algorithm" + f"{destination_path}", }, uuid, @@ -197,7 +197,7 @@ def get_workspace_apply_cadd(relative_path): { "type": "info", "message": f"Applying CADD algorithm to '{relative_path}' with " - + f"override: `{override}'...", + + f"override: '{override}'...", }, uuid, sid, diff --git a/app/back-end/src/routes/workspace_download_route.py b/app/back-end/src/routes/workspace_download_route.py index 8541b58..ad1fe69 100644 --- a/app/back-end/src/routes/workspace_download_route.py +++ b/app/back-end/src/routes/workspace_download_route.py @@ -64,7 +64,7 @@ def get_workspace_download_lovd(relative_path): { "type": "info", "message": f"Downloading LOVD data for gene '{gene}' to '{relative_path}' with " - + f"override: `{override}'...", + + f"override: '{override}'...", }, uuid, sid, @@ -134,7 +134,7 @@ def get_workspace_download_lovd(relative_path): ) return jsonify({"error": "An internal error occurred"}), 500 - return jsonify({"message": "LOVD data downloaded successful"}), 200 + return jsonify({"message": "LOVD data downloaded successfully"}), 200 @workspace_download_route_bp.route( @@ -180,7 +180,7 @@ def get_workspace_download_clinvar(relative_path): { "type": "info", "message": f"Downloading ClinVar data for gene '{gene}' to '{relative_path}' with " - + f"override: `{override}'...", + + f"override: '{override}'...", }, uuid, sid, @@ -252,7 +252,7 @@ def get_workspace_download_clinvar(relative_path): ) return jsonify({"error": "An internal error occurred"}), 500 - return jsonify({"message": "CliVar data downloaded successful"}), 200 + return jsonify({"message": "CliVar data downloaded successfullly"}), 200 @workspace_download_route_bp.route( @@ -296,7 +296,7 @@ def get_workspace_download_gnomad(relative_path): { "type": "info", "message": f"Downloading gnomAD data for gene '{gene}' to '{relative_path}' with " - + f"override: `{override}'...", + + f"override: '{override}'...", }, uuid, sid, @@ -366,4 +366,4 @@ def get_workspace_download_gnomad(relative_path): ) return jsonify({"error": "An internal error occurred"}), 500 - return jsonify({"message": "gnomAD data downloaded successful"}), 200 + return jsonify({"message": "gnomAD data downloaded successfullly"}), 200 diff --git a/app/back-end/src/routes/workspace_merge_route.py b/app/back-end/src/routes/workspace_merge_route.py index 150d958..6de3f6c 100644 --- a/app/back-end/src/routes/workspace_merge_route.py +++ b/app/back-end/src/routes/workspace_merge_route.py @@ -74,7 +74,7 @@ def get_workspace_merge_lovd_gnomad(relative_path): { "type": "info", "message": f"Merging LOVD and gnomAD data to '{relative_path}' with " - + f"override: `{override}'...", + + f"override: '{override}'...", }, uuid, sid, @@ -204,7 +204,7 @@ def get_workspace_merge_lovd_clinvar(relative_path): { "type": "info", "message": f"Merging LOVD and ClinVar data to '{relative_path}' with " - + f"override: `{override}'...", + + f"override: '{override}'...", }, uuid, sid, diff --git a/app/front-end/src/features/editor/utils/helpers.tsx b/app/front-end/src/features/editor/utils/helpers.tsx index e988e6e..19fa618 100644 --- a/app/front-end/src/features/editor/utils/helpers.tsx +++ b/app/front-end/src/features/editor/utils/helpers.tsx @@ -96,14 +96,14 @@ export const generateTimestamp = () => { return ( now.getFullYear() + '-' + - String(now.getMonth() + 1).padStart(2, '0') + // Months are zero-indexed + String(now.getMonth() + 1).padStart(2, '0') + '-' + String(now.getDate()).padStart(2, '0') + '_' + String(now.getHours()).padStart(2, '0') + - ':' + + '-' + String(now.getMinutes()).padStart(2, '0') + - ':' + + '-' + String(now.getSeconds()).padStart(2, '0') ); };