Skip to content
Snippets Groups Projects
Commit 32130bec authored by Tarek Shah's avatar Tarek Shah
Browse files

frontend aesthetics; need to implement deleting collections

parent 15fcee1b
No related branches found
No related tags found
No related merge requests found
Showing
with 222 additions and 143 deletions
frontend/crisis-events-text-summarization-frontend/public/images/canada_wildfires.jpg

675 KiB

frontend/crisis-events-text-summarization-frontend/public/images/covid.png

370 KiB

.App {
text-align: center;
}
.App-logo {
height: 40vmin;
pointer-events: none;
}
@media (prefers-reduced-motion: no-preference) {
.App-logo {
animation: App-logo-spin infinite 20s linear;
}
}
.App-header {
background-color: #282c34;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: white;
}
.App-link {
color: #61dafb;
}
@keyframes App-logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
text-align: left;
font-family: "Quicksand", Arial, sans-serif;
}
\ No newline at end of file
import logo from './logo.svg';
import './App.css';
import './login'
import Login from './login.js';
import React, { useState, useEffect, useContext } from 'react'
import Home from './Home.js';
import React, { useState, useEffect } from 'react'
// MUI imports
import Tabs from '@mui/material/Tabs';
import Tab from '@mui/material/Tab';
import Typography from '@mui/material/Typography';
import Toolbar from '@mui/material/Toolbar';
import AppBar from '@mui/material/AppBar';
import Box from '@mui/material/Box';
import Button from '@mui/material/Button';
import ButtonGroup from '@mui/material/ButtonGroup';
import Divider from '@mui/material/Divider';
import Grid from '@mui/material/Grid';
import TextField from '@mui/material/TextField';
import CollectionList from './collection_list';
import CollectionEditor from './collection_editor';
......@@ -65,11 +63,8 @@ function App() {
useEffect(
() => {
// console.log("Mounting App");
updateCollectionList();
},[]//Only runs once, equivalent of ComponentDidMount
},[]
);
useEffect(
......@@ -100,7 +95,7 @@ function App() {
const showEditor= () => {
if (selectedCollection == null) {
return (<h1>Select/Create a Collection</h1>);
return (<Home></Home>); // Landing page
} else {
return (<CollectionEditor collection={selectedCollection} onCollectionUpdate={setSelectedCollection} onFileSelect={onFileChange} loadedRawFiles={loadedRawFiles}/>);
}
......@@ -113,11 +108,7 @@ function App() {
}
const onFileChange = async (e) => {
// console.log(e.target.files[0])
var formData = new FormData();
formData.append(e.target.files[0].name, e.target.files[0]);
await fetch('http://127.0.0.1:5000//api/v1/upload_raw_text?collection=0', {
......@@ -137,8 +128,8 @@ function App() {
}
const logoutFunction = () => {
setAuthenticated(false);
sessionStorage.setItem('authenticated', 'false');
setAuthenticated(false);
sessionStorage.setItem('authenticated', 'false');
};
if (!authenticated) {
......@@ -169,26 +160,36 @@ function App() {
return (
<div className="App">
<Box sx={{padding:2}}>
<Box sx={{textAlign:"left", padding:1}}> {/*This is where the menu should go*/}
<ButtonGroup variant="contained" aria-label="Basic button group">
<Button>Home</Button>
<Button onClick={logoutFunction}>Logout</Button>
{/*<Button onClick={loginFunction}>Login</Button>*/}
</ButtonGroup>
<Box sx={{paddingTop: '50px', paddingLeft: '30px'}}>
{/* <Box sx={{textAlign:"left", padding:3}}> */}
<AppBar>
<Toolbar>
<Button
style={{border: '1px solid white', color: 'white', width: '100px'}}
onClick={() => {
setSelectedCollection(null);
showEditor();
}}
>
Home
</Button>
<Typography variant="h6" component="div" sx={{ flexGrow: 1, textAlign: 'center' }}>
Crisis Events Text Summarization (CETS)
</Typography>
<Button
style={{border: '1px solid white', color: 'white', width: '100px'}}
onClick={logoutFunction}
>
Logout
</Button>
</Toolbar>
</AppBar>
<br/>
{/* <b>Login Status: {displayLoginStatus()}</b> */}
</Box>
<h1>CETS API</h1>
{/* </Box> */}
<Divider orientation="horizontal" flexItem />
<Box sx={{border: '1px dashed grey', padding:1}}> {/*This provides creation of collections and selection*/}
{/* <Box sx={{border: '1px dashed grey', padding:1}}> */}
<Grid container spacing={2}>
<Grid item xs={2}>
<CollectionList collections={loadedCollections} onSelectCollection={setSelectedCollection} onListUpdate={updateCollectionList} onFileSelect={onFileSelect} collectionFileCache={collectionFileCache}/>
......@@ -197,10 +198,9 @@ function App() {
{
showEditor()
}
{/* <b>{JSON.stringify(selectedCollection)}</b> */}
</Grid>
</Grid>
</Box>
{/* </Box> */}
</Box>
</div>
);
......
function Home() {
const handleFileDownload = (filename, content) => {
const element = document.createElement('a');
const file = new Blob([content], { type: 'text/plain' });
element.href = URL.createObjectURL(file);
element.download = filename;
document.body.appendChild(element);
element.click();
document.body.removeChild(element);
};
return(
<div>
<h1>Welcome to CETS</h1>
<h2>Overview</h2>
<p>Stay informed about critical global events with CETS. We provide summaries of crisis events covering mass shootings, natural disasters, public health emergencies, and more.
Our mission is to deliver accurate information to help you understand and navigate crisis situations.
</p>
<h2>Create or select a collection to begin learning about crisis events</h2>
<p>Below, we have provided examples of crisis events that you may want to learn about.</p>
<h2>Example Crisis Events</h2>
<div className='event-container' style={{ display: 'flex', flexDirection: 'row', justifyContent: 'space-between'}}>
<div className='event' style={{ display: 'flex', flexDirection: 'column', width: '31%' }}>
<img src="images/monterey_park_shooting.jpg" alt="monterey park shooting" style={{ maxWidth: '100%', paddingRight: '10px' }} />
<p
style={{color: 'dodgerblue', textAlign: 'center', cursor: 'pointer', textDecoration: 'underline'}}
onClick={() => handleFileDownload('monterey_park_urls.txt', 'https://www.cnn.com/2023/01/24/us/monterey-park-california-mass-shooting-tuesday/index.html\n' +
'https://www.latimes.com/california/story/2023-01-22/la-me-monterey-park-mass-shooting\n' +
'https://www.npr.org/2023/01/23/1150667373/monterey-park-shooting-what-we-know-california\n' +
'https://abc7.com/monterey-park-mass-shooting-one-year-later-vigil/14346773/')}
>
Monterey Park Shooting
</p>
</div>
<div className='event' style={{ display: 'flex', flexDirection: 'column', width: '32.5%' }}>
<img src="images/canada_wildfires.jpg" alt="canada wildfires" style={{ height: '210px', maxWidth: '100%', paddingRight: '10px' }} />
<p
style={{color: 'dodgerblue', textAlign: 'center', cursor: 'pointer', textDecoration: 'underline'}}
onClick={() => handleFileDownload('canada_wildfire_urls.txt', 'https://earthobservatory.nasa.gov/images/151985/tracking-canadas-extreme-2023-fire-season\n' +
'https://www.washingtonpost.com/climate-environment/2024/02/24/canada-wildfires-zombie-fires/\n' +
'https://en.wikipedia.org/wiki/2023_Canadian_wildfires\n' +
'https://www.nytimes.com/interactive/2023/us/smoke-maps-canada-fires.html')}
>
Canada Wildfires
</p>
</div>
<div className='event' style={{ display: 'flex', flexDirection: 'column', width: '32.5%' }}>
<img src="images/covid.png" alt="covid 19" style={{ height: '210px', maxWidth: '100%'}} />
<p
style={{color: 'dodgerblue', textAlign: 'center', cursor: 'pointer', textDecoration: 'underline'}}
onClick={() => handleFileDownload('covid19_urls.txt', 'https://en.wikipedia.org/wiki/COVID-19\n' +
'https://www.mayoclinic.org/diseases-conditions/coronavirus/symptoms-causes/syc-20479963\n' +
'https://www.whitehouse.gov/covidplan/\n' +
'https://www.ecdc.europa.eu/en/covid-19')}
>
Covid-19
</p>
</div>
</div>
<p>To learn about one of the above crisis events, click on the one you would like to learn about to download the files for it. Then, create a new collection, upload the files, choose your desired summary and click generate summary.</p>
</div>
);
}
export default Home;
\ No newline at end of file
.sidebar-container {
position: fixed;
left: 0;
top: 0;
bottom: 0;
width: 225px; /* Adjust the width of the sidebar as needed */
background-color: #f0f0f0;
overflow-y: auto;
border-right: 1px solid #ccc; /* Add a border on the right side */
}
.sidebar {
padding: 20px;
}
\ No newline at end of file
// import './login.css';
import { Backdrop, Box, Button, CircularProgress, TextField, List, ListItem, ListItemButton, ListItemText, ListItemIcon, Select, MenuItem } from '@mui/material';
import React, { useState, useEffect } from 'react'
import { dbGetCollection, dbGetItems, dbUpdateCollectionGlob, dbUpdateCollectionSummary, dbUpdateCollectionSummaryNLTK, dbUpdateCollectionSummaryBERT } from './database_util';
import AddIcon from '@mui/icons-material/Add';
import { Backdrop, Box, Button, CircularProgress, TextField, List, ListItem, ListItemButton, ListItemText, Select, MenuItem } from '@mui/material';
import React, { useState } from 'react'
import { dbGetCollection, dbUpdateCollectionSummary } from './database_util';
const CollectionEditor = (props) => {
const [open, setOpen] = useState(false);
const [summarizer, setSummarizer] = useState('');
const updateGlob = (event) => {
// console.log();
let copy = JSON.parse(JSON.stringify(props.collection))
copy["collection_data"]["glob"] = event.target.value
props.onCollectionUpdate(copy)
// console.log(copy);
}
const summary_array = () => {
return [["T5",props.collection["t5_summary"]], ["NLTK", props.collection["nltk_summary"]], ["BERT",props.collection["bert_summary"]]]
return [["T5 Summary",props.collection["t5_summary"]], ["NLTK Summary", props.collection["nltk_summary"]], ["BERT Summary",props.collection["bert_summary"]]]
}
const generateSummary = async () => {
......@@ -41,9 +26,7 @@ const CollectionEditor = (props) => {
return (
<Box>
<h1>{props.collection["collection_name"]}</h1>
<h3>Loaded Files</h3>
<List sx={{boxShadow:1}}>
{
props.loadedRawFiles.map((f) => {
......@@ -75,19 +58,25 @@ const CollectionEditor = (props) => {
</Select>
</ListItem>
</List>
<Button onClick={generateSummary}>Generate Summary</Button>
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
<Button
style={{ height: '60px', width: '300px', marginTop: '10px', border: '1px solid blue', color: 'blue' }}
onClick={generateSummary}
>
Generate Summary
</Button>
</div>
{
summary_array().map((f) => {
return (
<div>
<h3>{f[0]}</h3>
<TextField disabled multiline maxRows={20} fullWidth label="Summary:" value={f[1]} />
<TextField style={{marginBottom: '10px'}} disabled multiline maxRows={20} fullWidth label="Summary:" value={f[1]} />
</div>
);
})
}
{/* {summaries.map((summary) => summary)} */}
<Backdrop
open={open}
......
import React, { useState, useEffect } from 'react'
import * as React from 'react'
import './Sidebar.css'
import {dbCreateCollection, dbGetCollection, dbUploadRawTextFiles, dbUploadUrlFile, dbUploadRawHTMLFiles} from './database_util'
//General MUI imports
import Box from '@mui/material/Box';
import Button from '@mui/material/Button';
import CircularProgress from '@mui/material/CircularProgress';
import Backdrop from '@mui/material/Backdrop';
import TextField from '@mui/material/TextField';
import Autocomplete from '@mui/material/Autocomplete';
import Select from '@mui/material/Select';
import MenuItem from '@mui/material/MenuItem';
import Radio from '@mui/material/Radio';
import RadioGroup from '@mui/material/RadioGroup';
import FormControlLabel from '@mui/material/FormControlLabel';
import FormControl from '@mui/material/FormControl';
import FormLabel from '@mui/material/FormLabel';
//Dialog Imports
import Dialog from '@mui/material/Dialog';
......@@ -25,6 +22,7 @@ import DialogActions from '@mui/material/DialogActions';
//icon
import LayersIcon from '@mui/icons-material/Layers';
import AddIcon from '@mui/icons-material/Add';
import DeleteIcon from '@mui/icons-material/Delete';
//List Imports
import List from '@mui/material/List';
......@@ -36,27 +34,40 @@ import ListItem from '@mui/material/ListItem';
const CollectionList = (props) => {
const [open, setOpen] = React.useState(false);
const [deleteOpen, setDeleteOpen] = React.useState(false);
const [displayedCollection, setDisplayedCollection] = React.useState('');
const [newCollectionName, setNewCollectionName] = React.useState("false");
const [newCollectionType, setNewCollectionType] = React.useState("text");
// Handles when the user closes out of the "Create New Collection" dialog box
const handleClose = () => {
setOpen(false);
};
// Handles when the user clicks the "Create New Collection" button
const handleOpen = () => {
setNewCollectionName("");
setOpen(true);
};
// Handles when the user closes out of the "Delete a Collection" dialog box
const handleDeleteClose = () => {
setDeleteOpen(false);
};
// Handles when the user clicks the "Delete a Collection" button
const handleDeleteOpen = () => {
setDeleteOpen(true);
};
const handleSubmit = async (e) => {
e.preventDefault();
console.log(newCollectionType);
let id = await dbCreateCollection(newCollectionName,newCollectionType);
if (newCollectionType == "text"){
if (newCollectionType === "text"){
await dbUploadRawTextFiles(id,props.collectionFileCache);
} else if (newCollectionType == "url"){
} else if (newCollectionType === "url"){
await dbUploadUrlFile(id,props.collectionFileCache)
} else if (newCollectionType == "html"){
} else if (newCollectionType === "html"){
await dbUploadRawHTMLFiles(id,props.collectionFileCache)
} else {
await dbUploadRawTextFiles(id,props.collectionFileCache);
......@@ -75,38 +86,45 @@ const CollectionList = (props) => {
}
return (
<Box sx={{
"boxShadow":3
}}>
<List>
<ListItem disablePadding key={999}>
<ListItemButton onClick={handleOpen}>
<ListItemIcon>
<AddIcon/>
</ListItemIcon>
<ListItemText primary={"Create New Collection"}/>
</ListItemButton>
</ListItem>
<Divider />
{
props.collections.map(
(c) => {
console.log("BRUH",c)
return (
<ListItem disablePadding key={c["collection_id"]}>
<ListItemButton onClick={() => handleSelect(c["collection_id"])}>
<ListItemIcon>
<LayersIcon />
</ListItemIcon>
<ListItemText primary={c["collection_name"]} secondary={c["collection_id"]}/>
</ListItemButton>
</ListItem>
)}
)
}
</List>
<div className="sidebar-container">
<aside id="aside" className="sidebar">
<List style={{marginTop: '60px'}}>
<ListItem disablePadding key={999}>
<ListItemButton style={{border: '1px grey'}} onClick={handleOpen}>
<ListItemIcon>
<AddIcon/>
</ListItemIcon>
<ListItemText style={{marginLeft: '-10px'}} primary={"Create New Collection"}/>
</ListItemButton>
</ListItem>
<Divider />
<ListItem disablePadding key={999}>
<ListItemButton style={{border: '1px grey'}} onClick={handleDeleteOpen}>
<ListItemIcon>
<DeleteIcon/>
</ListItemIcon>
<ListItemText style={{marginLeft: '-10px'}} primary={"Delete a Collection"}/>
</ListItemButton>
</ListItem>
<Divider />
{
props.collections.map(
(c) => {
console.log("BRUH",c)
return (
<ListItem disablePadding key={c["collection_id"]}>
<ListItemButton style={{border: '1px grey'}} onClick={() => handleSelect(c["collection_id"])}>
<ListItemIcon>
<LayersIcon />
</ListItemIcon>
<ListItemText style={{marginLeft: '-10px'}} primary={c["collection_name"]} secondary={c["collection_id"]}/>
</ListItemButton>
</ListItem>
)}
)
}
</List>
</aside>
<Dialog
open={open}
onClose={handleClose}
......@@ -116,7 +134,6 @@ const CollectionList = (props) => {
}}
>
<DialogTitle>Create New Collection</DialogTitle>
<DialogContent>
<br/>
<TextField label="Collection Name" variant="outlined" required value={newCollectionName} onChange={(e)=> {setNewCollectionName(e.target.value)}}/>
......@@ -136,16 +153,41 @@ const CollectionList = (props) => {
<FormControlLabel value="url" control={<Radio />} label=".txt file of urls" />
<FormControlLabel value="html" control={<Radio />} label=".zip of html files" />
</RadioGroup>
</DialogContent>
<DialogActions>
<Button onClick={handleClose}>Cancel</Button>
<Button type="submit">Create</Button>
</DialogActions>
</Dialog>
</Box>
<Dialog
open={deleteOpen}
onClose={handleDeleteClose}
>
<DialogTitle>Delete a Collection</DialogTitle>
<DialogContent>
<Select
value={displayedCollection}
onChange={(event) => {
setDisplayedCollection(event.target.value);
}}
sx={{width: '100%'}}
>
{props.collections.map((c, index) => (
<MenuItem
key={index}
value={c["collection_name"]}
>
{c["collection_name"]}
</MenuItem>
))}
</Select>
</DialogContent>
<DialogActions>
<Button onClick={handleDeleteClose}>Cancel</Button>
<Button >Delete</Button>
</DialogActions>
</Dialog>
</div>
);
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment