Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reuse the data type auto generated from openapi #76 #84

Draft
wants to merge 7 commits into
base: main
Choose a base branch
from
Draft
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
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
"lint": "eslint src",
"lint:fix": "npm run lint -- --fix",
"codegen:v1": "./node_modules/.bin/openapi -i https://clowder.ncsa.illinois.edu/clowder/swagger -o src/openapi/v1",
"codegen:v2": "./node_modules/.bin/openapi -i ${CLOWDER_REMOTE_HOSTNAME}/api/v2/openapi.json -o src/openapi/v2",
"codegen:v2": "export CLOWDER_REMOTE_HOSTNAME=http://localhost:8000 && ./node_modules/.bin/openapi -i ${CLOWDER_REMOTE_HOSTNAME}/api/v2/openapi.json -o src/openapi/v2",
"codegen": "npm run codegen:v1 && npm run codegen:v2",
"docs": "typedoc"
},
Expand Down
2 changes: 1 addition & 1 deletion src/actions/dataset.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ export function datasetDeleted(datasetId){
export const FOLDER_ADDED = "FOLDER_ADDED";
export function folderAdded(datasetId, folderName, parentFolder = null){
return (dispatch) => {
const folder = {"name": folderName, "parent_folder": parentFolder}
const folder = {"name": folderName, "parent_folder": parentFolder};
return V2.DatasetsService.addFolderApiV2DatasetsDatasetIdFoldersPost(datasetId, folder)
.then(json => {
dispatch({
Expand Down
58 changes: 19 additions & 39 deletions src/components/Dashbard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ import {Box, Button, Dialog, DialogTitle, Grid, Link, Tab, Tabs, Typography} fro

import {CreateDataset} from "./datasets/CreateDataset";

import {Dataset, RootState} from "../types/data";
import {RootState} from "../types/data";
import {DatasetOut as Dataset} from "../openapi/v2";
import {useDispatch, useSelector} from "react-redux";
import {datasetDeleted, fetchDatasets,} from "../actions/dataset";
import {resetFailedReason, resetLogout} from "../actions/common";
import {downloadThumbnail} from "../utils/thumbnail";
import TopBar from "./navigation/TopBar";

import {a11yProps, TabPanel} from "./tabs/TabComponent";
Expand All @@ -32,7 +32,7 @@ export const Dashboard = (): JSX.Element => {

// Redux connect equivalent
const dispatch = useDispatch();
const deleteDataset = (datasetId: string) => dispatch(datasetDeleted(datasetId));
const deleteDataset = (datasetId: string | undefined) => dispatch(datasetDeleted(datasetId));
const listDatasets = (skip: number | undefined, limit: number | undefined, mine: boolean | undefined) => dispatch(fetchDatasets(skip, limit, mine));
const dismissError = () => dispatch(resetFailedReason());
const dismissLogout = () => dispatch(resetLogout());
Expand All @@ -41,7 +41,6 @@ export const Dashboard = (): JSX.Element => {
const stack = useSelector((state: RootState) => state.error.stack);
const loggedOut = useSelector((state: RootState) => state.error.loggedOut);

const [datasetThumbnailList, setDatasetThumbnailList] = useState<any>([]);
// TODO add option to determine limit number; default show 5 datasets each time
const [currPageNum, setCurrPageNum] = useState<number>(0);
const [limit,] = useState<number>(20);
Expand All @@ -61,7 +60,7 @@ export const Dashboard = (): JSX.Element => {
deleteDataset(selectedDataset["id"]);
}
setConfirmationOpen(false);
}
};

// component did mount
useEffect(() => {
Expand All @@ -74,15 +73,15 @@ export const Dashboard = (): JSX.Element => {
if (reason !== "" && reason !== null && reason !== undefined) {
setErrorOpen(true);
}
}, [reason])
}, [reason]);
const handleErrorCancel = () => {
// reset error message and close the error window
dismissError();
setErrorOpen(false);
}
};
const handleErrorReport = () => {
window.open(`${config.GHIssueBaseURL}+${reason}&body=${encodeURIComponent(stack)}`);
}
};

// log user out if token expired/unauthorized
useEffect(() => {
Expand All @@ -93,24 +92,8 @@ export const Dashboard = (): JSX.Element => {
}
}, [loggedOut]);

// fetch thumbnails from each individual dataset/id calls
// check prev/next button valid or not
useEffect(() => {
(async () => {
if (datasets !== undefined && datasets.length > 0) {

// TODO change the type any to something else
const datasetThumbnailListTemp: any = [];
await Promise.all(datasets.map(async (dataset) => {
// add thumbnails
if (dataset["thumbnail"] !== null && dataset["thumbnail"] !== undefined) {
const thumbnailURL = await downloadThumbnail(dataset["thumbnail"]);
datasetThumbnailListTemp.push({"id": dataset["id"], "thumbnail": thumbnailURL});
}
}));
setDatasetThumbnailList(datasetThumbnailListTemp);
}
})();

// disable flipping if reaches the last page
if (datasets.length < limit) setNextDisabled(true);
else setNextDisabled(false);
Expand Down Expand Up @@ -170,7 +153,7 @@ export const Dashboard = (): JSX.Element => {
<div className="inner-container">
<Grid container spacing={4}>
<Grid item xs={8}>
<Box sx={{borderBottom: 1, borderColor: 'divider'}}>
<Box sx={{borderBottom: 1, borderColor: "divider"}}>
<Tabs value={selectedTabIndex} onChange={handleTabChange} aria-label="dashboard tabs">
<Tab sx={tab} label="Datasets" {...a11yProps(0)} />
<Tab sx={tab} label="Activity" {...a11yProps(1)} disabled={true}/>
Expand All @@ -182,19 +165,16 @@ export const Dashboard = (): JSX.Element => {
<TabPanel value={selectedTabIndex} index={0}>
<Grid container spacing={2}>
{
datasets !== undefined && datasetThumbnailList !== undefined ?
datasets.map((dataset) => {
return (
<Grid item xs>
<DatasetCard id={dataset.id} name={dataset.name}
author={dataset.author.email}
created={dataset.created}
description={dataset.description}/>
</Grid>
);
})
:
<></>
datasets.map((dataset) => {
return (
<Grid item xs>
<DatasetCard id={dataset.id} name={dataset.name}
author={dataset.author.full_name}
created={dataset.created}
description={dataset.description}/>
</Grid>
)
})
}
</Grid>
<Button onClick={previous} disabled={prevDisabled}>Prev</Button>
Expand Down
2 changes: 1 addition & 1 deletion src/components/auth/Login.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export const Login = (): JSX.Element => {
// component did mount
useEffect(() => {
if (isAuthorized()) { history("/");}
}, []);
}, []);

const handleKeyPressed= async (event: React.KeyboardEvent<{}>) => {
if (event.key === "Enter") { await handleLoginButtonClick();}
Expand Down
5 changes: 3 additions & 2 deletions src/components/auth/Logout.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// @ts-ignore
import React, {useEffect} from "react";
import {useDispatch} from "react-redux";
import {logout as logoutAction} from "../../actions/user";
Expand All @@ -11,5 +12,5 @@ export const Logout = (): JSX.Element => {

return (
<Navigate to={"/login"}/>
)
}
);
};
4 changes: 2 additions & 2 deletions src/components/auth/Register.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const textField = {
borderColor: "#212529",
},
},
}
};

export const Register = (): JSX.Element => {

Expand All @@ -51,7 +51,7 @@ export const Register = (): JSX.Element => {

useEffect(()=>{
if (registerSucceeded) history("/login");
}, [registerSucceeded])
}, [registerSucceeded]);

const changeUsername = (event: React.ChangeEvent<HTMLInputElement>) => {
setEmail(event.target.value);
Expand Down
75 changes: 34 additions & 41 deletions src/components/datasets/Dataset.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,13 @@ import {
fetchDatasetAbout,
fetchFilesInDataset, fetchFolderPath,
fetchFoldersInDataset,
folderAdded
} from "../../actions/dataset";
import {resetFailedReason, resetLogout} from "../../actions/common"
import {resetFailedReason, resetLogout} from "../../actions/common";

import {a11yProps, TabPanel} from "../tabs/TabComponent";
import TopBar from "../navigation/TopBar";
import {MainBreadcrumbs} from "../navigation/BreadCrumb";
import {UploadFile} from "../files/UploadFile";
import {V2} from "../../openapi";
import {ActionModal} from "../dialog/ActionModal";
import FilesTable from "../files/FilesTable";
import {CreateFolder} from "../folders/CreateFolder";
Expand All @@ -41,32 +39,27 @@ const optionMenuItem = {
fontSize: "14px",
color: "#212529",
marginTop:"8px",
}
};

export const Dataset = (): JSX.Element => {

// path parameter
const { datasetId } = useParams<{datasetId?: string}>();

// search parameters
let [searchParams, setSearchParams] = useSearchParams();
const [searchParams, _] = useSearchParams();
const folder = searchParams.get("folder");
useEffect(() => {
const currentParams = Object.fromEntries([...searchParams]);
console.log(currentParams); // get new values onchange
}, [searchParams]);

// use history hook to redirect/navigate between routes
const history = useNavigate();

// Redux connect equivalent
const dispatch = useDispatch();
const deleteDataset = (datasetId:string|undefined) => dispatch(datasetDeleted(datasetId));
const addFolder = (datasetId:string|undefined, folderName:string, parentFolder:string|null) => dispatch(folderAdded(datasetId, folderName, parentFolder));
const getFolderPath= (folderId:string|undefined) => dispatch(fetchFolderPath(folderId));
const listFilesInDataset = (datasetId:string|undefined, folderId:string|undefined) => dispatch(fetchFilesInDataset(datasetId, folderId));
const listFoldersInDataset = (datasetId:string|undefined, parentFolder:string|undefined) => dispatch(fetchFoldersInDataset(datasetId, parentFolder));
const listDatasetAbout= (datasetId:string|undefined) => dispatch(fetchDatasetAbout(datasetId));
const deleteDataset = (datasetId:string | undefined) => dispatch(datasetDeleted(datasetId));
const getFolderPath= (folderId: string | null) => dispatch(fetchFolderPath(folderId));
const listFilesInDataset = (datasetId: string | undefined, folderId: string | null) => dispatch(fetchFilesInDataset(datasetId, folderId));
const listFoldersInDataset = (datasetId: string | undefined, parentFolder: string | null) => dispatch(fetchFoldersInDataset(datasetId, parentFolder));
const listDatasetAbout= (datasetId?:string) => dispatch(fetchDatasetAbout(datasetId));
const dismissError = () => dispatch(resetFailedReason());
const dismissLogout = () => dispatch(resetLogout());

Expand Down Expand Up @@ -98,15 +91,15 @@ export const Dataset = (): JSX.Element => {
if (reason !== "" && reason !== null && reason !== undefined){
setErrorOpen(true);
}
}, [reason])
}, [reason]);
const handleErrorCancel = () => {
// reset error message and close the error window
dismissError();
setErrorOpen(false);
}
};
const handleErrorReport = (reason:string) => {
window.open(`${config.GHIssueBaseURL}+${reason}&body=${encodeURIComponent(stack)}`);
}
};

