Skip to content

Commit 8866c50

Browse files
longshuicylmariniddey2
authored
131 custom widget and appearance for reactivesearch (#134)
* replace dataset card * Explore page cleanup (#108) * Removed placeholder right column on Explore page. Switched to clickable card for datasets. * Show only 5 max lines for description of dataset card and add ellypsis. * Default sort dataset list by creation date descending. * Make sure Dataset CardActionArea fills the card so that CardAction is flushed at the bottom. * Fixed dataset grid so that items are same width even if we don't have enough for one row. * New previous/next buttons on dataset list. * Change default page size for dataset list to 20, a multiple of 4, the default screen size columns size. * Placeholder icons for download card download, favorite, share actions. * Black formatting. * Extra margin around dataset card icons to make it easier to click on icons. * Set outer grid item size for proper layout when there is few datasets. * remove wrong primary * add layout * add styling * customize the searchbox * styling the search dataset page * add links to the side bar * add files table * default to its original * add TODOs * Added endpoint to search both file and dataset. * embed datasearch to topbar * add embedded search to the correct place * wrap the search base on parent comp and dynamically switching between index for now * embedded search working now * multi search * combine two searches into one * identify based on index * work on result component * initial styles * add more index * include more fields on file * fix typo * no need to pass dataset name as a query parameter; get that info from backend * black linting * use react router link instead of the refreshing link * remove unused component * bump mui icon version up; use dataset icon Co-authored-by: Luigi Marini <[email protected]> Co-authored-by: Dipannita Dey <[email protected]>
1 parent 9283e54 commit 8866c50

File tree

22 files changed

+456
-239
lines changed

22 files changed

+456
-239
lines changed

backend/app/routers/files.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,10 @@ async def add_file_entry(
9797
"creator": file_db.creator.email,
9898
"created": file_db.created,
9999
"download": file_db.downloads,
100+
"dataset_id": str(file_db.dataset_id),
101+
"folder_id": str(file_db.folder_id),
102+
"bytes": file_db.bytes,
103+
"content_type": file_db.content_type,
100104
}
101105
insert_record(es, "file", doc, file_db.id)
102106

backend/app/search/config.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ class IndexSettings:
55
"created": {"type": "date"},
66
"creator": {"type": "keyword"},
77
"download": {"type": "long"},
8+
"dataset_id": {"type": "string"},
9+
"folder_id": {"type": "string"},
10+
"bytes": {"type": "long"},
11+
"content_type": {"type": "keyword"},
812
}
913
}
1014

backend/app/tests/test_elastic_search.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
import time
33
from datetime import datetime
44

5+
from bson import ObjectId
6+
57
from app.config import settings
68
from app.search.config import indexSettings
79
from app.search.connect import (
@@ -22,6 +24,10 @@
2224
"creator": "xyz",
2325
"created": datetime.now(),
2426
"download": 0,
27+
"dataset_id": str(ObjectId("63458339aaecb776733354ea")),
28+
"folder_id": None,
29+
"bytes": 123456,
30+
"content_type": "application/json",
2531
}
2632
updated_dummy_file_record = {
2733
"doc": {

frontend/src/components/Layout.tsx

Lines changed: 135 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,28 @@ import CssBaseline from '@mui/material/CssBaseline';
66
import MuiAppBar, {AppBarProps as MuiAppBarProps} from '@mui/material/AppBar';
77
import Toolbar from '@mui/material/Toolbar';
88
import List from '@mui/material/List';
9-
import Typography from '@mui/material/Typography';
109
import Divider from '@mui/material/Divider';
1110
import IconButton from '@mui/material/IconButton';
1211
import MenuIcon from '@mui/icons-material/Menu';
1312
import ChevronLeftIcon from '@mui/icons-material/ChevronLeft';
1413
import ChevronRightIcon from '@mui/icons-material/ChevronRight';
14+
import SearchDatasetIcon from '@mui/icons-material/Search';
1515
import ListItem from '@mui/material/ListItem';
1616
import ListItemButton from '@mui/material/ListItemButton';
1717
import ListItemIcon from '@mui/material/ListItemIcon';
1818
import ListItemText from '@mui/material/ListItemText';
19-
import InboxIcon from '@mui/icons-material/MoveToInbox';
20-
import MailIcon from '@mui/icons-material/Mail';
2119
import {Link} from "@mui/material";
22-
import {Link as RouterLink} from 'react-router-dom';
20+
import {Link as RouterLink, useLocation} from 'react-router-dom';
2321
import {useSelector} from "react-redux";
2422
import {RootState} from "../types/data";
2523
import {AddBox, Explore} from "@material-ui/icons";
24+
import {EmbeddedSearch} from "./search/EmbeddedSearch";
25+
import {searchTheme} from "../theme";
26+
import {ReactiveBase} from "@appbaseio/reactivesearch";
27+
import Cookies from "universal-cookie";
28+
import {useEffect} from "react";
29+
30+
const cookies = new Cookies();
2631

2732
const drawerWidth = 240;
2833

@@ -45,6 +50,13 @@ const Main = styled('main', {shouldForwardProp: (prop) => prop !== 'open'})<{
4550
}),
4651
}));
4752

