Skip to content

Commit 9c47d55

Browse files
committed
Many ui updates
1 parent 399b980 commit 9c47d55

19 files changed

+270
-57
lines changed

CHANGELOG.MD

+6
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file.
44
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
55
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
66

7+
## [3.3.0-rc9] - 2024-07-29
8+
9+
### Changed
10+
11+
- Many UI Updates check out [UI Fixes](/MythicReactUI/CHANGELOG.MD) for 2.0.8
12+
-
713
## [3.3.0-rc7] - 2024-07-29
814

915
### Changed

MythicReactUI/CHANGELOG.MD

+10
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,16 @@ All notable changes to this project will be documented in this file.
44
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
55
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
66

7+
## [0.2.8] - 2024-07-30
8+
9+
### Changed
10+
11+
- Fixed an issue with adjusting table columns
12+
- fixed an issue with download history not working in the file browser
13+
- updated file browser download history options with file, hex, and string previews
14+
- updated the new tag dialog to move the "new" down as a "plus" sign
15+
- updated comments on tasks to appear inline (with cut off elipsis)
16+
717
## [0.2.6] - 2024-07-29
818

919
### Changed

MythicReactUI/src/components/MythicComponents/MythicResizableGrid/DraggableHandles.js

+9-7
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,21 @@
11
import React, { useState } from 'react';
22
import {classes} from './styles';
33
import Draggable from 'react-draggable';
4+
import MoreVertIcon from '@mui/icons-material/MoreVert';
45

