import { Hidden, NativeSelect, Table, TableBody, TableCell, TableHead, TableRow, Tooltip, } from '@material-ui/core'; import AppBar from '@material-ui/core/AppBar'; import Button from '@material-ui/core/Button'; import Grid from '@material-ui/core/Grid'; import IconButton from '@material-ui/core/IconButton'; import Paper from '@material-ui/core/Paper'; import Toolbar from '@material-ui/core/Toolbar'; import Typography from '@material-ui/core/Typography'; import { Create as CreateIcon, Delete as DeleteIcon, FileCopyOutlined as CopyIcon, KeyboardArrowLeft, KeyboardArrowRight, } from '@material-ui/icons'; import React, { useState, useContext, useEffect } from 'react'; import { HTML5Backend } from 'react-dnd-html5-backend'; import { Link } from 'react-router-dom'; import uniqid from 'uniqid'; import * as Acsys from '../utils/Acsys/Acsys'; import { AcsysContext } from '../utils/Session/AcsysProvider'; import FieldDef from '../components/FieldControl/FieldDef'; import FieldControlDialog from '../components/Dialogs/FieldControlDialog'; import LoadingDialog from '../components/Dialogs/LoadingDialog'; import MessageDialog from '../components/Dialogs/MessageDialog'; import YesNoDialog from '../components/Dialogs/YesNoDialog'; import ViewDialog from '../components/Dialogs/ViewDialog'; let published = true; let lockedValue = true; let is_removable = true; let table_keys = []; let tempDetails = []; let view_orderField = 'none'; let view_order = 'asc'; let row_num = 10; const CollectionView = (props) => { const context = useContext(AcsysContext); const [content_id, setContentId] = useState(''); const [viewId, setViewId] = useState(0); const [initialViews, setInitialViews] = useState([]); const [documentDetails, setDocumentDetails] = useState([]); const [acsysView, setAcsysView] = useState([]); const [tableData, setTableData] = useState([]); const [apiCall, setApiCall] = useState(''); const [totalRows, setTotalRows] = useState(0); const [page, setPage] = useState(1); const [orderDir, setOrderDir] = useState(''); const [locked, setLocked] = useState(true); const [reset, setReset] = useState(false); const [view, setView] = useState(false); const [loading, setLoading] = useState(false); const [openKeyMessage, setOpenKeyMessage] = useState(false); const [setOpen, setSetOpen] = useState(false); const [setDetailOpen, setSetDetailOpen] = useState(false); const [setViewOpen, setSetViewOpen] = useState(false); const [filterLoading, setFilterLoading] = useState(false); const [view_order, setViewOrder] = useState(false); const [messageTitle, setMessageTitle] = useState(''); const [message, setMessage] = useState(''); const [deleteLoading, setDeleteLoading] = useState(false); const copy = () => { const el = document.createElement('textarea'); el.value = apiCall; document.body.appendChild(el); el.select(); document.execCommand('copy'); document.body.removeChild(el); }; const openKeyMessageFunc = () => { setOpenKeyMessage(true); setMessageTitle('Error'); setMessage('No keys set Please setUnique key for data.'); }; const closeKeyMessage = () => { setOpenKeyMessage(false); }; const handleViewChange = (value) => { published = value; let acsys_id = ''; if (published) { acsys_id = props.match.params.acsys_id; } else { acsys_id = 'acsys_' + props.match.params.acsys_id; } context.setPageData( acsys_id, context.getKeys(), row_num, view_order, orderDir ); context.setPage(1); mount(); }; const handleClickOpen = (id) => { setViewId(id); setSetOpen(true); }; const handleClose = () => { setSetOpen(false); }; const handleViewOpen = () => { setSetViewOpen(true); }; const handleViewClose = () => { setSetViewOpen(false); }; const handleDetailOpen = () => { setSetDetailOpen(true); }; const handleDetailClose = () => { setSetDetailOpen(false); }; const toggleTable = async (value) => { if (!value) { await Acsys.unlockTable(documentDetails[0].collection); setLocked(false); } else { Acsys.lockTable(documentDetails[0].collection); setLocked(true); } }; const setLockedValue = (value) => { lockedValue = value; }; const setOrderField = (field) => { view_orderField = field; }; const setOrder = (order) => { view_order = order; }; const setEntriesPerPage = (value) => { row_num = value; }; const setUpdateOnly = (value) => { is_removable = value; }; const saveViewsetTings = async () => { setLoading(true); let tempView = acsysView; if (view_orderField === 'none') { tempView['order_by'] = ''; tempView['view_order'] = ''; } else { tempView['order_by'] = view_orderField; tempView['view_order'] = view_order; } tempView['is_removable'] = is_removable; tempView['row_num'] = row_num; toggleTable(lockedValue); context.setHeld(false); await Acsys.updateData('acsys_views', tempView, [ ['acsys_id', '=', tempView.acsys_id], ]); setSetViewOpen(false); setReset(True); setTotalRows(0); setPage(1); table_keys = []; mount(); }; const showPopUp = () => { return <div>{Object.values(tableData).map((value, index) => {})}</div>; }; const deleteView = async () => { setDeleteLoading(true); if (table_keys[viewId]) { let keys = []; for (let i = 0; i < table_keys[viewId].length; i++) { let tKeys = [ table_keys[viewId][i].field, '=', table_keys[viewId][i].value, ]; keys.push(tKeys); } await Acsys.getData(documentDetails[0].collection, keys) .then(async (result) => { if (result.length < 1) { await Acsys.deleteData( 'acsys_' + documentDetails[0].collection, keys ); } else { await Acsys.deleteData(documentDetails[0].collection, keys); } }) .catch(async () => {}); } else { openKeyMessageFunc(); } handleClose(); setReset(True); table_keys = []; mount(); setDeleteLoading(false); }; const handleChangePrevPage = async () => { setLoading(true); let keys = []; for (let i = 0; i < table_keys[table_keys.length - 1].length; i++) { keys.push([table_keys[0][i].field, '=', table_keys[0][i].value]); } const currentData = await Acsys.getPage( tempDetails[0].collection, keys, row_num, view_order, orderDir, 'prev', page ); const apiCall = await Acsys.getOpenPageUrl( tempDetails[0].collection, keys, row_num, view_order, orderDir, 'prev', page ); setLoading(false); setTableData(currentData); setApiCall(apiCall); setPage(page - 1); context.setHeld(true); context.setPage(page); context.setPageData( tempDetails[0].collection, keys, row_num, view_order, orderDir ); context.setPageDirection('prev'); window.scrollTo(0, 0); }; const handleChangeNextPage = async () => { setLoading(true); let keys = []; for (let i = 0; i < table_keys[table_keys.length - 1].length; i++) { keys.push([ table_keys[table_keys.length - 1][i].field, '=', table_keys[table_keys.length - 1][i].value, ]); } const currentData = await Acsys.getPage( tempDetails[0].collection, keys, row_num, view_order, orderDir, 'next', page ); const apiCall = await Acsys.getOpenPageUrl( tempDetails[0].collection, keys, row_num, view_order, orderDir, 'next', page ); setLoading(false); setTableData(currentData); setApiCall(apiCall); setPage(page + 1); context.setHeld(true); context.setPage(page); context.setPageData( tempDetails[0].collection, keys, row_num, view_order, orderDir ); context.setPageDirection('next'); window.scrollTo(0, 0); }; const savesetTings = async () => { setFilterLoading(true); table_keys = []; for (var i = 0; i < tempDetails.length; i++) { tempDetails[i].view_order = i; await Acsys.updateData('acsys_document_details', tempDetails[i], [ ['acsys_id', '=', tempDetails[i].acsys_id], ]); } setFilterLoading(false); handleDetailClose(); }; const scan = async () => { setLoading(true); Acsys.deleteData('acsys_document_details', [ ['content_id', '=', content_id], ]) .then(async () => { mount(); }) .catch(() => { setLoading(false); }); }; useEffect(() => { if (content_id !== props.match.params.content_id && !loading) { mount(); } }, [content_id, props.match.params.content_id, loading]); useEffect(() => { props.setHeader('Content'); published = true; table_keys = []; setLoading(true); mount(); }, []); const mount = async () => { let acsysView; let locked = true; let details = []; let currentData; let apiCall; let order = []; let orderDir = 'asc'; lockedValue = true; is_removable = true; view_orderField = 'none'; // view_order = 'asc'; row_num = 10; if (!reset) { table_keys = props.location.state.table_keys; } let acsys_id = ''; if (published) { acsys_id = props.match.params.acsys_id; } else { acsys_id = 'acsys_' + props.match.params.acsys_id; } const content_id = props.match.params.content_id; const totalRows = await Acsys.getTableSize(acsys_id); try { acsysView = await Acsys.getData('acsys_views', [ ['acsys_id', '=', content_id], ]); is_removable = acsysView[0].is_removable; row_num = acsysView[0].row_num; if (acsysView[0].order_by.length > 0) { view_orderField = acsysView[0].order_by; view_order = acsysView[0].view_order; } let keys = []; try { for (let i = 0; i < table_keys.length; i++) { keys.push([table_keys[i].field, '=', table_keys[i].value]); } } catch (error) {} details = await Acsys.getData('acsys_document_details', [ ['content_id', '=', content_id], ]); await Acsys.getData('acsys_open_tables', [['table_name', '=', acsys_id]]) .then((result) => { if (result[0].table_name === acsys_id) { locked = false; lockedValue = false; } }) .catch(() => {}); if (details.length > 0) { details.sort((a, b) => (a.view_order > b.view_order ? 1 : -1)); if (acsysView[0].order_by.length > 0) { order.push(acsysView[0].order_by); orderDir = acsysView[0].view_order; } for (let i = 0; i < details.length; i++) { if (Boolean(details[i].is_key)) { order.push(details[i].field_name); } } if (context.isHeld()) { let direction = 'none'; const dbType = await Acsys.getDatabaseType(); if (dbType === 'firestore') { direction = context.getPageDirection(); } currentData = await Acsys.getPage( context.getTable(), context.getKeys(), context.getRowsPerPage(), context.getOrder(), context.getDirection(), direction, context.getPage() ); setPage(context.getPage()); } else { currentData = await Acsys.getData( acsys_id, [], row_num, order, orderDir ); apiCall = await Acsys.getOpenUrl( acsys_id, [], row_num, order, orderDir ); } } else { currentData = await Acsys.getData(acsys_id, keys, row_num); apiCall = await Acsys.getOpenUrl(acsys_id, keys, row_num); await Promise.all( Object.keys(currentData[0]).map(async (value, index) => { let collectionDetails = { acsys_id: uniqid(), content_id: content_id, collection: acsys_id, control: 'none', field_name: value, is_visible_on_page: true, is_visible_on_table: true, type: typeof currentData[0][value], is_key: false, view_order: index, width: 12, }; await Acsys.insertData( 'acsys_document_details', collectionDetails ).then(() => { details.push(collectionDetails); }); }) ).then(() => { details.sort((a, b) => (a.view_order > b.view_order ? 1 : -1)); }); } } catch (error) { console.log(error); } setReset(false); setView(props.location.state.view); setLoading(false); setLocked(locked); setContentId(content_id); setInitialViews(currentData); setTableData(currentData); setApiCall(apiCall); setAcsysView(acsysView[0]); setPage(page); setDocumentDetails(details); setTotalRows(totalRows); setViewOrder(order); setOrderDir(orderDir); }; const renderHeader = () => { const details = documentDetails; if (details.length > 0) { return ( <TableRow> {Object.values(details).map((value) => { if (value.is_visible_on_table) { return ( <TableCell style={{ paddingLeft: 16, paddingRight: 16, paddingTop: 5, paddingBottom: 5, }} > {value.field_name.toUpperCase()} </TableCell> ); } })} <TableCell style={{ paddingLeft: 16, paddingRight: 16, paddingTop: 5, paddingBottom: 5, }} align="right" > ACTIONS </TableCell> </TableRow> ); } }; const renderCellData = (rowData) => { return rowData.map((column) => { return <TableCell>{column}</TableCell>; }); }; const renderTableData = () => { return tableData.map((tableData, rowIndex) => { let tempKey = []; return ( <TableRow> {Object.values(documentDetails).map((details) => { let returnValue = ''; Object.values(tableData).map((value, index) => { if (Object.keys(tableData)[index] == details.field_name) { if (Boolean(details.is_key) && value !== undefined) { let tempObj = { field: details.field_name, value: value, }; tempKey.push(tempObj); table_keys[rowIndex] = tempKey; } if (details.is_visible_on_table) { if (details.control == 'dateTimePicker') { const date = new Date(value); const printDate = ('0' + (date.getMonth() + 1)).slice(-2) + '/' + ('0' + date.getDate()).slice(-2) + '/' + date.getFullYear(); returnValue = printDate; } else if (details.control == 'booleanSelect') { const tmpElement = document.createElement('DIV'); tmpElement.innerHTML = Boolean(value); const stringLimit = 100; let valueString = tmpElement.innerText; if (valueString.length >= stringLimit) { valueString = valueString.substr(0, stringLimit) + '...'; } returnValue = valueString; } else { const tmpElement = document.createElement('DIV'); tmpElement.innerHTML = value; const stringLimit = 100; let valueString = tmpElement.innerText; if (valueString.length >= stringLimit) { valueString = valueString.substr(0, stringLimit) + '...'; } returnValue = valueString; } } } }); if (details.is_visible_on_table) { return acsysView.link_view_id.length > 0 ? ( <TableCell to={{ pathname: '/CollectionView/' + acsysView.link_table + '/' + acsysView.link_view_id, state: { table_keys: table_keys[rowIndex], }, }} component={Link} style={{ overflow: 'hidden', textOverflow: 'ellipsis' }} > {returnValue} </TableCell> ) : ( <TableCell style={{ overflow: 'hidden', textOverflow: 'ellipsis' }} > {returnValue} </TableCell> ); } })} <TableCell align="right" style={{ minWidth: 100 }}> {table_keys.length > 0 ? ( <Tooltip title="Edit Entry"> <IconButton edge="start" color="inherit" aria-label="edit" to={{ pathname: '/DocumentView', state: { mode: 'update', is_removable: is_removable, table_keys: table_keys[rowIndex], routed: false, viewId: documentDetails[0].content_id, }, }} component={Link} style={{ marginRight: 10 }} > <CreateIcon /> </IconButton> </Tooltip> ) : ( <Tooltip title="Edit Entry"> <IconButton edge="start" color="inherit" aria-label="edit" onClick={() => openKeyMessageFunc()} style={{ marginRight: 10 }} > <CreateIcon /> </IconButton> </Tooltip> )} {Acsys.getMode() !== 'Viewer' && is_removable ? ( <Tooltip title="Delete Entry"> <IconButton edge="start" color="inherit" aria-label="delete" onClick={(event) => { event.stopPropagation(); handleClickOpen(rowIndex); }} > <DeleteIcon /> </IconButton> </Tooltip> ) : ( <div /> )} </TableCell> </TableRow> ); }); }; const renderPagination = (paginate) => { let startingElement = 0; if (totalRows > 0) { startingElement = page * row_num - row_num + 1; } const endingElement = page * row_num - row_num + 1 + tableData.length - 1; return paginate ? ( <Grid style={{ width: 190, float: 'right' }} container> <Grid style={{ float: 'right' }} item xs> <Typography variant={'body2'} style={{ margin: '10px auto' }}> {startingElement}-{endingElement} of {totalRows} </Typography> </Grid> <Grid item xs={6}> {page > 1 ? ( <IconButton onClick={() => handleChangePrevPage()}> <KeyboardArrowLeft color="inherit" /> </IconButton> ) : ( <IconButton> <KeyboardArrowLeft color="disabled" style={{ cursor: 'default' }} /> </IconButton> )} {page * row_num < totalRows ? ( <IconButton onClick={() => handleChangeNextPage()}> <KeyboardArrowRight color="inherit" /> </IconButton> ) : ( <IconButton> <KeyboardArrowRight color="disabled" style={{ cursor: 'default' }} /> </IconButton> )} </Grid> </Grid> ) : ( <div> <Typography style={{ height: 30, marginTop: 8 }}> Please setKeys for pagination. </Typography> </div> ); }; const renderTable = (paginate) => { let tableDetails = ''; try { tableDetails = tableData.details; } catch (error) {} if (tableDetails) { return <div style={{ margin: 30, overflow: 'auto' }}>{tableDetails}</div>; } else { try { return ( <div> <div style={{ margin: 'auto', overflow: 'auto' }}> <Table> <TableHead style={{ backgroundColor: '#fafafa' }}> {renderHeader()} </TableHead> <TableBody>{renderTableData()}</TableBody> </Table> </div> {renderPagination(paginate)} </div> ); } catch (error) {} } }; tempDetails = documentDetails; let projectId = ''; let viewTable = ''; let tempKey = []; let tempKeys = []; let paginate = false; try { projectId = acsysView.acsys_id; } catch (error) {} try { viewTable = tempDetails[0].collection; } catch (error) {} for (let i = 0; i < documentDetails.length; i++) { if (Boolean(documentDetails[i].is_key)) { let tempObj = { field: documentDetails[i].field_name, }; tempKey.push(tempObj); paginate = true; } } tempKeys[0] = tempKey; 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={2}> <Grid item xs style={{ overflow: 'hidden' }}> <Typography align="left" variant="subtitle2" noWrap style={{ marginTop: 10, color: '#000000' }} > View: {view} </Typography> </Grid> <Grid item> <Tooltip title="Choose Between Published Or Draft Rows"> <NativeSelect onChange={(e) => handleViewChange('true' == e.target.value)} > <option value={true}>Published</option> <option value={false}>Draft</option> </NativeSelect> </Tooltip> </Grid> {Acsys.getMode() === 'Administrator' ? ( <Grid item> <Tooltip title="Change How Data Is Presented"> <Button onClick={handleDetailOpen} variant="contained" color="primary" > Field Controls </Button> </Tooltip> </Grid> ) : ( <div /> )} {Acsys.getMode() === 'Administrator' ? ( <Grid item> <Tooltip title="Change How Data Is Organized"> <Button onClick={handleViewOpen} variant="contained" color="primary" > View setTings </Button> </Tooltip> </Grid> ) : ( <div /> )} <Grid item> {Acsys.getMode() !== 'Viewer' && is_removable ? ( <Tooltip title="Add New Entry To Table"> <Button to={{ pathname: '/DocumentView', state: { mode: 'add', table_keys: tempKeys[0], routed: false, viewId: projectId, }, }} component={Link} variant="contained" color="primary" > New Entry </Button> </Tooltip> ) : ( <div /> )} </Grid> </Grid> </Toolbar> </AppBar> {renderTable(paginate)} <LoadingDialog loading={loading} message={'Loading'} /> <MessageDialog open={openKeyMessage} closeDialog={closeKeyMessage} title={messageTitle} message={message} /> <YesNoDialog open={setOpen} closeDialog={handleClose} title={'Delete data?'} message={'Are you sure you want to delete this data?'} action={deleteView} actionProcess={deleteLoading} /> <FieldControlDialog open={setDetailOpen} closeDialog={handleDetailClose} title={'Field Controls'} backend={HTML5Backend} component={ <FieldDef docDetails={tempDetails} handleClick={savesetTings} /> } action={savesetTings} actionProcess={filterLoading} /> <ViewDialog open={setViewOpen} closeDialog={handleViewClose} viewOrderField={view_orderField} setOrderField={setOrderField} docDetails={tempDetails} viewOrder={view_order} setOrder={setOrder} rowNum={row_num} setEntriesPerPage={setEntriesPerPage} isRemovable={is_removable} setUpdateOnly={setUpdateOnly} viewTable={viewTable} locked={locked} setLockedValue={setLockedValue} action={saveViewsetTings} actionProcess={filterLoading} /> </Paper> <Hidden smDown implementation="css"> {!locked ? ( <div style={{ clear: 'both' }}> API Call:{' '} <a className="api-url" href={apiCall} target="_blank"> {apiCall} </a> <Tooltip title="Copy To Clipboard"> <IconButton edge="start" color="inherit" aria-label="edit" onClick={copy} style={{ marginLeft: 5 }} > <CopyIcon style={{ height: 15 }} /> </IconButton> </Tooltip> </div> ) : ( <div /> )} </Hidden> </div> ); }; export default CollectionView;