- Sponsor
-
Notifications
You must be signed in to change notification settings - Fork 18
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Loading status checks…
Merge pull request #205 from Tauffer-Consulting/feature/display-all-r…
…esults Feature/display-all-results
Showing
26 changed files
with
1,286 additions
and
421 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
import { Tooltip, type ButtonProps, Button } from "@mui/material"; | ||
import React, { useCallback } from "react"; | ||
|
||
interface Props extends ButtonProps { | ||
base64_content: string; | ||
file_type: string; | ||
} | ||
|
||
export const DownloadB64Button: React.FC<Props> = ({ | ||
base64_content, | ||
file_type, | ||
...props | ||
}) => { | ||
const downloadContent = useCallback(() => { | ||
let href = ""; | ||
switch (file_type) { | ||
case "txt": | ||
href = `data:text/plain;base64,${base64_content}`; | ||
break; | ||
case "plotly_json": | ||
case "json": | ||
href = `data:application/json;base64,${base64_content}`; | ||
break; | ||
case "jpeg": | ||
case "jpg": | ||
case "png": | ||
case "bmp": | ||
case "gif": | ||
case "tiff": | ||
href = `data:image/${file_type};base64,${base64_content}`; | ||
break; | ||
case "svg": | ||
href = `data:image/svg+xml;base64,${base64_content}`; | ||
break; | ||
case "md": | ||
href = `data:text/markdown;base64,${base64_content}`; | ||
break; | ||
case "pdf": | ||
href = `data:application/pdf;base64,${base64_content}`; | ||
break; | ||
case "html": | ||
href = `data:text/html;base64,${base64_content}`; | ||
break; | ||
default: | ||
href = `data:text/plain;base64,${base64_content}`; | ||
break; | ||
} | ||
|
||
const a = document.createElement("a"); // Create <a> | ||
a.href = href; // Image Base64 Goes here | ||
a.download = `download.${file_type}`; // File name Here | ||
a.click(); // Downloaded file | ||
}, [base64_content, file_type]); | ||
|
||
return ( | ||
<Tooltip | ||
title={ | ||
!base64_content || !file_type | ||
? "Missing base64_content of file_type" | ||
: "Will download the raw result content " | ||
} | ||
> | ||
<Button | ||
variant="contained" | ||
onClick={downloadContent} | ||
disabled={!base64_content || !file_type} | ||
{...props} | ||
> | ||
Download content | ||
</Button> | ||
</Tooltip> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import { Button, type ButtonProps } from "@mui/material"; | ||
import React, { useEffect, useState } from "react"; | ||
import { useReactToPrint } from "react-to-print"; | ||
|
||
interface Props extends ButtonProps { | ||
contentId: string; | ||
} | ||
|
||
export const DownloadAsPDF: React.FC<Props> = ({ contentId, ...props }) => { | ||
const [content, setContent] = useState<HTMLElement | null>(null); | ||
const handlePrint = useReactToPrint({ | ||
content: () => content, | ||
}); | ||
|
||
useEffect(() => { | ||
// Fetch the content element using the contentId | ||
const newContent = document.getElementById(contentId); | ||
setContent(newContent); | ||
}, [contentId]); | ||
|
||
const handlePrintWithTimeout = () => { | ||
// Add a short timeout to ensure styles are applied before printing | ||
setTimeout(() => { | ||
handlePrint(); | ||
}, 2000); // Adjust the timeout duration as needed | ||
}; | ||
|
||
return ( | ||
<Button variant="outlined" onClick={handlePrintWithTimeout} {...props}> | ||
Generate PDF | ||
</Button> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
import React, { useRef, useState } from "react"; | ||
|
||
interface Props { | ||
html: string; | ||
} | ||
|
||
const HtmlRenderer: React.FC<Props> = ({ html }) => { | ||
const iframeRef = useRef<HTMLIFrameElement | null>(null); | ||
const [minHeight, setMinHeight] = useState<number>(0); | ||
|
||
const handleLoad = () => { | ||
const iframe = iframeRef.current; | ||
if (iframe) { | ||
const newMinHeight = | ||
iframe.contentWindow?.document.body.scrollHeight ?? 0; | ||
setMinHeight(newMinHeight); | ||
iframe.style.height = `${newMinHeight}px`; | ||
} | ||
}; | ||
|
||
return ( | ||
<div | ||
style={{ | ||
minHeight: `${minHeight}px`, | ||
height: "100%", | ||
width: "100%", | ||
overflowY: "hidden", | ||
overflowX: "auto", | ||
}} | ||
> | ||
<iframe | ||
ref={iframeRef} | ||
title="html-renderer" | ||
srcDoc={html} | ||
width="100%" | ||
height="100%" | ||
style={{ border: "none" }} | ||
scrolling="no" | ||
onLoad={handleLoad} | ||
></iframe> | ||
</div> | ||
); | ||
}; | ||
|
||
export default HtmlRenderer; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
import { Typography } from "@mui/material"; | ||
import HtmlRenderer from "components/HTMLRender"; | ||
import { RenderPDF } from "components/RenderPDF"; | ||
import React, { type CSSProperties } from "react"; | ||
import ReactMarkdown from "react-markdown"; | ||
import Plot from "react-plotly.js"; | ||
import remarkGfm from "remark-gfm"; | ||
|
||
interface Props { | ||
base64_content: string; | ||
file_type: string; | ||
style?: CSSProperties; | ||
} | ||
|
||
export const RenderB64: React.FC<Props> = ({ | ||
base64_content, | ||
file_type, | ||
style, | ||
}) => { | ||
if (!base64_content || !file_type) { | ||
return <Typography variant="h2">No content</Typography>; | ||
} | ||
switch (file_type) { | ||
case "txt": | ||
return <pre style={style}>{window.atob(base64_content)}</pre>; | ||
case "json": | ||
return ( | ||
<pre style={style}> | ||
{JSON.stringify(JSON.parse(window.atob(base64_content)), null, 2)} | ||
</pre> | ||
); | ||
case "jpeg": | ||
case "jpg": | ||
case "png": | ||
case "bmp": | ||
case "gif": | ||
case "tiff": | ||
return ( | ||
<img | ||
src={`data:image/${file_type};base64,${base64_content}`} | ||
alt="Content" | ||
style={{ maxWidth: "100%", maxHeight: "100%", ...style }} | ||
/> | ||
); | ||
case "svg": | ||
return ( | ||
<object | ||
type="image/svg+xml" | ||
data={`data:image/svg+xml;base64,${base64_content}`} | ||
style={{ maxWidth: "100%", maxHeight: "100%", ...style }} | ||
> | ||
Your browser does not support SVG | ||
</object> | ||
); | ||
case "md": | ||
return ( | ||
<div | ||
style={{ overflow: "auto", maxWidth: "100%", width: "100%" }} | ||
className="markdown-container" | ||
> | ||
<ReactMarkdown | ||
className="react-markdown-component" | ||
remarkPlugins={[remarkGfm]} | ||
> | ||
{window.atob(base64_content)} | ||
</ReactMarkdown> | ||
; | ||
</div> | ||
); | ||
|
||
case "pdf": | ||
return <RenderPDF base64Content={base64_content} />; | ||
case "html": { | ||
const decodedHTML = atob(base64_content); | ||
|
||
return <HtmlRenderer html={decodedHTML} />; | ||
} | ||
case "plotly_json": { | ||
const utf8String = atob(base64_content); | ||
const decodedJSON = JSON.parse(utf8String); | ||
return ( | ||
<Plot | ||
data={decodedJSON.data} | ||
layout={decodedJSON.layout} | ||
style={{ width: "100%", height: "100%" }} | ||
/> | ||
); | ||
} | ||
default: | ||
return <div>Unsupported file type</div>; | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
89 changes: 89 additions & 0 deletions
89
frontend/src/features/myWorkflows/api/runs/getWorkflowRunReport.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
import { type AxiosResponse } from "axios"; | ||
import { useWorkspaces } from "context/workspaces"; | ||
import { type taskState } from "features/myWorkflows/types"; | ||
import { dominoApiClient } from "services/clients/domino.client"; | ||
import useSWR from "swr"; | ||
|
||
export interface IGetWorkflowRunResultReportParams { | ||
workflowId: string; | ||
runId: string; | ||
} | ||
|
||
export interface IGetWorkflowRunResultReportResponse { | ||
base64_content: string; | ||
file_type: string; | ||
piece_name: string; | ||
dag_id: string; | ||
duration: number; | ||
start_date: string; | ||
end_date: string; | ||
execution_date: string; | ||
task_id: string; | ||
state: taskState; | ||
} | ||
|
||
const getWorkflowRunResultReportUrl = ({ | ||
workspace, | ||
workflowId, | ||
runId, | ||
}: Partial<IGetWorkflowRunResultReportParams & { workspace: string }>) => { | ||
if (workspace && workflowId && runId) { | ||
return `/workspaces/${workspace}/workflows/${workflowId}/runs/${runId}/tasks/report`; | ||
} else { | ||
return null; | ||
} | ||
}; | ||
|
||
/** | ||
* Get workflows using GET /workflows | ||
* @returns workflow | ||
*/ | ||
const getWorkflowRunResultReport: ({ | ||
workspace, | ||
workflowId, | ||
runId, | ||
}: Partial< | ||
IGetWorkflowRunResultReportParams & { workspace: string } | ||
>) => Promise< | ||
| AxiosResponse<{ | ||
data: IGetWorkflowRunResultReportResponse[]; | ||
}> | ||
| undefined | ||
> = async ({ workspace, workflowId, runId }) => { | ||
if (workspace && workflowId && runId) { | ||
const url = getWorkflowRunResultReportUrl({ | ||
workspace, | ||
workflowId, | ||
runId, | ||
}); | ||
if (url) return await dominoApiClient.get(url); | ||
} | ||
}; | ||
|
||
/** | ||
* Get workflow runs | ||
* @returns runs as swr response | ||
*/ | ||
export const useAuthenticatedGetWorkflowRunResultReport = ( | ||
params: Partial<IGetWorkflowRunResultReportParams>, | ||
) => { | ||
const { workspace } = useWorkspaces(); | ||
if (!workspace) | ||
throw new Error( | ||
"Impossible to fetch workflows without specifying a workspace", | ||
); | ||
|
||
const url = getWorkflowRunResultReportUrl({ | ||
workspace: workspace.id, | ||
...params, | ||
}); | ||
|
||
return useSWR( | ||
url, | ||
async () => | ||
await getWorkflowRunResultReport({ | ||
workspace: workspace.id, | ||
...params, | ||
}).then((data) => data?.data), | ||
); | ||
}; |
Oops, something went wrong.