Skip to content

Commit

Permalink
update browse identifiers UI to support deletion
Browse files Browse the repository at this point in the history
  • Loading branch information
graft committed Mar 7, 2025
1 parent 4c521ca commit 717e90b
Show file tree
Hide file tree
Showing 5 changed files with 180 additions and 10 deletions.
46 changes: 46 additions & 0 deletions gnomon/lib/client/jsx/components/confirmation-code-modal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import React from 'react';
import Button from '@material-ui/core/Button';
import TextField from '@material-ui/core/TextField';
import Dialog from '@material-ui/core/Dialog';
import DialogActions from '@material-ui/core/DialogActions';
import DialogContent from '@material-ui/core/DialogContent';
import DialogContentText from '@material-ui/core/DialogContentText';
import DialogTitle from '@material-ui/core/DialogTitle';

export default function ConfirmationCodeModal({open, confirmation, confirmationError, onChange, onClose, onConfirm}:{ open: boolean, confirmation: string, onClose: Function, onConfirm: Function }) {
return (
<Dialog
open={open}
onClose={onClose}
aria-labelledby="message-modal-title"
aria-describedby="message-modal-description"
>
<DialogTitle id="message-modal-title">Confirmation Required</DialogTitle>
<DialogContent>
<DialogContentText id="message-modal-description">
{ confirmationError }
</DialogContentText>
<TextField
autoFocus
required
margin="dense"
name="confirmation"
label="Confirmation"
type="string"
fullWidth
variant="standard"
onChange={ e => onChange(e.target.value) }
value={ confirmation }
/>
</DialogContent>
<DialogActions>
<Button onClick={onClose} color="primary" autoFocus>
Close
</Button>
<Button onClick={onConfirm} color="primary" autoFocus>
Confirm
</Button>
</DialogActions>
</Dialog>
);
}
30 changes: 30 additions & 0 deletions gnomon/lib/client/jsx/components/message-modal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import React from 'react';
import Button from '@material-ui/core/Button';
import Dialog from '@material-ui/core/Dialog';
import DialogActions from '@material-ui/core/DialogActions';
import DialogContent from '@material-ui/core/DialogContent';
import DialogContentText from '@material-ui/core/DialogContentText';
import DialogTitle from '@material-ui/core/DialogTitle';

export default function MessageModal({open, title, message, onClose}:{ open: boolean, title: string, message: string, onClose: Function }) {
return (
<Dialog
open={open}
onClose={onClose}
aria-labelledby="message-modal-title"
aria-describedby="message-modal-description"
>
<DialogTitle id="message-modal-title">{ title }</DialogTitle>
<DialogContent>
<DialogContentText id="message-modal-description">
{ message }
</DialogContentText>
</DialogContent>
<DialogActions>
<Button onClick={onClose} color="primary" autoFocus>
Close
</Button>
</DialogActions>
</Dialog>
);
}
36 changes: 28 additions & 8 deletions gnomon/lib/client/jsx/components/names-browse/names-browse.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useEffect, useState } from 'react';
import React, { useEffect, useState, useCallback } from 'react';
import { useAppSelector as useSelector } from '../../hooks';
import { makeStyles } from '@material-ui/core/styles';

Expand All @@ -11,7 +11,9 @@ import { useDispatch } from '../../utils/redux';
import { setMagmaNamesListRequest } from '../../actions/names';
import { fetchAndAddRulesFromMagma } from '../../actions/rules';
import { selectMagmaNamesListsByRuleName } from '../../selectors/names';
import NamesBrowseToolbar from './toolbar';
import NamesToolbar from '../names-toolbar/toolbar';
import ExportButton from '../names-toolbar/export-button';
import DeleteIdentifiersButton from '../names-toolbar/delete-identifiers-button';
import Counts, { Count } from '../names-create/counts';
import Table from '../table';

Expand Down Expand Up @@ -89,7 +91,7 @@ const NamesBrowse = ({ project_name }: { project_name: string }) => {
addRulesFromMagma();
}, []);

useEffect(() => {
const fetchAllNames = useCallback(() => {
const fetchNamesForRule = createFnConcurrencyWrapper(fetchNamesWithRuleAndRegexFromMagma, 4);

async function fetchNamesFromMagma(ruleName: string) {
Expand All @@ -109,6 +111,10 @@ const NamesBrowse = ({ project_name }: { project_name: string }) => {
}

allRules.forEach(ruleName => fetchNamesFromMagma(ruleName));
}, [allRules]);

useEffect( () => {
fetchAllNames()
}, [allRules.length]);

useEffect(() => {
Expand Down Expand Up @@ -156,9 +162,24 @@ const NamesBrowse = ({ project_name }: { project_name: string }) => {
<React.Fragment>
<div className={classes.projectAndToolbarContainer}>
<ProjectHeader project_name={project_name} />
<NamesBrowseToolbar
exportData={selection.length ? selection : rowData}
exportButtonText={`Export${selection.length ? ' Selection' : ''}`}
<NamesToolbar
buttons={[
<ExportButton
small={true}
data={selection.length ? selection : rowData}
buttonText={`Export${selection.length ? ' Selection' : ''}`}
/>,
<DeleteIdentifiersButton
small={true}
data={selection}
refresh={ () => {
fetchAllNames();
setSelection([]);
} }
project_name={project_name}
buttonText={`Delete${selection.length ? ' Selection' : ''}`}
/>
]}
/>
<ProjectHeader project_name={project_name} className="placeholder" />
</div>
Expand All @@ -168,7 +189,6 @@ const NamesBrowse = ({ project_name }: { project_name: string }) => {
rows={rowData}
columns={['name', 'ruleName', 'author', 'createdAt']}
selectable={true}
showFocusedCell={true}
onSelectionChanged={setSelection}
className={classes.table}
dataTypeLabel='name'
Expand All @@ -179,4 +199,4 @@ const NamesBrowse = ({ project_name }: { project_name: string }) => {
};


export default NamesBrowse;
export default NamesBrowse;
4 changes: 2 additions & 2 deletions gnomon/lib/client/jsx/components/names-browse/toolbar.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';

import ExportButton from '../names-toolbar/export-button';
import DeleteButton from '../names-toolbar/delete-button';
import NamesToolbar from '../names-toolbar/toolbar';


Expand All @@ -22,4 +22,4 @@ const NamesBrowseToolbar = ({ exportData, exportButtonText }: {
);
};

export default NamesBrowseToolbar;
export default NamesBrowseToolbar;
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import React, { useState, useRef } from 'react';
import { useAppSelector as useSelector } from '../../hooks';
import DeleteOutlineOutlinedIcon from '@material-ui/icons/DeleteOutlineOutlined';

import { useDispatch } from '../../utils/redux';
import ToolbarButtonWithPopper from './toolbar-button-with-popper';
import ConfirmationPopper from '../confirmation-popper';
import MessageModal from '../message-modal';
import ConfirmationCodeModal from '../confirmation-code-modal';
import { json_get, json_post } from 'etna-js/utils/fetch';
import { magmaPath } from 'etna-js/api/magma_api';



const DeleteIdentifiersButton = ({ small, project_name, data, buttonText, className, refresh }: { small: boolean, className?: string, data: Array<any>, buttonText: string }) => {
const [confirmation, setConfirmation] = useState('');
const [confirmationError, setConfirmationError] = useState('');
const [ message, setMessage ] = useState('');
const [ messageTitle, setMessageTitle ] = useState('');

const handleDelete = () => {
json_post(magmaPath(`gnomon/${project_name}/delete`),
{ identifiers: data.map(d => d.name), confirmation }).then(
({success}) => {
setMessage(success);
setMessageTitle('Deleted Identifiers');
setConfirmation('');
refresh();
}
).catch(
(error) => error.then(
({error}) => {
setConfirmation('');
if (error.includes('confirmation')) setConfirmationError(error);
else {
setMessage(error.length > 100 ? `${error.substring(0,100)}...` : error);
setMessageTitle('Deletion Failed');
}
}
)
)
};

return (
<React.Fragment>
<ToolbarButtonWithPopper
text={ buttonText }
iconComponent={<DeleteOutlineOutlinedIcon />}
variant={small ? 'compact' : 'full'}
color="#FF0000"
onClickOrPopperChange={handleDelete}
disabled={data.length == 0}
className={className}
/>
<ConfirmationCodeModal
open={!!confirmationError}
confirmationError={ confirmationError }
confirmation={ confirmation }
onChange={ setConfirmation }
onClose={ () => {
setConfirmationError('');
setConfirmation('');
} }
onConfirm={ () => {
setConfirmationError('');
handleDelete();
}}
/>
<MessageModal title={messageTitle} open={!!message} onClose={ () => setMessage('') } message={message}/>
</React.Fragment>
);
};

export default DeleteIdentifiersButton;

0 comments on commit 717e90b

Please sign in to comment.