56
const DraggableHandles = React.forwardRef(({ height, rowHeight, width, minColumnWidth, columnWidths, onStop }, ref) => {
6-
const [isDragging, setIsDragging] = useState(false);
7+
const [isDragging, setIsDragging] = useState(-1);
78
return (
89
<div
910
ref={ref}
1011
className={classes.draggableHandlesContainer}
1112
style={{
1213
height: height,
1314
width: width,
14-
pointerEvents: isDragging ? 'initial' : 'none',
15+
pointerEvents: isDragging >= 0 ? 'initial' : 'none',
1516
}}>
1617
{columnWidths.map((_, i) => {
18+
// leftOffset is the sum of the width of all columns left of i
1719
const leftOffset = columnWidths.slice(0, i).reduce((a, b) => a + b, 0);
1820
return (
1921
<Draggable
@@ -25,15 +27,16 @@ const DraggableHandles = React.forwardRef(({ height, rowHeight, width, minColumn
2527
top: 0,
2628
bottom: 0,
2729
}}
28-
position={isDragging ? null : { x: 0, y: 0 }}
30+
defaultPosition={{x: 0, y:0}}
31+
position={{ x: 0, y: 0 }}
2932
onStart={() => {
3033
setIsDragging(i);
3134
}}
3235
onStop={(e, data) => {
33-
setIsDragging(false);
36+
setIsDragging(-1);
3437
onStop(data.x, i);
3538
}}>
36-
<div
39+
<MoreVertIcon
3740
className={classes.draggableHandlesClickArea}
3841
style={{
3942
left: leftOffset + columnWidths[i] - 1 - 8,
@@ -43,10 +46,9 @@ const DraggableHandles = React.forwardRef(({ height, rowHeight, width, minColumn
4346
className={classes.draggableHandlesIndicator}
4447
style={{
4548
display: isDragging === i ? 'block' : 'none',
46-
height: height / 2,
4749
}}
4850
/>
49-
</div>
51+
</MoreVertIcon>
5052
</Draggable>
5153
);
5254
})}

MythicReactUI/src/components/MythicComponents/MythicResizableGrid/MythicResizableGrid.js

+3-4
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,6 @@ const ResizableGridWrapper = ({
148148
} else {
149149
return 30;
150150
}
151-
152151
}
153152
if(columns[columnIndex].key){
154153
if(columns[columnIndex].key.includes("time")){
@@ -175,13 +174,13 @@ const ResizableGridWrapper = ({
175174
if(columns[columnIndex].inMetadata){
176175
return itemRow[columnIndex]?.props?.cellData.length;
177176
}
178-
if(!data){
177+
if(data === undefined){
179178
return MIN_COLUMN_WIDTH;
180179
}
181180
if(data.plaintext){
182-
return String(data.plaintext).length || -1;
181+
return String(data.plaintext)?.length;
183182
} else {
184-
return String(data).length || -1;
183+
return String(data)?.length ;
185184
}
186185
//return String(itemRow[columnIndex]?.props?.rowData?.[columns[columnIndex].key]).length || -1;
187186
} else if(typeof(itemRow[columnIndex]?.props?.cellData) === "string") {

MythicReactUI/src/components/MythicComponents/MythicTag.js

+23-6
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import DialogContent from '@mui/material/DialogContent';
55
import DialogTitle from '@mui/material/DialogTitle';
66
import MythicTextField from './MythicTextField';
77
import {useQuery, gql, useMutation} from '@apollo/client';
8-
import { Select, Input, MenuItem, Link, IconButton, } from '@mui/material';
8+
import { Select, Input, MenuItem, Link, IconButton } from '@mui/material';
99
import Table from '@mui/material/Table';
1010
import TableBody from '@mui/material/TableBody';
1111
import TableCell from '@mui/material/TableCell';
@@ -24,6 +24,8 @@ import WebhookIcon from '@mui/icons-material/Webhook';
2424
import Chip from '@mui/material/Chip';
2525
import LocalOfferOutlinedIcon from '@mui/icons-material/LocalOfferOutlined';
2626
import {MythicStyledTooltip} from "./MythicStyledTooltip";
27+
import AddCircleOutlineIcon from '@mui/icons-material/AddCircleOutline';
28+
import Typography from '@mui/material/Typography';
2729

2830
const createNewTagMutationTemplate = ({target_object}) => {
2931
// target_object should be something like "task_id"
@@ -404,7 +406,6 @@ const onAcceptDelete = () => {
404406
return (
405407
<React.Fragment>
406408
<DialogTitle id="form-dialog-title">Edit Tags
407-
<Button variant='contained' color="success" style={{float: "right"}} onClick={() => setOpenNewDialog(true)} >New</Button>
408409
</DialogTitle>
409410
<DialogContent dividers={true}>
410411
{openNewDialog ?
@@ -420,8 +421,13 @@ return (
420421
<Table size="small" style={{ "maxWidth": "100%", "overflow": "scroll"}}>
421422
<TableBody>
422423
<TableRow hover>
423-
<TableCell style={{width: "30%"}}>Select Existing Tag to Edit</TableCell>
424+
<TableCell style={{width: "30%"}}>Select Existing Tag to Edit or Add New</TableCell>
424425
<TableCell style={{display: "inline-flex", flexDirection: "row-reverse"}}>
426+
<MythicStyledTooltip title={"Add New Tag"}>
427+
<IconButton variant='contained' color="success" style={{float: "right"}} onClick={() => setOpenNewDialog(true)} >
428+
<AddCircleOutlineIcon />
429+
</IconButton>
430+
</MythicStyledTooltip>
425431
<Select
426432
labelId="demo-dialog-select-label"
427433
id="demo-dialog-select"
@@ -438,7 +444,6 @@ return (
438444
{selectedTag.id &&
439445
<IconButton size="small" style={{float: "right"}} onClick={()=>{setOpenDeleteDialog(true);}} color="error" variant="contained"><DeleteIcon/></IconButton>
440446
}
441-
442447
{openDelete &&
443448
<MythicConfirmDialog onClose={() => {setOpenDeleteDialog(false);}} onSubmit={onAcceptDelete} open={openDelete}/>
444449
}
@@ -547,13 +552,25 @@ export function NewTagDialog(props) {
547552

548553
return (
549554
<React.Fragment>
550-
<DialogTitle id="form-dialog-title">Create new Tag Instance</DialogTitle>
555+
<DialogTitle id="form-dialog-title">Add New Tag</DialogTitle>
551556
<DialogContent dividers={true}>
552557
<TableContainer className="mythicElement">
553558
<Table size="small" style={{ "maxWidth": "100%", "overflow": "scroll"}}>
554559
<TableBody>
555560
<TableRow hover>
556-
<TableCell style={{width: "30%"}}>Select Existing Tag Type</TableCell>
561+
<TableCell style={{width: "20%"}}>
562+
<Typography>
563+
Tag
564+
</Typography>
565+
<Typography size="small" component="span" style={{fontSize: theme.typography.pxToRem(15)}}>
566+
To create a new tag type click <Link style={{wordBreak: "break-all"}}
567+
color="textPrimary"
568+
href={"/new/tagtypes"}
569+
underline="always" target="_blank">
570+
here
571+
</Link>
572+
</Typography>
573+
</TableCell>
557574
<TableCell>
558575
<Select
559576
labelId="demo-dialog-select-label"

MythicReactUI/src/components/pages/Callbacks/CallbacksTabsFileBrowser.js

+1
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,7 @@ export const CallbacksTabsFileBrowserPanel = ({ index, value, tabInfo, me }) =>
288288
existingData.metadata.has_children = data.mythictree[i].metadata.has_children;
289289
}
290290
existingData.metadata.permissions = {...existingData.metadata.permissions, ...data.mythictree[i].metadata.permissions};
291+
existingData.filemeta = [...existingData.filemeta, ...data.mythictree[i].filemeta]
291292
treeRootDataRef.current[currentGroups[j]][data.mythictree[i]["host"]][data.mythictree[i]["full_path_text"]] = {...existingData};
292293
}
293294
}

MythicReactUI/src/components/pages/Callbacks/CallbacksTabsFileBrowserTable.js

+79-8
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import {TagsDisplay, ViewEditTags} from '../../MythicComponents/MythicTag';
3838
import SettingsIcon from '@mui/icons-material/Settings';
3939
import { toLocalTime } from '../../utilities/Time';
4040
import ListSubheader from '@mui/material/ListSubheader';
41+
import {b64DecodeUnicode} from "./ResponseDisplay";
4142

4243

4344
const getPermissionsDataQuery = gql`
@@ -49,8 +50,8 @@ const getPermissionsDataQuery = gql`
4950
}
5051
`;
5152
const getFileDownloadHistory = gql`
52-
query getFileDownloadHistory($mythictree_id: Int!) {
53-
mythictree_by_pk(id: $mythictree_id) {
53+
query getFileDownloadHistory($full_path_text: String!, $host: String!, $group: [String!]) {
54+
mythictree(where: {tree_type: {_eq: "file"}, full_path_text: {_eq: $full_path_text}, host: {_eq: $host}, callback: {mythictree_groups: {_contains: $group}}}) {
5455
filemeta {
5556
id
5657
comment
@@ -59,6 +60,8 @@ const getFileDownloadHistory = gql`
5960
complete
6061
total_chunks
6162
timestamp
63+
filename_text
64+
full_remote_path_text
6265
task {
6366
id
6467
display_id
@@ -302,6 +305,38 @@ export const CallbacksTabsFileBrowserTable = (props) => {
302305
};
303306
const FileBrowserTableRowNameCell = ({cellData, rowData, treeRootData, selectedFolderData }) => {
304307
const theme = useTheme();
308+
const [downloadHistory, setDownloadHistory] = React.useState([]);
309+
const [fileHistoryDialogOpen, setFileHistoryDialogOpen] = React.useState(false);
310+
const [getHistory] = useLazyQuery(getFileDownloadHistory, {
311+
onCompleted: (data) => {
312+
if (data.mythictree.length === 0) {
313+
snackActions.warning('No download history recorded');
314+
} else {
315+
let files = [];
316+
for(let i = 0; i < data.mythictree.length; i++){
317+
files.push(...data.mythictree[i].filemeta);
318+
}
319+
if(files.length === 0){
320+
snackActions.warning('No download history recorded');
321+
return;
322+
}
323+
files = files.map(f => {
324+
return {...f, filename_text: b64DecodeUnicode(f.filename_text),
325+
full_remote_path_text: b64DecodeUnicode(f.full_remote_path_text)}
326+
});
327+
setDownloadHistory(files);
328+
setFileHistoryDialogOpen(true);
329+
}
330+
},
331+
fetchPolicy: 'network-only',
332+
});
333+
const onGetHistory = () => {
334+
getHistory({ variables: {
335+
full_path_text: treeRootData[selectedFolderData.host][cellData].full_path_text,
336+
host: selectedFolderData.host,
337+
group: [selectedFolderData.group],
338+
} });
339+
}
305340
return (
306341
<div style={{ alignItems: 'center', display: 'flex', maxHeight: "100%", textDecoration: treeRootData[selectedFolderData.host][cellData]?.deleted ? 'line-through' : '' }}>
307342
{!treeRootData[selectedFolderData.host][cellData]?.can_have_children ? (
@@ -319,7 +354,28 @@ const FileBrowserTableRowNameCell = ({cellData, rowData, treeRootData, selected
319354
}}
320355
/>
321356
)}
322-
{treeRootData[selectedFolderData.host][cellData]?.filemeta.length > 0 ? <GetAppIcon color="success" /> : null}
357+
{treeRootData[selectedFolderData.host][cellData]?.filemeta.length > 0 ?
358+
<GetAppIcon onClick={onGetHistory} style={{cursor: "pointer"}} color="success" />
359+
: null}
360+
{fileHistoryDialogOpen && (
361+
<MythicDialog
362+
fullWidth={true}
363+
maxWidth='xl'
364+
open={fileHistoryDialogOpen}
365+
onClose={() => {
366+
setFileHistoryDialogOpen(false);
367+
}}
368+
innerDialog={
369+
<DownloadHistoryDialog
370+
title='Download History'
371+
value={downloadHistory}
372+
onClose={() => {
373+
setFileHistoryDialogOpen(false);
374+
}}
375+
/>
376+
}
377+
/>
378+
)}
323379
<pre
324380
style={{
325381
color:
@@ -434,11 +490,22 @@ const FileBrowserTableRowActionCell = ({ rowData, cellData, onTaskRowAction, tre
434490
});
435491
const [getHistory] = useLazyQuery(getFileDownloadHistory, {
436492
onCompleted: (data) => {
437-
//console.log(data);
438-
if (data.mythictree_by_pk.filemeta.length === 0) {
493+
if (data.mythictree.length === 0) {
439494
snackActions.warning('No download history recorded');
440495
} else {
441-
setDownloadHistory(data.mythictree_by_pk.filemeta);
496+
let files = [];
497+
for(let i = 0; i < data.mythictree.length; i++){
498+
files.push(...data.mythictree[i].filemeta);
499+
}
500+
if(files.length === 0){
501+
snackActions.warning('No download history recorded');
502+
return;
503+
}
504+
files = files.map(f => {
505+
return {...f, filename_text: b64DecodeUnicode(f.filename_text),
506+
full_remote_path_text: b64DecodeUnicode(f.full_remote_path_text)}
507+
});
508+
setDownloadHistory(files);
442509
setFileHistoryDialogOpen(true);
443510
}
444511
},
@@ -497,7 +564,11 @@ const FileBrowserTableRowActionCell = ({ rowData, cellData, onTaskRowAction, tre
497564
icon: <HistoryIcon style={{ paddingRight: '5px' }} />,
498565
click: (evt, callback_id, callback_display_id) => {
499566
evt.stopPropagation();
500-
getHistory({ variables: { mythictree_id: treeRootData[selectedFolderData.host][cellData].id } });
567+
getHistory({ variables: {
568+
full_path_text: treeRootData[selectedFolderData.host][cellData].full_path_text,
569+
host: selectedFolderData.host,
570+
group: [selectedFolderData.group],
571+
} });
501572
},
502573
},
503574
{
@@ -690,7 +761,7 @@ const FileBrowserTableRowActionCell = ({ rowData, cellData, onTaskRowAction, tre
690761
{fileHistoryDialogOpen && (
691762
<MythicDialog
692763
fullWidth={true}
693-
maxWidth='md'
764+
maxWidth='xl'
694765
open={fileHistoryDialogOpen}
695766
onClose={() => {
696767
setFileHistoryDialogOpen(false);

0 commit comments

Comments
 (0)