mirror of
https://github.com/its-a-feature/Mythic
synced 2026-06-08 14:55:38 +00:00
callback table row updates
This commit is contained in:
+73
-30
@@ -1,18 +1,17 @@
|
||||
import React, {useEffect} from 'react';
|
||||
import Button from '@mui/material/Button';
|
||||
import DialogActions from '@mui/material/DialogActions';
|
||||
import DialogContent from '@mui/material/DialogContent';
|
||||
import DialogTitle from '@mui/material/DialogTitle';
|
||||
import Box from '@mui/material/Box';
|
||||
import AceEditor from 'react-ace';
|
||||
import "ace-builds/src-noconflict/mode-json";
|
||||
import "ace-builds/src-noconflict/theme-github";
|
||||
import "ace-builds/src-noconflict/theme-monokai";
|
||||
import "ace-builds/src-noconflict/ext-searchbox";
|
||||
import {useTheme} from '@mui/material/styles';
|
||||
import {HexColorInput, HexColorPicker} from 'react-colorful';
|
||||
import Typography from '@mui/material/Typography';
|
||||
import NotificationsActiveTwoToneIcon from '@mui/icons-material/NotificationsActiveTwoTone';
|
||||
import MythicTextField from "../../MythicComponents/MythicTextField";
|
||||
import {
|
||||
MythicDialogBody,
|
||||
MythicDialogButton,
|
||||
MythicDialogFooter,
|
||||
MythicDialogSection,
|
||||
MythicForm,
|
||||
MythicFormField
|
||||
} from "../../MythicComponents/MythicDialogLayout";
|
||||
|
||||
export function CallbacksTableEditTriggerOnCheckinDialog(props) {
|
||||
const [comment, setComment] = React.useState(0);
|
||||
@@ -31,29 +30,73 @@ export function CallbacksTableEditTriggerOnCheckinDialog(props) {
|
||||
}
|
||||
return (
|
||||
<React.Fragment>
|
||||
<DialogTitle id="form-dialog-title">{"Adjust this callback's trigger threshold"}</DialogTitle>
|
||||
<DialogContent dividers={true} style={{height: "100%"}}>
|
||||
<Typography >
|
||||
This adjusts how long, in minutes, this callback must <b>not</b> checkin before finally checking in to trigger an <b>eventing workflow</b> (trigger is callback_checkin).
|
||||
</Typography>
|
||||
<Typography >
|
||||
A zero value means never trigger.
|
||||
</Typography>
|
||||
<Typography >
|
||||
If no eventing workflow for <b>callback_checkin</b> that matches the right payload_types and supported_os restrictions, then nothing will happen.
|
||||
</Typography>
|
||||
<MythicTextField autoFocus={true} onChange={onChange} type={"number"} value={comment} onEnter={onSubmit} name={"trigger threshold in minutes"} showLabel={false} />
|
||||
<DialogTitle id="form-dialog-title">Callback check-in alert</DialogTitle>
|
||||
<DialogContent dividers={true}>
|
||||
<MythicDialogBody>
|
||||
<div className="mythic-callback-trigger-summary">
|
||||
<span className={`mythic-callback-trigger-summary-icon ${comment > 0 ? "mythic-callback-trigger-summary-icon-active" : ""}`}>
|
||||
<NotificationsActiveTwoToneIcon fontSize="small" />
|
||||
</span>
|
||||
<div className="mythic-callback-trigger-summary-copy">
|
||||
<Typography className="mythic-callback-trigger-summary-title">
|
||||
{comment > 0 ? `Alert after ${comment} minute${comment === 1 ? "" : "s"} without a check-in` : "Alerting disabled"}
|
||||
</Typography>
|
||||
<Typography className="mythic-callback-trigger-summary-description">
|
||||
This setting only triggers when the callback checks in after crossing the configured threshold.
|
||||
</Typography>
|
||||
</div>
|
||||
</div>
|
||||
<MythicDialogSection
|
||||
title="Threshold"
|
||||
description="Set how many minutes this callback can remain silent before its next check-in can trigger eventing."
|
||||
>
|
||||
<MythicForm>
|
||||
<MythicFormField
|
||||
label="Minutes without a check-in"
|
||||
description="Use 0 to disable this alert for the callback."
|
||||
>
|
||||
<div className="mythic-form-field-control">
|
||||
<MythicTextField
|
||||
autoFocus={true}
|
||||
onChange={onChange}
|
||||
type="number"
|
||||
value={comment}
|
||||
onEnter={onSubmit}
|
||||
name="Trigger threshold"
|
||||
showLabel={false}
|
||||
marginTop="0"
|
||||
marginBottom="0"
|
||||
InputProps={{inputProps: {min: 0}}}
|
||||
/>
|
||||
</div>
|
||||
</MythicFormField>
|
||||
</MythicForm>
|
||||
</MythicDialogSection>
|
||||
<MythicDialogSection title="Eventing behavior">
|
||||
<div className="mythic-callback-trigger-rule-list">
|
||||
<div className="mythic-callback-trigger-rule">
|
||||
Trigger name: <strong>callback_checkin</strong>
|
||||
</div>
|
||||
<div className="mythic-callback-trigger-rule">
|
||||
Matching workflow filters still apply, including payload type and supported OS restrictions.
|
||||
</div>
|
||||
<div className="mythic-callback-trigger-rule">
|
||||
If no matching workflow exists, no workflow will run.
|
||||
</div>
|
||||
</div>
|
||||
</MythicDialogSection>
|
||||
</MythicDialogBody>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={props.onClose} variant="contained" color="primary">
|
||||
<MythicDialogFooter>
|
||||
<MythicDialogButton onClick={props.onClose}>
|
||||
Close
|
||||
</Button>
|
||||
</MythicDialogButton>
|
||||
{props.onSubmit &&
|
||||
<Button onClick={onSubmit} variant="contained" color="success">
|
||||
Submit
|
||||
</Button>
|
||||
<MythicDialogButton onClick={onSubmit} intent="primary">
|
||||
Save Threshold
|
||||
</MythicDialogButton>
|
||||
}
|
||||
</DialogActions>
|
||||
</MythicDialogFooter>
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,6 @@ import {
|
||||
} from './CallbackMutations';
|
||||
import {useMutation } from '@apollo/client';
|
||||
import SnoozeIcon from '@mui/icons-material/Snooze';
|
||||
import {useTheme} from '@mui/material/styles';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import {faQuestion, faSkullCrossbones, faRobot} from '@fortawesome/free-solid-svg-icons';
|
||||
import {faLinux, faApple, faWindows, faChrome, faAndroid} from '@fortawesome/free-brands-svg-icons';
|
||||
@@ -133,20 +132,23 @@ export const CallbacksTableIDCell = React.memo(({rowData, callbackDropdown}) =>{
|
||||
</IconButton>
|
||||
{rowDataStatic.locked &&
|
||||
<MythicStyledTooltip title={`Locked by ${lockOwner}`}>
|
||||
<span className="mythic-callback-lockBadge">
|
||||
<span className="mythic-callback-statusBadge mythic-callback-statusBadgeLock">
|
||||
<LockIcon fontSize="inherit" />
|
||||
<span>Locked</span>
|
||||
</span>
|
||||
</MythicStyledTooltip>
|
||||
}
|
||||
{rowDataStatic.trigger_on_checkin_after_time > 0 &&
|
||||
<MythicStyledTooltip title={`Alert on callback after no checkin for ${rowDataStatic.trigger_on_checkin_after_time} minutes`}>
|
||||
<NotificationsActiveTwoToneIcon className="mythic-callback-statusIcon mythic-callback-statusIconSuccess" fontSize="small" />
|
||||
<span className="mythic-callback-statusBadge mythic-callback-statusBadgeAlert">
|
||||
<NotificationsActiveTwoToneIcon fontSize="inherit" />
|
||||
</span>
|
||||
</MythicStyledTooltip>
|
||||
}
|
||||
{rowDataStatic.callbackports.length > 0 &&
|
||||
<MythicStyledTooltip title={proxyMessage()}>
|
||||
<FontAwesomeIcon icon={faSocks} className="mythic-callback-statusIcon mythic-callback-statusIconSuccess" />
|
||||
<span className="mythic-callback-statusBadge mythic-callback-statusBadgeProxy">
|
||||
<FontAwesomeIcon icon={faSocks} />
|
||||
</span>
|
||||
</MythicStyledTooltip>
|
||||
}
|
||||
</div>
|
||||
@@ -168,32 +170,34 @@ export const CallbacksTableLastCheckinCell = React.memo( ({rowData, cellData, me
|
||||
return moment(rowData.last_checkin + "Z", "YYYY-MM-DDTHH:mm:ss.SSSSSSZ").subtract(me?.user?.server_skew || 0, 'millisecond').fromNow(true);
|
||||
//return newTime;
|
||||
}
|
||||
const theme = useTheme();
|
||||
if(rowData?.payload?.payloadtype?.agent_type !== "agent"){
|
||||
return ""
|
||||
}
|
||||
if(rowData.last_checkin === "1970-01-01T00:00:00"){
|
||||
return (
|
||||
<>
|
||||
{rowData.dead &&
|
||||
<MythicStyledTooltip title={"Based on callback's last checkin and sleep info, it's likely dead"}>
|
||||
<FontAwesomeIcon disabled icon={faSkullCrossbones} style={{
|
||||
color: theme.palette.error.main, cursor: "pointer", marginRight: "10px",}} />
|
||||
</MythicStyledTooltip>
|
||||
}
|
||||
{"Streaming Now"}
|
||||
</>
|
||||
<div className="mythic-callback-cellInline">
|
||||
{rowData.dead &&
|
||||
<MythicStyledTooltip title={"Based on callback's last checkin and sleep info, it's likely dead"}>
|
||||
<span className="mythic-callback-statusBadge mythic-callback-statusBadgeDead">
|
||||
<FontAwesomeIcon icon={faSkullCrossbones} />
|
||||
</span>
|
||||
</MythicStyledTooltip>
|
||||
}
|
||||
<span className="mythic-callback-cellText">Streaming Now</span>
|
||||
</div>
|
||||
|
||||
)
|
||||
}
|
||||
return (
|
||||
<div style={{display: "flex", alignItems: "center"}}>
|
||||
<div className="mythic-callback-cellInline">
|
||||
{rowData.dead &&
|
||||
<MythicStyledTooltip title={"Based on callback's last checkin and sleep info, it's likely dead"}>
|
||||
<FontAwesomeIcon icon={faSkullCrossbones} style={{
|
||||
color: theme.palette.error.main, cursor: "pointer", marginRight: "10px",}} />
|
||||
<span className="mythic-callback-statusBadge mythic-callback-statusBadgeDead">
|
||||
<FontAwesomeIcon icon={faSkullCrossbones} />
|
||||
</span>
|
||||
</MythicStyledTooltip>
|
||||
}
|
||||
<span className="mythic-callback-cellText">
|
||||
<Moment filter={adjustOutput} interval={1000} parse={"YYYY-MM-DDTHH:mm:ss.SSSSSSZ"}
|
||||
withTitle
|
||||
titleFormat={"YYYY-MM-DD HH:mm:ss"}
|
||||
@@ -201,6 +205,7 @@ export const CallbacksTableLastCheckinCell = React.memo( ({rowData, cellData, me
|
||||
>
|
||||
{rowData.last_checkin + "Z"}
|
||||
</Moment>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
)
|
||||
@@ -231,7 +236,8 @@ export const CallbacksTableIPCell = React.memo(({cellData, rowData}) => {
|
||||
const updateIPsInfo = React.useCallback( ({callback_display_id, ips}) => {
|
||||
updateIPs({variables: {callback_display_id: callback_display_id, ips}})
|
||||
}, []);
|
||||
const onClick = () => {
|
||||
const onClick = (event) => {
|
||||
event.stopPropagation();
|
||||
setOpenPickIP(true);
|
||||
}
|
||||
const editIPSubmit = (selected_ip) => {
|
||||
@@ -251,13 +257,18 @@ export const CallbacksTableIPCell = React.memo(({cellData, rowData}) => {
|
||||
}, [cellData]);
|
||||
return (
|
||||
<>
|
||||
<div style={{display: "inline-flex", alignItems: "center", height: "100%"}}>
|
||||
<div className="mythic-callback-cellInline">
|
||||
{options.length > 1 &&
|
||||
<MythicStyledTooltip title={"Adjust Displayed"}>
|
||||
<UnfoldMoreIcon onClick={onClick} style={{paddingTop: "5px", cursor: "pointer", width: "unset"}} />
|
||||
<IconButton
|
||||
className="mythic-callback-iconButton mythic-callback-cellIconButton"
|
||||
onClick={onClick}
|
||||
>
|
||||
<UnfoldMoreIcon fontSize="small" />
|
||||
</IconButton>
|
||||
</MythicStyledTooltip>
|
||||
}
|
||||
{displayIP}
|
||||
<span className="mythic-callback-cellText">{displayIP}</span>
|
||||
</div>
|
||||
{openPickIP &&
|
||||
<MythicDialog fullWidth={true} open={openPickIP} onClose={() => {setOpenPickIP(false);}}
|
||||
@@ -275,11 +286,10 @@ export const CallbacksTableIPCell = React.memo(({cellData, rowData}) => {
|
||||
)
|
||||
}, areEqual)
|
||||
export const CallbacksTableC2Cell = React.memo(({rowData}) => {
|
||||
const theme = useTheme();
|
||||
const [localRowData, setLocalRowData] = React.useState(rowData);
|
||||
const initialCallbackGraphEdges = useContext(CallbackGraphEdgesContext);
|
||||
const onOpenTab = useContext(OnOpenTabContext);
|
||||
const [activeEgress, setActiveEgress] = React.useState(theme.palette.success.main);
|
||||
const [egressActive, setEgressActive] = React.useState(true);
|
||||
const [hasEgressRoute, setHasEgressRoute] = React.useState(true);
|
||||
const [openC2Dialog, setOpenC2Dialog] = React.useState(false);
|
||||
const [callbackgraphedges, setCallbackgraphedges] = React.useState([]);
|
||||
@@ -363,11 +373,11 @@ export const CallbacksTableC2Cell = React.memo(({rowData}) => {
|
||||
return false
|
||||
});
|
||||
if(activeRoutes.length === 0){
|
||||
setActiveEgress(theme.palette.error.main);
|
||||
setEgressActive(false);
|
||||
}else{
|
||||
setActiveEgress(theme.palette.success.main);
|
||||
setEgressActive(true);
|
||||
}
|
||||
}, [callbackgraphedges, theme.palette.success.main, theme.palette.error.main]);
|
||||
}, [callbackgraphedges]);
|
||||
useEffect( () => {
|
||||
if(rowData.id !== localRowData.id){
|
||||
setLocalRowData(rowData);
|
||||
@@ -376,12 +386,20 @@ export const CallbacksTableC2Cell = React.memo(({rowData}) => {
|
||||
if(rowData?.payload?.payloadtype?.agent_type !== "agent"){
|
||||
return null
|
||||
}
|
||||
const c2ButtonClass = `mythic-callback-iconButton mythic-callback-cellIconButton ${egressActive && hasEgressRoute ? "mythic-callback-cellIconButtonSuccess" : "mythic-callback-cellIconButtonError"}`;
|
||||
const c2Tooltip = hasEgressRoute ?
|
||||
(egressActive ? "View C2 path information" : "No active egress route. View C2 path information") :
|
||||
"No egress route detected. View C2 path information";
|
||||
return (
|
||||
<div>
|
||||
{hasEgressRoute ?
|
||||
<WifiIcon onClick={onOpenC2Dialog} style={{color: activeEgress, cursor: "pointer"}}/> :
|
||||
<InsertLinkTwoToneIcon onClick={onOpenC2Dialog} style={{color: activeEgress, cursor: "pointer"}} />
|
||||
}
|
||||
<div className="mythic-callback-cellInline mythic-callback-cellInlineCenter">
|
||||
<MythicStyledTooltip title={c2Tooltip}>
|
||||
<IconButton className={c2ButtonClass} onClick={onOpenC2Dialog}>
|
||||
{hasEgressRoute ?
|
||||
<WifiIcon fontSize="small" /> :
|
||||
<InsertLinkTwoToneIcon fontSize="small" />
|
||||
}
|
||||
</IconButton>
|
||||
</MythicStyledTooltip>
|
||||
{openC2Dialog &&
|
||||
<MythicDialog
|
||||
fullWidth={true}
|
||||
@@ -408,34 +426,42 @@ export const CallbacksTableOSCell = React.memo( ({rowData, cellData}) => {
|
||||
const [openOSDialog, setOpenOSDialog] = React.useState(false);
|
||||
const getOSIcon = useCallback( () => {
|
||||
if(rowData?.payload?.payloadtype?.agent_type !== "agent"){
|
||||
return <FontAwesomeIcon icon={faRobot} style={{cursor: "pointer"}} onClick={displayOSInfo} />
|
||||
return <FontAwesomeIcon icon={faRobot} />
|
||||
}
|
||||
switch(rowData.payload.os.toLowerCase()){
|
||||
case "windows":
|
||||
return <FontAwesomeIcon icon={faWindows} style={{cursor: "pointer"}} onClick={displayOSInfo} />
|
||||
return <FontAwesomeIcon icon={faWindows} />
|
||||
case "linux":
|
||||
case "centos":
|
||||
case "redhat":
|
||||
case "debian":
|
||||
case "fedora":
|
||||
case "freebsd":
|
||||
return <FontAwesomeIcon icon={faLinux} style={{cursor: "pointer"}} onClick={displayOSInfo} />
|
||||
return <FontAwesomeIcon icon={faLinux} />
|
||||
case "macos":
|
||||
return <FontAwesomeIcon icon={faApple} style={{cursor: "pointer"}} onClick={displayOSInfo}/>
|
||||
return <FontAwesomeIcon icon={faApple} />
|
||||
case "chrome":
|
||||
return <FontAwesomeIcon icon={faChrome} style={{cursor: "pointer"}} onClick={displayOSInfo} />
|
||||
return <FontAwesomeIcon icon={faChrome} />
|
||||
case "android":
|
||||
return <FontAwesomeIcon icon={faAndroid} style={{cursor: "pointer"}} onClick={displayOSInfo} />
|
||||
return <FontAwesomeIcon icon={faAndroid} />
|
||||
default:
|
||||
return <FontAwesomeIcon icon={faQuestion} style={{cursor: "pointer"}} onClick={displayOSInfo} />
|
||||
return <FontAwesomeIcon icon={faQuestion} />
|
||||
}
|
||||
}, [rowData?.payload?.os]);
|
||||
const displayOSInfo = React.useCallback( () => {
|
||||
const displayOSInfo = React.useCallback( (event) => {
|
||||
event.stopPropagation();
|
||||
setOpenOSDialog(true);
|
||||
}, []);
|
||||
return (
|
||||
<div>
|
||||
{getOSIcon()}
|
||||
<div className="mythic-callback-cellInline mythic-callback-cellInlineCenter">
|
||||
<MythicStyledTooltip title={"View operating system information"}>
|
||||
<IconButton
|
||||
className="mythic-callback-iconButton mythic-callback-cellIconButton mythic-callback-cellIconButtonNeutral"
|
||||
onClick={displayOSInfo}
|
||||
>
|
||||
{getOSIcon()}
|
||||
</IconButton>
|
||||
</MythicStyledTooltip>
|
||||
{ openOSDialog &&
|
||||
<MythicDisplayTextDialog
|
||||
onClose={()=>{setOpenOSDialog(false);}}
|
||||
@@ -452,7 +478,6 @@ export const CallbacksTableOSCell = React.memo( ({rowData, cellData}) => {
|
||||
)
|
||||
}, areEqual);
|
||||
export const CallbacksTableSleepCell = React.memo( ({rowData, cellData, updateSleepInfo}) => {
|
||||
const theme = useTheme();
|
||||
const [openSleepDialog, setOpenSleepDialog] = React.useState(false);
|
||||
const editSleepSubmit = (sleep) => {
|
||||
updateSleepInfo({sleep_info: sleep, callback_display_id: rowData.display_id});
|
||||
@@ -465,10 +490,15 @@ export const CallbacksTableSleepCell = React.memo( ({rowData, cellData, updateSl
|
||||
return null
|
||||
}
|
||||
return (
|
||||
<div style={{height: "100%", display: "flex", alignItems: "center"}}>
|
||||
<SnoozeIcon onClick={onOpenSleepDialog}
|
||||
style={{color: cellData === "" ? theme.palette.warning.main : theme.palette.info.main, cursor: "pointer"}}
|
||||
/>
|
||||
<div className="mythic-callback-cellInline mythic-callback-cellInlineCenter">
|
||||
<MythicStyledTooltip title={cellData === "" ? "No sleep information set" : "View or edit sleep information"}>
|
||||
<IconButton
|
||||
className={`mythic-callback-iconButton mythic-callback-cellIconButton ${cellData === "" ? "mythic-callback-cellIconButtonWarning" : "mythic-callback-cellIconButtonInfo"}`}
|
||||
onClick={onOpenSleepDialog}
|
||||
>
|
||||
<SnoozeIcon fontSize="small" />
|
||||
</IconButton>
|
||||
</MythicStyledTooltip>
|
||||
{ openSleepDialog &&
|
||||
<MythicDialog fullWidth={true} open={openSleepDialog} maxWidth={"md"}
|
||||
style={{height: "100%"}}
|
||||
|
||||
@@ -657,7 +657,6 @@ const TaskActionsToolbarGeneric = ({toggleViewBrowserScript, toggleSelectAllOutp
|
||||
</MythicStyledTooltip>
|
||||
<Button size="small" variant="text" startIcon={<MoreHorizIcon fontSize="small" />} onClick={openActionsMenu}
|
||||
sx={{ml: 0.25, minWidth: "auto", textTransform: "none"}}>
|
||||
More
|
||||
</Button>
|
||||
<Menu anchorEl={actionsMenuAnchor}
|
||||
open={Boolean(actionsMenuAnchor)}
|
||||
|
||||
@@ -584,6 +584,39 @@ tspan {
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
}
|
||||
.mythic-callback-interactCell > span[data-tooltip-id="my-tooltip"] {
|
||||
align-items: center;
|
||||
display: inline-flex !important;
|
||||
flex: 0 0 auto;
|
||||
height: 22px;
|
||||
line-height: 1;
|
||||
}
|
||||
.mythic-callback-cellInline {
|
||||
align-items: center;
|
||||
display: inline-flex;
|
||||
gap: 0.28rem;
|
||||
height: 100%;
|
||||
max-width: 100%;
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
}
|
||||
.mythic-callback-cellInlineCenter {
|
||||
justify-content: center;
|
||||
}
|
||||
.mythic-callback-cellInline > span[data-tooltip-id="my-tooltip"] {
|
||||
align-items: center;
|
||||
display: inline-flex !important;
|
||||
flex: 0 0 auto;
|
||||
height: 22px;
|
||||
line-height: 1;
|
||||
}
|
||||
.mythic-callback-cellText {
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.mythic-callback-iconButton.MuiIconButton-root {
|
||||
border: 1px solid transparent;
|
||||
border-radius: ${(props) => props.theme.shape.borderRadius}px;
|
||||
@@ -598,6 +631,59 @@ tspan {
|
||||
background-color: ${(props) => alpha(props.theme.palette.primary.main, props.theme.palette.mode === "dark" ? 0.16 : 0.09)};
|
||||
color: ${(props) => props.theme.palette.primary.main};
|
||||
}
|
||||
.mythic-callback-cellIconButton.MuiIconButton-root {
|
||||
background-color: ${(props) => props.theme.palette.mode === "dark" ? "rgba(255,255,255,0.045)" : "rgba(0,0,0,0.025)"};
|
||||
border-color: ${(props) => props.theme.table?.borderSoft || props.theme.borderColor};
|
||||
}
|
||||
.mythic-callback-cellIconButton.MuiIconButton-root svg {
|
||||
display: block;
|
||||
font-size: 0.92rem;
|
||||
}
|
||||
.mythic-callback-cellIconButtonNeutral.MuiIconButton-root:hover {
|
||||
background-color: ${(props) => alpha(props.theme.palette.primary.main, props.theme.palette.mode === "dark" ? 0.16 : 0.09)};
|
||||
border-color: ${(props) => alpha(props.theme.palette.primary.main, props.theme.palette.mode === "dark" ? 0.42 : 0.28)};
|
||||
color: ${(props) => props.theme.palette.primary.main};
|
||||
}
|
||||
.mythic-callback-cellIconButtonSuccess.MuiIconButton-root {
|
||||
background-color: ${(props) => alpha(props.theme.palette.success.main, props.theme.palette.mode === "dark" ? 0.12 : 0.07)};
|
||||
border-color: ${(props) => alpha(props.theme.palette.success.main, props.theme.palette.mode === "dark" ? 0.32 : 0.2)};
|
||||
color: ${(props) => props.theme.palette.success.main};
|
||||
}
|
||||
.mythic-callback-cellIconButtonSuccess.MuiIconButton-root:hover {
|
||||
background-color: ${(props) => alpha(props.theme.palette.success.main, props.theme.palette.mode === "dark" ? 0.2 : 0.12)};
|
||||
border-color: ${(props) => alpha(props.theme.palette.success.main, props.theme.palette.mode === "dark" ? 0.54 : 0.36)};
|
||||
color: ${(props) => props.theme.palette.success.main};
|
||||
}
|
||||
.mythic-callback-cellIconButtonInfo.MuiIconButton-root {
|
||||
background-color: ${(props) => alpha(props.theme.palette.info.main, props.theme.palette.mode === "dark" ? 0.12 : 0.07)};
|
||||
border-color: ${(props) => alpha(props.theme.palette.info.main, props.theme.palette.mode === "dark" ? 0.32 : 0.2)};
|
||||
color: ${(props) => props.theme.palette.info.main};
|
||||
}
|
||||
.mythic-callback-cellIconButtonInfo.MuiIconButton-root:hover {
|
||||
background-color: ${(props) => alpha(props.theme.palette.info.main, props.theme.palette.mode === "dark" ? 0.2 : 0.12)};
|
||||
border-color: ${(props) => alpha(props.theme.palette.info.main, props.theme.palette.mode === "dark" ? 0.54 : 0.36)};
|
||||
color: ${(props) => props.theme.palette.info.main};
|
||||
}
|
||||
.mythic-callback-cellIconButtonWarning.MuiIconButton-root {
|
||||
background-color: ${(props) => alpha(props.theme.palette.warning.main, props.theme.palette.mode === "dark" ? 0.12 : 0.07)};
|
||||
border-color: ${(props) => alpha(props.theme.palette.warning.main, props.theme.palette.mode === "dark" ? 0.32 : 0.2)};
|
||||
color: ${(props) => props.theme.palette.warning.main};
|
||||
}
|
||||
.mythic-callback-cellIconButtonWarning.MuiIconButton-root:hover {
|
||||
background-color: ${(props) => alpha(props.theme.palette.warning.main, props.theme.palette.mode === "dark" ? 0.2 : 0.12)};
|
||||
border-color: ${(props) => alpha(props.theme.palette.warning.main, props.theme.palette.mode === "dark" ? 0.54 : 0.36)};
|
||||
color: ${(props) => props.theme.palette.warning.main};
|
||||
}
|
||||
.mythic-callback-cellIconButtonError.MuiIconButton-root {
|
||||
background-color: ${(props) => alpha(props.theme.palette.error.main, props.theme.palette.mode === "dark" ? 0.12 : 0.07)};
|
||||
border-color: ${(props) => alpha(props.theme.palette.error.main, props.theme.palette.mode === "dark" ? 0.32 : 0.2)};
|
||||
color: ${(props) => props.theme.palette.error.main};
|
||||
}
|
||||
.mythic-callback-cellIconButtonError.MuiIconButton-root:hover {
|
||||
background-color: ${(props) => alpha(props.theme.palette.error.main, props.theme.palette.mode === "dark" ? 0.2 : 0.12)};
|
||||
border-color: ${(props) => alpha(props.theme.palette.error.main, props.theme.palette.mode === "dark" ? 0.54 : 0.36)};
|
||||
color: ${(props) => props.theme.palette.error.main};
|
||||
}
|
||||
.mythic-callback-interactButtonHighIntegrity.MuiIconButton-root {
|
||||
background-color: ${(props) => alpha(props.theme.palette.error.main, props.theme.palette.mode === "dark" ? 0.18 : 0.1)};
|
||||
border-color: ${(props) => alpha(props.theme.palette.error.main, props.theme.palette.mode === "dark" ? 0.48 : 0.32)};
|
||||
@@ -615,44 +701,130 @@ tspan {
|
||||
color: ${(props) => props.theme.palette.error.main};
|
||||
}
|
||||
.mythic-callback-displayId {
|
||||
align-items: center;
|
||||
color: ${(props) => props.theme.palette.text.primary};
|
||||
display: inline-flex;
|
||||
flex: 0 0 auto;
|
||||
font-weight: 700;
|
||||
line-height: 1;
|
||||
height: 22px;
|
||||
line-height: 22px;
|
||||
max-width: 3.8rem;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.mythic-callback-lockBadge {
|
||||
.mythic-callback-statusBadge {
|
||||
align-items: center;
|
||||
background-color: ${(props) => alpha(props.theme.palette.warning.main, props.theme.palette.mode === "dark" ? 0.18 : 0.12)};
|
||||
border: 1px solid ${(props) => alpha(props.theme.palette.warning.main, props.theme.palette.mode === "dark" ? 0.46 : 0.34)};
|
||||
background-color: ${(props) => props.theme.palette.mode === "dark" ? "rgba(255,255,255,0.045)" : "rgba(0,0,0,0.025)"};
|
||||
border: 1px solid ${(props) => props.theme.table?.borderSoft || props.theme.borderColor};
|
||||
border-radius: ${(props) => props.theme.shape.borderRadius}px;
|
||||
color: ${(props) => props.theme.palette.warning.main};
|
||||
color: ${(props) => props.theme.palette.text.secondary};
|
||||
display: inline-flex;
|
||||
flex: 0 1 auto;
|
||||
font-size: 0.68rem;
|
||||
font-weight: 700;
|
||||
gap: 0.12rem;
|
||||
height: 18px;
|
||||
line-height: 1;
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
padding: 0 0.28rem;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.mythic-callback-lockBadge span {
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.mythic-callback-statusIcon {
|
||||
flex: 0 0 auto;
|
||||
font-size: 0.9rem;
|
||||
font-size: 0.82rem;
|
||||
height: 20px;
|
||||
justify-content: center;
|
||||
line-height: 1;
|
||||
margin-left: 0.08rem;
|
||||
transition: background-color 120ms ease, border-color 120ms ease, color 120ms ease;
|
||||
width: 22px;
|
||||
}
|
||||
.mythic-callback-statusIconSuccess {
|
||||
color: ${(props) => props.theme.palette.success.main};
|
||||
.mythic-callback-statusBadgeAlert {
|
||||
background-color: ${(props) => alpha(props.theme.palette.warning.main, props.theme.palette.mode === "dark" ? 0.14 : 0.08)};
|
||||
border-color: ${(props) => alpha(props.theme.palette.warning.main, props.theme.palette.mode === "dark" ? 0.36 : 0.24)};
|
||||
color: ${(props) => props.theme.palette.warning.main};
|
||||
}
|
||||
.mythic-callback-statusBadgeProxy {
|
||||
background-color: ${(props) => alpha(props.theme.palette.info.main, props.theme.palette.mode === "dark" ? 0.12 : 0.07)};
|
||||
border-color: ${(props) => alpha(props.theme.palette.info.main, props.theme.palette.mode === "dark" ? 0.32 : 0.2)};
|
||||
color: ${(props) => props.theme.palette.info.main};
|
||||
}
|
||||
.mythic-callback-statusBadgeLock {
|
||||
background-color: ${(props) => alpha(props.theme.palette.warning.main, props.theme.palette.mode === "dark" ? 0.12 : 0.07)};
|
||||
border-color: ${(props) => alpha(props.theme.palette.warning.main, props.theme.palette.mode === "dark" ? 0.32 : 0.2)};
|
||||
color: ${(props) => props.theme.palette.warning.main};
|
||||
}
|
||||
.mythic-callback-statusBadgeDead {
|
||||
background-color: ${(props) => alpha(props.theme.palette.error.main, props.theme.palette.mode === "dark" ? 0.12 : 0.07)};
|
||||
border-color: ${(props) => alpha(props.theme.palette.error.main, props.theme.palette.mode === "dark" ? 0.32 : 0.2)};
|
||||
color: ${(props) => props.theme.palette.error.main};
|
||||
}
|
||||
.mythic-callback-statusBadgeAlert:hover {
|
||||
background-color: ${(props) => alpha(props.theme.palette.warning.main, props.theme.palette.mode === "dark" ? 0.22 : 0.13)};
|
||||
border-color: ${(props) => alpha(props.theme.palette.warning.main, props.theme.palette.mode === "dark" ? 0.58 : 0.42)};
|
||||
}
|
||||
.mythic-callback-statusBadgeProxy:hover {
|
||||
background-color: ${(props) => alpha(props.theme.palette.info.main, props.theme.palette.mode === "dark" ? 0.2 : 0.12)};
|
||||
border-color: ${(props) => alpha(props.theme.palette.info.main, props.theme.palette.mode === "dark" ? 0.54 : 0.36)};
|
||||
}
|
||||
.mythic-callback-statusBadgeLock:hover {
|
||||
background-color: ${(props) => alpha(props.theme.palette.info.main, props.theme.palette.mode === "dark" ? 0.2 : 0.12)};
|
||||
border-color: ${(props) => alpha(props.theme.palette.info.main, props.theme.palette.mode === "dark" ? 0.54 : 0.36)};
|
||||
}
|
||||
.mythic-callback-statusBadgeDead:hover {
|
||||
background-color: ${(props) => alpha(props.theme.palette.error.main, props.theme.palette.mode === "dark" ? 0.2 : 0.12)};
|
||||
border-color: ${(props) => alpha(props.theme.palette.error.main, props.theme.palette.mode === "dark" ? 0.54 : 0.36)};
|
||||
}
|
||||
.mythic-callback-statusBadge svg {
|
||||
display: block;
|
||||
font-size: inherit;
|
||||
}
|
||||
.mythic-callback-trigger-summary {
|
||||
align-items: flex-start;
|
||||
background-color: ${(props) => props.theme.surfaces?.muted || props.theme.palette.background.paper};
|
||||
border: 1px solid ${(props) => props.theme.table?.borderSoft || props.theme.borderColor};
|
||||
border-radius: ${(props) => props.theme.shape.borderRadius}px;
|
||||
display: flex;
|
||||
gap: 0.75rem;
|
||||
min-width: 0;
|
||||
padding: 0.75rem;
|
||||
}
|
||||
.mythic-callback-trigger-summary-icon {
|
||||
align-items: center;
|
||||
background-color: ${(props) => props.theme.palette.mode === "dark" ? "rgba(255,255,255,0.045)" : "rgba(0,0,0,0.025)"};
|
||||
border: 1px solid ${(props) => props.theme.table?.borderSoft || props.theme.borderColor};
|
||||
border-radius: ${(props) => props.theme.shape.borderRadius}px;
|
||||
color: ${(props) => props.theme.palette.text.secondary};
|
||||
display: inline-flex;
|
||||
flex: 0 0 auto;
|
||||
height: 34px;
|
||||
justify-content: center;
|
||||
width: 34px;
|
||||
}
|
||||
.mythic-callback-trigger-summary-icon-active {
|
||||
background-color: ${(props) => alpha(props.theme.palette.warning.main, props.theme.palette.mode === "dark" ? 0.16 : 0.1)};
|
||||
border-color: ${(props) => alpha(props.theme.palette.warning.main, props.theme.palette.mode === "dark" ? 0.42 : 0.3)};
|
||||
color: ${(props) => props.theme.palette.warning.main};
|
||||
}
|
||||
.mythic-callback-trigger-summary-copy {
|
||||
min-width: 0;
|
||||
}
|
||||
.mythic-callback-trigger-summary-title.MuiTypography-root {
|
||||
color: ${(props) => props.theme.palette.text.primary};
|
||||
font-size: 0.9rem;
|
||||
font-weight: 800;
|
||||
line-height: 1.25;
|
||||
}
|
||||
.mythic-callback-trigger-summary-description.MuiTypography-root {
|
||||
color: ${(props) => props.theme.palette.text.secondary};
|
||||
font-size: 0.78rem;
|
||||
line-height: 1.4;
|
||||
margin-top: 0.2rem;
|
||||
}
|
||||
.mythic-callback-trigger-rule-list {
|
||||
display: grid;
|
||||
gap: 0.45rem;
|
||||
}
|
||||
.mythic-callback-trigger-rule {
|
||||
background-color: ${(props) => props.theme.palette.mode === "dark" ? "rgba(255,255,255,0.035)" : "rgba(0,0,0,0.025)"};
|
||||
border: 1px solid ${(props) => props.theme.table?.borderSoft || props.theme.borderColor};
|
||||
border-radius: ${(props) => props.theme.shape.borderRadius}px;
|
||||
color: ${(props) => props.theme.palette.text.secondary};
|
||||
font-size: 0.78rem;
|
||||
line-height: 1.4;
|
||||
padding: 0.55rem 0.65rem;
|
||||
}
|
||||
.mythic-callback-trigger-rule strong {
|
||||
color: ${(props) => props.theme.palette.text.primary};
|
||||
}
|
||||
.MythicInteractiveTerminal {
|
||||
background-color: ${(props) => props.theme.outputBackgroundColor};
|
||||
|
||||
Reference in New Issue
Block a user