@material-ui/core#TablePagination JavaScript Examples
The following examples show how to use
@material-ui/core#TablePagination.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: ApplicationListPage.jsx From frontend with MIT License | 5 votes |
ApplicationPage = () => {
const classes = useStyles();
const [handlePageChange,
handleChangeRowsPerPage,
pagination, paginateData] = usePaginateHandlers(applications);
return (
<>
<Box mb={2}>
<Typography variant="h4">Applications</Typography>
</Box>
<Box>
<Paper elevation={2}>
<Table>
<TableHead>
<TableRow>
{columns.map((c) => <TableCell key={c.label}>{c.label}</TableCell>)}
</TableRow>
</TableHead>
<TableBody>
{paginateData.map((x) => (
<TableRow key={x.id}>
<TableCell>
{x.requestId}
</TableCell>
<TableCell>{x.firstName}</TableCell>
<TableCell>{x.lastName}</TableCell>
<TableCell>{x.phone}</TableCell>
<TableCell>{x.help}</TableCell>
<TableCell>
{x.status
? (
<Select
value={x.status}
classes={{ root: classes[x.status], select: classes[x.status] }}
>
<MenuItem value="on_hold">On hold</MenuItem>
<MenuItem value="in_progress">In progress</MenuItem>
<MenuItem value="receieved">Received</MenuItem>
<MenuItem value="closed">Closed</MenuItem>
</Select>
) : 'Pending'}
</TableCell>
<TableCell align="right">
{!x.approved && (
<>
<IconButton color="primary">
<Icon>check</Icon>
</IconButton>
<IconButton color="secondary">
<Icon>clear</Icon>
</IconButton>
</>
)}
</TableCell>
</TableRow>
))}
</TableBody>
<TableFooter>
<TableRow>
<TablePagination
count={applications.length}
onChangePage={handlePageChange}
page={pagination.page}
rowsPerPage={pagination.limit}
onChangeRowsPerPage={handleChangeRowsPerPage}
/>
</TableRow>
</TableFooter>
</Table>
</Paper>
</Box>
</>
);
}
Example #2
Source File: Storage.js From acsys with MIT License | 4 votes |
Storage = (props) => {
const [locked, setLocked] = useState(true);
const [isDialog, setIsDialog] = useState(false);
const [mode, setMode] = useState('');
const [imgUrl, setImgUrl] = useState(undefined);
const [con, setCon] = useState(true);
const [fileName, setFileName] = useState('');
const [currentDir, setCurrentDir] = useState('');
const [newFolderName, setNewFolderName] = useState('');
const [files, setFiles] = useState([]);
const [uploadFile, setUploadFile] = useState('');
const [page, setPage] = useState(0);
const [rowsPerPage] = useState(15);
const [openMessage, setOpenMessage] = useState(false);
const [loading, setLoading] = useState(false);
const [syncing, setSyncing] = useState(false);
const [newFolder, setNewFolder] = useState(false);
const [isOpenImage, setIsOpenImage] = useState(false);
const [messageTitle, setMessageTitle] = useState('');
const [message, setMessage] = useState('');
const [setError] = useState('');
const [deleteLoading, setDeleteLoading] = useState(false);
const [deleting, setDeleting] = useState(false);
const [previousDir, setPreviousDir] = useState('');
const set = (name, ref) => {
try {
props.setFile(name, ref);
} catch (error) {}
};
const closeMessage = () => {
setOpenMessage(false);
};
const openDir = async (dir) => {
setLoading(true);
const parentDir = files[0].parent;
const filesTemp = await Acsys.getData('acsys_storage_items', [
['parent', '=', dir],
]);
for (var i = 0; i < filesTemp.length; i++) {
await Acsys.getStorageURL(filesTemp[i].acsys_id)
.then((result) => {
filesTemp[i]['url'] = result;
})
.catch((error) => console.log(error));
}
filesTemp.sort((a, b) => (a.file_order > b.file_order ? 1 : -1));
setLoading(false);
setPreviousDir(parentDir);
setCurrentDir('/' + dir);
setFiles(filesTemp);
};
const openDirPage = async (dir) => {
props.history.push('/Storage?' + dir);
setLocked(false);
};
const previousDirFunc = async () => {
setLoading(true);
let parentFile = '/';
let currentDir;
let files;
if (previousDir !== '/') {
const parent = await Acsys.getData(
'acsys_storage_items',
[['acsys_id', '=', previousDir]],
1
);
parentFile = parent[0].parent;
currentDir = '/' + previousDir;
files = await Acsys.getData('acsys_storage_items', [
['parent', '=', previousDir],
]);
} else {
currentDir = previousDir;
files = await Acsys.getData('acsys_storage_items', [
['parent', '=', '/'],
]);
}
for (var i = 0; i < files.length; i++) {
await Acsys.getStorageURL(files[i].acsys_id)
.then((result) => {
files[i]['url'] = result;
})
.catch((error) => console.log(error));
}
files.sort((a, b) => (a.file_order > b.file_order ? 1 : -1));
setLoading(false);
setPreviousDir(parentFile);
setCurrentDir(currentDir);
setFiles(files);
};
const setRef = (ref) => {
setUploadFile(ref);
};
const uploadFileFunc = async () => {
try {
setLoading(true);
await Acsys.uploadFile(uploadFile.files[0], currentDir).then(async () => {
await loadFiles();
});
setLoading(false);
} catch (error) {}
};
const syncFiles = async () => {
handleSyncClose();
setLoading(true);
await Acsys.syncFiles();
let files = await Acsys.getData('acsys_storage_items', [
['parent', '=', '/'],
]);
for (var i = 0; i < files.length; i++) {
await Acsys.getStorageURL(files[i].acsys_id)
.then((result) => {
files[i]['url'] = result;
})
.catch((error) => console.log(error));
}
files.sort((a, b) => (a.file_order > b.file_order ? 1 : -1));
setLoading(false);
setFiles(files);
};
const handleSyncOpen = () => {
setSyncing(true);
};
const handleSyncClose = () => {
setSyncing(false);
};
const openImg = (url) => {
setIsOpenImage(true);
setImgUrl(url);
};
const handleImgClose = () => {
setIsOpenImage(false);
};
const handleChange = (event) => {
setNewFolderName(event);
};
const newFolderOpen = () => {
setNewFolder(true);
};
const newFolderClose = () => {
setNewFolder(false);
};
const createNewFolder = async () => {
if (newFolderName.indexOf(' ') >= 0) {
setNewFolder(false);
setOpenMessage(true);
setMessageTitle('Error');
setMessage('Folder name cannot contain spaces.');
} else {
setLoading(true);
setNewFolder(false);
await Acsys.createNewFolder(newFolderName, currentDir);
await loadFiles();
setLoading(false);
}
};
const makeFilePublic = async (fileName) => {
setLoading(true);
await Acsys.makeFilePublic(fileName)
.then(async () => {
await loadFiles();
})
.catch((error) => setError(error));
setLoading(false);
};
const makeFilePrivate = async (fileName) => {
setLoading(true);
await Acsys.makeFilePrivate(fileName)
.then(async () => {
await loadFiles();
})
.catch((error) => setError(error));
setLoading(false);
};
const deleteFile = async () => {
setDeleteLoading(true);
await Acsys.deleteFile(fileName)
.then(async () => {
await loadFiles();
})
.catch((error) => setError(error));
handleDeleteClose();
};
const handleDeleteOpen = async (fileName) => {
setDeleting(true);
setFileName(fileName);
};
const handleDeleteClose = () => {
setDeleting(false);
setDeleteLoading(false);
};
const loadFiles = async () => {
setTimeout(() => {}, 1000);
let dir = currentDir;
if (dir !== '/') {
dir = dir.substring(1, dir.length);
}
const files = await Acsys.getData('acsys_storage_items', [
['parent', '=', dir],
]);
for (var i = 0; i < files.length; i++) {
await Acsys.getStorageURL(files[i].acsys_id)
.then((result) => {
files[i]['url'] = result;
})
.catch((error) => console.log(error));
}
files.sort((a, b) => (a.file_order > b.file_order ? 1 : -1));
setFiles(files);
};
const handleChangePage = (event, page) => {
setPage(page);
};
useEffect(async () => {
try {
if (
props.location.search.substring(1) !== currentDir.substring(1) &&
!locked
) {
let newDir = props.location.search.substring(1);
if (newDir.length < 1) {
newDir = '/';
}
setLocked(true);
setLoading(true);
setIsOpenImage(false);
const files = await Acsys.getData('acsys_storage_items', [
['parent', '=', newDir],
]).catch();
for (var i = 0; i < files.length; i++) {
await Acsys.getStorageURL(files[i].acsys_id)
.then((result) => {
files[i]['url'] = result;
})
.catch((error) => console.log(error));
}
files.sort((a, b) => (a.file_order > b.file_order ? 1 : -1));
let currentDir = '/';
if (newDir !== '/') {
currentDir += newDir;
}
setLocked(false);
setLoading(false);
setCurrentDir(currentDir);
setFiles(files);
}
} catch (error) {}
}, [locked, currentDir, props.location]);
useEffect(async () => {
setLoading(true);
let parent = '/';
let mode = 'standard';
try {
if (props.mode.length > 0) {
mode = props.mode;
}
} catch (error) {
props.setHeader('Storage');
}
let con;
let files;
try {
con = await Acsys.isStorageConnected();
if (!con) {
setLoading(false);
setCon(con);
}
files = await Acsys.getData('acsys_storage_items', [
['parent', '=', parent],
]);
for (var i = 0; i < files.length; i++) {
await Acsys.getStorageURL(files[i].acsys_id)
.then((result) => {
files[i]['url'] = result;
})
.catch((error) => console.log(error));
}
files.sort((a, b) => (a.file_order > b.file_order ? 1 : -1));
} catch (error) {}
setLoading(false);
setIsDialog(isDialog);
setMode(mode);
setCon(con);
setFiles(files);
}, []);
const getPrevButton = () => {
return mode !== 'standard' ? (
<Grid item>
<Tooltip title="Back">
<IconButton onClick={() => previousDirFunc()}>
<KeyboardArrowLeft color="inherit" />
</IconButton>
</Tooltip>
</Grid>
) : (
<div></div>
);
};
const renderIcon = (content_type, url) => {
if (content_type === 'Folder') {
return (
<TableCell style={{ width: 40, paddingRight: 0 }}>
<FolderOpen />
</TableCell>
);
} else if (content_type.includes('image')) {
return (
<TableCell style={{ width: 40, paddingRight: 0 }}>
<img
src={url}
style={{ cursor: 'pointer', height: 40, width: 40, margin: 0 }}
onClick={() => openImg(url)}
/>
</TableCell>
);
} else {
return (
<TableCell style={{ width: 40, paddingRight: 0 }}>
<Description
style={{ cursor: 'pointer', height: 40, width: 40, margin: 0 }}
onClick={() => window.open(url, '_blank')}
/>
</TableCell>
);
}
};
const renderName = (id, content_type, name) => {
if (content_type === 'Folder') {
if (mode === 'standard') {
return (
<TableCell>
<a onClick={() => openDirPage(id)} style={{ cursor: 'pointer' }}>
{name}
</a>
</TableCell>
);
} else {
return (
<TableCell>
<a onClick={() => openDir(id)} style={{ cursor: 'pointer' }}>
{name}
</a>
</TableCell>
);
}
} else {
if (mode === 'standard') {
return (
<TableCell>
<a>{name}</a>
</TableCell>
);
} else {
return (
<TableCell>
<a onClick={() => set(name, id)} style={{ cursor: 'pointer' }}>
{name}
</a>
</TableCell>
);
}
}
};
const renderTableData = () => {
return files
.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
.map((file, index) => {
const { acsys_id, name, content_type, updated, is_public, url } = file;
if (name.length > 0) {
return (
<TableRow key={index}>
{renderIcon(content_type, url, name)}
{renderName(acsys_id, content_type, name)}
<TableCell>{content_type}</TableCell>
<TableCell>{updated}</TableCell>
{Acsys.getMode() !== 'Viewer' ? (
<TableCell style={{ minWidth: 100 }} align="right">
{is_public ? (
<Tooltip title="Public To Internet">
<IconButton
edge="start"
color="inherit"
aria-label="make private"
onClick={() => makeFilePrivate(acsys_id)}
style={{ marginRight: 10 }}
>
<LockOpen />
</IconButton>
</Tooltip>
) : (
<Tooltip title="Not Public">
<IconButton
edge="start"
color="inherit"
aria-label="make public"
onClick={() => makeFilePublic(acsys_id)}
style={{ marginRight: 10 }}
>
<Lock />
</IconButton>
</Tooltip>
)}
<Tooltip title="Delete File">
<IconButton
edge="start"
color="inherit"
aria-label="delete"
onClick={() => handleDeleteOpen(acsys_id)}
>
<Delete />
</IconButton>
</Tooltip>
</TableCell>
) : (
<div />
)}
</TableRow>
);
} else {
return <div />;
}
});
};
if (con) {
try {
return (
<div>
<Paper style={{ margin: 'auto', overflow: 'hidden', clear: 'both' }}>
<AppBar
position="static"
elevation={0}
style={{
backgroundColor: '#fafafa',
borderBottom: '1px solid #dcdcdc',
}}
>
<Toolbar style={{ margin: 4, paddingLeft: 12, paddingRight: 12 }}>
{Acsys.getMode() !== 'Viewer' ? (
<Grid container spacing={1}>
<Grid item xs style={{ overflow: 'hidden' }}>
<Typography
align="left"
variant="subtitle2"
noWrap
style={{ marginTop: 10, color: '#000000' }}
>
{currentDir}
</Typography>
</Grid>
{getPrevButton()}
<Grid item style={{ minWidth: 20 }}>
<Tooltip title="Scan For File Updates">
<Button
variant="contained"
color="primary"
onClick={handleSyncOpen}
>
Scan
</Button>
</Tooltip>
</Grid>
<Grid item style={{ minWidth: 20 }}>
<input
id="contained-button-file"
type="file"
style={{ display: 'none' }}
ref={setRef}
onChange={uploadFileFunc}
/>
<label htmlFor="contained-button-file">
<Tooltip title="Upload File">
<Button
variant="contained"
color="primary"
component="span"
>
Upload
</Button>
</Tooltip>
</label>
</Grid>
<Grid item style={{ minWidth: 20 }}>
<Tooltip title="New Folder">
<Button
variant="contained"
color="primary"
onClick={newFolderOpen}
>
New Folder
</Button>
</Tooltip>
</Grid>
</Grid>
) : (
<Grid container spacing={1}>
<Grid item xs style={{ overflow: 'hidden' }}>
<Typography
align="left"
variant="subtitle2"
noWrap
style={{ marginTop: 10, color: '#000000' }}
>
{currentDir}
</Typography>
</Grid>
{getPrevButton()}
</Grid>
)}
</Toolbar>
</AppBar>
<div style={{ margin: 'auto', overflow: 'auto' }}>
<Table>
<TableHead style={{ backgroundColor: '#fafafa' }}>
<TableRow>
<TableCell
colSpan={2}
style={{
paddingLeft: 16,
paddingRight: 16,
paddingTop: 5,
paddingBottom: 5,
}}
>
NAME
</TableCell>
<TableCell
style={{
paddingLeft: 16,
paddingRight: 16,
paddingTop: 5,
paddingBottom: 5,
width: 100,
}}
>
TYPE
</TableCell>
<TableCell
style={{
paddingLeft: 16,
paddingRight: 16,
paddingTop: 5,
paddingBottom: 5,
width: 110,
}}
>
LAST MODIFIED
</TableCell>
{Acsys.getMode() !== 'Viewer' ? (
<TableCell
style={{
paddingLeft: 16,
paddingRight: 16,
paddingTop: 5,
paddingBottom: 5,
width: 100,
}}
align="right"
>
ACTIONS
</TableCell>
) : (
<div />
)}
</TableRow>
</TableHead>
<TableBody>{renderTableData()}</TableBody>
</Table>
</div>
<TablePagination
rowsPerPageOptions={[25]}
component="div"
count={files.length}
rowsPerPage={rowsPerPage}
page={page}
backIconButtonProps={{
'aria-label': 'previous page',
}}
nextIconButtonProps={{
'aria-label': 'next page',
}}
onChangePage={handleChangePage}
// onChangeRowsPerPage={handleChangeRowsPerPage}
/>
<LoadingDialog loading={loading} message={'Loading'} />
<MessageDialog
open={openMessage}
closeDialog={closeMessage}
title={messageTitle}
message={message}
/>
<YesNoDialog
open={syncing}
closeDialog={handleSyncClose}
title={'Sync files?'}
message={
'Are you sure you want to resync files? This operation can require multiple writes.'
}
action={syncFiles}
/>
<ImageDialog
open={isOpenImage}
closeDialog={handleImgClose}
imgUrl={imgUrl}
/>
<NewFolderDialog
open={newFolder}
closeDialog={newFolderClose}
handleChange={handleChange}
createNewFolder={createNewFolder}
/>
<YesNoDialog
open={deleting}
closeDialog={handleDeleteClose}
title={'Delete file?'}
message={'Are you sure you want to delete this file?'}
action={deleteFile}
actionProcess={deleteLoading}
/>
</Paper>
</div>
);
} catch (error) {
console.log('error', error);
return (
<div style={{ maxWidth: 1236, margin: 'auto' }}>
<Paper style={{ height: 40 }}>
<div style={{ padding: 10, margin: 'auto' }}>
Please make sure database has been created.
</div>
</Paper>
</div>
);
}
} else {
return (
<div style={{ maxWidth: 1236, margin: 'auto' }}>
<Paper style={{ height: 40 }}>
<div style={{ padding: 10, margin: 'auto' }}>
Please configure storage.
</div>
</Paper>
</div>
);
}
}
Example #3
Source File: ListUrls.js From fireshort with MIT License | 4 votes |
export default function ListUrls(props) {
const classes = useStyles();
const [page, setPage] = React.useState(0);
const [rowsPerPage, setRowsPerPage] = React.useState(10);
const handleChangePage = (event, newPage) => {
setPage(newPage);
};
const handleChangeRowsPerPage = (event) => {
setRowsPerPage(+event.target.value);
setPage(0);
};
return (
<Container className={classes.cardGrid} maxWidth="md">
<Paper className={classes.root}>
<TableContainer className={classes.container}>
<Table stickyHeader aria-label="sticky table">
<TableHead>
<TableRow>
<TableCell key="curl" align="left" style={{ minWidth: "100px" }}>
Short URL
</TableCell>
<TableCell key="lurl" align="left" style={{ minWidth: "100px" }}>
Long URL
</TableCell>
<TableCell key="action" align="right" style={{ minWidth: "100px" }}>
Action
</TableCell>
</TableRow>
</TableHead>
<TableBody>
{props.shortUrls.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage).map((card) => {
return (
<TableRow hover role="checkbox" tabIndex={-1} key={card.id}>
<TableCell key="curl" align="left" style={{ minWidth: "100px" }}>
<Button
startIcon={
<FileCopyOutlinedIcon />
}
onClick={() => { navigator.clipboard.writeText(window.location.hostname + "/" + card.data.curl) }}
classes={{
label: classes.label
}}
>{card.data.curl}</Button>
</TableCell>
<TableCell key="lurl" align="left" style={{ minWidth: "100px" }}>
<Box bgcolor="text.primary" color="background.paper" p={2} style={{ overflowX: 'auto', overflowY: 'hidden', whiteSpace: "nowrap" }}>
{card.data.lurl}
</Box>
</TableCell>
<TableCell key="action" align="right" style={{ minWidth: "100px" }}>
<ButtonGroup variant="outlined" color="default">
<Button size="small" color="primary" href={card.data.lurl} target="_blank">
<VisibilityIcon />
</Button>
<Button size="small" onClick={() => props.handleEditShortUrl(card.data.curl)}>
<EditIcon />
</Button>
<Button size="small" color="secondary" onClick={() => props.handleDeleteShortUrl(card.data.curl)}>
<DeleteForeverIcon />
</Button>
</ButtonGroup>
</TableCell>
</TableRow>
);
})}
</TableBody>
</Table>
</TableContainer>
<TablePagination
rowsPerPageOptions={[10, 25, 100]}
component="div"
count={props.shortUrls.length}
rowsPerPage={rowsPerPage}
page={page}
onChangePage={handleChangePage}
onChangeRowsPerPage={handleChangeRowsPerPage}
/>
</Paper>
</Container>
);
}
Example #4
Source File: ListUrls.js From FireShort with MIT License | 4 votes |
export default function ListUrls(props) {
const classes = useStyles();
const history = useHistory();
const [page, setPage] = React.useState(0);
const [rowsPerPage, setRowsPerPage] = React.useState(10);
const handleChangePage = (event, newPage) => {
setPage(newPage);
};
const handleChangeRowsPerPage = (event) => {
setRowsPerPage(+event.target.value);
setPage(0);
};
return (
<Container className={classes.cardGrid} maxWidth="lg">
<Paper className={classes.root}>
<TableContainer className={classes.container}>
<Table stickyHeader aria-label="sticky table">
<TableHead>
<TableRow>
<TableCell
key="curl"
align="left"
style={{
minWidth: "100px",
}}
>
Short URL
</TableCell>
<TableCell
key="action"
align="center"
style={{
minWidth: "100px",
}}
>
Action
</TableCell>
<TableCell
key="lurl"
align="left"
style={{ minWidth: "100px" }}
>
Long URL
</TableCell>
</TableRow>
</TableHead>
<TableBody>
{props.shortUrls
.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
.map((card) => {
return (
<TableRow hover role="checkbox" tabIndex={-1} key={card.id}>
<TableCell
key="curl"
align="left"
style={{ minWidth: "100px" }}
>
<Tooltip title="Copy to clipboard">
<Button
startIcon={<FileCopyOutlinedIcon />}
onClick={() => {
navigator.clipboard.writeText(
window.location.origin + "/" + card.data.curl
);
}}
classes={{ label: classes.label }}
>
{card.data.curl}
</Button>
</Tooltip>
<Tooltip title={card.data.hits + " Hits"}>
<IconButton onClick={() => { props.openHits(card.data.curl) }} style={{ cursor: "pointer" }}>
<Badge
badgeContent={card.data.hits}
color="secondary"
max={Infinity}
showZero
>
<OpenInBrowser />
</Badge>
</IconButton>
</Tooltip>
</TableCell>
<TableCell
key="action"
align="right"
style={{ minWidth: "100px" }}
>
<ButtonGroup variant="outlined" color="default">
<Tooltip title="Preview link">
<Button
size="small"
color="primary"
href={card.data.lurl}
target="_blank"
>
<VisibilityIcon />
</Button>
</Tooltip>
<Tooltip title="Analytics">
<Button
size='small'
disabled={!card.data.track}
onClick={() => history.push(`/analytics/${card.data.curl}`)}
>
<AnalyticsIcon />
</Button>
</Tooltip>
<Tooltip title="Edit link">
<Button
size="small"
onClick={() =>
props.handleEditShortUrl(card.data.curl)
}
>
<EditIcon />
</Button>
</Tooltip>
<Tooltip title="Delete link">
<Button
size="small"
color="secondary"
onClick={() =>
props.handleDeleteShortUrl(card.data.curl)
}
>
<DeleteForeverIcon />
</Button>
</Tooltip>
<Tooltip title="Toggle link protection">
<Button
size="small"
color="default"
onClick={() => props.toggleSecurity(card.data.curl)}
>
{card.data.locked ? <LockIcon /> : <LockOpenIcon />}
</Button>
</Tooltip>
</ButtonGroup>
</TableCell>
<TableCell
key="lurl"
align="left"
style={{ minWidth: "100px" }}
>
<Box
bgcolor="text.primary"
color="background.paper"
p={2}
style={{
overflowX: "auto",
overflowY: "hidden",
whiteSpace: "nowrap",
}}
>
{card.data.lurl}
</Box>
</TableCell>
</TableRow>
);
})}
</TableBody>
</Table>
</TableContainer>
<TablePagination
rowsPerPageOptions={[10, 25, 100]}
component="div"
count={props.shortUrls.length}
rowsPerPage={rowsPerPage}
page={page}
onChangePage={handleChangePage}
onChangeRowsPerPage={handleChangeRowsPerPage}
/>
</Paper>
</Container>
);
}
Example #5
Source File: table-pagination-container.js From horondi_admin with MIT License | 4 votes |
TablePaginator = () => {
const styles = useStyles();
const dispatch = useDispatch();
const { itemsCount, rowsPerPage, rowsPerPageOptions, currentPage } =
useSelector(selectTablePaginationCurrentRowsOptions);
const formSchema = Yup.object().shape({
pageInput: Yup.number()
.min(1)
.max(Math.ceil(itemsCount / rowsPerPage), PAGE_NOT_FOUND)
.typeError(MUST_BE_NUMBER)
.positive(MUST_BE_POSITIVE)
});
const { values, handleChange, handleSubmit, errors } = useFormik({
validationSchema: formSchema,
validateOnBlur: true,
initialValues: {
pageInput: ''
},
onSubmit: (data) => {
dispatch(setCurrentPage(data.pageInput - 1));
}
});
const handleChangePage = (event, newPage) => {
dispatch(setCurrentPage(newPage));
};
const handlePressEnter = (event) => {
if (event.key === 'Enter' && values.pageInput && !errors.pageInput) {
handleSubmit(values);
}
};
const handleChangeRowsPerPage = (event) => {
const rowsPerPageValue = parseInt(event.target.value);
dispatch(setCurrentPage(0));
dispatch(setRowsPerPage(rowsPerPageValue));
};
const getDisplayedRowsLabel = (from, to, count) => `${from}-${to} з ${count}`;
return (
<div className={styles.pagination}>
<TablePagination
component='div'
rowsPerPageOptions={rowsPerPageOptions}
count={itemsCount}
rowsPerPage={rowsPerPage}
page={currentPage}
SelectProps={{ native: true }}
labelRowsPerPage={ROWS_PER_PAGE}
labelDisplayedRows={({ from, to, count }) =>
getDisplayedRowsLabel(from, to, count)
}
onChangePage={handleChangePage}
onChangeRowsPerPage={handleChangeRowsPerPage}
ActionsComponent={PaginationController}
/>
<div className={styles.goToPage}>
<Typography variant='body2'>{goToPage}</Typography>
<TextField
id='pageInput'
className={styles.root}
variant='outlined'
value={values.pageInput}
onChange={handleChange}
onKeyPress={handlePressEnter}
error={!!errors.pageInput}
/>
<Button
disabled={!values.pageInput || !!errors.pageInput}
onClick={handleSubmit}
variant='outlined'
color='default'
>
{GO}
</Button>
{errors.pageInput && (
<div className={styles.error}>{errors.pageInput}</div>
)}
</div>
</div>
);
}
Example #6
Source File: UsersTable.js From git-insights with MIT License | 4 votes |
UsersTable = props => {
const { className, users, ...rest } = props;
const classes = useStyles();
const [selectedUsers, setSelectedUsers] = useState([]);
const [rowsPerPage, setRowsPerPage] = useState(10);
const [page, setPage] = useState(0);
const handleSelectAll = event => {
const { users } = props;
let selectedUsers;
if (event.target.checked) {
selectedUsers = users.map(user => user.id);
} else {
selectedUsers = [];
}
setSelectedUsers(selectedUsers);
};
const handleSelectOne = (event, id) => {
const selectedIndex = selectedUsers.indexOf(id);
let newSelectedUsers = [];
if (selectedIndex === -1) {
newSelectedUsers = newSelectedUsers.concat(selectedUsers, id);
} else if (selectedIndex === 0) {
newSelectedUsers = newSelectedUsers.concat(selectedUsers.slice(1));
} else if (selectedIndex === selectedUsers.length - 1) {
newSelectedUsers = newSelectedUsers.concat(selectedUsers.slice(0, -1));
} else if (selectedIndex > 0) {
newSelectedUsers = newSelectedUsers.concat(
selectedUsers.slice(0, selectedIndex),
selectedUsers.slice(selectedIndex + 1)
);
}
setSelectedUsers(newSelectedUsers);
};
const handlePageChange = (event, page) => {
setPage(page);
};
const handleRowsPerPageChange = event => {
setRowsPerPage(event.target.value);
};
return (
<Card
{...rest}
className={clsx(classes.root, className)}
>
<CardContent className={classes.content}>
<PerfectScrollbar>
<div className={classes.inner}>
<Table>
<TableHead>
<TableRow>
<TableCell padding="checkbox">
<Checkbox
checked={selectedUsers.length === users.length}
color="primary"
indeterminate={
selectedUsers.length > 0 &&
selectedUsers.length < users.length
}
onChange={handleSelectAll}
/>
</TableCell>
<TableCell>Name</TableCell>
<TableCell>Email</TableCell>
<TableCell>Location</TableCell>
<TableCell>Phone</TableCell>
<TableCell>Registration date</TableCell>
</TableRow>
</TableHead>
<TableBody>
{users.slice(0, rowsPerPage).map(user => (
<TableRow
className={classes.tableRow}
hover
key={user.id}
selected={selectedUsers.indexOf(user.id) !== -1}
>
<TableCell padding="checkbox">
<Checkbox
checked={selectedUsers.indexOf(user.id) !== -1}
color="primary"
onChange={event => handleSelectOne(event, user.id)}
value="true"
/>
</TableCell>
<TableCell>
<div className={classes.nameContainer}>
<Avatar
className={classes.avatar}
src={user.avatarUrl}
>
{getInitials(user.name)}
</Avatar>
<Typography variant="body1">{user.name}</Typography>
</div>
</TableCell>
<TableCell>{user.email}</TableCell>
<TableCell>
{user.address.city}, {user.address.state},{' '}
{user.address.country}
</TableCell>
<TableCell>{user.phone}</TableCell>
<TableCell>
{moment(user.createdAt).format('DD/MM/YYYY')}
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</div>
</PerfectScrollbar>
</CardContent>
<CardActions className={classes.actions}>
<TablePagination
component="div"
count={users.length}
onChangePage={handlePageChange}
onChangeRowsPerPage={handleRowsPerPageChange}
page={page}
rowsPerPage={rowsPerPage}
rowsPerPageOptions={[5, 10, 25]}
/>
</CardActions>
</Card>
);
}
Example #7
Source File: ContributorsTable.js From git-insights with MIT License | 4 votes |
ContributorsTable = props => {
const { className, repoid, ...rest } = props;
const [data, dataLoading] = useFetch(
`api/repo/${repoid}/contributors`
);
const classes = useStyles();
const [page, setPage] = React.useState(0);
const rowsPerPage = 5;
let emptyRows = 0;
if (data) {
emptyRows = rowsPerPage - Math.min(rowsPerPage, data.length - page * rowsPerPage);
}
const handleChangePage = (event, newPage) => {
setPage(newPage);
};
return (
<div {...rest} className={clsx(classes.root, className)}>
<Paper className={classes.paper}>
{dataLoading ? (
<Grid
container
spacing={0}
alignItems="center"
justify="center"
style={{ minHeight: "100%" }}
>
<Grid item xs={6} align="center">
<CircularProgress/>
<Typography>
Loading Chart..
</Typography>
</Grid>
</Grid>
) : (
<div>
<TableContainer>
<Table className={classes.table} aria-label="custom pagination table">
<TableHead>
<TableRow>
<TableCell>Contributor Name</TableCell>
<TableCell align="right">Total Contributions</TableCell>
<TableCell align="right">Code Contributions</TableCell>
<TableCell align="right">Issue Contributions</TableCell>
<TableCell align="right">Code Reviews</TableCell>
</TableRow>
</TableHead>
<TableBody>
{(rowsPerPage > 0
? data.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
: data
).map(row => (
<TableRow key={row.name}>
<TableCell component="th" scope="row">
{row.name}
</TableCell>
<TableCell align="right">{row.total}</TableCell>
<TableCell align="right">{row.code}</TableCell>
<TableCell align="right">{row.issues}</TableCell>
<TableCell align="right">{row.reviews}</TableCell>
</TableRow>
))}
{emptyRows > 0 && (
<TableRow style={{ height: 53 * emptyRows }}>
<TableCell colSpan={6} />
</TableRow>
)}
</TableBody>
<TableFooter>
<TableRow>
</TableRow>
</TableFooter>
</Table>
</TableContainer>
<TablePagination
colSpan={3}
count={data.length}
rowsPerPage={5}
page={page}
onChangePage={handleChangePage}
rowsPerPageOptions={-1}
ActionsComponent={TablePaginationActions}
/>
</div>
)}
</Paper>
</div>
);
}
Example #8
Source File: InventoryTable.js From inventory-management-web with MIT License | 4 votes |
export default function InventoryTable() {
// list of inventory got from API
const [inventoryList, setInventoryList] = useState([]);
// contains the index of the row, if delete is used
const [deletedRow, setDeletedRow] = useState([]);
// true when waiting for an response from API
const [isLoading, setIsLoading] = useState(false);
// dialog box
const [open, setOpen] = useState(false);
// row to be selected on clicking the delete icon
const [selectedRow, setSelectedRow] = useState({});
// list of search results got from API
const [searchList, setSearchList] = useState([]);
// search results input field
const [search, setSearch] = useState('');
// pagination
const [page, setPage] = useState(0);
const [rowsPerPage, setRowsPerPage] = useState(10);
const [count, setCount] = useState(0);
// search pagination
const [searchPage, setSearchPage] = useState(0);
const [searchRowsPerPage, setSearchRowsPerPage] = useState(10);
const [searchCount, setSearchCount] = useState(0);
const handleClose = () => {
setOpen(false);
};
const history = useHistory();
const { setSnack } = useContext(SnackContext);
const handleSearchChangePage = async (event, newPage) => {
try {
setIsLoading(true);
setSearchPage(newPage);
const response = await getEndPoint(
`/api/productlist/?limit=${searchRowsPerPage}&offset=${newPage *
searchRowsPerPage}&search=${search}`,
null,
history
);
// Use utility function
// console.log("error",response) check error code here for reference
const { data } = response;
setSearchCount(data.count);
const list = data.results.map(val => ({
name: val.name,
quantity: val.quantity,
sellingPrice: val.latest_selling_price,
loose: val.loose,
id: val.id,
upperLimit: val.upper_limit === null ? '' : val.upper_limit,
lowerLimit: val.lower_limit === null ? '' : val.lower_limit,
}));
setInventoryList(list);
setIsLoading(false);
} catch (e) {
console.log(e);
}
};
const handleSearchChangeRowsPerPage = async event => {
try {
setIsLoading(true);
setSearchPage(0);
setSearchRowsPerPage(+event.target.value);
const response = await getEndPoint(
`/api/productlist/?limit=${+event.target
.value}&offset=0&search=${search}`,
null,
history
);
// Use utility function
// console.log("error",response) check error code here for reference
const { data } = response;
setSearchCount(data.count);
const list = data.results.map(val => ({
name: val.name,
quantity: val.quantity,
sellingPrice: val.latest_selling_price,
loose: val.loose,
id: val.id,
upperLimit: val.upper_limit === null ? '' : val.upper_limit,
lowerLimit: val.lower_limit === null ? '' : val.lower_limit,
}));
setInventoryList(list);
setIsLoading(false);
} catch (e) {
console.log(e);
}
};
const handleChangePage = async (event, newPage) => {
try {
setIsLoading(true);
setPage(newPage);
const response = await getEndPoint(
`/api/productlist/?limit=${rowsPerPage}&offset=${newPage *
rowsPerPage}`,
null,
history
);
// Use utility function
// console.log("error",response) check error code here for reference
const { data } = response;
setCount(data.count);
const list = data.results.map(val => ({
name: val.name,
quantity: val.quantity,
sellingPrice: val.latest_selling_price,
loose: val.loose,
id: val.id,
upperLimit: val.upper_limit === null ? '' : val.upper_limit,
lowerLimit: val.lower_limit === null ? '' : val.lower_limit,
}));
setSearchList(list);
setIsLoading(false);
} catch (e) {
console.log(e);
}
};
const handleChangeRowsPerPage = async event => {
try {
setIsLoading(true);
setPage(0);
setRowsPerPage(+event.target.value);
const response = await getEndPoint(
`/api/productlist/?limit=${+event.target.value}&offset=0`,
null,
history
);
// Use utility function
// console.log("error",response) check error code here for reference
const { data } = response;
setCount(data.count);
const list = data.results.map(val => ({
name: val.name,
quantity: val.quantity,
sellingPrice: val.latest_selling_price,
loose: val.loose,
id: val.id,
upperLimit: val.upper_limit === null ? '' : val.upper_limit,
lowerLimit: val.lower_limit === null ? '' : val.lower_limit,
}));
setSearchList(list);
setIsLoading(false);
} catch (e) {
console.log(e);
}
};
const handleClickOpen = () => {
setOpen(true);
};
const handleSearch = async data => {
setSearch(data); // set data
// console.log("data",data) //reference
setSearchPage(0);
const response = await getEndPoint(
`/api/productlist/?limit=${searchRowsPerPage}&offset=0&search=${data}`,
null,
history
);
// console.log("res2",response.data.results) // reference
setSearchCount(response.data.count);
const list = response.data.results.map(val => ({
name: val.name,
quantity: val.quantity,
sellingPrice: val.latest_selling_price,
loose: val.loose,
id: val.id,
upperLimit: val.upper_limit === null ? '' : val.upper_limit,
lowerLimit: val.lower_limit === null ? '' : val.lower_limit,
}));
console.log(list);
setInventoryList(list); // set state
};
const apiFetch = async () => {
try {
setIsLoading(true);
const response = await getEndPoint(
'/api/productlist/?limit=10&offset=0',
null,
history
);
// Use utility function
// console.log("error",response) check error code here for reference
console.log(response.data.results);
const { data } = response;
setCount(data.count);
const list = data.results.map(val => ({
name: val.name,
quantity: val.quantity,
sellingPrice: val.latest_selling_price,
loose: val.loose,
id: val.id,
upperLimit: val.upper_limit === null ? '' : val.upper_limit,
lowerLimit: val.lower_limit === null ? '' : val.lower_limit,
}));
setSearchList(list);
setInventoryList(list);
setIsLoading(false);
} catch (e) {
console.log(e);
}
};
// call API on component load
useEffect(() => {
apiFetch();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
const classes = useStyles();
// handle product delete
const handleDelete = async row => {
setIsLoading(true);
const { id } = row;
setDeletedRow(prevState => [...prevState, inventoryList.indexOf(row)]);
try {
await axios.delete(`/api/productlist/${id}/`);
// add success snackbar on successful request
const { name } = inventoryList.find(val => val.id === id);
setIsLoading(false);
setSnack({
open: true,
message: `Succesfully deleted ${name}`,
action: '',
actionParams: '',
type: 'success',
});
} catch (e) {
console.log(e);
}
};
// handle product edit
const handleEdit = row => {
history.push('/updateproduct', {
name: row.name,
sellingPrice: row.sellingPrice,
loose: row.loose,
id: row.id,
upperLimit: row.upperLimit,
lowerLimit: row.lowerLimit,
});
};
return (
<>
{isLoading ? <Spinner /> : null}
<div className={classes.search}>
<TextField
onChange={e => handleSearch(e.target.value)}
style={{ width: '350px' }}
id='standard-basic'
label='Search'
variant='filled'
InputProps={{
startAdornment: (
<InputAdornment position='start'>
<SearchIcon />
</InputAdornment>
),
}}
/>
</div>
{search === '' ? (
<>
{' '}
<Paper className={classes.paper}>
<TableContainer>
<Table className={classes.table} aria-label='simple table'>
<TableHead>
<TableRow>
<TableCell />
<TableCell>Product</TableCell>
<TableCell align='right'>Items</TableCell>
<TableCell align='right'>Price (Rs)</TableCell>
</TableRow>
</TableHead>
<TableBody>
{searchList.map((row, index) => (
<TableRow
key={row.name}
hover
className={deletedRow.includes(index) ? 'delete' : ''}
>
<TableCell className={classes.firstColumn}>
<Hidden xsDown>
<IconButton
onClick={() => {
handleEdit(row);
}}
>
<EditIcon />
</IconButton>
<IconButton
onClick={() => {
setSelectedRow(row);
handleClickOpen();
}}
>
<DeleteIcon />
</IconButton>
</Hidden>
<Hidden smUp>
<MobileEditMenu
handleDelete={() => {
setSelectedRow(row);
handleClickOpen();
}}
handleEdit={handleEdit}
row={row}
/>
</Hidden>
</TableCell>
<TableCell>{row.name}</TableCell>
<TableCell align='right'>{row.quantity}</TableCell>
<TableCell align='right'>
{row.sellingPrice || 'Not Set'}
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
<TablePagination
rowsPerPageOptions={[5, 10]}
component='div'
count={count}
page={page}
rowsPerPage={rowsPerPage}
onChangePage={handleChangePage}
onChangeRowsPerPage={handleChangeRowsPerPage}
/>
</Paper>
<DialogBox
open={open}
handleClose={handleClose}
selectedRow={selectedRow}
handleDelete={handleDelete}
number='1'
/>
</>
) : (
<>
<Paper className={classes.paper}>
<TableContainer>
<Table className={classes.table} aria-label='simple table'>
<TableHead>
<TableRow>
<TableCell />
<TableCell>Product</TableCell>
<TableCell align='right'>Items</TableCell>
<TableCell align='right'>Price (Rs)</TableCell>
</TableRow>
</TableHead>
<TableBody>
{inventoryList.map((row, index) => (
<TableRow
key={row.name}
hover
className={deletedRow.includes(index) ? 'delete' : ''}
>
<TableCell className={classes.firstColumn}>
<Hidden xsDown>
<IconButton
onClick={() => {
handleEdit(row);
}}
>
<EditIcon />
</IconButton>
<IconButton
onClick={() => {
setSelectedRow(row);
handleClickOpen();
}}
>
<DeleteIcon />
</IconButton>
</Hidden>
<Hidden smUp>
<MobileEditMenu
handleDelete={() => {
setSelectedRow(row);
handleClickOpen();
}}
handleEdit={handleEdit}
row={row}
/>
</Hidden>
</TableCell>
<TableCell>{row.name}</TableCell>
<TableCell align='right'>{row.quantity}</TableCell>
<TableCell align='right'>
{row.sellingPrice || 'Not Set'}
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
<TablePagination
rowsPerPageOptions={[5, 10]}
component='div'
count={searchCount}
page={searchPage}
rowsPerPage={searchRowsPerPage}
onChangePage={handleSearchChangePage}
onChangeRowsPerPage={handleSearchChangeRowsPerPage}
/>
</Paper>
<DialogBox
open={open}
handleClose={handleClose}
selectedRow={selectedRow}
handleDelete={handleDelete}
number='1'
/>
</>
)}
</>
);
}
Example #9
Source File: ExpiryTable.js From inventory-management-web with MIT License | 4 votes |
export default function ExpiryTable() {
// list of near expiry products got from API
const [expiryList, setExpiryList] = useState([]);
// true when waiting for an response from API
const [isLoading, setIsLoading] = useState(false);
// pagination
const [page, setPage] = useState(0);
const [rowsPerPage, setRowsPerPage] = useState(10);
const [count, setCount] = useState(0);
const history = useHistory();
const handleChangePage = async (event, newPage) => {
try {
setIsLoading(true);
setPage(newPage);
const response = await getEndPoint(
`/api/explist/?limit=${rowsPerPage}&offset=${newPage * rowsPerPage}`,
null,
history
);
const { data } = response;
setCount(data.count);
console.log(data);
const list = data.results.map(val => ({
name: val.Product,
quantity: val['No. of items'],
daysLeft: val['Days left'],
}));
setExpiryList(list);
setIsLoading(false);
} catch (e) {
console.log(e);
}
};
const handleChangeRowsPerPage = async event => {
try {
setIsLoading(true);
setPage(0);
setRowsPerPage(+event.target.value);
const response = await getEndPoint(
`/api/explist/?limit=${+event.target.value}&offset=0`,
null,
history
);
const { data } = response;
setCount(data.count);
console.log(data);
const list = data.results.map(val => ({
name: val.Product,
quantity: val['No. of items'],
daysLeft: val['Days left'],
}));
setExpiryList(list);
setIsLoading(false);
} catch (e) {
console.log(e);
}
};
const apiFetch = async () => {
try {
setIsLoading(true);
const response = await getEndPoint(
'/api/explist/?limit=10&offset=0',
null,
history
);
const { data } = response;
setCount(data.count);
console.log(data);
const list = data.results.map(val => ({
name: val.Product,
quantity: val['No. of items'],
daysLeft: val['Days left'],
}));
setExpiryList(list);
setIsLoading(false);
} catch (e) {
console.log(e);
}
};
// call API on component load
useEffect(() => {
apiFetch();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
const classes = useStyles();
return (
<>
{isLoading ? <Spinner /> : null}
<Paper className={classes.paper}>
<TableContainer className={classes.tableContainer}>
<Table className={classes.table} aria-label='simple table'>
<TableHead>
<TableRow>
<TableCell>Product</TableCell>
<TableCell align='right'>Items</TableCell>
<TableCell align='right'>Days Left</TableCell>
</TableRow>
</TableHead>
<TableBody>
{expiryList.map(row => (
<TableRow key={row.name} hover>
<TableCell>{row.name}</TableCell>
<TableCell align='right'>{row.quantity}</TableCell>
<TableCell align='right'>{row.daysLeft}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
<TablePagination
rowsPerPageOptions={[5, 10]}
component='div'
count={count}
page={page}
rowsPerPage={rowsPerPage}
onChangePage={handleChangePage}
onChangeRowsPerPage={handleChangeRowsPerPage}
/>
</Paper>
</>
);
}
Example #10
Source File: Users.js From acsys with MIT License | 4 votes |
Users = (props) => {
const [userId, setUserId] = useState(0);
const [message, setMessage] = useState('');
const [users, setUsers] = useState([]);
const [username, setUsername] = useState('');
const [role, setRole] = useState('Administrator');
const [email, setEmail] = useState('');
const [passwordOne, setPasswordOne] = useState('');
const [passwordTwo, setPasswordTwo] = useState('');
const [page, setPage] = useState(0);
const [rowsPerPage] = useState(15);
const [setOpen, setSetOpen] = useState(false);
const [addLoading, setAddLoading] = useState(false);
const [deleting, setDeleting] = useState(false);
const [deleteLoading, setDeleteLoading] = useState(false);
const [setError] = useState('');
const [projectName, setProjectName] = useState('');
const deleteUser = async () => {
await Acsys.deleteData('acsys_users', [['acsys_id', '=', userId]])
.then(() => {
inDidMount();
})
.catch((error) => setError(error));
setDeleting(false);
setDeleteLoading(false);
};
const handleChangePage = (event, page) => {
setPage(page);
};
const handleClickOpen = () => {
setSetOpen(true);
};
const handleClose = () => {
setSetOpen(false);
};
const handleDeleteOpen = async (userId) => {
setDeleting(true);
setUserId(userId);
};
const handleDeleteClose = () => {
setDeleting(false);
setDeleteLoading(false);
};
const inDidMount = async () => {
props.setHeader('Users');
let projectName = await Acsys.getProjectName();
let users = [];
try {
users = await Acsys.getUsers(Acsys.getUser());
} catch (error) {}
setProjectName(projectName);
setUsers(users);
};
const addUser = async () => {
setAddLoading(true);
if (
username.length < 1 ||
email.length < 1 ||
passwordOne.length < 1 ||
passwordTwo.length < 1
) {
setMessage('Please fill all fields.');
} else if (passwordOne !== passwordTwo) {
setMessage('Passwords do not match.');
} else {
const user = {
acsys_id: uniqid(),
role: role,
mode: role,
username: username,
email: email,
password: passwordOne,
};
await Acsys.createUser(user)
.then((result) => {
if (result === true) {
setSetOpen(false);
inDidMount();
} else {
setMessage(result);
}
})
.catch((error) => {
setError(error);
});
setUsername('');
setEmail('');
setPasswordOne('');
setPasswordTwo('');
setMessage('');
}
setAddLoading(false);
};
useEffect(() => {
inDidMount();
}, []);
const renderTableData = () => {
return users
.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
.map((users) => {
const { acsys_id, username, email, role } = users;
return (
<TableRow key={acsys_id}>
<TableCell>{username}</TableCell>
<TableCell>{role}</TableCell>
<TableCell>{email}</TableCell>
<TableCell align="right">
<Tooltip title="Remove User">
<IconButton
edge="start"
color="inherit"
aria-label="delete"
onClick={() => handleDeleteOpen(acsys_id)}
>
<DeleteIcon />
</IconButton>
</Tooltip>
</TableCell>
</TableRow>
);
});
};
try {
return (
<div>
<Paper
style={{
margin: 'auto',
overflow: 'hidden',
clear: 'both',
marginBottom: 20,
}}
>
<AppBar
position="static"
elevation={0}
style={{
backgroundColor: '#fafafa',
borderBottom: '1px solid #dcdcdc',
}}
>
<Toolbar style={{ margin: 4, paddingLeft: 12, paddingRight: 12 }}>
<Grid container spacing={1}>
<Grid item xs style={{ overflow: 'hidden' }}>
<Typography
align="left"
variant="subtitle2"
noWrap
style={{ marginTop: 10, color: '#000000' }}
>
Project: {projectName}
</Typography>
</Grid>
<Grid item>
<Tooltip title="Add New User">
<Button
variant="contained"
color="primary"
onClick={handleClickOpen}
>
Add User
</Button>
</Tooltip>
</Grid>
</Grid>
</Toolbar>
</AppBar>
<div style={{ margin: 'auto', overflow: 'auto' }}>
<Table>
<TableHead style={{ backgroundColor: '#fafafa' }}>
<TableRow>
<TableCell
style={{
paddingLeft: 16,
paddingRight: 16,
paddingTop: 5,
paddingBottom: 5,
}}
>
USERNAME
</TableCell>
<TableCell
style={{
paddingLeft: 16,
paddingRight: 16,
paddingTop: 5,
paddingBottom: 5,
}}
>
ROLE
</TableCell>
<TableCell
style={{
paddingLeft: 16,
paddingRight: 16,
paddingTop: 5,
paddingBottom: 5,
}}
>
EMAIL
</TableCell>
<TableCell
style={{
paddingLeft: 16,
paddingRight: 16,
paddingTop: 5,
paddingBottom: 5,
}}
align="right"
>
ACTIONS
</TableCell>
</TableRow>
</TableHead>
<TableBody>{renderTableData()}</TableBody>
</Table>
</div>
<TablePagination
rowsPerPageOptions={[25]}
component="div"
count={users.length}
rowsPerPage={rowsPerPage}
page={page}
backIconButtonProps={{
'aria-label': 'previous page',
}}
nextIconButtonProps={{
'aria-label': 'next page',
}}
onChangePage={handleChangePage}
// onChangeRowsPerPage={handleChangeRowsPerPage}
/>
<NewUserDialog
open={setOpen}
closeDialog={handleClose}
message={message}
setRole={(value) => setRole(value)}
email={email}
setEmail={(value) => setEmail(value)}
username={username}
setUsername={(value) => {
setUsername(value);
}}
passwordOne={passwordOne}
setPasswordOne={(value) => {
setPasswordOne(value);
}}
passwordTwo={passwordTwo}
setPasswordTwo={(value) => setPasswordTwo(value)}
action={addUser}
actionProcess={addLoading}
/>
<YesNoDialog
open={deleting}
closeDialog={handleDeleteClose}
title={'Delete data?'}
message={'Are you sure you want to delete this user?'}
action={deleteUser}
actionProcess={deleteLoading}
/>
</Paper>
</div>
);
} catch (error) {
console.log(error, 'error');
return (
<div style={{ maxWidth: 1236, margin: 'auto' }}>
<Paper style={{ height: 40 }}>
<div style={{ padding: 10, margin: 'auto' }}>
Please make sure database has been created.
</div>
</Paper>
</div>
);
}
}
Example #11
Source File: AdminEventList.js From AdaptivApps-fe with MIT License | 4 votes |
AdminEventList = props => {
// Declare Create, Update, and Delete mutation functions
const [CreateEvent] = useMutation(CREATE_EVENT);
const [UpdateEvent] = useMutation(UPDATE_EVENT);
const [DeleteEvent] = useMutation(DELETE_EVENT);
// Grab the events data from props
const events = props.events;
//commented out to remove console warning, eventType defined but never used
//const eventType = props.events.type;
const useStyles = makeStyles({
grid: {
maxWidth: "120rem",
marginLeft: "3rem",
"& .MuiButton-label": {
fontSize: "1.6rem",
fontWeight: "500",
},
},
tableHead: {
"& th": {
fontSize: "1.6rem",
},
},
addBtn: {
color: "#2763FF",
textTransform: "none",
},
img: { width: "15rem", objectFit: "contain" },
label: {
marginTop: ".8rem",
color: "red",
fontSize: "1rem",
},
});
const classes = useStyles();
// This code is returning a material table object
// For more info on material table, please visit their docs at
// https://material-table.com/
return (
<Grid className={classes.grid}>
<MaterialTable
components={{
Pagination: props => (
<TablePagination
{...props}
SelectProps={{
style: {
fontSize: "1.4rem",
},
}}
/>
),
}}
title=""
columns={[
{
title: "Title",
field: "title",
render: rowData => (
<div
style={{
fontSize: "1.6rem",
width: "20rem",
}}
>
{rowData.title}
</div>
),
editComponent: props => (
<>
<Input
type="text"
value={props.value}
onChange={e => props.onChange(e.target.value)}
/>
<InputLabel className={classes.label}>*Required</InputLabel>
</>
),
},
{
title: "Type",
field: "type",
render: rowData => (
<div
style={{
fontSize: "1.6rem",
width: "10rem",
}}
>
{rowData.type}
</div>
),
editComponent: props => (
<>
<Select
value={props.value}
onChange={e => props.onChange(e.target.value)}
>
<MenuItem value="In Person">In Person</MenuItem>
<MenuItem value="Webinar">Webinar</MenuItem>
</Select>
<InputLabel className={classes.label}>*Required</InputLabel>
</>
),
},
{
title: "Host",
field: "host",
render: rowData => (
<div
style={{
fontSize: "1.6rem",
width: "16rem",
}}
>
{rowData.host}
</div>
),
editComponent: props => (
<Input
type="text"
value={props.value}
onChange={e => props.onChange(e.target.value)}
/>
),
},
{
title: "Speakers",
field: "speakers",
render: rowData => (
<div
style={{
overflow: "scroll",
maxHeight: "10rem",
fontSize: "1.6rem",
width: "20rem",
}}
>
{rowData.speakers}
</div>
),
editComponent: props => (
<Input
type="text"
value={props.value}
onChange={e => props.onChange(e.target.value)}
/>
),
},
{
title: "Start Time",
field: "startTime",
editComponent: props => (
<Input
type="time"
value={props.value}
onChange={e => props.onChange(e.target.value)}
/>
),
},
{
title: "Start Date",
field: "startDate",
render: rowData => (
<div
style={{
fontSize: "1.6rem",
width: "9rem",
}}
>
{rowData.startDate}
</div>
),
editComponent: props => (
<>
<Input
type="date"
value={props.value}
onChange={e => props.onChange(e.target.value)}
/>
<InputLabel className={classes.label}>*Required</InputLabel>
</>
),
},
{
title: "End Date",
field: "endDate",
render: rowData => (
<div
style={{
fontSize: "1.6rem",
width: "9rem",
}}
>
{rowData.endDate}
</div>
),
editComponent: props => (
<>
<Input
type="date"
value={props.value}
onChange={e => props.onChange(e.target.value)}
/>
<InputLabel className={classes.label}>*Required</InputLabel>
</>
),
},
{
title: "Location",
field: "location",
render: rowData => (
<div
style={{
fontSize: "1.6rem",
width: "14rem",
}}
>
{rowData.location}
</div>
),
editComponent: props => (
<>
<Input
type="text"
value={props.value}
onChange={e => props.onChange(e.target.value)}
/>
<InputLabel className={classes.label}>*Required</InputLabel>
</>
),
},
{
title: "Link",
field: "link",
render: rowData => (
<div
style={{
overflow: "scroll",
fontSize: "1.6rem",
width: "22rem",
}}
>
{rowData.link}
</div>
),
editComponent: props => (
<Input
type="url"
value={props.value}
onChange={e => props.onChange(e.target.value)}
/>
),
},
{
title: "Image Url",
field: "imgUrl",
render: rowData => (
<img
style={{
maxHeight: "12rem",
}}
src={rowData.imgUrl}
alt="Event"
className={classes.img}
/>
),
editComponent: props => (
<Input
type="text"
value={props.value}
onChange={e => props.onChange(e.target.value)}
/>
),
},
{
title: "Sponsors",
field: "sponsors",
render: rowData => (
<div
style={{
overflow: "scroll",
fontSize: "1.6rem",
width: "20rem",
}}
>
{rowData.sponsors}
</div>
),
editComponent: props => (
<Input
type="text"
value={props.value}
onChange={e => props.onChange(e.target.value)}
/>
),
},
{
title: "Details",
field: "details",
render: rowData => (
<div
style={{
fontSize: "1.6rem",
width: "30rem",
maxHeight: "14rem",
overflow: "scroll",
}}
>
{rowData.details}
</div>
),
editComponent: props => (
<textarea
style={{
fontSize: "1.6rem",
}}
rows="8"
cols="60"
type="text"
value={props.value}
onChange={e => props.onChange(e.target.value)}
/>
),
},
]}
data={events}
editable={{
onRowAdd: async newData => {
await CreateEvent({
variables: {
title: newData.title,
type: newData.type,
host: newData.host,
speakers: newData.speakers,
startTime: newData.startTime,
startDate: newData.startDate,
endDate: newData.endDate,
location: newData.location,
imgUrl: newData.imgUrl,
sponsors: newData.sponsors,
details: newData.details,
link: newData.link,
},
});
props.eventsRefetch();
},
onRowUpdate: async (newData, oldData) => {
await UpdateEvent({
variables: {
id: newData.id,
title: newData.title,
type: newData.type,
host: newData.host,
speakers: newData.speakers,
startTime: newData.startTime,
startDate: newData.startDate,
endDate: newData.endDate,
location: newData.location,
imgUrl: newData.imgUrl,
sponsors: newData.sponsors,
details: newData.details,
link: newData.link,
},
});
props.eventsRefetch();
},
onRowDelete: async oldData => {
await DeleteEvent({
variables: {
id: oldData.id,
},
});
props.eventsRefetch();
},
}}
icons={{
Add: () => (
<>
<AddCircleOutlineIcon
style={{ color: "#2962FF" }}
fontSize="large"
/>
<Button className={classes.addBtn}>Add Event</Button>
</>
),
Edit: () => (
<EditIcon style={{ color: "#2962FF" }} fontSize="large" />
),
Delete: () => (
<DeleteIcon style={{ color: "#2962FF" }} fontSize="large" />
),
}}
detailPanel={[
{
tooltip: "Show Activities",
isFreeAction: true,
render: rowData => {
// When clicking on a row, display a list of activities associated
// With the event
const event_id = rowData.id;
return <AdminActivityList event_id={event_id} />;
},
},
]}
options={{
cellStyle: {
fontSize: "1.6rem",
},
headerStyle: {
fontSize: "4rem",
backgroundColor: "#2962FF",
color: "#FFF",
},
rowStyle: {
backgroundColor: "#FFF",
},
emptyRowsWhenPaging: false,
toolbarButtonAlignment: "left",
searchFieldStyle: {
width: "20rem",
fontSize: "1.6rem",
},
doubleHorizontalScrolldoubleHorizontalScroll: false,
columnsButton: true,
}}
/>
</Grid>
);
}
Example #12
Source File: LogicalContent.js From acsys with MIT License | 4 votes |
LogicalContent = (props) => {
const [viewId, setViewId] = useState('');
const [name, setName] = useState('');
const [collectionArr, setCollectionArr] = useState([]);
const [collection, setCollection] = useState('');
const [description, setDescription] = useState('');
const [views, setViews] = useState([]);
const [page, setPage] = useState(0);
const [rowsPerPage] = useState(15);
const [loading, setLoading] = useState(false);
const [deleting, setDeleting] = useState(false);
const [open, setOpen] = useState(false);
const [editOpen, setEditOpen] = useState(false);
const [addLoading, setAddLoading] = useState(false);
const [saveLoading, setSaveLoading] = useState(false);
const [deleteLoading, setDeleteLoading] = useState(false);
const context = useContext(AcsysContext);
const [projectName, setProjectName] = useState('');
const setPosition = (pos) => {
position = pos;
};
const setTempName = (value) => {
tempView['name'] = value;
};
const setTempDescription = (value) => {
tempView['description'] = value;
};
const deleteView = async () => {
setDeleteLoading(true);
if (viewId.length > 0) {
await Acsys.deleteView(viewId);
}
handleDeleteClose();
mount();
};
const handleChangePage = (event, page) => {
setPage(page);
};
const handleClickOpen = async () => {
let collections = [];
await Acsys.getTables().then((json) => {
collections = json;
setCollectionArr(collections);
setOpen(true);
});
};
const handleClose = () => {
setOpen(false);
setAddLoading(false);
};
const handleEditOpen = (view) => {
tempView = view;
position = tempView.position;
setEditOpen(true);
};
const handleEditClose = () => {
setEditOpen(false);
};
const editView = async () => {
if (position === tempView.position) {
await Acsys.updateData('acsys_logical_content', tempView, [
['acsys_id', '=', tempView.acsys_id],
]);
} else {
const oldPosition = tempView['position'];
tempView['position'] = position;
await Acsys.repositionViews(tempView, oldPosition, position);
await sleep(1000);
}
const currentView = await Acsys.getData('acsys_logical_content', [], '', [
'position',
]);
setSaveLoading(false);
setEditOpen(false);
setViews(currentView);
};
const handleDeleteOpen = async (viewId) => {
setDeleting(true);
setViewId(viewId);
};
const handleDeleteClose = () => {
setDeleting(false);
setDeleteLoading(false);
};
const sleep = (time) => {
return new Promise((resolve) => setTimeout(resolve, time));
};
useEffect(() => {
mount();
}, []);
const mount = async () => {
props.setHeader('Content');
context.setHeld(false);
tempView = [];
setLoading(true);
let projectName = '';
await Acsys.getProjectName().then((result) => {
projectName = result;
});
let currentView = [];
currentView = await Acsys.getData('acsys_logical_content', [], '', [
'position',
]);
setLoading(false);
setProjectName(projectName);
setViews(currentView);
setLoading(false);
};
const addView = async () => {
setAddLoading(true);
const uId = uniqid();
let newView = {
acsys_id: uId,
is_table_mode: true,
is_removable: true,
link_view_id: '',
link_table: '',
order_by: '',
view_order: '',
row_num: 10,
};
await Acsys.insertData('acsys_views', { ...newView }).then(async () => {
let newEntry = {
acsys_id: uniqid(),
name: name,
description: description,
viewId: uId,
source_collection: collection,
position: views.length + 1,
table_keys: [],
};
await Acsys.insertData('acsys_logical_content', { ...newEntry });
});
setAddLoading(false);
handleClose();
mount();
};
const renderTableData = () => {
return views
.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
.map((views, key) => {
const {
acsys_id,
name,
description,
viewId,
source_collection,
table_keys,
} = views;
return (
<TableRow key={key}>
{table_keys.length < 1 ? (
<TableCell
to={{
pathname:
'/CollectionView/' + source_collection + '/' + viewId,
state: {
table_keys: [],
view: name,
},
}}
component={Link}
style={{ minWidth: 150 }}
>
{name}
</TableCell>
) : (
<TableCell
to={{
pathname: '/DocumentView',
state: {
mode: 'update',
table_keys: views.table_keys,
routed: true,
viewId: views.viewId,
},
}}
component={Link}
style={{ minWidth: 150 }}
>
{name}
</TableCell>
)}
{table_keys.length < 1 ? (
<TableCell
to={{
pathname:
'/CollectionView/' + source_collection + '/' + viewId,
state: {
table_keys: [],
view: name,
},
}}
component={Link}
style={{ width: '100%' }}
>
{description}
</TableCell>
) : (
<TableCell
to={{
pathname: '/DocumentView',
state: {
mode: 'update',
table_keys: views.table_keys,
routed: true,
viewId: views.viewId,
},
}}
component={Link}
>
{description}
</TableCell>
)}
{Acsys.getMode() === 'Administrator' ? (
<TableCell style={{ minWidth: 70 }} align="right">
<Tooltip title="Edit View">
<IconButton
edge="start"
color="inherit"
aria-label="edit"
onClick={() => handleEditOpen(views)}
style={{ marginRight: 10 }}
>
<CreateIcon />
</IconButton>
</Tooltip>
<Tooltip title="Delete View">
<IconButton
edge="start"
color="inherit"
aria-label="delete"
onClick={() => handleDeleteOpen(viewId)}
>
<DeleteIcon />
</IconButton>
</Tooltip>
</TableCell>
) : (
<div />
)}
</TableRow>
);
});
};
try {
return (
<div>
<Paper
style={{
margin: 'auto',
overflow: 'hidden',
clear: 'both',
marginBottom: 20,
}}
>
<AppBar
position="static"
elevation={0}
style={{
backgroundColor: '#fafafa',
borderBottom: '1px solid #dcdcdc',
}}
>
<Toolbar style={{ margin: 4, paddingLeft: 12, paddingRight: 12 }}>
{Acsys.getMode() === 'Administrator' ? (
<Grid container spacing={1}>
<Grid item xs style={{ overflow: 'hidden' }}>
<Typography
align="left"
variant="subtitle2"
noWrap
style={{ marginTop: 10, color: '#000000' }}
>
Project: {projectName}
</Typography>
</Grid>
<Grid item>
<Tooltip title="Add New View For Table">
<Button
variant="contained"
color="primary"
onClick={handleClickOpen}
>
Add View
</Button>
</Tooltip>
</Grid>
</Grid>
) : (
<Grid container spacing={1}>
<Grid item xs style={{ overflow: 'hidden' }}>
<Typography
align="left"
variant="subtitle2"
noWrap
style={{ marginTop: 5, color: '#000000' }}
>
Project: {projectName}
</Typography>
</Grid>
</Grid>
)}
</Toolbar>
</AppBar>
<div style={{ margin: 'auto', overflow: 'auto' }}>
<Table>
<TableHead style={{ backgroundColor: '#fafafa' }}>
<TableRow>
<TableCell
style={{
paddingLeft: 16,
paddingRight: 16,
paddingTop: 5,
paddingBottom: 5,
width: 150,
}}
>
NAME
</TableCell>
<TableCell
style={{
paddingLeft: 16,
paddingRight: 16,
paddingTop: 5,
paddingBottom: 5,
}}
>
DESCRIPTION
</TableCell>
{Acsys.getMode() === 'Administrator' ? (
<TableCell
style={{
paddingLeft: 16,
paddingRight: 16,
paddingTop: 5,
paddingBottom: 5,
}}
align="right"
>
ACTIONS
</TableCell>
) : (
<div />
)}
</TableRow>
</TableHead>
<TableBody>{renderTableData()}</TableBody>
</Table>
</div>
<TablePagination
rowsPerPageOptions={[25]}
component="div"
count={views.length}
rowsPerPage={rowsPerPage}
page={page}
backIconButtonProps={{
'aria-label': 'previous page',
}}
nextIconButtonProps={{
'aria-label': 'next page',
}}
onChangePage={handleChangePage}
// onChangeRowsPerPage={this.handleChangeRowsPerPage}
/>
<LoadingDialog loading={loading} message={'Loading'} />
<AddViewDialog
open={open}
closeDialog={handleClose}
title={'Add Logical View'}
collection={collection}
setCollection={(value) => setCollection(value)}
collectionArr={collectionArr}
setName={(value) => setName(value)}
setDescription={(value) => setDescription(value)}
action={addView}
actionProcess={addLoading}
/>
<EditViewDialog
open={editOpen}
closeDialog={handleEditClose}
title={'Edit Logical View'}
position={tempView.position}
setPosition={setPosition}
views={views}
name={tempView.name}
setName={setTempName}
description={tempView.description}
setDescription={setTempDescription}
action={editView}
actionProcess={saveLoading}
/>
<YesNoDialog
open={deleting}
closeDialog={handleDeleteClose}
title={'Delete data?'}
message={'Are you sure you want to delete this data?'}
action={deleteView}
actionProcess={deleteLoading}
/>
</Paper>
</div>
);
} catch (error) {
return (
<div style={{ maxWidth: 1236, margin: 'auto' }}>
<Paper style={{ height: 40 }}>
<div style={{ padding: 10, margin: 'auto' }}>
Please make sure database has been created.
</div>
</Paper>
</div>
);
}
}
Example #13
Source File: Database.js From acsys with MIT License | 4 votes |
Database = (props) => {
const context = useContext(AcsysContext);
const [viewId, setviewId] = useState('');
const [views, setviews] = useState([]);
const [page, setpage] = useState(0);
const [rowsPerPage] = useState(15);
const [message, setmessage] = useState('');
const [loading, setloading] = useState(false);
const [deleting, setdeleting] = useState(false);
const [open, setOpen] = useState(false);
const [addLoading, setAddLoading] = useState(false);
const [deleteLoading, setdeleteLoading] = useState(false);
const [openMessage, setopenMessage] = useState(false);
const [projectName] = useState('');
const deleteTable = async () => {
setdeleteLoading(true);
if (viewId.length > 0) {
await Acsys.dropTable(viewId);
}
handleDeleteClose();
inDidMount();
};
const handleChangePage = (event, page) => {
setpage(page);
};
const handleClickOpen = async () => {
entry = [];
entry.push({ dataType: 'string', fieldName: '', value: '' });
setOpen(true);
};
const handleClose = () => {
tableName = '';
setOpen(false);
setAddLoading(false);
};
const handleMessageClose = () => {
setopenMessage(false);
};
const editView = async () => {
await Acsys.updateData('acsys_logical_content', tempView, [
['acsys_id', '=', tempView.acsys_id],
]);
const currentView = await Acsys.getData('acsys_logical_content');
setviews(currentView);
};
const handleDeleteOpen = async (viewId) => {
setdeleting(true);
setviewId(viewId);
};
const handleDeleteClose = () => {
setdeleting(false);
setdeleteLoading(false);
};
const inDidMount = async () => {
props.setHeader('Database');
context.setHeld(false);
tempView = [];
setloading(true);
let projectName = await Acsys.getProjectName();
let currentView = [];
currentView = await Acsys.getTableData();
projectName: projectName, setloading(false);
setAddLoading(false);
setviews(currentView);
};
useEffect(() => {
inDidMount();
}, []);
const setName = (name) => {
tableName = name;
};
const addTable = async () => {
setAddLoading(true);
let error = false;
let newEntry = {};
entry.forEach((obj) => {
const field = obj['fieldName'];
const value = obj['value'];
if (value.length < 1 || field.length < 1) {
error = true;
}
if (obj['dataType'] === 'string') {
newEntry[field] = value;
} else if (obj['dataType'] === 'number') {
newEntry[field] = parseInt(value);
} else if (obj['dataType'] === 'boolean') {
newEntry[field] = 'true' == value;
}
});
if (error || tableName.length < 1) {
setAddLoading(false);
setopenMessage(true);
setmessage('Allfields must be filled before submitting.');
} else {
await Acsys.createTable(tableName, newEntry);
handleClose();
inDidMount();
}
};
const renderTableData = () => {
return views
.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
.map((views) => {
const { acsys_id, table, rows } = views;
return (
<TableRow key={acsys_id}>
<TableCell>{table}</TableCell>
<TableCell style={{ width: 50 }}>{rows}</TableCell>
<TableCell style={{ width: 100 }} align="right">
<Tooltip title="Delete Table">
<IconButton
edge="start"
color="inherit"
aria-label="delete"
onClick={() => handleDeleteOpen(table)}
>
<DeleteIcon />
</IconButton>
</Tooltip>
</TableCell>
</TableRow>
);
});
};
try {
return (
<div>
<Paper
style={{
margin: 'auto',
overflow: 'hidden',
clear: 'both',
marginBottom: 20,
}}
>
<AppBar
position="static"
elevation={0}
style={{
backgroundColor: '#fafafa',
borderBottom: '1px solid #dcdcdc',
}}
>
<Toolbar style={{ margin: 4, paddingLeft: 12, paddingRight: 12 }}>
<Grid container spacing={1}>
<Grid item xs style={{ overflow: 'hidden' }}>
<Typography
align="left"
variant="subtitle2"
noWrap
style={{ marginTop: 10, color: '#000000' }}
>
Project: {projectName}
</Typography>
</Grid>
<Grid item>
<Tooltip title="Create New Table">
<Button
variant="contained"
color="primary"
onClick={handleClickOpen}
>
Add Table
</Button>
</Tooltip>
</Grid>
</Grid>
</Toolbar>
</AppBar>
<div style={{ margin: 'auto', overflow: 'auto' }}>
<Table>
<TableHead style={{ backgroundColor: '#fafafa' }}>
<TableRow>
<TableCell
style={{
paddingLeft: 16,
paddingRight: 16,
paddingTop: 5,
paddingBottom: 5,
}}
>
TABLE NAME
</TableCell>
<TableCell
style={{
paddingLeft: 16,
paddingRight: 16,
paddingTop: 5,
paddingBottom: 5,
width: 50,
}}
>
ROWS
</TableCell>
<TableCell
style={{
paddingLeft: 16,
paddingRight: 16,
paddingTop: 5,
paddingBottom: 5,
width: 100,
}}
align="right"
>
ACTIONS
</TableCell>
</TableRow>
</TableHead>
<TableBody>{renderTableData()}</TableBody>
</Table>
</div>
<TablePagination
rowsPerPageOptions={[25]}
component="div"
count={views.length}
rowsPerPage={rowsPerPage}
page={page}
backIconButtonProps={{
'aria-label': 'previous page',
}}
nextIconButtonProps={{
'aria-label': 'next page',
}}
onChangePage={handleChangePage}
// onChangeRowsPerPage={handleChangeRowsPerPage}
/>
<LoadingDialog loading={loading} message={'Loading'} />
<FieldControlDialog
open={open}
closeDialog={handleClose}
title={'Add Table'}
backend={HTML5Backend}
component={<TableControl setName={setName} entry={entry} />}
action={addTable}
actionProcess={addLoading}
/>
<YesNoDialog
open={deleting}
closeDialog={handleDeleteClose}
title={'Delete data?'}
message={'Are you sure you want to delete this data?'}
action={deleteTable}
actionProcess={deleteLoading}
/>
<MessageDialog
open={openMessage}
closeDialog={handleMessageClose}
title={'Error'}
message={message}
/>
</Paper>
</div>
);
} catch (error) {
alert(error);
return (
<div style={{ maxWidth: 1236, margin: 'auto' }}>
<Paper style={{ height: 40 }}>
<div style={{ padding: 10, margin: 'auto' }}>
Please make sure database has been created.
</div>
</Paper>
</div>
);
}
}
Example #14
Source File: List.js From course-manager with MIT License | 4 votes |
export default function List() {
const [page, setPage] = useState(0);
const [order, setOrder] = useState('asc');
const [selected, setSelected] = useState([]);
const [orderBy, setOrderBy] = useState('fullName');
const [filterName, setFilterName] = useState('');
const [rowsPerPage, setRowsPerPage] = useState(5);
const [users, setUsers] = useState([]);
const [total, setTotal] = useState(0);
useEffect(() => {
const fetchData = async () => {
console.log(order.toUpperCase());
const queryString = RequestQueryBuilder.create({
page,
limit: rowsPerPage,
join: [
{
field: 'account',
select: ['username']
},
{
field: 'roles',
select: ['name']
}
],
sort: [{ field: orderBy, order: order.toUpperCase() }]
});
const response = await apis.user.find(queryString.query());
const { data: fetchedUsers, total: fetchedTotal } = response;
if (fetchedUsers && fetchedUsers.length > 0) {
setUsers(
fetchedUsers.map(({ id, email, fullName, account: { username }, roles }) => ({
id,
email,
fullName,
username,
roles: roles.map(({ name }) => name).join(',')
}))
);
}
setTotal(fetchedTotal);
};
fetchData();
}, [page, orderBy, order, rowsPerPage]);
const handleRequestSort = (event, property) => {
const isAsc = orderBy === property && order === 'asc';
setOrder(isAsc ? 'desc' : 'asc');
setOrderBy(property);
};
const handleSelectAllClick = (event) => {
if (event.target.checked) {
const newSelecteds = users.map((n) => n.name);
setSelected(newSelecteds);
return;
}
setSelected([]);
};
const handleClick = (event, name) => {
const selectedIndex = selected.indexOf(name);
let newSelected = [];
if (selectedIndex === -1) {
newSelected = newSelected.concat(selected, name);
} else if (selectedIndex === 0) {
newSelected = newSelected.concat(selected.slice(1));
} else if (selectedIndex === selected.length - 1) {
newSelected = newSelected.concat(selected.slice(0, -1));
} else if (selectedIndex > 0) {
newSelected = newSelected.concat(
selected.slice(0, selectedIndex),
selected.slice(selectedIndex + 1)
);
}
setSelected(newSelected);
};
const handleChangePage = (event, newPage) => {
setPage(newPage);
};
const handleChangeRowsPerPage = (event) => {
setRowsPerPage(parseInt(event.target.value, 10));
setPage(0);
};
const handleFilterByName = (event) => {
setFilterName(event.target.value);
};
const emptyRows = page > 0 ? Math.max(0, (1 + page) * rowsPerPage - users.length) : 0;
const filteredUsers = applySortFilter(users, getComparator(order, orderBy), filterName);
const isUserNotFound = filteredUsers.length === 0;
return (
<Page title="Users">
<Container>
<Stack direction="row" alignItems="center" justifyContent="space-between" mb={5}>
<Typography variant="h4" gutterBottom>
Users
</Typography>
<Button
variant="contained"
component={RouterLink}
to="/dashboard/user/create"
startIcon={<Icon icon={plusFill} />}
>
New User
</Button>
</Stack>
<Card>
<UserListToolbar
numSelected={selected.length}
filterName={filterName}
onFilterName={handleFilterByName}
/>
<Scrollbar>
<TableContainer sx={{ minWidth: 800 }}>
<Table>
<UserListHead
order={order}
orderBy={orderBy}
headLabel={TABLE_HEAD}
rowCount={total}
numSelected={selected.length}
onRequestSort={handleRequestSort}
onSelectAllClick={handleSelectAllClick}
/>
<TableBody>
{filteredUsers
.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
.map((row) => {
const { id, fullName, roles, email, username } = row;
const isItemSelected = selected.indexOf(fullName) !== -1;
return (
<TableRow
hover
key={id}
tabIndex={-1}
role="checkbox"
selected={isItemSelected}
aria-checked={isItemSelected}
>
<TableCell padding="checkbox">
<Checkbox
checked={isItemSelected}
onChange={(event) => handleClick(event, fullName)}
/>
</TableCell>
<TableCell component="th" scope="row" padding="none">
<Stack direction="row" alignItems="center" spacing={2}>
{/* <Avatar alt={fullName} src={avatarUrl} /> */}
<Typography variant="subtitle2" noWrap>
{fullName}
</Typography>
</Stack>
</TableCell>
<TableCell align="left">{username}</TableCell>
<TableCell align="left">{email}</TableCell>
<TableCell align="left">{roles}</TableCell>
<TableCell align="right">
<UserMoreMenu id={id} />
</TableCell>
</TableRow>
);
})}
{emptyRows > 0 && (
<TableRow style={{ height: 53 * emptyRows }}>
<TableCell colSpan={6} />
</TableRow>
)}
</TableBody>
{isUserNotFound && (
<TableBody>
<TableRow>
<TableCell align="center" colSpan={6} sx={{ py: 3 }}>
<SearchNotFound searchQuery={filterName} />
</TableCell>
</TableRow>
</TableBody>
)}
</Table>
</TableContainer>
</Scrollbar>
<TablePagination
rowsPerPageOptions={[5, 10, 25]}
component="div"
count={total}
rowsPerPage={rowsPerPage}
page={page}
onPageChange={handleChangePage}
onRowsPerPageChange={handleChangeRowsPerPage}
/>
</Card>
</Container>
</Page>
);
}
Example #15
Source File: KailonaTable.js From ehr with GNU Affero General Public License v3.0 | 4 votes |
render() {
const columnsLength = this.props.columns.length;
const noDataColSpan = this.props.contextMenu ? columnsLength + 1 : columnsLength;
const rowHeight = 50;
const isWayPointAvailable = !this.state.loading && this.state.previousDataLength !== this.props.data.length;
const tableHeight = (this.props.rowsPerPage + 1) * rowHeight;
return (
<Paper style={{ height: `${tableHeight}px`, width: '100%', position: 'relative', overflowY: 'auto' }}>
<TableContainer>
<Table>
<TableHead>
<TableRow>
{this.props.columns.map(col => (
<HeadCell>{col.label}</HeadCell>
))}
{this.props.contextMenu && <HeadCell></HeadCell>}
</TableRow>
</TableHead>
<TableBody>
{this.props.data.map(record => (
<TableRow>
{this.props.columns.map((col, index) => {
let displayText = record[col.key];
if (col.display && typeof col.display === 'function') {
displayText = col.display(record, record[col.key]);
}
return (
<TableCell>
<div>{displayText}</div>
{index === 0 && (
<div>
<Link color="primary">{record.source}</Link>
</div>
)}
</TableCell>
);
})}
{this.props.contextMenu && (
<TableCell>
<IconButton onClick={e => this.toggleContextMenu(e, record)}>
<MoreHoriz />
</IconButton>
</TableCell>
)}
</TableRow>
))}
</TableBody>
<TableFooter>
{this.props.loading && (
<TableRow>
<TableCell colSpan={this.props.columns.length} align="center">
<Loader />
</TableCell>
</TableRow>
)}
{!this.props.loading && (!this.props.data || !this.props.data.length) && (
<TableRow>
<TableCell colSpan={noDataColSpan} align="center">
<Typography variant="h5">{t('ehr', 'No data available')}</Typography>
</TableCell>
</TableRow>
)}
</TableFooter>
</Table>
</TableContainer>
{isWayPointAvailable && (
<div style={{ marginTop: `10px`, height: '20px' }}>
<Waypoint onEnter={this.handleScroll}></Waypoint>
</div>
)}
{this.props.pagination && (
<TablePagination
rowsPerPageOptions={[1, 5, 10, 25]}
component="div"
count={this.props.data.length}
rowsPerPage={this.props.rowsPerPage}
page={this.state.page}
onChangePage={(e, page) => this.props.onChangePage(e, page)}
onChangeRowsPerPage={e => this.props.onChangeRowsPerPage(e)}
/>
)}
<Menu
id="table-context-menu"
anchorEl={this.state.anchorEl}
keepMounted
open={Boolean(this.state.anchorEl)}
onClose={this.handleContextMenuClose}
>
{this.props.contextMenu &&
this.props.contextMenu.map(menuItem => {
return (
<MenuItem onClick={() => this.handleMenuItemClick(menuItem.onClick)}>
<ListItemIcon size="small" style={{ minWidth: '32px' }}>
{menuItem.icon}
</ListItemIcon>
<ListItemText primary={menuItem.label} />
</MenuItem>
);
})}
</Menu>
</Paper>
);
}
Example #16
Source File: CustomTable.js From treetracker-admin-client with GNU Affero General Public License v3.0 | 4 votes |
/**
* @function
* @name CustomTable
* @description displays table containing rows with data
*
* @param {Object} props - properties passed to component
* @param {Object} props.sortBy - current sort by field and sort order
* @param {Object} props.selectedRow - selected row
* @param {Object[]} props.tableMetaData - meta data of the table (carries infomation about table columns etc..)
* @param {function} props.handleGetData - handler function that triggers get data to be displayed in table
* @param {function} props.openDateFilter - opens date filter
* @param {function} props.openMainFilter - opens main filter
* @param {function} props.setPage - sets current page number
* @param {function} props.setRowsPerPage - sets number of rows per page number
* @param {function} props.setSortBy - sets sort by field and sort order
* @param {function} props.onSelectFile - callback function to be called when file is selected
* @param {function} props.setSelectedRow - sets selected/clicked row
* @param {string} props.headerTitle - title of the table header
* @param {string} props.actionButtonType - determines which action button to render(value can either be 'export' or 'upload')
* @param {string} props.activeDateRage - string representing the active date range (i.e. 'Oct 1 - Oct 5') in the date filter button
* @param {boolean} props.isLoading - shows loading spinner when true
* @param {number} props.page - current page number
* @param {number} props.rowsPerPage - current number of rows per page
* @param {number} props.totalCount - total number of rows to be displayed
* @param {number} props.activeFiltersCount - number of active filters
* @param {Array} props.rows - rows to be displayed in table
* @param {React.Component} props.rowDetails - row component to display details of a selected row
* @param {React.Component} props.mainFilterComponent - renders main filter component
* @param {React.Component} props.dateFilterComponent - renders date filter component
*
* @returns {React.Component} custom table
*/
function CustomTable({
tableMetaData,
mainFilterComponent,
dateFilterComponent,
headerTitle,
actionButtonType,
exportDataFetch,
setSelectedRow,
selectedRow,
sortBy,
rows,
totalCount,
rowDetails,
openDateFilter,
openMainFilter,
setPage,
setRowsPerPage,
rowsPerPage,
setSortBy,
isLoading,
activeDateRange,
onSelectFile,
page,
activeFiltersCount,
}) {
// managing custom table state
const classes = useStyles();
const [sortableColumnsObject, setSortableColumnsObject] = useState({});
const [growerDetail, setGrowerDetail] = useState({
isOpen: false,
grower: {},
});
const handleChangePage = (event, newPage) => {
setPage(newPage);
};
const handleChangeRowsPerPage = (event) => {
setRowsPerPage(parseInt(event.target.value, 10));
setPage(0);
};
const handleOpenRowDetails = (row) => {
setSelectedRow(row);
};
const handleSortableColumns = (column) => {
const sortableColumns = {
...sortableColumnsObject,
[column.name]: sortableColumnsObject[column.name]
? sortableColumnsObject[column.name] === 'asc'
? 'desc'
: 'asc'
: 'asc',
};
setSortableColumnsObject(sortableColumns);
setSortBy({ field: column.name, order: sortableColumns[column.name] });
};
const handleShowGrowerDetail = (e, grower) => {
e.preventDefault();
e.stopPropagation();
setGrowerDetail({
isOpen: true,
growerId: grower.worker_id,
});
};
function handleCloseGrowerDetail() {
setGrowerDetail({
isOpen: false,
growerId: null,
});
}
const isRowSelected = (id) => id === selectedRow?.id;
const tablePagination = () => {
return (
<TablePagination
rowsPerPageOptions={[20, 50, 100]}
component="div"
count={totalCount || 0}
page={page}
rowsPerPage={rowsPerPage}
onChangePage={handleChangePage}
onChangeRowsPerPage={handleChangeRowsPerPage}
aria-label="rows per page"
/>
);
};
return (
<Paper className={classes.customTable}>
<CustomTableHeader
openDateFilter={openDateFilter}
openMainFilter={openMainFilter}
data={rows}
headerTitle={headerTitle}
activeDateRange={activeDateRange}
actionButtonType={actionButtonType}
onSelectFile={onSelectFile}
activeFiltersCount={activeFiltersCount}
exportDataFetch={exportDataFetch}
/>
{tablePagination()}
<TableContainer className={classes.tableHeight}>
<Table stickyHeader aria-label="sticky table">
<TableHead>
<TableRow className={classes.customTableHeader}>
{tableMetaData.map((column, i) => (
<TableCell
key={`${i}-${column.description}`}
sortDirection={
sortableColumnsObject[column.name] || column.sortDirection
}
style={{
textAlign: column.align === 'right' ? 'right' : 'inherit',
}}
>
{column?.sortable ? (
<TableSortLabel
active={sortBy?.field === column.name}
onClick={() => handleSortableColumns(column)}
direction={sortableColumnsObject[column.name]}
classes={{ icon: classes.customTableHeadSortIcon }}
IconComponent={ArrowDropDownIcon}
>
<Typography
variant="h6"
align={column.align === 'right' ? 'right' : 'inherit'}
>
{column.description}
{column?.showInfoIcon && (
<Tooltip title={column.showInfoIcon}>
<InfoOutlinedIcon className={classes.infoIcon} />
</Tooltip>
)}
</Typography>
</TableSortLabel>
) : (
<Typography
variant="h6"
align={column.align === 'right' ? 'right' : 'inherit'}
>
{column.description}
{column?.showInfoIcon && (
<Tooltip title={column.showInfoIcon}>
<InfoOutlinedIcon className={classes.infoIcon} />
</Tooltip>
)}
</Typography>
)}
</TableCell>
))}
</TableRow>
</TableHead>
<TableBody>
{isLoading ? (
<TableRow>
<TableCell>
<Grid item container className={classes.progressContainer}>
<CircularProgress />
</Grid>
</TableCell>
</TableRow>
) : rows.length > 0 ? (
<>
{rows.map((row, i) => (
<TableRow
key={`${i}-${row.id}`}
onClick={() => handleOpenRowDetails(row)}
className={
isRowSelected(row.id) ? classes.selectedRow : null
}
>
{tableMetaData.map((column, j) => (
<TableCell key={`${i}-${j}-${column.name}`}>
{column.name === 'grower' ? (
<Grid item>
<Typography
variant="body1"
style={{ textTransform: 'capitalize' }}
>
{row[column.name]}
<IconButton
onClick={(e) => {
handleShowGrowerDetail(e, row);
}}
aria-label={`View/Edit Grower details`}
title={`View/Edit Grower details`}
style={{ padding: '0 2px 2px 0' }}
disabled
>
<Person color="disabled" />
</IconButton>
</Typography>
</Grid>
) : (
<Typography
variant="body1"
style={{
textTransform: 'capitalize',
textAlign:
column.align === 'right' ? 'right' : 'inherit',
}}
>
{row[column.name]}
</Typography>
)}
</TableCell>
))}
</TableRow>
))}
</>
) : (
<TableRow>
<TableCell>
<Typography
variant="body1"
className={classes.noDataToDisplay}
>
No data to display
</Typography>
</TableCell>
</TableRow>
)}
</TableBody>
</Table>
</TableContainer>
{tablePagination()}
<GrowerProvider>
<GrowerDetail
open={growerDetail.isOpen}
growerId={growerDetail.growerId}
onClose={() => handleCloseGrowerDetail()}
/>
</GrowerProvider>
{/* start table main filter */}
{mainFilterComponent}
{/* end table main filter */}
{/* start table date filter */}
{dateFilterComponent}
{/* end table date filter */}
{/* start table row details */}
{rowDetails}
{/* end table row details */}
</Paper>
);
}
Example #17
Source File: SpeciesTable.js From treetracker-admin-client with GNU Affero General Public License v3.0 | 4 votes |
SpeciesTable = (props) => {
const { classes } = props;
const sortOptions = { byId: 'id', byName: 'name' };
const speciesContext = useContext(SpeciesContext);
const { isLoading } = useContext(SpeciesContext);
const [page, setPage] = useState(0);
const [rowsPerPage, setRowsPerPage] = useState(25);
const [isEdit, setIsEdit] = useState(false);
const [isAdding, setIsAdding] = useState(false);
const [speciesEdit, setSpeciesEdit] = useState(undefined);
const [openDelete, setOpenDelete] = useState(false);
const [sortedSpeciesList, setSortedSpeciesList] = useState([]);
const [option, setOption] = useState(sortOptions.byName);
const [selected, setSelected] = useState([]);
const [showCombine, setShowCombine] = useState(false);
const tableRef = useRef(null);
useEffect(() => {
const sortBy = (option) => {
let sortedSpecies;
if (option === sortOptions.byId) {
sortedSpecies = [...speciesContext.speciesList].sort(
(a, b) => a[option] - b[option]
);
}
if (option === sortOptions.byName) {
sortedSpecies = [...speciesContext.speciesList].sort((a, b) =>
a[option].localeCompare(b[option])
);
}
setSortedSpeciesList(sortedSpecies);
};
sortBy(option);
}, [
option,
sortOptions.byId,
sortOptions.byName,
speciesContext.speciesList,
]);
const handleChangePage = (event, newPage) => {
setPage(newPage);
};
const handleChangeRowsPerPage = (event) => {
tableRef.current && tableRef.current.scrollIntoView();
setRowsPerPage(parseInt(event.target.value, 10));
setPage(0);
};
const handleEdit = (species) => {
setSpeciesEdit(species);
setIsEdit(true);
};
const openDeleteDialog = (species) => {
setSpeciesEdit(species);
setOpenDelete(true);
};
const openCombineModal = () => {
if (selected.length > 1) setShowCombine(true);
else alert('Please select two or more species to be combined!');
};
const handleSelect = (checked, id) => {
if (checked) setSelected([...selected, id]);
else setSelected(selected.filter((item) => item !== id));
};
const renderSpecies = () => {
return (rowsPerPage > 0
? sortedSpeciesList.slice(
page * rowsPerPage,
page * rowsPerPage + rowsPerPage
)
: sortedSpeciesList
).map((species) => (
<TableRow key={species.id} role="listitem">
<TableCell>
<Checkbox
onChange={(e) => handleSelect(e.target.checked, species.id)}
checked={selected.includes(species.id)}
/>
</TableCell>
<TableCell component="th" scope="row">
{species.id}
</TableCell>
<TableCell component="th" scope="row" data-testid="species">
{species.name}
</TableCell>
<TableCell>{species.desc}</TableCell>
<TableCell>{species.captureCount}</TableCell>
<TableCell>
<IconButton title="edit" onClick={() => handleEdit(species)}>
<Edit />
</IconButton>
<IconButton title="delete" onClick={() => openDeleteDialog(species)}>
<Delete />
</IconButton>
</TableCell>
</TableRow>
));
};
const tablePagination = () => (
<TablePagination
count={speciesContext.speciesList.length}
rowsPerPageOptions={[25, 50, 100, { label: 'All', value: -1 }]}
colSpan={3}
page={page}
rowsPerPage={rowsPerPage}
onChangePage={handleChangePage}
onChangeRowsPerPage={handleChangeRowsPerPage}
SelectProps={{
inputProps: { 'aria-label': 'rows per page' },
native: true,
}}
/>
);
return (
<Grid className={classes.speciesTableContainer}>
<Paper elevation={3} className={classes.menu}>
<Menu variant="plain" />
</Paper>
<Grid item container className={classes.rightBox}>
<Grid item xs={12}>
<Grid container justify="space-between" className={classes.titleBox}>
<Grid item>
<Grid container>
<Grid item>
<Typography variant="h2">Species</Typography>
</Grid>
</Grid>
</Grid>
<Grid item className={classes.addUserBox}>
<Button
onClick={openCombineModal}
variant="outlined"
color="primary"
>
COMBINE SPECIES
</Button>
<Button
onClick={() => setIsAdding(true)}
variant="contained"
className={classes.addUser}
color="primary"
>
ADD NEW SPECIES
</Button>
</Grid>
</Grid>
<Grid container direction="column" className={classes.bodyBox}>
<TableContainer component={Paper} ref={tableRef}>
<Table className={classes.table} aria-label="simple table">
<TableHead>
<TableRow>
<TableCell></TableCell>
<TableCell>
ID
<IconButton
title="sortbyId"
onClick={() => setOption(sortOptions.byId)}
>
<SortIcon />
</IconButton>
</TableCell>
<TableCell>
name
<IconButton
title="sortbyName"
onClick={() => setOption(sortOptions.byName)}
>
<SortIcon />
</IconButton>
</TableCell>
<TableCell>Description</TableCell>
<TableCell>Tagged Captures</TableCell>
<TableCell>Operations</TableCell>
</TableRow>
</TableHead>
{isLoading ? (
<Grid item container className={classes.loadingIndicator}>
<CircularProgress />
</Grid>
) : (
<TableBody>{renderSpecies()}</TableBody>
)}
<TableFooter>
<TableRow>{tablePagination()}</TableRow>
</TableFooter>
</Table>
</TableContainer>
</Grid>
</Grid>
</Grid>
<EditModal
isEdit={isAdding || isEdit}
setIsEdit={isAdding ? setIsAdding : setIsEdit}
speciesEdit={speciesEdit}
setSpeciesEdit={setSpeciesEdit}
styles={{ ...classes }}
editSpecies={
isAdding ? speciesContext.createSpecies : speciesContext.editSpecies
}
loadSpeciesList={speciesContext.loadSpeciesList}
data={sortedSpeciesList}
/>
<DeleteDialog
speciesEdit={speciesEdit}
setSpeciesEdit={setSpeciesEdit}
openDelete={openDelete}
setOpenDelete={setOpenDelete}
deleteSpecies={speciesContext.deleteSpecies}
loadSpeciesList={speciesContext.loadSpeciesList}
/>
<CombineModal
show={showCombine}
setShow={setShowCombine}
data={sortedSpeciesList}
combineSpecies={speciesContext.combineSpecies}
loadSpeciesList={speciesContext.loadSpeciesList}
selected={selected}
styles={{ ...classes }}
/>
</Grid>
);
}
Example #18
Source File: Regions.js From treetracker-admin-client with GNU Affero General Public License v3.0 | 4 votes |
RegionTable = (props) => {
const { classes } = props;
// const sortOptions = { byName: 'name' };
const {
regions,
collections,
currentPage,
pageSize,
showCollections,
changeCurrentPage,
changePageSize,
// changeSort,
setShowCollections,
regionCount,
collectionCount,
upload,
updateRegion,
updateCollection,
deleteRegion,
deleteCollection,
} = useContext(RegionContext);
const { orgList, userHasOrg } = useContext(AppContext);
const [openEdit, setOpenEdit] = useState(false);
const [isUpload, setIsUpload] = useState(false);
const [selectedItem, setSelectedItem] = useState(undefined);
const [openDelete, setOpenDelete] = useState(false);
const [snackbarOpen, setSnackbarOpen] = useState(false);
const [snackbarMessage, setSnackbarMesssage] = useState('');
useEffect(() => {
if (!openDelete && !openEdit) {
// Wait for the dialog to disappear before clearing the selected item.
setTimeout(() => {
setSelectedItem(undefined);
setIsUpload(false);
}, 300);
}
}, [openDelete, openEdit]);
const tableRef = useRef(null);
const handleChangeCurrentPage = (event, value) => {
tableRef.current && tableRef.current.scrollIntoView();
changeCurrentPage(value);
};
const handleChangeRowsPerPage = (event) => {
changePageSize(Number(event.target.value));
changeCurrentPage(0);
};
const handleEdit = (item, isCollection) => {
setSelectedItem({
...item,
isCollection,
});
setOpenEdit(true);
};
const handleDelete = (item, isCollection) => {
setSelectedItem({
...item,
isCollection,
});
setOpenDelete(true);
};
const handleChangeShowCollections = (event, val) => {
if (val !== null) {
setShowCollections(val);
}
};
const handleUploadClick = () => {
setIsUpload(true);
setOpenEdit(true);
};
const handleSnackbarClose = (event, reason) => {
if (reason === 'clickaway') {
return;
}
setSnackbarOpen(false);
setSnackbarMesssage('');
};
const showSnackbar = (message) => {
setSnackbarMesssage(message);
setSnackbarOpen(true);
};
const RegionProperties = ({ region, max = 0 }) => {
return Object.keys(region.properties || {}).map((key, idx) => {
if (max === 0 || idx < max)
return (
<Grid key={`prop_${region.id}_${key}_${max}`}>
<span>
<b>{key}:</b>
</span>
<span>{JSON.stringify(region.properties[key])}</span>
{max > 0 && idx === max - 1 && <span> …</span>}
</Grid>
);
});
};
const RegionTableRows = () => {
return (showCollections ? collections : regions).map((item) => (
<TableRow key={item.id} role="listitem">
{/* <TableCell>
<Checkbox
onChange={(e) => handleSelect(e.target.checked, region.id)}
checked={selected.includes(region.id)}
/>
</TableCell> */}
<TableCell component="th" scope="row" data-testid="region">
{item.name}
</TableCell>
{!userHasOrg && (
<TableCell>
{orgList.find((org) => org.stakeholder_uuid === item.owner_id)
?.name || '---'}
</TableCell>
)}
{!showCollections && (
<>
<TableCell>{item.collection_name || '---'}</TableCell>
<Tooltip title={<RegionProperties region={item} />}>
<TableCell>
<RegionProperties region={item} max={3} />
</TableCell>
</Tooltip>
<TableCell align="center">
{item.show_on_org_map ? 'Yes' : 'No'}
</TableCell>
<TableCell align="center">
{item.calculate_statistics ? 'Yes' : 'No'}
</TableCell>
</>
)}
<TableCell align="right" className={classes.operations}>
<IconButton
title="edit"
onClick={() => handleEdit(item, showCollections)}
>
<Edit />
</IconButton>
<IconButton
title="delete"
onClick={() => handleDelete(item, showCollections)}
>
<Delete />
</IconButton>
</TableCell>
</TableRow>
));
};
const RegionTablePagination = () => (
<TablePagination
count={Number(showCollections ? collectionCount : regionCount)}
rowsPerPageOptions={[25, 50, 100, { label: 'All', value: -1 }]}
page={currentPage}
rowsPerPage={pageSize}
onChangePage={handleChangeCurrentPage}
onChangeRowsPerPage={handleChangeRowsPerPage}
SelectProps={{
inputProps: { 'aria-label': 'rows per page' },
native: true,
}}
/>
);
return (
<>
<Grid container className={classes.regionsTableContainer}>
<Paper elevation={3} className={classes.menu}>
<Menu variant="plain" />
</Paper>
<Grid item container className={classes.rightBox}>
<Grid item xs={12}>
<Grid
container
justify="space-between"
className={classes.titleBox}
>
<Grid item>
<Grid container>
<Grid item>
<Typography variant="h2">Regions</Typography>
</Grid>
</Grid>
</Grid>
<Grid item className={classes.headerButtonBox}>
<ToggleButtonGroup
color="primary"
value={showCollections}
exclusive
onChange={handleChangeShowCollections}
>
<ToggleButton value={false}>Regions</ToggleButton>
<ToggleButton value={true}>Collections</ToggleButton>
</ToggleButtonGroup>
</Grid>
<Grid item className={classes.headerButtonBox}>
<Button
onClick={handleUploadClick}
variant="contained"
className={classes.upload}
color="primary"
>
UPLOAD
</Button>
</Grid>
</Grid>
<Grid container direction="column" className={classes.bodyBox}>
<TableContainer component={Paper} ref={tableRef}>
<Table className={classes.table} aria-label="simple table">
<TableHead>
<TableRow>
<TableCell>
Name
{/* <IconButton
title="sortbyName"
onClick={() => changeSort(sortOptions.byName)}
>
<SortIcon />
</IconButton> */}
</TableCell>
{!userHasOrg && <TableCell>Owner</TableCell>}
{!showCollections && (
<>
<TableCell>Collection</TableCell>
<TableCell>Properties</TableCell>
<TableCell align="center">Shown on Org Map</TableCell>
<TableCell align="center">
Statistics Calculated
</TableCell>
</>
)}
<TableCell></TableCell>
</TableRow>
</TableHead>
<TableBody>
<RegionTableRows />
</TableBody>
<TableFooter>
<TableRow>
<RegionTablePagination />
</TableRow>
</TableFooter>
</Table>
</TableContainer>
</Grid>
</Grid>
</Grid>
</Grid>
<EditModal
openEdit={openEdit}
setOpenEdit={setOpenEdit}
isUpload={isUpload}
selectedItem={selectedItem}
styles={{ ...classes }}
upload={upload}
updateRegion={updateRegion}
updateCollection={updateCollection}
showSnackbar={showSnackbar}
/>
<DeleteDialog
selectedItem={selectedItem}
openDelete={openDelete}
setOpenDelete={setOpenDelete}
deleteRegion={deleteRegion}
deleteCollection={deleteCollection}
showSnackbar={showSnackbar}
/>
<Snackbar
open={snackbarOpen}
autoHideDuration={3000}
onClose={handleSnackbarClose}
message={snackbarMessage}
action={
<>
<IconButton
size="small"
aria-label="close"
color="inherit"
onClick={handleSnackbarClose}
>
<Close fontSize="small" />
</IconButton>
</>
}
/>
</>
);
}
Example #19
Source File: CaptureTable.js From treetracker-admin-client with GNU Affero General Public License v3.0 | 4 votes |
CaptureTable = () => {
const {
filter,
rowsPerPage,
page,
order,
orderBy,
captures,
capture,
captureCount,
isLoading,
setPage,
setRowsPerPage,
setOrder,
setOrderBy,
setCapture,
getCaptureAsync,
} = useContext(CapturesContext);
const speciesContext = useContext(SpeciesContext);
const tagsContext = useContext(TagsContext);
const [isDetailsPaneOpen, setIsDetailsPaneOpen] = useState(false);
const [speciesLookup, setSpeciesLookup] = useState({});
const [tagLookup, setTagLookup] = useState({});
const [captureTagLookup, setCaptureTagLookup] = useState({});
const [isOpenExport, setOpenExport] = useState(false);
const [disableHoverListener, setDisableHoverListener] = useState(false);
const classes = useStyle();
useEffect(() => {
populateSpeciesLookup();
}, [speciesContext.speciesList]);
useEffect(() => {
populateTagLookup();
}, [tagsContext.tagList]);
const getCaptureTags = async () => {
// Don't do anything if there are no captures
if (!captures?.length) {
return;
}
// Get the capture tags for all of the displayed captures
const captureTags = await api.getCaptureTags({
captureIds: captures.map((c) => c.id),
});
// Populate a lookup for quick access when rendering the table
let lookup = {};
captureTags.forEach((captureTag) => {
if (!lookup[captureTag.treeId]) {
lookup[captureTag.treeId] = [];
}
lookup[captureTag.treeId].push(tagLookup[captureTag.tagId]);
});
setCaptureTagLookup(lookup);
};
useEffect(() => {
getCaptureTags();
}, [captures, tagLookup]);
const populateSpeciesLookup = async () => {
let species = {};
speciesContext.speciesList.forEach((s) => {
species[s.id] = s.name;
});
setSpeciesLookup(species);
};
const populateTagLookup = async () => {
let tags = {};
tagsContext.tagList.forEach((t) => {
tags[t.id] = t.tagName;
});
setTagLookup(tags);
};
const toggleDrawer = (id) => {
getCaptureAsync(id);
setIsDetailsPaneOpen(!isDetailsPaneOpen);
};
const createToggleDrawerHandler = (id) => {
return () => {
toggleDrawer(id);
};
};
const closeDrawer = () => {
setIsDetailsPaneOpen(false);
setDisableHoverListener(false);
setCapture({});
};
const handleOpenExport = () => {
setOpenExport(true);
};
const handlePageChange = (e, page) => {
setPage(page);
};
const handleRowsPerPageChange = (e) => {
setRowsPerPage(parseInt(e.target.value));
};
const createSortHandler = (attr) => {
return () => {
const newOrder = orderBy === attr && order === 'asc' ? 'desc' : 'asc';
const newOrderBy = attr;
setOrder(newOrder);
setOrderBy(newOrderBy);
};
};
const tablePagination = () => {
return (
<TablePagination
rowsPerPageOptions={[25, 50, 100, 250, 500]}
component="div"
count={captureCount || 0}
page={page}
rowsPerPage={rowsPerPage}
onChangePage={handlePageChange}
onChangeRowsPerPage={handleRowsPerPageChange}
/>
);
};
const enableTooltips = process.env.REACT_APP_ENABLE_TOOLTIPS === 'true';
return (
<Grid style={{ height: '100%', overflow: 'auto', textAlign: 'center' }}>
<Grid
container
direction="row"
justify="space-between"
alignItems="center"
>
<Typography variant="h5" className={classes.title}>
Captures
</Typography>
<Grid className={classes.cornerTable}>
<Button
variant="outlined"
color="primary"
startIcon={<GetApp />}
className={classes.buttonCsv}
onClick={handleOpenExport}
>
Export Captures
</Button>
<ExportCaptures
isOpen={isOpenExport}
handleClose={() => setOpenExport(false)}
columns={columns}
filter={filter}
speciesLookup={speciesLookup}
captureTagLookup={captureTagLookup}
/>
{tablePagination()}
</Grid>
</Grid>
<Table data-testid="captures-table">
<TableHead>
<TableRow>
{columns.map(({ attr, label, noSort }) => (
<TableCell
key={attr}
sortDirection={orderBy === attr ? order : false}
>
<TableSortLabel
active={orderBy === attr}
direction={orderBy === attr ? order : 'asc'}
onClick={createSortHandler(attr)}
disabled={noSort}
>
{label}
</TableSortLabel>
</TableCell>
))}
</TableRow>
</TableHead>
<TableBody data-testid="captures-table-body">
{isLoading && !captures?.length ? (
<TableRow className={classes.loadingIndicator}>
<TableCell className={classes.loadingIndicator}>
<CircularProgress />
</TableCell>
</TableRow>
) : (
<>
{captures &&
captures.map((capture) => (
<Tooltip
key={capture.id}
placement="top"
arrow={true}
interactive={!disableHoverListener}
enterDelay={500}
enterNextDelay={500}
disableFocusListener={true}
disableHoverListener={disableHoverListener}
classes={{
tooltipPlacementTop: classes.tooltipTop,
arrow: classes.arrow,
}}
title={
enableTooltips ? (
<CaptureTooltip
capture={capture}
toggleDrawer={createToggleDrawerHandler}
/>
) : (
''
)
}
>
<TableRow
key={capture.id}
onClick={createToggleDrawerHandler(capture.id)}
className={classes.tableRow}
>
{columns.map(({ attr, renderer }, i) => (
<TableCell key={`${attr}_${i}`}>
{formatCell(
capture,
speciesLookup,
captureTagLookup[capture.id] || [],
attr,
renderer
)}
</TableCell>
))}
</TableRow>
</Tooltip>
))}
</>
)}
</TableBody>
</Table>
{tablePagination()}
<CaptureDetailProvider>
<CaptureDetailDialog
open={isDetailsPaneOpen}
capture={capture}
onClose={closeDrawer}
/>
</CaptureDetailProvider>
</Grid>
);
}
Example #20
Source File: Observations.jsx From Corona-tracker with MIT License | 4 votes |
Observations = props => {
const classes = useStyles();
const { detailData, observations, tempUnit } = props;
const [page, setPage] = React.useState(0);
const [rowsPerPage, setRowsPerPage] = React.useState(4);
const handleChangePage = (event, newPage) => {
setPage(newPage);
};
const handleChangeRowsPerPage = event => {
setRowsPerPage(+event.target.value);
setPage(0);
};
return (
<div className={classes.root}>
{(detailData.length ? detailData : observations)
.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
.map(observation => (
<ExpansionPanel
className={classes.expansionPanel}
defaultExpanded={detailData.length === 1}
key={observation.date}
>
<ExpansionPanelSummary
expandIcon={<ExpandMoreIcon />}
aria-controls="observation"
id="observation"
className={classes.summary}
>
<Grid container alignItems="center" justify="center" spacing={1}>
<Grid item justify="center">
<RedFont>
<span>Date:</span> {new Date(observation.date).toLocaleDateString()}
</RedFont>
</Grid>
<Grid item>
<RedFont>
<span>Overall Feeling:</span> {`${observation.physical.dailyfeeling} /5`}
</RedFont>
</Grid>
<Grid item>
<RedFont>
{tempUnit === 'fahrenheit' ? (
<>
<span>Temperature:</span> {observation.physical.feverSeverity} ℉
</>
) : (
<>
<span>Temperature:</span> {observation.physical.feverSeverity} ℃
</>
)}
</RedFont>
</Grid>
</Grid>
</ExpansionPanelSummary>
<ExpansionPanelDetails className={classes.detailed}>
<Grid container alignItems="center" justify="center" spacing={2}>
<Grid item xs={12} sm={6}>
<WhiteFont>
<span>Cough:</span> {observation.physical.coughSeverity}
</WhiteFont>
</Grid>
<Grid item xs={12} sm={6}>
<WhiteFont>
<span>Chills:</span> {observation.physical.chillsSeverity}
</WhiteFont>
</Grid>
<Grid item xs={12} sm={6}>
<WhiteFont>
<span>Shortness Of Breath:</span> {observation.physical.shortnessOfBreathSeverity}
</WhiteFont>
</Grid>
<Grid item xs={12} sm={6}>
<WhiteFont>
<span>Sore Throat:</span> {observation.physical.soreThroatSeverity}
</WhiteFont>
</Grid>
<Grid item xs={12} sm={6}>
<WhiteFont>
<span>Fatigue:</span> {observation.physical.fatigueSeverity}
</WhiteFont>
</Grid>
<Grid item xs={12} sm={6}>
<WhiteFont>
<span>Bluishness:</span> {observation.physical.bluishnessSeverity}
</WhiteFont>
</Grid>
<Grid item xs={12} sm={6}>
<WhiteFont>
<span>Gastrointestinnal Issues: </span>
{observation.physical.giIssueSeverity}
</WhiteFont>
</Grid>
<Grid item xs={12} sm={6}>
<WhiteFont>
<span>Headache: </span>
{observation.physical.headacheSeverity}
</WhiteFont>
</Grid>
<Grid item xs={12} sm={6}>
<WhiteFont>
<span>Loss of Smell:</span> {observation.physical.lostSmellSeverity}
</WhiteFont>
</Grid>
<Grid item xs={12} sm={6}>
<WhiteFont>
<span>Loss of Taste:</span> {observation.physical.lostTasteSeverity}
</WhiteFont>
</Grid>
<Grid item xs={12}>
<WhiteFont>
<span>Comments:</span>{' '}
{observation.nonPhysical.openComment ? observation.nonPhysical.openComment : 'N/A'}
</WhiteFont>
</Grid>
</Grid>
</ExpansionPanelDetails>
</ExpansionPanel>
))}
<Grid container justify="center">
<TablePagination
rowsPerPageOptions={[2, 4, 8, 12]}
component="div"
count={observations.length}
rowsPerPage={rowsPerPage}
page={page}
onChangePage={handleChangePage}
onChangeRowsPerPage={handleChangeRowsPerPage}
/>
</Grid>
</div>
);
}