diff --git a/webapp/src/components/App/Singlestudy/explore/Debug/Data/Folder.tsx b/webapp/src/components/App/Singlestudy/explore/Debug/Data/Folder.tsx
index 3aa92463c5..e52a403c90 100644
--- a/webapp/src/components/App/Singlestudy/explore/Debug/Data/Folder.tsx
+++ b/webapp/src/components/App/Singlestudy/explore/Debug/Data/Folder.tsx
@@ -13,7 +13,6 @@ import {
type TreeFolder,
type DataCompProps,
} from "../utils";
-import ViewWrapper from "../../../../../common/page/ViewWrapper";
import { Fragment } from "react";
import EmptyView from "../../../../../common/page/SimpleContent";
import { useTranslation } from "react-i18next";
@@ -28,47 +27,45 @@ function Folder({
const list = Object.entries(treeData as TreeFolder);
return (
-
- {filename}}
- sx={{
- height: 1,
- overflow: "auto",
- }}
- dense
- >
- {list.length > 0 ? (
- list.map(([filename, data], index, arr) => {
- const fileType = getFileType(data);
- const Icon = getFileIcon(fileType);
- const isLast = index === arr.length - 1;
+ {filename}}
+ sx={{
+ height: 1,
+ overflow: "auto",
+ }}
+ dense
+ >
+ {list.length > 0 ? (
+ list.map(([filename, data], index, arr) => {
+ const fileType = getFileType(data);
+ const Icon = getFileIcon(fileType);
+ const isLast = index === arr.length - 1;
- return (
-
-
- setSelectedFile({
- fileType,
- filename,
- filePath: `${filePath}/${filename}`,
- treeData: data,
- })
- }
- >
-
-
-
-
-
- {!isLast && }
-
- );
- })
- ) : (
-
- )}
-
-
+ return (
+
+
+ setSelectedFile({
+ fileType,
+ filename,
+ filePath: `${filePath}/${filename}`,
+ treeData: data,
+ })
+ }
+ >
+
+
+
+
+
+ {!isLast && }
+
+ );
+ })
+ ) : (
+
+ )}
+
);
}
diff --git a/webapp/src/components/App/Singlestudy/explore/Debug/Data/Image.tsx b/webapp/src/components/App/Singlestudy/explore/Debug/Data/Image.tsx
index 874cb7691a..8ef8ea39c1 100644
--- a/webapp/src/components/App/Singlestudy/explore/Debug/Data/Image.tsx
+++ b/webapp/src/components/App/Singlestudy/explore/Debug/Data/Image.tsx
@@ -1,16 +1,11 @@
import { useTranslation } from "react-i18next";
import EmptyView from "../../../../../common/page/SimpleContent";
-import ViewWrapper from "../../../../../common/page/ViewWrapper";
import ImageIcon from "@mui/icons-material/Image";
function Image() {
const { t } = useTranslation();
- return (
-
-
-
- );
+ return ;
}
export default Image;
diff --git a/webapp/src/components/App/Singlestudy/explore/Debug/Data/Json.tsx b/webapp/src/components/App/Singlestudy/explore/Debug/Data/Json.tsx
index 463a605855..6863fd92b1 100644
--- a/webapp/src/components/App/Singlestudy/explore/Debug/Data/Json.tsx
+++ b/webapp/src/components/App/Singlestudy/explore/Debug/Data/Json.tsx
@@ -1,16 +1,19 @@
import { useTranslation } from "react-i18next";
import { useSnackbar } from "notistack";
-import { Box } from "@mui/material";
import { editStudy, getStudyData } from "../../../../../../services/api/study";
import JSONEditor, { JSONEditorProps } from "../../../../../common/JSONEditor";
import usePromiseWithSnackbarError from "../../../../../../hooks/usePromiseWithSnackbarError";
import UsePromiseCond from "../../../../../common/utils/UsePromiseCond";
-import ViewWrapper from "../../../../../common/page/ViewWrapper";
import type { DataCompProps } from "../utils";
+import DownloadButton from "../../../../../common/buttons/DownloadButton";
+import { downloadFile } from "../../../../../../utils/fileUtils";
+import { useEffect, useState } from "react";
+import { Flex, Menubar } from "./styles";
-function Json({ filePath, studyId }: DataCompProps) {
+function Json({ filePath, filename, studyId }: DataCompProps) {
const [t] = useTranslation();
const { enqueueSnackbar } = useSnackbar();
+ const [currentJson, setCurrentJson] = useState();
const res = usePromiseWithSnackbarError(
() => getStudyData(studyId, filePath, -1),
@@ -20,6 +23,10 @@ function Json({ filePath, studyId }: DataCompProps) {
},
);
+ useEffect(() => {
+ setCurrentJson(res.data);
+ }, [res.data]);
+
////////////////////////////////////////////////////////////////
// Event Handlers
////////////////////////////////////////////////////////////////
@@ -28,34 +35,43 @@ function Json({ filePath, studyId }: DataCompProps) {
return editStudy(json, studyId, filePath);
};
- const handleSaveSuccessful = () => {
+ const handleSaveSuccessful: JSONEditorProps["onSaveSuccessful"] = (json) => {
+ setCurrentJson(json);
+
enqueueSnackbar(t("studies.success.saveData"), {
variant: "success",
});
};
+ const handleDownload = () => {
+ if (currentJson !== undefined) {
+ downloadFile(JSON.stringify(currentJson, null, 2), `${filename}.json`);
+ }
+ };
+
////////////////////////////////////////////////////////////////
// JSX
////////////////////////////////////////////////////////////////
return (
-
- (
-
-
-
- )}
- />
-
+ (
+
+
+
+
+
+
+ )}
+ />
);
}
diff --git a/webapp/src/components/App/Singlestudy/explore/Debug/Data/Matrix.tsx b/webapp/src/components/App/Singlestudy/explore/Debug/Data/Matrix.tsx
index efcdd7089d..f48e93cca0 100644
--- a/webapp/src/components/App/Singlestudy/explore/Debug/Data/Matrix.tsx
+++ b/webapp/src/components/App/Singlestudy/explore/Debug/Data/Matrix.tsx
@@ -1,19 +1,16 @@
import { MatrixStats } from "../../../../../../common/types";
import MatrixInput from "../../../../../common/MatrixInput";
-import ViewWrapper from "../../../../../common/page/ViewWrapper";
import type { DataCompProps } from "../utils";
function Matrix({ studyId, filename, filePath, enableImport }: DataCompProps) {
return (
-
-
-
+
);
}
diff --git a/webapp/src/components/App/Singlestudy/explore/Debug/Data/Text.tsx b/webapp/src/components/App/Singlestudy/explore/Debug/Data/Text.tsx
index 9674993132..3a8e17169e 100644
--- a/webapp/src/components/App/Singlestudy/explore/Debug/Data/Text.tsx
+++ b/webapp/src/components/App/Singlestudy/explore/Debug/Data/Text.tsx
@@ -3,7 +3,6 @@ import { Box, useTheme } from "@mui/material";
import { getStudyData } from "../../../../../../services/api/study";
import usePromiseWithSnackbarError from "../../../../../../hooks/usePromiseWithSnackbarError";
import UsePromiseCond from "../../../../../common/utils/UsePromiseCond";
-import ViewWrapper from "../../../../../common/page/ViewWrapper";
import {
Light as SyntaxHighlighter,
type SyntaxHighlighterProps,
@@ -14,6 +13,9 @@ import ini from "react-syntax-highlighter/dist/esm/languages/hljs/ini";
import properties from "react-syntax-highlighter/dist/esm/languages/hljs/properties";
import { atomOneDark } from "react-syntax-highlighter/dist/esm/styles/hljs";
import type { DataCompProps } from "../utils";
+import DownloadButton from "../../../../../common/buttons/DownloadButton";
+import { downloadFile } from "../../../../../../utils/fileUtils";
+import { Flex, Menubar } from "./styles";
SyntaxHighlighter.registerLanguage("xml", xml);
SyntaxHighlighter.registerLanguage("plaintext", plaintext);
@@ -46,7 +48,7 @@ function getSyntaxProps(data: string | string[]): SyntaxHighlighterProps {
};
}
-function Text({ studyId, filePath }: DataCompProps) {
+function Text({ studyId, filePath, filename }: DataCompProps) {
const { t } = useTranslation();
const theme = useTheme();
@@ -58,15 +60,28 @@ function Text({ studyId, filePath }: DataCompProps) {
},
);
+ ////////////////////////////////////////////////////////////////
+ // Event Handlers
+ ////////////////////////////////////////////////////////////////
+
+ const handleDownload = () => {
+ if (res.data) {
+ downloadFile(res.data, `${filename}.txt`);
+ }
+ };
+
////////////////////////////////////////////////////////////////
// JSX
////////////////////////////////////////////////////////////////
return (
-
- (
+ (
+
+
+
+
- )}
- />
-
+
+ )}
+ />
);
}
diff --git a/webapp/src/components/App/Singlestudy/explore/Debug/Data/index.tsx b/webapp/src/components/App/Singlestudy/explore/Debug/Data/index.tsx
index be4dc19c54..1423274252 100644
--- a/webapp/src/components/App/Singlestudy/explore/Debug/Data/index.tsx
+++ b/webapp/src/components/App/Singlestudy/explore/Debug/Data/index.tsx
@@ -5,6 +5,7 @@ import Matrix from "./Matrix";
import Folder from "./Folder";
import type { FileInfo, FileType } from "../utils";
import type { DataCompProps } from "../utils";
+import ViewWrapper from "../../../../../common/page/ViewWrapper";
interface Props extends FileInfo {
studyId: string;
@@ -30,12 +31,14 @@ function Data({ studyId, setSelectedFile, ...fileInfo }: Props) {
const DataViewer = componentByFileType[fileType];
return (
-
+
+
+
);
}
diff --git a/webapp/src/components/App/Singlestudy/explore/Debug/Data/styles.ts b/webapp/src/components/App/Singlestudy/explore/Debug/Data/styles.ts
new file mode 100644
index 0000000000..416233c03c
--- /dev/null
+++ b/webapp/src/components/App/Singlestudy/explore/Debug/Data/styles.ts
@@ -0,0 +1,13 @@
+import { styled } from "@mui/material";
+
+export const Flex = styled("div")(({ theme }) => ({
+ height: "100%",
+ display: "flex",
+ flexDirection: "column",
+ gap: theme.spacing(1),
+}));
+
+export const Menubar = styled("div")({
+ display: "flex",
+ justifyContent: "flex-end",
+});