53+
const SearchDiv = styled("div")(({ theme }) => ({
54+
position: "relative",
55+
marginLeft: theme.spacing(3),
56+
marginBottom: "-5px", // to compoensate the tags div
57+
width: "50%",
58+
}));
59+
4860
interface AppBarProps extends MuiAppBarProps {
4961
open?: boolean;
5062
}
@@ -87,6 +99,7 @@ export default function PersistentDrawerLeft(props) {
8799
const {children} = props;
88100
const theme = useTheme();
89101
const [open, setOpen] = React.useState(false);
102+
const [embeddedSearchHidden, setEmbeddedSearchHidden] = React.useState(false);
90103

91104
const handleDrawerOpen = () => {
92105
setOpen(true);
@@ -96,83 +109,127 @@ export default function PersistentDrawerLeft(props) {
96109
setOpen(false);
97110
};
98111

112+
const location = useLocation();
113+
114+
useEffect(()=>{
115+
if (location.pathname.includes("search")){
116+
setEmbeddedSearchHidden(true);
117+
}
118+
else{
119+
setEmbeddedSearchHidden(false);
120+
}
121+
}, [location])
122+
99123
const loggedOut = useSelector((state: RootState) => state.error.loggedOut);
100124

125+
101126
return (
102-
<Box sx={{display: 'flex'}}>
103-
<CssBaseline/>
104-
<AppBar position="fixed" open={open}>
105-
<Toolbar>
106-
<IconButton
107-
color="inherit"
108-
aria-label="open drawer"
109-
onClick={handleDrawerOpen}
110-
edge="start"
111-
sx={{mr: 2, ...(open && {display: 'none'})}}
112-
>
113-
<MenuIcon/>
114-
</IconButton>
115-
<Link href="/">
116-
<Box component="img" src="../../public/clowder-logo-sm.svg" alt="clowder-logo-sm" sx={{verticalAlign:"middle"}}/>
117-
</Link>
118-
<Box sx={{marginLeft: "auto"}}>
119-
{
120-
loggedOut ?
121-
<>
122-
<Link href="/auth/register" sx={link}>Register</Link>
123-
<Link href="/auth/login" sx={link}>Login</Link>
124-
</>
125-
:
126-
<Link href="/auth/logout" sx={link}>Logout</Link>
127-
}
128-
</Box>
129-
</Toolbar>
130-
</AppBar>
131-
<Drawer
132-
sx={{
133-
width: drawerWidth,
134-
flexShrink: 0,
135-
'& .MuiDrawer-paper': {
127+
// Wrap reactive search base on the most outside component
128+
<ReactiveBase
129+
// TODO put it in the Config file or other ways to dynamically pass in
130+
url="http://localhost:8000/api/v2/elasticsearch"
131+
app="file,dataset"
132+
headers={{"Authorization": cookies.get("Authorization")}}
133+
// transformResponse={(elasticsearchResponse) => {
134+
// console.log(elasticsearchResponse)
135+
// // if (elasticsearchResponse.detail.error === "invalid_token"){
136+
// // console.log("token expired!");
137+
// // }
138+
// }}
139+
theme={searchTheme}
140+
>
141+
<Box sx={{display: 'flex'}}>
142+
<CssBaseline/>
143+
<AppBar position="fixed" open={open}>
144+
<Toolbar>
145+
<IconButton
146+
color="inherit"
147+
aria-label="open drawer"
148+
onClick={handleDrawerOpen}
149+
edge="start"
150+
sx={{mr: 2, ...(open && {display: 'none'})}}
151+
>
152+
<MenuIcon/>
153+
</IconButton>
154+
<Link href="/">
155+
<Box component="img" src="../../public/clowder-logo-sm.svg" alt="clowder-logo-sm" sx={{verticalAlign:"middle"}}/>
156+
</Link>
157+
158+
{/*for searching*/}
159+
<SearchDiv hidden={embeddedSearchHidden}>
160+
<EmbeddedSearch />
161+
</SearchDiv>
162+
<Box sx={{ flexGrow: 1 }} />
163+
<Box sx={{marginLeft: "auto"}}>
164+
{
165+
loggedOut ?
166+
<>
167+
<Link href="/auth/register" sx={link}>Register</Link>
168+
<Link href="/auth/login" sx={link}>Login</Link>
169+
</>
170+
:
171+
<Link href="/auth/logout" sx={link}>Logout</Link>
172+
}
173+
</Box>
174+
</Toolbar>
175+
</AppBar>
176+
<Drawer
177+
sx={{
136178
width: drawerWidth,
137-
boxSizing: 'border-box',
138-
},
139-
}}
140-
variant="persistent"
141-
anchor="left"
142-
open={open}
143-
>
144-
<DrawerHeader>
145-
<IconButton onClick={handleDrawerClose}>
146-
{theme.direction === 'ltr' ? <ChevronLeftIcon/> : <ChevronRightIcon/>}
147-
</IconButton>
148-
</DrawerHeader>
149-
<Divider/>
150-
<List>
151-
<ListItem key={"explore"} disablePadding>
152-
<ListItemButton component={RouterLink} to="/">
153-
<ListItemIcon>
154-
<Explore/>
155-
</ListItemIcon>
156-
<ListItemText primary={"Explore"}/>
157-
</ListItemButton>
158-
</ListItem>
159-
</List>
160-
<Divider/>
161-
<List>
162-
<ListItem key={"newdataset"} disablePadding>
163-
<ListItemButton component={RouterLink} to="/create-dataset">
164-
<ListItemIcon>
165-
<AddBox/>
166-
</ListItemIcon>
167-
<ListItemText primary={"New Dataset"}/>
168-
</ListItemButton>
169-
</ListItem>
170-
</List>
171-
</Drawer>
172-
<Main open={open}>
173-
<DrawerHeader/>
174-
{children}
175-
</Main>
176-
</Box>
179+
flexShrink: 0,
180+
'& .MuiDrawer-paper': {
181+
width: drawerWidth,
182+
boxSizing: 'border-box',
183+
},
184+
}}
185+
variant="persistent"
186+
anchor="left"
187+
open={open}
188+
>
189+
<DrawerHeader>
190+
<IconButton onClick={handleDrawerClose}>
191+
{theme.direction === 'ltr' ? <ChevronLeftIcon/> : <ChevronRightIcon/>}
192+
</IconButton>
193+
</DrawerHeader>
194+
<Divider/>
195+
<List>
196+
<ListItem key={"explore"} disablePadding>
197+
<ListItemButton component={RouterLink} to="/">
198+
<ListItemIcon>
199+
<Explore/>
200+
</ListItemIcon>
201+
<ListItemText primary={"Explore"}/>
202+
</ListItemButton>
203+
</ListItem>
204+
</List>
205+
<Divider/>
206+
<List>
207+
<ListItem key={"search"} disablePadding>
208+
<ListItemButton component={RouterLink} to="/search">
209+
<ListItemIcon>
210+
<SearchDatasetIcon/>
211+
</ListItemIcon>
212+
<ListItemText primary={"Search"}/>
213+
</ListItemButton>
214+
</ListItem>
215+
</List>
216+
<Divider/>
217+
<List>
218+
<ListItem key={"newdataset"} disablePadding>
219+
<ListItemButton component={RouterLink} to="/create-dataset">
220+
<ListItemIcon>
221+
<AddBox/>
222+
</ListItemIcon>
223+
<ListItemText primary={"New Dataset"}/>
224+
</ListItemButton>
225+
</ListItem>
226+
</List>
227+
</Drawer>
228+
<Main open={open}>
229+
<DrawerHeader/>
230+
{children}
231+
</Main>
232+
</Box>
233+
</ReactiveBase>
177234
);
178235
}

frontend/src/components/datasets/Dataset.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ export const Dataset = (): JSX.Element => {
264264
</Tabs>
265265
</Box>
266266
<TabPanel value={selectedTabIndex} index={0}>
267-
<FilesTable datasetId={datasetId} datasetName={about.name}/>
267+
<FilesTable datasetId={datasetId}/>
268268
</TabPanel>
269269
<TabPanel value={selectedTabIndex} index={1}>
270270
{

frontend/src/components/files/File.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import {EditMetadata} from "../metadata/EditMetadata";
2828
import {ClowderButton} from "../styledComponents/ClowderButton";
2929
import CloseIcon from "@mui/icons-material/Close";
3030
import Layout from "../Layout";
31+
import {fetchDatasetAbout} from "../../actions/dataset";
3132

3233
const tab = {
3334
fontStyle: "normal",
@@ -44,7 +45,8 @@ export const File = (): JSX.Element => {
4445
// query parameter get dataset id
4546
const search = useLocation().search;
4647
const datasetId = new URLSearchParams(search).get("dataset");
47-
const datasetName = new URLSearchParams(search).get("name");
48+
const listDatasetAbout= (datasetId:string|undefined) => dispatch(fetchDatasetAbout(datasetId));
49+
const about = useSelector((state: RootState) => state.dataset.about);
4850

4951
const dispatch = useDispatch();
5052
const listFileSummary = (fileId:string|undefined) => dispatch(fetchFileSummary(fileId));
@@ -71,6 +73,7 @@ export const File = (): JSX.Element => {
7173
// load file information
7274
listFileSummary(fileId);
7375
listFileVersions(fileId);
76+
listDatasetAbout(datasetId); // get dataset name
7477
}, []);
7578

7679

@@ -169,7 +172,7 @@ export const File = (): JSX.Element => {
169172
"url": "/",
170173
},
171174
{
172-
"name":datasetName,
175+
"name":about["name"],
173176
"url":`/datasets/${datasetId}`
174177
}
175178
];

frontend/src/components/files/FilesTable.tsx

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,11 @@ import FolderIcon from '@mui/icons-material/Folder';
1515
import InsertDriveFileIcon from '@mui/icons-material/InsertDriveFile';
1616
import {parseDate} from "../../utils/common";
1717
import {VersionChip} from "../versions/VersionChip";
18-
import theme from "../../theme";
18+
import {theme} from "../../theme";
19+
import {FilesTableFileEntry} from "./FilesTableFileEntry";
1920

2021
type FilesTableProps = {
2122
datasetId: string | undefined,
22-
datasetName: string
2323
}
2424

2525
const iconStyle = {
@@ -35,7 +35,7 @@ export default function FilesTable(props: FilesTableProps) {
3535
const history = useNavigate();
3636
const selectFile = (selectedFileId: string|undefined) => {
3737
// Redirect to file route with file Id and dataset id
38-
history(`/files/${selectedFileId}?dataset=${props.datasetId}&name=${props.datasetName}`);
38+
history(`/files/${selectedFileId}?dataset=${props.datasetId}`);
3939
};
4040
const selectFolder = (selectedFolderId: string|undefined) => {
4141
// Redirect to file route with file Id and dataset id
@@ -72,21 +72,11 @@ export default function FilesTable(props: FilesTableProps) {
7272
}
7373
{
7474
filesInDataset.map((file) => (
75-
<TableRow
76-
key={file.id}
77-
sx={{ '&:last-child td, &:last-child th': { border: 0 } }}
78-
>
79-
<TableCell component="th" scope="row">
80-
<InsertDriveFileIcon color="primary" sx={iconStyle}/>
81-
<Button onClick={() => selectFile(file.id)}>{file.name}</Button>
82-
{/*TODO this should be version number; for now put version ID instead*/}
83-
<VersionChip versionNumber={file.version_num}/>
84-
</TableCell>
85-
<TableCell align="right">{parseDate(file.created)} by {file.creator.first_name} {file.creator.last_name}</TableCell>
86-
<TableCell align="right">{file.bytes} bytes</TableCell>
87-
<TableCell align="right">{file.content_type}</TableCell>
88-
<TableCell align="right"><FileMenu file={file}/></TableCell>
89-
</TableRow>))
75+
<FilesTableFileEntry
76+
iconStyle={iconStyle}
77+
selectFile={selectFile}
78+
file={file} />
79+
))
9080
}
9181
</TableBody>
9282
</Table>

0 commit comments

Comments
 (0)