// log user out if token expired/unauthorized
useEffect(() => {
Expand All @@ -121,7 +114,7 @@ export const Dataset = (): JSX.Element => {
const [newFolder, setNewFolder] = React.useState<boolean>(false);
const handleCloseNewFolder = () => {
setNewFolder(false);
}
};

const handleTabChange = (_event:React.ChangeEvent<{}>, newTabIndex:number) => {
setSelectedTabIndex(newTabIndex);
Expand Down Expand Up @@ -153,10 +146,10 @@ export const Dataset = (): JSX.Element => {
paths.push({
"name": folderBread["folder_name"],
"url": `/datasets/${datasetId}?folder=${folderBread["folder_id"]}`
})
});
}
} else {
paths.slice(0, 1)
paths.slice(0, 1);
}

return (
Expand All @@ -171,7 +164,7 @@ export const Dataset = (): JSX.Element => {
<div className="inner-container">
<Grid container spacing={4}>
<Grid item xs={8}>
<Box sx={{ borderBottom: 1, borderColor: 'divider' }}>
<Box sx={{ borderBottom: 1, borderColor: "divider" }}>
<Tabs value={selectedTabIndex} onChange={handleTabChange} aria-label="dataset tabs">
<Tab sx={tab} label="Files" {...a11yProps(0)} />
<Tab sx={tab} label="Metadata" {...a11yProps(1)} disabled={true}/>
Expand All @@ -192,17 +185,17 @@ export const Dataset = (): JSX.Element => {
{/*option menus*/}
<Box className="infoCard">
<Button aria-haspopup="true" onClick={handleOptionClick}
sx={{
padding: "6px 12px",
width: "100px",
background: "#6C757D",
borderRadius: "4px",
color: "white",
textTransform: "capitalize",
'&:hover': {
color: "black"
},
}} endIcon={<ArrowDropDownIcon />}>
sx={{
padding: "6px 12px",
width: "100px",
background: "#6C757D",
borderRadius: "4px",
color: "white",
textTransform: "capitalize",
"&:hover": {
color: "black"
},
}} endIcon={<ArrowDropDownIcon />}>
Options
</Button>
<Menu
Expand Down Expand Up @@ -241,7 +234,7 @@ export const Dataset = (): JSX.Element => {
// Go to Explore page
history("/");
}
}>Delete Dataset</MenuItem>
}>Delete Dataset</MenuItem>
<MenuItem onClick={handleOptionClose} sx={optionMenuItem} disabled={true}>Follow</MenuItem>
<MenuItem onClick={handleOptionClose} sx={optionMenuItem} disabled={true}>Collaborators</MenuItem>
<MenuItem onClick={handleOptionClose} sx={optionMenuItem} disabled={true}>Extraction</MenuItem>
Expand All @@ -259,11 +252,11 @@ export const Dataset = (): JSX.Element => {
setNewDatasetName(value);
}} defaultValue={about["name"]}/>
<Button onClick={() => {
V2.DatasetsService.editDatasetApiV2DatasetsDatasetIdPut(about["id"]).then((json: any) => {
// TODO: Dispatch response back to Redux
console.log("PUT Dataset Response:", json);
setEditingName(false);
});
// V2.DatasetsService.editDatasetApiV2DatasetsDatasetIdPut(about["id"]).then((json: any) => {
// // TODO: Dispatch response back to Redux
// console.log("PUT Dataset Response:", json);
// setEditingName(false);
// });
}} disabled={true}>Save</Button>
<Button onClick={() => setEditingName(false)}>Cancel</Button>
</> :
Expand All @@ -272,11 +265,11 @@ export const Dataset = (): JSX.Element => {
</Typography>
}
<Typography className="content">Dataset ID: {about["id"]}</Typography>
<Typography className="content">Owner: {about["authorId"]}</Typography>
<Typography className="content">Owner: {about["author"]["full_name"]}</Typography>
<Typography className="content">Description: {about["description"]}</Typography>
<Typography className="content">Created on: {parseDate(about["created"])}</Typography>
{/*/!*TODO use this to get thumbnail*!/*/}
<Typography className="content">Thumbnail: {about["thumbnail"]}</Typography>
{/*<Typography className="content">Thumbnail: {about["thumbnail"]}</Typography>*/}
{/*<Typography className="content">Belongs to spaces: {about["authorId"]}</Typography>*/}
{/*/!*TODO not sure how to use this info*!/*/}
{/*<Typography className="content">Resource type: {about["resource_type"]}</Typography>*/}
Expand Down
23 changes: 12 additions & 11 deletions src/components/datasets/DatasetCard.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,27 @@
// @ts-ignore
import React from "react";
import Card from '@mui/material/Card';
import CardActions from '@mui/material/CardActions';
import CardContent from '@mui/material/CardContent';
import Button from '@mui/material/Button';
import Typography from '@mui/material/Typography';
import Card from "@mui/material/Card";
import CardActions from "@mui/material/CardActions";
import CardContent from "@mui/material/CardContent";
import Button from "@mui/material/Button";
import Typography from "@mui/material/Typography";
import {useNavigate} from "react-router-dom";
import {parseDate} from "../../utils/common";

type DatasetCardProps = {
id: string,
name: string,
author: string,
created: string | Date,
description: string
id?: string,
name?: string,
author?: string,
created?: string | Date,
description?: string
}

export default function DatasetCard(props: DatasetCardProps) {
const { id, name, author, created, description} = props;
const formattedCreated = parseDate(created);
// use history hook to redirect/navigate between routes
const history = useNavigate();
const selectDataset = (selectedDatasetId: string) => {
const selectDataset = (selectedDatasetId: string | undefined) => {
// Redirect to dataset route with dataset Id
history(`/datasets/${selectedDatasetId}`);
};
Expand Down
Loading