"modernizing" of the UI components

This commit is contained in:
its-a-feature
2026-05-03 17:48:02 -05:00
parent ae4b756fc0
commit 8c4ade6b81
52 changed files with 1532 additions and 520 deletions
+48 -49
View File
@@ -25,9 +25,9 @@ export const defaultShortcuts = [
"CreatePayload", "Eventing",
].sort();
export const operatorSettingDefaults = {
fontSize: 12,
fontSize: 13,
navBarOpen: false,
fontFamily: "Verdana, Arial, sans-serif",
fontFamily: 'Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
showMedia: true,
hideUsernames: false,
showIP: false,
@@ -47,36 +47,36 @@ export const operatorSettingDefaults = {
sideShortcuts: defaultShortcuts,
palette: {
primary: {
dark: "#75859b",
light: "#75859b",
dark: "#8ab4f8",
light: "#2563eb",
},
error: {
dark: '#bd5142',
light: '#c42c32'
dark: '#f87171',
light: '#dc2626'
},
success: {
dark: '#85b089',
light: '#0e7004',
dark: '#4ade80',
light: '#15803d',
},
secondary: {
dark: '#bebebe',
light: '#a6a5a5'
dark: '#94a3b8',
light: '#64748b'
},
info: {
dark: '#84b4dc',
light: '#4990b2'
dark: '#38bdf8',
light: '#0284c7'
},
warning: {
dark: "#dc8455",
light: "#ffb74d",
dark: "#fbbf24",
light: "#d97706",
},
background: {
dark: '#282828',
light: '#f6f6f6'
dark: '#0f141b',
light: '#f4f6f8'
},
paper: {
dark: '#282828',
light: '#ececec'
dark: '#161b22',
light: '#ffffff'
},
tableHeader: {
dark: '#484848',
@@ -87,20 +87,20 @@ export const operatorSettingDefaults = {
light: "#e8e8e8",
},
pageHeader: {
dark: '#1b2025',
light: '#706c6e'
dark: '#171d25',
light: '#ffffff'
},
text: {
dark: "#e4e4e4",
light: "#000000",
dark: "#e5e7eb",
light: "#111827",
},
selectedCallbackColor: {
dark: '#26456e',
light: '#c6e5f6',
dark: '#1e3a5f',
light: '#dbeafe',
},
selectedCallbackHierarchyColor: {
dark: '#273e5d',
light: '#deeff8',
dark: '#22324c',
light: '#eef4ff',
},
backgroundImage: {
dark: null,
@@ -115,48 +115,48 @@ export const operatorSettingDefaults = {
light: '#ffffff'
},
navBarColor: {
dark: "#194573",
light: "#3b606d",
dark: "#111827",
light: "#111827",
},
navBarBottomColor: {
dark: "#330814",
light: "#283581",
dark: "#1f2937",
light: "#1f2937",
},
taskPromptTextColor: {
dark: '#bebebe',
light: '#a6a5a5'
dark: '#9ca3af',
light: '#64748b'
},
taskPromptCommandTextColor: {
dark: "#e4e4e4",
light: "#000000",
dark: "#f8fafc",
light: "#111827",
},
taskContextColor: {
dark: "#122848",
light: "#acc0da",
dark: "#14253d",
light: "#dbeafe",
},
taskContextImpersonationColor: {
dark: "#641616",
light: "#dec0c0",
dark: "#4c1d20",
light: "#fee2e2",
},
taskContextExtraColor: {
dark: "#2a5953",
light: "#a7ce9d",
dark: "#123d39",
light: "#dcfce7",
},
emptyFolderColor: {
dark: '#bebebe',
light: '#a6a5a5'
dark: '#94a3b8',
light: '#64748b'
},
outputBackgroundColor: {
dark: '#282828',
light: '#f6f6f6'
dark: '#0b1017',
light: '#f8fafc'
},
outputTextColor: {
dark: '#f6f6f6',
light: '#282828',
dark: '#e5e7eb',
light: '#111827',
},
borderColor: {
dark: "#595858",
light: "#c5c5c5"
dark: "#2f3742",
light: "#d9dee7"
}
},
}
@@ -227,4 +227,3 @@ export const FailedRefresh = (restart_websockets) =>{
}
}
+460 -4
View File
@@ -62,6 +62,438 @@ query getUserSettings {
}
`;
const getModernThemeAdditions = (themeMode, preferences = operatorSettingDefaults) => {
const isDark = themeMode === "dark";
const mode = isDark ? "dark" : "light";
const safePreferences = preferences || operatorSettingDefaults;
const getColor = (key) => {
return safePreferences?.palette?.[key]?.[mode] || operatorSettingDefaults.palette[key][mode];
};
const withAlpha = (color, alphaHex) => {
if(typeof color === "string" && color.startsWith("#") && color.length === 7){
return `${color}${alphaHex}`;
}
return color;
};
const textPrimary = getColor("text");
const textSecondary = isDark ? "#9ca3af" : "#475569";
const borderColor = getColor("borderColor");
const backgroundDefault = getColor("background");
const backgroundPaper = getColor("paper");
const navBackground = getColor("navBarColor");
const navAccent = getColor("navBarBottomColor");
const navText = getColor("navBarText");
const navIcon = getColor("navBarIcons");
const primary = getColor("primary");
const tableHeaderColor = getColor("tableHeader");
const tableHoverColor = getColor("tableHover");
const tableRowStripeColor = withAlpha(tableHoverColor, isDark ? "55" : "66");
const tableRowHoverColor = withAlpha(tableHoverColor, "CC");
const hoverColor = tableRowHoverColor;
const tableSelectedColor = withAlpha(getColor("selectedCallbackColor"), "CC");
const tableSelectedHierarchyColor = withAlpha(getColor("selectedCallbackHierarchyColor"), "CC");
const tableBorderSoft = withAlpha(borderColor, isDark ? "AA" : "CC");
return {
shape: {
borderRadius: 6,
},
pageHeaderText: {
main: textPrimary,
},
navigation: {
background: `linear-gradient(180deg, ${navBackground}, ${navAccent})`,
backgroundColor: navBackground,
border: borderColor,
hover: withAlpha(getColor("tableHover"), "66"),
selected: withAlpha(getColor("selectedCallbackColor"), "99"),
text: navText,
icon: navIcon,
muted: withAlpha(navText, "B3"),
accent: navAccent,
},
surfaces: {
app: backgroundDefault,
paper: backgroundPaper,
raised: isDark ? "#1b222c" : "#ffffff",
muted: isDark ? withAlpha(backgroundDefault, "DD") : withAlpha(backgroundDefault, "EE"),
hover: tableRowHoverColor,
selected: tableSelectedColor,
},
table: {
header: tableHeaderColor,
headerHover: tableRowHoverColor,
rowStripe: tableRowStripeColor,
rowHover: tableRowHoverColor,
selected: tableSelectedColor,
selectedHierarchy: tableSelectedHierarchyColor,
border: borderColor,
borderSoft: tableBorderSoft,
},
typography: {
fontSize: safePreferences?.fontSize || operatorSettingDefaults.fontSize,
fontFamily: safePreferences?.fontFamily || operatorSettingDefaults.fontFamily,
h5: {
fontWeight: 650,
letterSpacing: 0,
},
h6: {
fontWeight: 650,
letterSpacing: 0,
},
subtitle1: {
fontWeight: 650,
},
button: {
textTransform: "none",
fontWeight: 650,
letterSpacing: 0,
},
},
components: {
MuiCssBaseline: {
styleOverrides: {
body: {
backgroundColor: backgroundDefault,
color: textPrimary,
WebkitFontSmoothing: "antialiased",
MozOsxFontSmoothing: "grayscale",
},
},
},
MuiPaper: {
defaultProps: {
elevation: 0,
},
styleOverrides: {
root: {
backgroundImage: "none",
boxShadow: "none",
},
},
},
MuiButton: {
defaultProps: {
disableElevation: true,
size: "small",
},
styleOverrides: {
root: {
minHeight: 30,
borderRadius: 6,
textTransform: "none",
fontWeight: 650,
},
contained: {
boxShadow: "none",
},
},
},
MuiIconButton: {
styleOverrides: {
root: {
borderRadius: 6,
padding: 5,
color: textSecondary,
"&:hover": {
backgroundColor: hoverColor,
color: textPrimary,
},
},
},
},
MuiAppBar: {
styleOverrides: {
root: {
backgroundImage: "none",
boxShadow: "none",
borderBottom: `1px solid ${borderColor}`,
},
},
},
MuiDialog: {
styleOverrides: {
paper: {
borderRadius: 8,
border: `1px solid ${borderColor}`,
backgroundImage: "none",
boxShadow: isDark ? "0 24px 80px rgba(0, 0, 0, 0.45)" : "0 24px 80px rgba(15, 23, 42, 0.14)",
},
},
},
MuiDialogTitle: {
styleOverrides: {
root: {
padding: "10px 14px",
fontSize: "1rem",
fontWeight: 650,
borderBottom: `1px solid ${borderColor}`,
},
},
},
MuiDialogContent: {
styleOverrides: {
root: {
padding: "12px 14px",
},
},
},
MuiDialogActions: {
styleOverrides: {
root: {
gap: 8,
padding: "10px 14px",
borderTop: `1px solid ${borderColor}`,
},
},
},
MuiOutlinedInput: {
styleOverrides: {
root: {
borderRadius: 6,
backgroundColor: backgroundPaper,
"&:hover .MuiOutlinedInput-notchedOutline": {
borderColor: textSecondary,
},
"&.Mui-focused .MuiOutlinedInput-notchedOutline": {
borderColor: primary,
borderWidth: 1,
},
},
notchedOutline: {
borderColor,
},
},
},
MuiInput: {
styleOverrides: {
root: {
"&:before": {
borderBottomColor: borderColor,
},
"&:after": {
borderBottomColor: primary,
},
},
},
},
MuiInputBase: {
styleOverrides: {
root: {
fontSize: "0.92rem",
},
},
},
MuiInputLabel: {
styleOverrides: {
root: {
color: textSecondary,
"&.Mui-focused": {
color: primary,
},
},
},
},
MuiTabs: {
styleOverrides: {
root: {
minHeight: 34,
},
indicator: {
height: 2,
borderRadius: 2,
},
},
},
MuiTab: {
styleOverrides: {
root: {
minHeight: 34,
padding: "6px 10px",
textTransform: "none",
fontSize: "0.82rem",
fontWeight: 650,
letterSpacing: 0,
},
},
},
MuiMenu: {
styleOverrides: {
paper: {
border: `1px solid ${borderColor}`,
borderRadius: 8,
boxShadow: isDark ? "0 18px 48px rgba(0, 0, 0, 0.40)" : "0 18px 48px rgba(15, 23, 42, 0.12)",
},
},
},
MuiList: {
styleOverrides: {
root: {
backgroundImage: "none",
},
},
},
MuiTooltip: {
styleOverrides: {
tooltip: {
borderRadius: 6,
fontSize: 12,
},
},
},
MuiAccordion: {
styleOverrides: {
root: {
boxShadow: "none",
"&:before": {
display: "none",
},
},
},
},
MuiChip: {
styleOverrides: {
root: {
borderRadius: 5,
fontWeight: 650,
},
},
},
MuiTableContainer: {
styleOverrides: {
root: {
backgroundColor: backgroundPaper,
borderRadius: 6,
},
},
},
MuiTable: {
styleOverrides: {
root: {
backgroundColor: backgroundPaper,
borderCollapse: "separate",
borderSpacing: 0,
},
},
},
MuiTableCell: {
styleOverrides: {
root: {
borderBottom: `1px solid ${tableBorderSoft}`,
color: textPrimary,
fontSize: "0.86rem",
lineHeight: 1.35,
padding: "6px 10px",
verticalAlign: "middle",
},
head: {
backgroundColor: tableHeaderColor,
borderBottom: `1px solid ${borderColor}`,
borderTop: 0,
color: textPrimary,
fontSize: "0.76rem",
fontWeight: 700,
letterSpacing: 0,
textTransform: "uppercase",
whiteSpace: "nowrap",
},
stickyHeader: {
backgroundColor: tableHeaderColor,
zIndex: 3,
},
},
},
MuiTableRow: {
styleOverrides: {
root: {
"&:last-child .MuiTableCell-root": {
borderBottom: 0,
},
"&.Mui-selected": {
backgroundColor: tableSelectedColor,
"&:hover": {
backgroundColor: tableSelectedColor,
},
},
"&.MuiTableRow-hover:hover": {
backgroundColor: tableRowHoverColor,
},
},
},
},
MuiTableSortLabel: {
styleOverrides: {
root: {
color: textSecondary,
"&.Mui-active": {
color: textPrimary,
},
"&:hover": {
color: textPrimary,
},
},
icon: {
color: `${textSecondary} !important`,
},
},
},
MuiDataGrid: {
styleOverrides: {
root: {
backgroundColor: backgroundPaper,
border: `1px solid ${borderColor}`,
borderRadius: 6,
color: textPrimary,
fontSize: "0.86rem",
"--DataGrid-rowBorderColor": tableBorderSoft,
"--DataGrid-containerBackground": tableHeaderColor,
"& .MuiDataGrid-columnHeaders": {
backgroundColor: tableHeaderColor,
borderBottom: `1px solid ${borderColor}`,
minHeight: 34,
},
"& .MuiDataGrid-columnHeader": {
backgroundColor: tableHeaderColor,
color: textPrimary,
fontWeight: 700,
},
"& .MuiDataGrid-columnHeaderTitle": {
fontSize: "0.76rem",
fontWeight: 700,
letterSpacing: 0,
textTransform: "uppercase",
},
"& .MuiDataGrid-cell": {
borderBottom: `1px solid ${tableBorderSoft}`,
outline: "none",
},
"& .MuiDataGrid-row:nth-of-type(even)": {
backgroundColor: tableRowStripeColor,
},
"& .MuiDataGrid-row:hover": {
backgroundColor: tableRowHoverColor,
},
"& .MuiDataGrid-row.Mui-selected": {
backgroundColor: tableSelectedColor,
"&:hover": {
backgroundColor: tableSelectedColor,
},
},
"& .MuiDataGrid-footerContainer": {
borderTop: `1px solid ${borderColor}`,
minHeight: 34,
},
"& .MuiDataGrid-toolbarContainer": {
borderBottom: `1px solid ${tableBorderSoft}`,
minHeight: 34,
},
},
},
},
},
};
};
export function App(props) {
const me = useReactiveVar(meState);
@@ -117,8 +549,17 @@ export function App(props) {
text: {
primary: themeMode === 'dark' ? preferences?.palette?.text?.dark || operatorSettingDefaults.palette.text.dark :
preferences?.palette?.text?.light || operatorSettingDefaults.palette.text.light,
secondary: themeMode === 'dark' ? '#9ca3af' : '#475569',
disabled: themeMode === 'dark' ? '#6b7280' : '#94a3b8',
contrast: themeMode === 'dark' ? '#000' : '#fff',
},
action: {
hover: themeMode === 'dark' ? 'rgba(255, 255, 255, 0.07)' : 'rgba(15, 23, 42, 0.06)',
selected: themeMode === 'dark' ? 'rgba(255, 255, 255, 0.11)' : 'rgba(37, 99, 235, 0.10)',
focus: themeMode === 'dark' ? 'rgba(138, 180, 248, 0.20)' : 'rgba(37, 99, 235, 0.18)',
},
divider: themeMode === 'dark' ? preferences?.palette?.borderColor?.dark || operatorSettingDefaults.palette.borderColor.dark :
preferences?.palette?.borderColor?.light || operatorSettingDefaults.palette.borderColor.light,
graphGroupRGBA: themeMode === 'dark' ? 'rgba(57, 76, 93, 0.5)' : 'rgba(211, 215, 232, 0.5)',
speedDialAction: themeMode === 'dark' ? '#495054' : '#ffffff',
},
@@ -168,6 +609,7 @@ export function App(props) {
preferences?.palette?.outputTextColor?.light || operatorSettingDefaults.palette.outputTextColor.light,
borderColor: themeMode === 'dark' ? preferences?.palette?.borderColor?.dark || operatorSettingDefaults.palette.borderColor.dark :
preferences?.palette?.borderColor?.light || operatorSettingDefaults.palette.borderColor.light,
...getModernThemeAdditions(themeMode, preferences),
})
}catch(error){
console.log(error);
@@ -218,8 +660,17 @@ export function App(props) {
text: {
primary: themeMode === 'dark' ? operatorSettingDefaults.palette.text.dark :
operatorSettingDefaults.palette.text.light,
secondary: themeMode === 'dark' ? '#9ca3af' : '#475569',
disabled: themeMode === 'dark' ? '#6b7280' : '#94a3b8',
contrast: themeMode === 'dark' ? '#000' : '#fff',
},
action: {
hover: themeMode === 'dark' ? 'rgba(255, 255, 255, 0.07)' : 'rgba(15, 23, 42, 0.06)',
selected: themeMode === 'dark' ? 'rgba(255, 255, 255, 0.11)' : 'rgba(37, 99, 235, 0.10)',
focus: themeMode === 'dark' ? 'rgba(138, 180, 248, 0.20)' : 'rgba(37, 99, 235, 0.18)',
},
divider: themeMode === 'dark' ? operatorSettingDefaults.palette.borderColor.dark :
operatorSettingDefaults.palette.borderColor.light,
graphGroupRGBA: themeMode === 'dark' ? 'rgba(57, 76, 93, 0.5)' : 'rgba(211, 215, 232, 0.5)',
speedDialAction: themeMode === 'dark' ? '#495054' : '#ffffff',
},
@@ -259,9 +710,10 @@ export function App(props) {
fontSize: 12,//operatorSettingDefaults?.fontSize,
fontFamily: operatorSettingDefaults?.fontFamily
},
...getModernThemeAdditions(themeMode, operatorSettingDefaults),
})
}
},[themeMode, loadingPreference, preferences.fontSize, preferences.fontFamily, preferences.palette]
},[themeMode, preferences]
);
const mountedRef = React.useRef(true);
const [openRefreshDialog, setOpenRefreshDialog] = React.useState(false);
@@ -358,7 +810,7 @@ export function App(props) {
flexDirection: 'column',
overflow: "hidden",
}}>
<div style={{height: "5px", width: "100%", background: me.loggedIn ? `linear-gradient(25deg, ${theme.topAppBarColor}, ${theme.topAppBarBottomColor})` : ""}}/>
<div style={{height: me.loggedIn ? "2px" : 0, width: "100%", background: me.loggedIn ? `linear-gradient(90deg, ${theme.topAppBarColor}, ${theme.topAppBarBottomColor})` : ""}}/>
{me.loggedIn && me?.user?.current_operation_banner_text !== "" &&
<Typography style={{
backgroundColor: me?.user?.current_operation_banner_color,
@@ -366,7 +818,9 @@ export function App(props) {
textAlign: "center",
fontWeight: "600",
color: "white",
border: `1px solid ${theme.topAppBarColor || "grey"}`
borderBottom: `1px solid ${theme.borderColor}`,
fontSize: theme.typography.pxToRem(12),
lineHeight: "24px",
}}>
{me?.user?.current_operation_banner_text}
</Typography>
@@ -379,7 +833,9 @@ export function App(props) {
textAlign: "center",
fontWeight: "600",
color: "white",
border: `1px solid ${theme.topAppBarColor || "grey"}`
borderBottom: `1px solid ${theme.borderColor}`,
fontSize: theme.typography.pxToRem(12),
lineHeight: "24px",
}}>
{"Can't connect to Mythic. Please check connection and refresh"}
</Typography>
@@ -0,0 +1,80 @@
import React from 'react';
import Box from '@mui/material/Box';
import {HexColorInput} from 'react-colorful';
export const isValidHexColor = (color) => {
if(typeof color !== "string"){
return false;
}
if(color.length !== 7){
return false;
}
if(color[0] !== "#"){
return false;
}
return /^#[0-9a-fA-F]{6}$/.test(color);
}
export const getReadableTextColor = (backgroundColor) => {
if(!isValidHexColor(backgroundColor)){
return "#ffffff";
}
const red = parseInt(backgroundColor.slice(1, 3), 16);
const green = parseInt(backgroundColor.slice(3, 5), 16);
const blue = parseInt(backgroundColor.slice(5, 7), 16);
const brightness = (red * 299 + green * 587 + blue * 114) / 1000;
return brightness >= 140 ? "#111827" : "#ffffff";
}
export const MythicColorSwatchInput = ({color, label, onChange, inputWidth = "96px", sx = {}}) => {
const safeColor = isValidHexColor(color) ? color : "#000000";
return (
<Box sx={{display: "flex", alignItems: "center", gap: 1, minWidth: 0, ...sx}}>
<Box
component="input"
type="color"
value={safeColor}
onChange={(evt) => onChange(evt.target.value)}
aria-label={label}
sx={{
width: 34,
height: 30,
flex: "0 0 auto",
p: 0,
border: "none",
backgroundColor: "transparent",
cursor: "pointer",
"&::-webkit-color-swatch-wrapper": {p: 0},
"&::-webkit-color-swatch": {
border: "1px solid",
borderColor: "divider",
borderRadius: "4px",
},
"&::-moz-color-swatch": {
border: "1px solid",
borderColor: "divider",
borderRadius: "4px",
},
}}
/>
<HexColorInput
color={color}
onChange={onChange}
prefixed={true}
style={{
width: inputWidth,
minWidth: 0,
height: "30px",
boxSizing: "border-box",
borderRadius: "4px",
border: "1px solid rgba(128,128,128,0.45)",
background: "transparent",
color: "inherit",
padding: "0 8px",
fontFamily: "inherit",
fontSize: "0.85rem",
}}
/>
</Box>
);
}
@@ -25,6 +25,7 @@ import Draggable from 'react-draggable';
import {MythicDraggableDialogTitle} from "./MythicDraggableDialogTitle";
export function MythicDialog(props) {
const theme = useTheme();
const [draggedState, setDraggedState] = React.useState({
style: {},
paperStyle: {
@@ -121,10 +122,13 @@ export function MythicDialog(props) {
aria-labelledby="scroll-dialog-title"
aria-describedby="scroll-dialog-description"
sx={{
[".MuiPaper-root"]: {
".MuiPaper-root": {
borderRadius: "8px",
backgroundColor: theme.palette.background.paper,
border: `1px solid ${theme.borderColor}`,
...draggedState.paperStyle
},
[".MuiDialog-container"]: {
".MuiDialog-container": {
...draggedState.containerStyle
}
}}
@@ -480,4 +484,4 @@ export const TableRowSizeCell = ({ cellData, rowData }) => {
}
};
return getStringSize(cellData);
};
};
@@ -1,10 +1,17 @@
import DialogTitle from '@mui/material/DialogTitle';
import {useTheme} from '@mui/material/styles';
export const MythicDraggableDialogTitle = ({children}) => {
const theme = useTheme();
return (
<DialogTitle id="mythic-draggable-title" style={{ cursor: 'move', width: "100%" }}>
<DialogTitle id="mythic-draggable-title" style={{
cursor: 'move',
width: "100%",
backgroundColor: theme.palette.background.paper,
color: theme.palette.text.primary,
}}>
{children}
</DialogTitle>
)
}
}
@@ -5,9 +5,12 @@ export const MythicPageBody = ({children}) => {
height: "100%",
display: "flex",
flexDirection: "column",
margin: "0.5rem",
padding: "0.75rem",
gap: "0.5rem",
minWidth: 0,
minHeight: 0,
}}>
{children}
</div>
)
}
}
@@ -2,31 +2,41 @@ import {useTheme} from '@mui/material/styles';
import Paper from '@mui/material/Paper';
import {Typography} from "@mui/material";
export const MythicPageHeader = ({children, title, style={}, headerVariant="h5"}) => {
export const MythicPageHeader = ({children, title, style={}, headerVariant="h6"}) => {
const theme = useTheme();
const headerTextColor = theme.palette.getContrastText(theme.pageHeader.main);
return (
<Paper elevation={2}
variant={"elevation"}
<Paper elevation={0}
style={{
backgroundColor: theme.pageHeader.main,
color: theme.pageHeaderText.main,
color: headerTextColor,
border: `1px solid ${theme.borderColor}`,
alignItems: "center",
display: "flex",
justifyContent: "space-between",
marginBottom: "0.5rem",
padding: "0.5rem",
borderRadius: "5px",
gap: "0.75rem",
minHeight: "44px",
marginBottom: "0rem",
padding: "0.5rem 0.75rem",
borderRadius: theme.shape.borderRadius,
...style
}}
>
<Typography variant={headerVariant} style={{textAlign: "left", display: "inline-block", marginLeft: "1rem", width: "100%"}}>
<Typography variant={headerVariant} style={{
textAlign: "left",
display: "inline-block",
marginLeft: "0.25rem",
width: "100%",
fontWeight: 650,
letterSpacing: 0,
color: headerTextColor,
}}>
{title}
</Typography>
<div style={{display: "flex", marginRight: "1rem", alignItems: "center"}}>
<div style={{display: "flex", marginRight: "0.25rem", alignItems: "center", gap: "0.35rem", color: headerTextColor}}>
{children}
</div>
</Paper>
)
}
}
@@ -9,6 +9,7 @@ import MenuList from '@mui/material/MenuList';
import ClickAwayListener from '@mui/material/ClickAwayListener';
import Paper from '@mui/material/Paper';
import Badge from '@mui/material/Badge';
import {useTheme} from '@mui/material/styles';
import {
Draggable,
} from "@hello-pangea/dnd";
@@ -72,6 +73,7 @@ export function MythicTabLabel(props) {
};
const [openContextMenu, setOpenContextMenu] = React.useState(false);
const dropdownAnchorRef = React.useRef(null);
const theme = useTheme();
const handleContextClick = (event) => {
event.preventDefault();
event.stopPropagation();
@@ -94,8 +96,11 @@ export function MythicTabLabel(props) {
{(provided, snapshot) => (
<div ref={provided.innerRef}
{...provided.draggableProps}>
{(() => {
const selected = selectedIndex === index || snapshot.isDragging;
const tabAccent = tabInfo?.color || theme.palette.primary.main;
return (
<Tab
className={selectedIndex === index || snapshot.isDragging ? "selectedCallback" : "" }
label={
<span onContextMenu={handleContextClick} style={{}} ref={dropdownAnchorRef}>
<Badge color="success" variant="dot" invisible={!highlight} >
@@ -109,10 +114,20 @@ export function MythicTabLabel(props) {
{...a11yProps(index)}
{...other}
{...provided.dragHandleProps}
style={{padding: "0px 5px 0px 5px", borderRadius: "4px", margin: 0,
borderBottom: selectedIndex === index ? `2px solid grey` : '',
backgroundColor: selectedIndex === index ? tabInfo.color : snapshot.isDragging ? tabInfo.color : ""}}
style={{
padding: "0px 6px",
margin: "0 3px 0 0",
minHeight: "32px",
borderRadius: `${theme.shape.borderRadius}px ${theme.shape.borderRadius}px 0 0`,
border: `1px solid ${theme.borderColor}`,
borderTop: `2px solid ${selected ? tabAccent : "transparent"}`,
borderBottom: selected ? `1px solid ${theme.palette.background.paper}` : `1px solid ${theme.borderColor}`,
backgroundColor: selected ? theme.palette.background.paper : theme.surfaces?.muted,
color: theme.palette.text.primary,
}}
/>
);
})()}
<Popper open={openContextMenu} anchorEl={dropdownAnchorRef.current} role={undefined} transition style={{zIndex: 40}}>
{({ TransitionProps, placement }) => (
<Grow
@@ -1,6 +1,19 @@
import {styled} from '@mui/material/styles';
import TableCell from '@mui/material/TableCell';
const MythicStyledTableCell = styled(TableCell, {})({
padding: "2px 0 2px 10px !important",
});
const MythicStyledTableCell = styled(TableCell, {})(({theme}) => ({
borderBottom: `1px solid ${theme.table?.borderSoft || theme.borderColor}`,
lineHeight: 1.35,
padding: "6px 10px !important",
verticalAlign: "middle",
"&.MuiTableCell-head": {
borderBottom: `1px solid ${theme.table?.border || theme.borderColor}`,
padding: "6px 10px !important",
},
"&:first-of-type": {
paddingLeft: "12px !important",
},
"&:last-of-type": {
paddingRight: "12px !important",
},
}));
export default MythicStyledTableCell;
@@ -17,20 +17,31 @@ const Root = styled('div')(({theme}) => ({
const ValidationTextField = styled(TextField)(({theme}) => ({
[`&.${classes.textFieldRoot}`]: {
'& .MuiInputBase-root': {
backgroundColor: theme.palette.background.paper,
borderRadius: theme.shape.borderRadius,
},
'& fieldset': {
borderColor: 'grey',
borderColor: theme.borderColor,
borderWidth: 1,
},
'&:hover fieldset': {
borderColor: theme.palette.text.secondary,
},
'& .Mui-focused fieldset': {
borderColor: `${theme.palette.primary.main} !important`,
borderWidth: '1px !important',
},
'& input:invalid + fieldset': {
borderColor: 'red',
borderColor: theme.palette.error.main,
borderWidth: 2,
},
'& input:valid:focus + fieldset': {
borderLeftWidth: 6,
borderLeftWidth: 2,
padding: '4px !important', // override inline-style
},
'& textarea:focus + textarea + fieldset': {
borderLeftWidth: 6,
borderLeftWidth: 2,
//padding: '4px !important', // override inline-style
},
},
@@ -92,14 +92,16 @@ const openedMixin = (theme) => ({
overflowX: 'hidden',
borderRadius: "0 !important",
border: "0px !important",
backgroundColor: "unset !important",
background: `${theme.navigation.background} !important`,
backgroundColor: `${theme.navigation.backgroundColor} !important`,
});
const closedMixin = (theme) => ({
overflowX: 'hidden',
width: `calc(${theme.spacing(4)} + 1px)`,
borderRadius: "0 !important",
border: "0px !important",
backgroundColor: "unset !important",
background: `${theme.navigation.background} !important`,
backgroundColor: `${theme.navigation.backgroundColor} !important`,
[theme.breakpoints.up('sm')]: {
width: `calc(${theme.spacing(5)} + 1px)`,
borderRadius: "0 !important",
@@ -112,18 +114,25 @@ const Drawer = styled(MuiDrawer, { shouldForwardProp: (prop) => prop !== 'open'
flexShrink: 0,
whiteSpace: 'nowrap',
boxSizing: 'border-box',
background: `linear-gradient(180deg, ${theme.topAppBarColor}, ${theme.topAppBarBottomColor}) !important`,
backgroundColor: `unset !important`,
background: `${theme.navigation.background} !important`,
backgroundColor: `${theme.navigation.backgroundColor} !important`,
color: theme.navigation.text,
'& .MuiDrawer-paper': {
border: "0 !important",
borderRight: "0 !important",
borderRadius: "0 !important",
boxShadow: "none !important",
},
'& .MuiList-root': {
border: "0 !important",
borderRadius: "0 !important",
},
[`& .${classes.listSubHeader}`]: {
//color: ` ${theme.navBarTextIconColor} !important`,
//backgroundColor: `${theme.topAppBarColor} !important`,
backgroundColor: "unset !important",
backgroundColor: "transparent !important",
},
[`& .${classes.listSubHeader}:hover`]: {
//backgroundColor: `${theme.topAppBarColor} !important`,
filter: `brightness(90%)`,
color: `${theme.navBarTextIconColor} !important`,
backgroundColor: "unset !important",
color: `${theme.navigation.text} !important`,
backgroundColor: `${theme.navigation.hover} !important`,
},
variants: [
{
@@ -132,9 +141,16 @@ const Drawer = styled(MuiDrawer, { shouldForwardProp: (prop) => prop !== 'open'
...openedMixin(theme),
'& .MuiDrawer-paper': {
...openedMixin(theme),
backgroundColor: "unset !important",
background: `${theme.navigation.background} !important`,
backgroundColor: `${theme.navigation.backgroundColor} !important`,
border: "0 !important",
borderRight: "0 !important",
borderRadius: "0 !important",
boxShadow: "none !important",
'& .MuiList-root': {
backgroundColor: "unset !important",
backgroundColor: "transparent !important",
border: "0 !important",
borderRadius: "0 !important",
}
},
},
@@ -145,9 +161,16 @@ const Drawer = styled(MuiDrawer, { shouldForwardProp: (prop) => prop !== 'open'
...closedMixin(theme),
'& .MuiDrawer-paper': {
...closedMixin(theme),
backgroundColor: "unset !important",
background: `${theme.navigation.background} !important`,
backgroundColor: `${theme.navigation.backgroundColor} !important`,
border: "0 !important",
borderRight: "0 !important",
borderRadius: "0 !important",
boxShadow: "none !important",
'& .MuiList-root': {
backgroundColor: "unset !important",
backgroundColor: "transparent !important",
border: "0 !important",
borderRadius: "0 !important",
}
},
},
@@ -157,13 +180,22 @@ const Drawer = styled(MuiDrawer, { shouldForwardProp: (prop) => prop !== 'open'
);
export const StyledListItem = styled(ListItem)(
({ theme }) => ({
paddingTop: "2px",
paddingLeft: "10px",
paddingRight: "10px",
marginTop: 0,
paddingBottom: "2px",
color: theme.navBarTextColor,
backgroundColor: "unset !important",
minHeight: "34px",
paddingTop: "4px",
paddingLeft: "8px",
paddingRight: "8px",
margin: "2px 4px",
paddingBottom: "4px",
borderRadius: theme.shape.borderRadius,
color: theme.navigation.text,
backgroundColor: "transparent !important",
"& .MuiListItemText-primary": {
fontSize: theme.typography.pxToRem(12.5),
fontWeight: 600,
},
"&:hover": {
backgroundColor: `${theme.navigation.hover} !important`,
},
}),
);
export const StyledListItemIcon = styled(ListItemIcon)(
@@ -171,9 +203,10 @@ export const StyledListItemIcon = styled(ListItemIcon)(
paddingTop:0,
marginTop: 0,
paddingBottom: 0,
minWidth: "45px",
//color: theme.navBarTextIconColor,
backgroundColor: "unset !important",
minWidth: "32px",
justifyContent: "center",
color: theme.navigation.icon,
backgroundColor: "transparent !important",
}),
);
@@ -758,33 +791,33 @@ export function TopAppBarVertical(props) {
<>
{me?.user?.current_operation_id ? (<EventFeedNotifications me={me} />) : null }
<Drawer anchor="left" variant="permanent" open={menuOpen} onClose={handleDrawerClose}
style={{borderRight: "1px solid grey !important", backgroundColor: "unset !important"
}}>
PaperProps={{sx: {border: "0 !important", borderRight: "0 !important", borderRadius: "0 !important", boxShadow: "none !important"}}}
style={{background: theme.navigation.background, backgroundColor: theme.navigation.backgroundColor}}>
<List style={{paddingTop: 0, marginTop: 0, height: "100%", display: "flex", flexDirection: "column",
backgroundColor: "unset !important",
borderBottom: "unset !important", borderLeft: "unset !important", borderTop: "unset !important"}}>
<ListItem className={classes.listSubHeader} style={{marginTop:0, paddingTop: 0, paddingLeft: "2px", paddingBottom: 0}}>
backgroundColor: "transparent !important",
border: "0 !important", borderRadius: 0}}>
<ListItem className={classes.listSubHeader} style={{margin: "4px 4px 6px", paddingTop: "5px", paddingLeft: "4px", paddingBottom: "5px", borderRadius: theme.shape.borderRadius}}>
<ListItemIcon >
<img src={ReactLogo} onClick={()=>navigate('/new')} width={"40px"} height={"35px"}/>
<img src={ReactLogo} onClick={()=>navigate('/new')} width={"40px"} height={"35px"} alt="Mythic" style={{cursor: "pointer"}}/>
</ListItemIcon>
<ListItemText style={{margin: 0}} primary={
<>
<Typography style={{ fontSize: 12, color: theme.navBarTextColor, display: "inline-block"}}>
<Typography style={{ fontSize: 12, color: theme.navigation.muted, display: "inline-block", lineHeight: 1.35}}>
<b>Mythic:</b> v{serverVersion}<br/>
<b>UI:</b> v{mythicUIVersion}<br/>
</Typography>
<IconButton onClick={props.toggleTheme} style={{float:"right", display: menuOpen ? "" : "none"}} >
<IconButton onClick={props.toggleTheme} style={{float:"right", display: menuOpen ? "" : "none", color: theme.navigation.icon}} >
{theme.palette.mode === 'light' &&
<DarkModeTwoToneIcon style={{color: "#2f0e67"}} fontSize={"medium"} className="mythicElement" />
<DarkModeTwoToneIcon style={{color: theme.navigation.icon}} fontSize={"medium"} className="mythicElement" />
}
{theme.palette.mode === 'dark' &&
<LightModeTwoToneIcon style={{color: '#eacc1b'}} fontSize={"medium"} className="mythicElement" />
<LightModeTwoToneIcon style={{color: theme.palette.warning.main}} fontSize={"medium"} className="mythicElement" />
}
</IconButton>
</>
} />
</ListItem>
<StyledListItem className={classes.listSubHeader} onClick={toggleDrawerOpen} style={{height: "30px"}} >
<StyledListItem className={classes.listSubHeader} onClick={toggleDrawerOpen} style={{height: "32px"}} >
<StyledListItemIcon ><MenuIcon style={{color: theme.navBarTextIconColor}} onClick={toggleDrawerOpen} fontSize={"medium"} className="mythicElement" /></StyledListItemIcon>
<ListItemText primary={
<>
@@ -815,10 +848,10 @@ export function TopAppBarVertical(props) {
} />
</StyledListItem>
<Divider style={{borderColor: "white"}} />
<Divider style={{borderColor: theme.navigation.muted, margin: "4px 8px"}} />
<div style={{flexGrow: 1, overflowY: "auto", overflowX: "hidden"}}>
{getShortcuts({shortcuts: sideShortcuts})}
<Divider style={{borderColor: "white"}} />
<Divider style={{borderColor: theme.navigation.muted, margin: "4px 8px"}} />
<StyledListItem className={classes.listSubHeader} onClick={handleToggleExtra}>
<StyledListItemIcon>
<MoreHorizIcon style={{color: theme.navBarTextIconColor}} fontSize={"medium"} />
@@ -827,7 +860,7 @@ export function TopAppBarVertical(props) {
{openExtra ? <ExpandLess /> : <ExpandMore />}
</StyledListItem>
{openExtra && getExtraShortcuts()}
<Divider style={{borderColor: "white"}} />
<Divider style={{borderColor: theme.navigation.muted, margin: "4px 8px"}} />
<div className={classes.listSubHeader} style={{ flexGrow: 1}}></div>
</div>
<TopBarRightShortcutsVertical me={me} menuOpen={menuOpen} serverName={serverName} />
@@ -1044,4 +1077,4 @@ function TopBarRightShortcutsVertical({me, menuOpen, serverName}){
</StyledListItem>
</>
)
}
}
@@ -11,6 +11,7 @@ import {reorder} from "../../MythicComponents/MythicDraggableList";
import Paper from '@mui/material/Paper';
import IconButton from '@mui/material/IconButton';
import {MythicStyledTooltip} from "../../MythicComponents/MythicStyledTooltip";
import {useTheme} from '@mui/material/styles';
export const getCallbackIdFromClickedTab = (tabId) => {
if(tabId === null || tabId === undefined){return 0}
@@ -32,6 +33,7 @@ export const getCallbackIdFromClickedTab = (tabId) => {
}
export function Callbacks({me}) {
const theme = useTheme();
const [openCallbackImport, setOpenCallbackImport] = React.useState(false);
const [topDisplay, setTopDisplay] = React.useState('table');
const [newDataForTab, setNewDataForTab] = React.useState({});
@@ -216,8 +218,18 @@ export function Callbacks({me}) {
onDragEnd={(sizes) => localStorage.setItem('callbackTableSplitSizes', JSON.stringify(sizes))}
style={{ height: "100%" }}>
<div style={{display: "flex", flexDirection: "row-reverse"}}>
<Paper elevation={5} style={{width: "30px", display: "flex", flexDirection: "column", alignItems: "center", overflow: "hidden",
backgroundColor: "transparent"}}>
<Paper elevation={0} style={{
width: "34px",
display: "flex",
flexDirection: "column",
alignItems: "center",
overflow: "hidden",
backgroundColor: theme.palette.background.paper,
border: `1px solid ${theme.borderColor}`,
borderRight: 0,
borderRadius: `${theme.shape.borderRadius}px 0 0 ${theme.shape.borderRadius}px`,
paddingTop: "3px",
}}>
{topDisplay !== 'table' &&
<MythicStyledTooltip title={"Table View"}>
<IconButton onClick={() =>setTopDisplay("table")}>
@@ -270,4 +282,4 @@ export function Callbacks({me}) {
</Split>
</>
);
}
}
@@ -10,15 +10,17 @@ 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 {isValidHexColor, MythicColorSwatchInput} from '../../MythicComponents/MythicColorInput';
export function CallbacksTableEditDescriptionColorDialog(props) {
const [comment, setComment] = React.useState("");
const [color, setColor] = React.useState("");
const theme = useTheme();
const onCommitSubmit = () => {
if(color === "ffffff" || color === "000000"){
const normalizedColor = color?.toLowerCase() || "";
if(normalizedColor === "" || normalizedColor === "ffffff" || normalizedColor === "#ffffff" ||
normalizedColor === "000000" || normalizedColor === "#000000"){
props.onSubmit(comment, "");
} else {
props.onSubmit(comment, color);
@@ -39,6 +41,8 @@ export function CallbacksTableEditDescriptionColorDialog(props) {
}
setColor(props.color);
}, [props.description, props.color]);
const previewColor = isValidHexColor(color) ? color : "";
const previewBorder = previewColor === "" ? "1px dashed" : `2px solid ${previewColor}`;
return (
<React.Fragment>
<DialogTitle id="form-dialog-title">{props.title}</DialogTitle>
@@ -61,14 +65,62 @@ export function CallbacksTableEditDescriptionColorDialog(props) {
showInvisibles: false,
}}
/>
<HexColorPicker color={color} onChange={setColor} style={{width: "100%"}} />
<HexColorInput color={color} onChange={setColor} style={{width: "80%"}} />
<Button onClick={()=>setColor("ffffff")} color={"success"}>
Clear
</Button>
<Box sx={{width: "100%", height: 25, backgroundColor: color}} >
<Typography style={{color: "white", display: "inline-block", marginRight: "10px"}}>DarkMode Text With Color Background</Typography>
<Typography style={{color: "black", display: "inline-block"}}>LightMode Text With Color Background</Typography>
<Box sx={{p: 1.5, borderTop: "1px solid", borderColor: "divider", backgroundColor: "background.paper"}}>
<Box
sx={{
p: 1.5,
border: "1px solid",
borderColor: "divider",
borderRadius: "8px",
}}
>
<Box sx={{display: "flex", alignItems: "center", justifyContent: "space-between", gap: 2, mb: 1}}>
<Box sx={{minWidth: 0}}>
<Typography variant="body2" sx={{fontWeight: 700}}>Callback Color</Typography>
<Typography variant="caption" sx={{color: "text.secondary"}}>Callback row and tasking accent</Typography>
</Box>
<Box sx={{display: "flex", alignItems: "center", gap: 1, flexWrap: "wrap", justifyContent: "flex-end"}}>
<MythicColorSwatchInput
color={isValidHexColor(color) ? color : "#000000"}
label="Callback color"
onChange={setColor}
/>
<Button onClick={() => setColor("")} color="success" variant="outlined" size="small">
Clear
</Button>
</Box>
</Box>
<Box sx={{display: "grid", gridTemplateColumns: {xs: "1fr", sm: "1fr 1fr"}, gap: 1}}>
<Box
sx={{
minHeight: 40,
px: 1.5,
display: "flex",
alignItems: "center",
borderRadius: "6px",
border: previewBorder,
borderColor: previewColor === "" ? "divider" : previewColor,
backgroundColor: "#1f2937",
}}
>
<Typography sx={{color: "#ffffff", fontWeight: 700}}>Dark callback row</Typography>
</Box>
<Box
sx={{
minHeight: 40,
px: 1.5,
display: "flex",
alignItems: "center",
borderRadius: "6px",
border: previewBorder,
borderColor: previewColor === "" ? "divider" : previewColor,
backgroundColor: "#f8fafc",
}}
>
<Typography sx={{color: "#111827", fontWeight: 700}}>Light callback row</Typography>
</Box>
</Box>
</Box>
</Box>
</DialogContent>
<DialogActions>
@@ -83,4 +135,4 @@ export function CallbacksTableEditDescriptionColorDialog(props) {
</DialogActions>
</React.Fragment>
);
}
}
@@ -3,6 +3,7 @@ import TableCell from '@mui/material/TableCell';
import TableRow from '@mui/material/TableRow';
import Table from '@mui/material/Table';
import TableBody from '@mui/material/TableBody';
import TableContainer from '@mui/material/TableContainer';
import TableHead from '@mui/material/TableHead';
import Typography from '@mui/material/Typography';
import {useQuery, gql, useMutation} from '@apollo/client';
@@ -346,6 +347,7 @@ export function DetailedCallbackTable(props){
Payload Information
</Typography>
</Paper>
<TableContainer className="mythicElement">
<Table size="small" aria-label="details" style={{ "overflowWrap": "break-word"}}>
<TableHead>
<TableRow hover>
@@ -451,11 +453,13 @@ export function DetailedCallbackTable(props){
}
</TableBody>
</Table>
</TableContainer>
<Paper elevation={5} style={{backgroundColor: theme.pageHeader.main, color: theme.pageHeaderText.main,marginBottom: "5px", marginTop: "10px"}} variant={"elevation"}>
<Typography variant="h6" style={{textAlign: "left", display: "inline-block", marginLeft: "20px", color: theme.pageHeaderColor}}>
Build Parameters
</Typography>
</Paper>
<TableContainer className="mythicElement">
<Table size="small" aria-label="details" style={{ "overflowWrap": "break-word"}}>
<TableHead>
<TableRow>
@@ -491,11 +495,13 @@ export function DetailedCallbackTable(props){
}
</TableBody>
</Table>
</TableContainer>
<Paper elevation={5} style={{backgroundColor: theme.pageHeader.main, color: theme.pageHeaderText.main,marginBottom: "5px", marginTop: "10px"}} variant={"elevation"}>
<Typography variant="h6" style={{textAlign: "left", display: "inline-block", marginLeft: "20px", color: theme.pageHeaderColor}}>
Build Steps
</Typography>
</Paper>
<TableContainer className="mythicElement">
<Table size="small" aria-label="details" style={{ "overflowWrap": "break-word"}}>
<TableHead>
<TableRow>
@@ -521,6 +527,7 @@ export function DetailedCallbackTable(props){
}
</TableBody>
</Table>
</TableContainer>
{ c2Profiles.map( (c2) => (
<React.Fragment key={"c2frag" + data.callback_by_pk.payload.id + c2.c2_profile}>
<Paper elevation={5} style={{backgroundColor: theme.pageHeader.main, color: theme.pageHeaderText.main,marginBottom: "5px", marginTop: "10px"}} variant={"elevation"}>
@@ -528,6 +535,7 @@ export function DetailedCallbackTable(props){
{c2.c2_profile}
</Typography>
</Paper>
<TableContainer className="mythicElement">
<Table size="small" aria-label="details" style={{"overflowWrap": "break-word"}}>
<TableHead>
<TableRow>
@@ -554,6 +562,7 @@ export function DetailedCallbackTable(props){
}
</TableBody>
</Table>
</TableContainer>
</React.Fragment>
))}
<Paper elevation={5} style={{backgroundColor: theme.pageHeader.main, color: theme.pageHeaderText.main,marginBottom: "5px", marginTop: "10px"}} variant={"elevation"}>
@@ -563,6 +572,7 @@ export function DetailedCallbackTable(props){
</Typography>
<Button style={{float: "right"}} variant="contained" size="small" onClick={()=>{setOpenAddRemoveCommandsDialog(true)}} >Add/Remove Commands</Button>
</Paper>
<TableContainer className="mythicElement">
<Table size="small" aria-label="details" style={{"overflowWrap": "break-word"}}>
<TableHead>
<TableRow>
@@ -638,6 +648,7 @@ export function DetailedCallbackTable(props){
}
</TableBody>
</Table>
</TableContainer>
</DialogContent>
<DialogActions>
<Button onClick={props.onClose} variant="contained" color="primary">
@@ -647,4 +658,3 @@ export function DetailedCallbackTable(props){
</React.Fragment>
)
}
@@ -2,6 +2,7 @@ import React from 'react';
import TableRow from '@mui/material/TableRow';
import Table from '@mui/material/Table';
import TableBody from '@mui/material/TableBody';
import TableContainer from '@mui/material/TableContainer';
import TableHead from '@mui/material/TableHead';
import {useQuery, gql, useMutation} from '@apollo/client';
import FormControl from '@mui/material/FormControl';
@@ -122,6 +123,7 @@ export function ModifyCallbackMythicTreeGroupsDialog(props){
<b>Note:</b> Having <b>no</b> group entries will hide all information from this callback from your FileBrowser and ProcessBrowser views.
</div>
<DialogContent dividers={true}>
<TableContainer className="mythicElement">
<Table size="small" aria-label="details" style={{ "overflowWrap": "break-word"}}>
<TableHead>
</TableHead>
@@ -167,6 +169,7 @@ export function ModifyCallbackMythicTreeGroupsDialog(props){
</TableBody>
</Table>
</TableContainer>
</DialogContent>
<DialogActions>
<Button onClick={props.onClose} variant="contained" color="primary">
@@ -190,4 +193,3 @@ export function ModifyCallbackMythicTreeGroupsDialog(props){
</React.Fragment>
)
}
@@ -49,7 +49,7 @@ import CodeIcon from '@mui/icons-material/Code';
import DownloadIcon from '@mui/icons-material/Download';
import {b64DecodeUnicode} from "./ResponseDisplay";
import {MythicDialog, TableRowSizeCell} from "../../MythicComponents/MythicDialog";
import {Table, TableHead, TableRow, TableBody, TableCell, Paper} from '@mui/material';
import {Table, TableContainer, TableHead, TableRow, TableBody, TableCell, Paper} from '@mui/material';
import MythicStyledTableCell from "../../MythicComponents/MythicTableCell";
import WarningOutlinedIcon from '@mui/icons-material/WarningOutlined';
import {TagsDisplay, ViewEditTags} from "../../MythicComponents/MythicTag";
@@ -376,6 +376,7 @@ export const DisplayMedia = ({agent_file_id, filename, expand, task, fileMetaDat
const MaxRenderSize = 2000000; // 2MB
const DisplayFileMetaData = ({fileMetaData}) => {
return (
<TableContainer className="mythicElement">
<Table style={{marginLeft: "0px", width: "100%", tableLayout: "fixed"}}>
<TableHead>
<TableRow>
@@ -423,6 +424,7 @@ const DisplayFileMetaData = ({fileMetaData}) => {
</TableRow>
</TableBody>
</Table>
</TableContainer>
)
}
const DisplayText = ({agent_file_id, expand, filename, preview, fileMetaData}) => {
@@ -895,6 +897,7 @@ const DisplayDatabaseResult = ({result}) => {
const [columns, setColumns] = React.useState(result.columns);
const [rows, setRows] = React.useState(result.values?.slice(0, MAX_ROWS));
return (
<TableContainer className="mythicElement" style={{height: "100%", position: "relative"}}>
<Table stickyHeader style={{width: "100%", height: "100%", position: "absolute"}}>
<TableHead >
<TableRow>
@@ -915,5 +918,6 @@ const DisplayDatabaseResult = ({result}) => {
))}
</TableBody>
</Table>
</TableContainer>
)
}
}
@@ -60,12 +60,14 @@ export const StyledPaper = styled(Paper)((
}
) => ({
[`&.${classes.root}`]: {
marginTop: "3px",
marginTop: "4px",
marginRight: "0px",
height: "auto",
width: "100%",
boxShadow: "unset",
backgroundColor: theme.palette.background.default + "CC",
backgroundColor: theme.palette.background.paper,
border: `1px solid ${theme.borderColor}`,
borderRadius: theme.shape.borderRadius,
},
[`& .${classes.heading}`]: {
@@ -235,8 +237,8 @@ const ColoredTaskDisplay = ({task, theme, children, expanded}) => {
}, [task.status, task.completed])
return(
<span style={{display: "flex", margin: 0, borderWidth: 0, padding: 0, minHeight: "48px", alignItems: "center",
height: "100%", borderLeft: "6px solid " + themeColor, paddingLeft: "5px", width: "100%", maxWidth: "100%",
borderTopLeftRadius: "4px", borderBottomLeftRadius: expanded ? 0 : "4px"}}>
height: "100%", borderLeft: "4px solid " + themeColor, paddingLeft: "7px", width: "100%", maxWidth: "100%",
borderTopLeftRadius: theme.shape.borderRadius, borderBottomLeftRadius: expanded ? 0 : theme.shape.borderRadius}}>
{children}
</span>
)
@@ -1008,7 +1008,7 @@ export function TaskParametersDialog(props) {
}
</Typography>
<TableContainer>
<TableContainer className="mythicElement">
<Table size="small" style={{"tableLayout": "fixed", "maxWidth": "100%", "overflow": "scroll"}}>
<TableHead>
<TableRow>
@@ -1044,4 +1044,3 @@ export function TaskParametersDialog(props) {
</React.Fragment>
);
}
@@ -801,7 +801,7 @@ export function TaskParametersDialogRow(props){
)
case "Array":
return (
<TableContainer >
<TableContainer className="mythicElement">
<Table size="small" style={{tableLayout: "fixed", maxWidth: "100%", "overflow": "auto"}}>
<TableBody>
<TableRow>
@@ -846,7 +846,7 @@ export function TaskParametersDialogRow(props){
)
case "TypedArray":
return (
<TableContainer >
<TableContainer className="mythicElement">
<Table size="small" style={{tableLayout: "fixed", maxWidth: "100%", "overflow": "auto"}}>
<TableBody>
<TableRow>
@@ -3,6 +3,7 @@ import TableRow from '@mui/material/TableRow';
import Table from '@mui/material/Table';
import TableCell from '@mui/material/TableCell';
import TableBody from '@mui/material/TableBody';
import TableContainer from '@mui/material/TableContainer';
import TableHead from '@mui/material/TableHead';
import {useQuery, gql} from '@apollo/client';
import DialogActions from '@mui/material/DialogActions';
@@ -111,6 +112,7 @@ export function ViewCallbackMythicTreeGroupsDialog(props){
<Backdrop open={backdropOpen} style={{zIndex: 2, position: "absolute"}} invisible={false}>
<CircularProgress color="inherit" />
</Backdrop>
<TableContainer className="mythicElement">
<Table stickyHeader={true} size="small" style={{ "overflowWrap": "break-word", width: "100%"}}>
<TableHead>
<TableRow>
@@ -154,6 +156,7 @@ export function ViewCallbackMythicTreeGroupsDialog(props){
))}
</TableBody>
</Table>
</TableContainer>
</DialogContent>
<DialogActions>
<Button onClick={props.onClose} variant="contained" color="primary">
@@ -240,6 +243,7 @@ export function ViewAllCallbackMythicTreeGroupsDialog(props){
{g.group}
</Typography>
</Paper>
<TableContainer className="mythicElement">
<Table size="small" aria-label="details" style={{ "overflowWrap": "break-word", width: "100%"}}>
<TableHead>
<TableRow>
@@ -283,6 +287,7 @@ export function ViewAllCallbackMythicTreeGroupsDialog(props){
))}
</TableBody>
</Table>
</TableContainer>
</div>
))}
@@ -1,6 +1,7 @@
import React from 'react';
import Table from '@mui/material/Table';
import TableBody from '@mui/material/TableBody';
import TableContainer from '@mui/material/TableContainer';
import TableHead from '@mui/material/TableHead';
import TableRow from '@mui/material/TableRow';
import { CreatePayloadParameter } from './CreatePayloadParameter';
@@ -13,6 +14,7 @@ export function CreatePayloadC2ProfileParametersTable(props){
props.onChange(props.name, paramName, value, error);
}
return (
<TableContainer className="mythicElement">
<Table size="small" style={{"tableLayout": "fixed", "maxWidth": "calc(100vw)", "overflow": "auto"}}>
<TableHead>
<TableRow>
@@ -26,5 +28,6 @@ export function CreatePayloadC2ProfileParametersTable(props){
))}
</TableBody>
</Table>
</TableContainer>
);
}
@@ -586,7 +586,7 @@ export function CreatePayloadParameter({onChange, parameter_type, default_value,
);
case "Array":
return (
<TableContainer >
<TableContainer className="mythicElement">
<Table size="small" style={{tableLayout: "fixed", maxWidth: "100%", "overflow": "auto"}}>
<TableBody>
{arrayValue.map( (a, i) => (
@@ -616,7 +616,7 @@ export function CreatePayloadParameter({onChange, parameter_type, default_value,
);
case "TypedArray":
return (
<TableContainer >
<TableContainer className="mythicElement">
<Table size="small" style={{tableLayout: "fixed", maxWidth: "100%", "overflow": "auto"}}>
<TableBody>
{typedArrayValue.map( (a, i) => (
@@ -819,4 +819,3 @@ export function CreatePayloadParameter({onChange, parameter_type, default_value,
</TableRow>
)
}
@@ -8,6 +8,7 @@ import { snackActions } from '../../utilities/Snackbar';
import Table from '@mui/material/Table';
import TableBody from '@mui/material/TableBody';
import TableCell from '@mui/material/TableCell';
import TableContainer from '@mui/material/TableContainer';
import TableHead from '@mui/material/TableHead';
import TableRow from '@mui/material/TableRow';
import { meState } from '../../../cache';
@@ -199,7 +200,7 @@ export function PayloadSelect(props) {
props.finished(payload);
}
return (
<div style={{height: "100%", overflow: "auto"}}>
<TableContainer className="mythicElement" style={{height: "100%", overflow: "auto"}}>
<Table stickyHeader size="small" style={{tableLayout:"fixed", maxWidth: "100%",}}>
<TableHead>
<TableRow>
@@ -222,7 +223,7 @@ export function PayloadSelect(props) {
))}
</TableBody>
</Table>
</div>
</TableContainer>
);
}
@@ -262,4 +263,4 @@ export function PayloadsTableRow(props){
</TableRow>
</React.Fragment>
)
}
}
@@ -8,7 +8,7 @@ import DialogContent from '@mui/material/DialogContent';
import DeleteIcon from '@mui/icons-material/Delete';
import { useReactiveVar } from '@apollo/client';
import {meState} from "../../../cache";
import {Table, TableBody, TableHead, TableRow, Typography, IconButton, Paper, Switch} from '@mui/material';
import {Table, TableBody, TableContainer, TableHead, TableRow, Typography, IconButton, Paper, Switch} from '@mui/material';
import FormControl from '@mui/material/FormControl';
import MenuItem from '@mui/material/MenuItem';
import TextField from '@mui/material/TextField';
@@ -632,7 +632,7 @@ const CreateEventingStep1 = ({finished, back, first, last, cancel, prevData}) =>
}, [prevData]);
return (
<>
<div style={{flexGrow: 1, width: "100%", display: "flex", flexDirection: "column", overflowY: "auto"}}>
<TableContainer className="mythicElement" style={{flexGrow: 1, width: "100%", display: "flex", flexDirection: "column", overflowY: "auto"}}>
<Table style={{tableLayout: "fixed", width: "100%",}}>
<TableHead >
<TableRow>
@@ -742,7 +742,7 @@ const CreateEventingStep1 = ({finished, back, first, last, cancel, prevData}) =>
</TableRow>
</TableBody>
</Table>
</div>
</TableContainer>
<CreateEventingStepperNavigationButtons first={first} last={last} finished={finishedStep1} back={back} cancel={cancel} />
</>
)
@@ -8,6 +8,7 @@ import {useMutation, gql} from '@apollo/client';
import Table from '@mui/material/Table';
import TableBody from '@mui/material/TableBody';
import TableCell from '@mui/material/TableCell';
import TableContainer from '@mui/material/TableContainer';
import TableHead from '@mui/material/TableHead';
import TableRow from '@mui/material/TableRow';
@@ -64,6 +65,7 @@ export function EventGroupTableRunAsDialog({eventgroupapprovals, me, onClose, se
<b>Run As: </b>{selectedEventGroup.run_as} <br/>
{getRunAsHelp(selectedEventGroup.run_as)}
</DialogContentText>
<TableContainer className="mythicElement">
<Table>
<TableHead>
<TableRow>
@@ -126,6 +128,7 @@ export function EventGroupTableRunAsDialog({eventgroupapprovals, me, onClose, se
))}
</TableBody>
</Table>
</TableContainer>
</DialogContent>
<DialogActions>
@@ -136,4 +139,3 @@ export function EventGroupTableRunAsDialog({eventgroupapprovals, me, onClose, se
</React.Fragment>
);
}
@@ -7,6 +7,7 @@ import DialogTitle from '@mui/material/DialogTitle';
import {useMutation, gql} from '@apollo/client';
import Table from '@mui/material/Table';
import TableBody from '@mui/material/TableBody';
import TableContainer from '@mui/material/TableContainer';
import TableRow from '@mui/material/TableRow';
import {snackActions} from "../../utilities/Snackbar";
@@ -52,6 +53,7 @@ export function EventFileManageDialog({onClose, selectedEventGroup}) {
<DialogContentText>
These files can be accessed via `workflow.filename` in a step's inputs.
</DialogContentText>
<TableContainer className="mythicElement">
<Table>
<TableBody>
{selectedEventGroup.filemeta.map( e => (
@@ -59,6 +61,7 @@ export function EventFileManageDialog({onClose, selectedEventGroup}) {
))}
</TableBody>
</Table>
</TableContainer>
</DialogContent>
<DialogActions>
<Button onClick={onClose} variant="contained" color="primary">
@@ -127,4 +130,4 @@ function EventFileManageDialogTableRow({eventFile}) {
</MythicStyledTableCell>
</TableRow>
)
}
}
@@ -6,6 +6,7 @@ import DialogTitle from '@mui/material/DialogTitle';
import Table from '@mui/material/Table';
import TableBody from '@mui/material/TableBody';
import TableCell from '@mui/material/TableCell';
import TableContainer from '@mui/material/TableContainer';
import TableHead from '@mui/material/TableHead';
import TableRow from '@mui/material/TableRow';
@@ -22,6 +23,7 @@ export function EventGroupConsumingContainersDialog({onClose, selectedEventGroup
</DialogTitle>
<DialogContent dividers={true} style={{maxHeight: "calc(70vh)"}}>
<TableContainer className="mythicElement">
<Table>
<TableHead>
<TableRow>
@@ -37,6 +39,7 @@ export function EventGroupConsumingContainersDialog({onClose, selectedEventGroup
))}
</TableBody>
</Table>
</TableContainer>
</DialogContent>
<DialogActions>
<Button onClick={onClose} variant="contained" color="primary">
@@ -84,4 +87,4 @@ function EventGroupConsumingContainersDialogTableRow({container}) {
</MythicStyledTableCell>
</TableRow>
)
}
}
@@ -21,6 +21,7 @@ import AddCircleIcon from '@mui/icons-material/AddCircle';
import Table from '@mui/material/Table';
import TableBody from '@mui/material/TableBody';
import TableCell from '@mui/material/TableCell';
import TableContainer from '@mui/material/TableContainer';
import TableHead from '@mui/material/TableHead';
import TableRow from '@mui/material/TableRow';
import IconButton from '@mui/material/IconButton';
@@ -210,6 +211,7 @@ export function EventGroupTable({selectedEventGroup, me, showInstances, showGrap
)
}
<br/><Typography variant={"h8"}>{selectedEventGroup?.description}</Typography>
<TableContainer className="mythicElement">
<Table>
<TableHead>
<TableRow>
@@ -343,6 +345,7 @@ export function EventGroupTable({selectedEventGroup, me, showInstances, showGrap
</TableRow>
</TableBody>
</Table>
</TableContainer>
</div>
}
@@ -474,4 +477,4 @@ function RenderSteps({selectedEventGroup, selectedInstanceID}){
{getRenderer()}
</div>
)
}
}
@@ -31,6 +31,7 @@ import MythicTableCell from "../../MythicComponents/MythicTableCell";
import Table from '@mui/material/Table';
import TableBody from '@mui/material/TableBody';
import TableCell from '@mui/material/TableCell';
import TableContainer from '@mui/material/TableContainer';
import TableHead from '@mui/material/TableHead';
import TableRow from '@mui/material/TableRow';
import MythicStyledTableCell from "../../MythicComponents/MythicTableCell";
@@ -1106,6 +1107,7 @@ function EventStepInstanceDetailDialog({selectedEventStepInstance, onClose}) {
Original and Instance Metadata
</AccordionSummary>
<AccordionDetails style={{cursor: "default"}}>
<TableContainer className="mythicElement">
<Table style={{width: "100%", overflow: "auto", tableLayout: "fixed", }}>
<TableHead>
<TableRow>
@@ -1167,6 +1169,7 @@ function EventStepInstanceDetailDialog({selectedEventStepInstance, onClose}) {
</TableRow>
</TableBody>
</Table>
</TableContainer>
</AccordionDetails>
</Accordion>
</Paper>
@@ -1241,6 +1244,7 @@ function EventStepInstanceDetailDialog({selectedEventStepInstance, onClose}) {
Callbacks Generated
</Typography>
</Paper>
<TableContainer className="mythicElement">
<Table>
<TableBody>
{data.eventstepinstance_by_pk.callbacks.map(trackedData => (
@@ -1253,6 +1257,7 @@ function EventStepInstanceDetailDialog({selectedEventStepInstance, onClose}) {
))}
</TableBody>
</Table>
</TableContainer>
</>
}
<EventDetailsFilesTable files={data.eventstepinstance_by_pk.filemeta} />
@@ -1265,6 +1270,7 @@ function EventStepInstanceDetailDialog({selectedEventStepInstance, onClose}) {
API Tokens generated
</Typography>
</Paper>
<TableContainer className="mythicElement">
<Table>
<TableHead>
<TableRow>
@@ -1287,6 +1293,7 @@ function EventStepInstanceDetailDialog({selectedEventStepInstance, onClose}) {
))}
</TableBody>
</Table>
</TableContainer>
</>
}
</DialogContent>
@@ -1395,6 +1402,7 @@ function EventGroupInstanceDetailDialog({selectedEventGroupInstance, onClose}) {
Callbacks Generated
</Typography>
</Paper>
<TableContainer className="mythicElement">
<Table>
<TableBody>
{data.callback.map(trackedData => (
@@ -1410,6 +1418,7 @@ function EventGroupInstanceDetailDialog({selectedEventGroupInstance, onClose}) {
))}
</TableBody>
</Table>
</TableContainer>
</>
}
<EventDetailsFilesTable files={data?.filemeta} />
@@ -1422,6 +1431,7 @@ function EventGroupInstanceDetailDialog({selectedEventGroupInstance, onClose}) {
API Tokens generated
</Typography>
</Paper>
<TableContainer className="mythicElement">
<Table>
<TableHead>
<TableRow>
@@ -1444,6 +1454,7 @@ function EventGroupInstanceDetailDialog({selectedEventGroupInstance, onClose}) {
))}
</TableBody>
</Table>
</TableContainer>
</>
}
@@ -1518,6 +1529,7 @@ function EventStepDetailDialog({selectedEventStep, onClose}) {
variant={'h5'} component={Paper} >
Action: <b>{data.eventstep_by_pk.action}</b>
</Typography>
<TableContainer className="mythicElement">
<Table style={{width: "100%", overflow: "auto", tableLayout: "fixed"}}>
<TableHead>
<TableRow>
@@ -1564,6 +1576,7 @@ function EventStepDetailDialog({selectedEventStep, onClose}) {
</TableRow>
</TableBody>
</Table>
</TableContainer>
</DialogContent>
<DialogActions>
<Button onClick={onClose} variant="contained" color="primary">
@@ -1630,6 +1643,7 @@ function EventDetailsPayloadsTable({payloads, deletePayload}){
<ArchiveIcon/>Zip & Download All Available Payloads
</Button>
</Paper>
<TableContainer className="mythicElement">
<Table>
<TableBody>
{openDelete &&
@@ -1674,6 +1688,7 @@ function EventDetailsPayloadsTable({payloads, deletePayload}){
))}
</TableBody>
</Table>
</TableContainer>
</>
)
}
@@ -1687,6 +1702,7 @@ function EventDetailsTaskTable({tasks}){
Tasks Issued
</Typography>
</Paper>
<TableContainer className="mythicElement">
<Table>
<TableBody>
{tasks.map(trackedData => (
@@ -1713,6 +1729,7 @@ function EventDetailsTaskTable({tasks}){
))}
</TableBody>
</Table>
</TableContainer>
</>
)
}
@@ -1757,6 +1774,7 @@ function EventDetailsFilesTable({files}){
<ArchiveIcon/>Zip & Download All Files
</Button>
</Paper>
<TableContainer className="mythicElement">
<Table>
<TableHead>
<TableRow>
@@ -1794,6 +1812,7 @@ function EventDetailsFilesTable({files}){
))}
</TableBody>
</Table>
</TableContainer>
</>
)
}
@@ -8,6 +8,7 @@ import {useMutation,useQuery, gql} from '@apollo/client';
import Table from '@mui/material/Table';
import TableBody from '@mui/material/TableBody';
import TableCell from '@mui/material/TableCell';
import TableContainer from '@mui/material/TableContainer';
import TableHead from '@mui/material/TableHead';
import TableRow from '@mui/material/TableRow';
import {IconButton} from '@mui/material';
@@ -223,6 +224,7 @@ export function EventTriggerContextSelectDialog({onClose, triggerContext}) {
{selectedEventGroup.id !== 0 &&
<EventGroupTable me={me} selectedEventGroup={selectedEventGroup} showInstances={false} showGraph={false} height={"unset"}/>
}
<TableContainer className="mythicElement">
<Table>
<TableHead>
<TableRow>
@@ -269,6 +271,7 @@ export function EventTriggerContextSelectDialog({onClose, triggerContext}) {
</TableRow>
</TableBody>
</Table>
</TableContainer>
</DialogContent>
<DialogActions>
@@ -281,4 +284,4 @@ export function EventTriggerContextSelectDialog({onClose, triggerContext}) {
</DialogActions>
</React.Fragment>
);
}
}
@@ -8,6 +8,7 @@ import {useMutation, gql} from '@apollo/client';
import Table from '@mui/material/Table';
import TableBody from '@mui/material/TableBody';
import TableCell from '@mui/material/TableCell';
import TableContainer from '@mui/material/TableContainer';
import TableHead from '@mui/material/TableHead';
import TableRow from '@mui/material/TableRow';
import {IconButton} from '@mui/material';
@@ -120,6 +121,7 @@ export function EventTriggerKeywordDialog({onClose, selectedEventGroup}) {
))
}
</Select>
<TableContainer className="mythicElement">
<Table>
<TableHead>
<TableRow>
@@ -166,6 +168,7 @@ export function EventTriggerKeywordDialog({onClose, selectedEventGroup}) {
</TableRow>
</TableBody>
</Table>
</TableContainer>
</DialogContent>
<DialogActions>
@@ -178,4 +181,4 @@ export function EventTriggerKeywordDialog({onClose, selectedEventGroup}) {
</DialogActions>
</React.Fragment>
);
}
}
@@ -2,6 +2,7 @@ import React, {useEffect} from 'react';
import Table from '@mui/material/Table';
import TableBody from '@mui/material/TableBody';
import TableCell from '@mui/material/TableCell';
import TableContainer from '@mui/material/TableContainer';
import TableHead from '@mui/material/TableHead';
import TableRow from '@mui/material/TableRow';
import Paper from '@mui/material/Paper';
@@ -56,6 +57,7 @@ export function ExpandedCallbackSideDetailsTable(props){
updateSleep({variables: {callback_display_id: callback_display_id, sleep_info}})
}, [])
return (
<TableContainer className="mythicElement">
<Table size="small" style={{tableLayout: "fixed"}}>
<TableHead>
<TableRow>
@@ -220,5 +222,6 @@ export function ExpandedCallbackSideDetailsTable(props){
</TableRow>
</TableBody>
</Table>
</TableContainer>
)
}
@@ -10,6 +10,7 @@ import {Gauge, GaugeContainer,
GaugeReferenceArc,
useGaugeState} from '@mui/x-charts/Gauge';
import Table from '@mui/material/Table';
import TableContainer from '@mui/material/TableContainer';
import { BarChart } from '@mui/x-charts/BarChart';
import {MythicStyledTooltip} from "../../MythicComponents/MythicStyledTooltip";
import DeleteIcon from '@mui/icons-material/Delete';
@@ -53,7 +54,7 @@ export const PieChartCard = ({
width: width,
height: "100%",
border: `1px solid ${theme.borderColor}`,
borderRadius: "5px",
borderRadius: theme.shape.borderRadius,
overflow: "hidden",
}}>
<h3 style={{marginTop: 0, marginLeft: "0.5rem", marginBottom: 0, paddingBottom: 0,}}>
@@ -172,7 +173,7 @@ export const GaugeCard = ({data, width = "100%", additionalStyles, innerElement,
width: width,
height: "100%",
border: `1px solid ${theme.borderColor}`,
borderRadius: "5px",
borderRadius: theme.shape.borderRadius,
overflow: "hidden",
}}>
<h3 style={{marginTop: 0, marginLeft: "0.5rem", marginBottom: 0, paddingBottom: 0,}}>
@@ -221,7 +222,7 @@ export const CallbackDataCard = ({mainTitle, secondTitle, mainElement, secondary
width: width,
height: "100%",
border: `1px solid ${theme.borderColor}`,
borderRadius: "5px",
borderRadius: theme.shape.borderRadius,
overflow: "hidden",
}} >
<h2 style={{marginTop: 0, marginLeft: "0.5rem", marginBottom: 0, paddingBottom: 0}}>
@@ -256,7 +257,7 @@ export const TableDataCard = ({title, width = "100%", tableHead, tableBody, edit
width: width,
height: "100%",
border: `1px solid ${theme.borderColor}`,
borderRadius: "5px",
borderRadius: theme.shape.borderRadius,
overflow: "hidden",
}}>
<h3 style={{marginTop: 0, marginLeft: "0.5rem", marginBottom: 0, paddingBottom: 0}}>
@@ -274,12 +275,12 @@ export const TableDataCard = ({title, width = "100%", tableHead, tableBody, edit
{customizeElement}
</span>
</h3>
<div style={{height: 200, overflowY: "auto", width: "100%"}}>
<TableContainer className="mythicElement" style={{height: 200, overflowY: "auto", width: "100%"}}>
<Table style={{ maxWidth: "100%", overflow: "auto"}} stickyHeader size="small">
{tableHead}
{tableBody}
</Table>
</div>
</TableContainer>
</Paper>
)
}
@@ -319,7 +320,7 @@ export const LineTimeChartCard = ({data, additionalStyles}) => {
width: "100%",
height: "100%",
border: `1px solid ${theme.borderColor}`,
borderRadius: "5px",
borderRadius: theme.shape.borderRadius,
overflow: "hidden",
}} >
<Typography variant={"h3"} style={{margin: 0, padding: 0, position: "relative", left: "30%"}}>
@@ -434,7 +435,7 @@ export const LineTimeMultiChartCard = ({data, additionalStyles, colors=normalCol
marginRight: "0.5rem",
height: "100%",
border: `1px solid ${theme.borderColor}`,
borderRadius: "5px",
borderRadius: theme.shape.borderRadius,
overflow: "hidden",
}} >
<Typography variant={"h3"} style={{margin: 0, padding: 0, position: "relative", left: "30%"}}>
@@ -522,7 +523,7 @@ export const StackedBarChartCard = ({data, labels, title, width="100%", hidden,
width: width,
height: "100%",
border: `1px solid ${theme.borderColor}`,
borderRadius: "5px",
borderRadius: theme.shape.borderRadius,
overflow: "hidden",
}} >
<h3 style={{marginTop: 0, marginLeft: "5px", marginBottom: 0, paddingBottom: 0, position: "absolute"}}>
@@ -554,4 +555,4 @@ export const StackedBarChartCard = ({data, labels, title, width="100%", hidden,
}} />
</Paper>
);
}
}
@@ -3,6 +3,7 @@ import TableCell from '@mui/material/TableCell';
import TableRow from '@mui/material/TableRow';
import Table from '@mui/material/Table';
import TableBody from '@mui/material/TableBody';
import TableContainer from '@mui/material/TableContainer';
import TableHead from '@mui/material/TableHead';
import Typography from '@mui/material/Typography';
import { meState } from '../../../cache';
@@ -89,6 +90,7 @@ function DetailedCommandMappingTables({commands}){
{c[0]}
</Typography>
</Paper>
<TableContainer className="mythicElement">
<Table size="small" aria-label="details" style={{ "overflowWrap": "break-word"}}>
<TableHead>
<TableRow>
@@ -108,6 +110,7 @@ function DetailedCommandMappingTables({commands}){
))}
</TableBody>
</Table>
</TableContainer>
</div>
))}
</React.Fragment>
@@ -126,6 +129,7 @@ function DetailedTaskMappingTables({tasks}){
{c[0]}
</Typography>
</Paper>
<TableContainer className="mythicElement">
<Table size="small" aria-label="details" style={{ "overflowWrap": "break-word"}}>
<TableHead>
<TableRow>
@@ -150,8 +154,9 @@ function DetailedTaskMappingTables({tasks}){
))}
</TableBody>
</Table>
</TableContainer>
</React.Fragment>
))}
</React.Fragment>
)
}
}
@@ -8,9 +8,9 @@ import MythicTextField from '../../MythicComponents/MythicTextField';
import {useQuery, gql} from '@apollo/client';
import {snackActions} from '../../utilities/Snackbar';
import Switch from '@mui/material/Switch';
import {HexColorInput, HexColorPicker} from 'react-colorful';
import Typography from '@mui/material/Typography';
import Box from '@mui/material/Box';
import {getReadableTextColor, MythicColorSwatchInput} from '../../MythicComponents/MythicColorInput';
const GET_OperationData = gql`
query GetOperations($operation_id: Int!) {
@@ -118,10 +118,43 @@ export function OperationTableRowNotificationsDialog(props) {
onChange={onTextChange}
name="Banner Text"
/>
<HexColorPicker color={bannerColor} onChange={setBannerColor} />
<HexColorInput color={bannerColor} onChange={setBannerColor} />
<Box sx={{width: "100%", height: 25, backgroundColor: bannerColor}} >
<Typography style={{color: "white"}}>{bannerText}</Typography>
<Box
sx={{
mt: 2,
p: 1.5,
border: "1px solid",
borderColor: "divider",
borderRadius: "8px",
backgroundColor: "background.paper",
}}
>
<Box sx={{display: "flex", alignItems: "center", justifyContent: "space-between", gap: 2, mb: 1}}>
<Box sx={{minWidth: 0}}>
<Typography variant="body2" sx={{fontWeight: 700}}>Banner Color</Typography>
<Typography variant="caption" sx={{color: "text.secondary"}}>Operation banner background</Typography>
</Box>
<MythicColorSwatchInput
color={bannerColor}
label="Operation banner color"
onChange={setBannerColor}
/>
</Box>
<Box
sx={{
minHeight: 38,
px: 1.5,
display: "flex",
alignItems: "center",
borderRadius: "6px",
backgroundColor: bannerColor,
border: "1px solid",
borderColor: "divider",
}}
>
<Typography sx={{color: getReadableTextColor(bannerColor), fontWeight: 700}}>
{bannerText || "Operation Banner"}
</Typography>
</Box>
</Box>
</DialogContent>
<DialogActions>
@@ -135,4 +168,3 @@ export function OperationTableRowNotificationsDialog(props) {
</React.Fragment>
);
}
@@ -9,6 +9,7 @@ import TableCell from '@mui/material/TableCell';
import TableRow from '@mui/material/TableRow';
import Table from '@mui/material/Table';
import TableBody from '@mui/material/TableBody';
import TableContainer from '@mui/material/TableContainer';
import TableHead from '@mui/material/TableHead';
import LinearProgress from '@mui/material/LinearProgress';
import { getDefaultChoices } from '../CreatePayload/Step2SelectPayloadType';
@@ -91,6 +92,7 @@ export function C2ProfileBuildDialog(props) {
<DialogContentText>
These are the build parameters associated with this payload
</DialogContentText>
<TableContainer className="mythicElement">
<Table size="small" aria-label="details" style={{"tableLayout": "fixed", "overflowWrap": "break-word"}}>
<TableHead>
<TableRow>
@@ -127,6 +129,7 @@ export function C2ProfileBuildDialog(props) {
}
</TableBody>
</Table>
</TableContainer>
</DialogContent>
<DialogActions>
<Button variant="contained" onClick={props.onClose} color="primary">
@@ -136,4 +139,3 @@ export function C2ProfileBuildDialog(props) {
</React.Fragment>
);
}
@@ -111,7 +111,7 @@ export function C2ProfileListFilesDialog(props) {
<input onChange={onFileChange} type="file" multiple hidden />
</Button>
</DialogTitle>
<TableContainer >
<TableContainer className="mythicElement">
<Table stickyHeader size="small" style={{ "maxWidth": "100%", "overflow": "scroll"}}>
<TableHead>
<TableRow>
@@ -225,4 +225,3 @@ const C2ProfileListFilesDialogTableRow = ({container_name, id, filename}) => {
</React.Fragment>
)
}
@@ -17,6 +17,7 @@ import {MythicDialog} from "../../MythicComponents/MythicDialog";
import {C2ProfileListFilesDialog} from "./C2ProfileListFilesDialog";
import Table from '@mui/material/Table';
import TableBody from '@mui/material/TableBody';
import TableContainer from '@mui/material/TableContainer';
import TableHead from '@mui/material/TableHead';
const toggleDeleteStatus = gql`
@@ -103,6 +104,7 @@ export function CustomBrowserRow({service, showDeleted}) {
</MythicStyledTooltip>
</MythicTableCell>
<MythicTableCell style={{padding: 0}}>
<TableContainer className="mythicElement">
<Table>
<TableHead>
<TableRow hover>
@@ -119,6 +121,8 @@ export function CustomBrowserRow({service, showDeleted}) {
))}
</TableBody>
</Table>
</TableContainer>
<TableContainer className="mythicElement">
<Table>
<TableHead>
<TableRow hover>
@@ -135,6 +139,8 @@ export function CustomBrowserRow({service, showDeleted}) {
))}
</TableBody>
</Table>
</TableContainer>
<TableContainer className="mythicElement">
<Table>
<TableHead>
<TableRow hover>
@@ -155,6 +161,7 @@ export function CustomBrowserRow({service, showDeleted}) {
))}
</TableBody>
</Table>
</TableContainer>
</MythicTableCell>
{openListFilesDialog &&
@@ -9,6 +9,7 @@ import TableCell from '@mui/material/TableCell';
import TableRow from '@mui/material/TableRow';
import Table from '@mui/material/Table';
import TableBody from '@mui/material/TableBody';
import TableContainer from '@mui/material/TableContainer';
import TableHead from '@mui/material/TableHead';
import LinearProgress from '@mui/material/LinearProgress';
import { getDefaultChoices } from '../CreatePayload/Step2SelectPayloadType';
@@ -99,6 +100,7 @@ export function PayloadTypeBuildDialog(props) {
<DialogContentText>
These are the build parameters associated with this payload
</DialogContentText>
<TableContainer className="mythicElement">
<Table size="small" aria-label="details" style={{"tableLayout": "fixed", "overflowWrap": "break-word"}}>
<TableHead>
<TableRow>
@@ -135,6 +137,7 @@ export function PayloadTypeBuildDialog(props) {
}
</TableBody>
</Table>
</TableContainer>
</DialogContent>
<DialogActions>
<Button variant="contained" onClick={props.onClose} color="primary">
@@ -144,4 +147,3 @@ export function PayloadTypeBuildDialog(props) {
</React.Fragment>
);
}
@@ -10,6 +10,7 @@ import TableCell from '@mui/material/TableCell';
import TableRow from '@mui/material/TableRow';
import Table from '@mui/material/Table';
import TableBody from '@mui/material/TableBody';
import TableContainer from '@mui/material/TableContainer';
import TableHead from '@mui/material/TableHead';
import LinearProgress from '@mui/material/LinearProgress';
import MenuBookIcon from '@mui/icons-material/MenuBook';
@@ -93,6 +94,7 @@ export function PayloadTypeCommandDialog({service, payload_name, onClose}) {
<React.Fragment>
<DialogTitle id="form-dialog-title">{payload_name}'s Commands</DialogTitle>
<DialogContent dividers={true} style={{padding: 0}}>
<TableContainer className="mythicElement" style={{height: "100%"}}>
<Table size="small" stickyHeader={true} aria-label="details"
style={{"tableLayout": "fixed", "overflowWrap": "break-word", overflowY:"auto", width: "100%", height: "100%"}}>
<TableHead>
@@ -136,6 +138,7 @@ export function PayloadTypeCommandDialog({service, payload_name, onClose}) {
}
</TableBody>
</Table>
</TableContainer>
{openScriptDialog.open &&
<MythicDialog fullWidth={true} maxWidth="lg" open={openScriptDialog.open}
onClose={()=>{setOpenScriptDialog({open: false, command_id: 0});}}
@@ -226,6 +229,7 @@ export function ScriptingCommandDialog({command_id, command_name, onClose}){
Parameter Group: {paramGroup[0].parameter_group_name}
</Typography>
</Paper>
<TableContainer className="mythicElement">
<Table style={{tableLayout: "fixed"}}>
<TableHead>
<TableRow>
@@ -373,6 +377,7 @@ export function ScriptingCommandDialog({command_id, command_name, onClose}){
))}
</TableBody>
</Table>
</TableContainer>
</div>
))}
@@ -385,4 +390,3 @@ export function ScriptingCommandDialog({command_id, command_name, onClose}){
</React.Fragment>
)
}
@@ -423,7 +423,7 @@ A few examples are github.com/MythicAgents/bloodhound and github.com/MythicAgent
return (
<MythicTabPanel {...props} >
<div style={{display: "flex", flexGrow: 1, overflowY: "auto"}}>
<TableContainer>
<TableContainer className="mythicElement">
<Table stickyHeader size="small" style={{"maxWidth": "100%", "overflow": "scroll"}}>
<TableHead>
<TableRow>
@@ -492,7 +492,7 @@ You can extend this auth capability to support your own LDAP, SSO, or otherwise
return (
<MythicTabPanel {...props} >
<div style={{display: "flex", flexGrow: 1, overflowY: "auto"}}>
<TableContainer>
<TableContainer className="mythicElement">
<Table stickyHeader size="small" style={{"maxWidth": "100%", "overflow": "scroll"}}>
<TableHead>
<TableRow>
@@ -542,7 +542,7 @@ const ContainersTabCustomBrowsersPanel = (props) => {
return (
<MythicTabPanel {...props} >
<div style={{display: "flex", flexGrow: 1, overflowY: "auto"}}>
<TableContainer>
<TableContainer className="mythicElement">
<Table stickyHeader size="small" style={{"maxWidth": "100%", "overflow": "scroll"}}>
<TableHead>
<TableRow>
@@ -3,6 +3,7 @@ import TableCell from '@mui/material/TableCell';
import TableRow from '@mui/material/TableRow';
import Table from '@mui/material/Table';
import TableBody from '@mui/material/TableBody';
import TableContainer from '@mui/material/TableContainer';
import TableHead from '@mui/material/TableHead';
import Typography from '@mui/material/Typography';
import {useQuery, gql, useMutation} from '@apollo/client';
@@ -551,6 +552,7 @@ function DetailedPayloadInnerTable(props){
Payload Information
</Typography>
</Paper>
<TableContainer className="mythicElement">
<Table size="small" aria-label="details" style={{ "overflowWrap": "break-word"}}>
<TableHead>
<TableRow hover>
@@ -656,11 +658,13 @@ function DetailedPayloadInnerTable(props){
}
</TableBody>
</Table>
</TableContainer>
<Paper elevation={5} style={{backgroundColor: theme.pageHeader.main, color: theme.pageHeaderText.main,marginBottom: "5px", marginTop: "10px"}} variant={"elevation"}>
<Typography variant="h6" style={{textAlign: "left", display: "inline-block", marginLeft: "20px", color: theme.pageHeaderColor}}>
Build Parameters
</Typography>
</Paper>
<TableContainer className="mythicElement">
<Table size="small" aria-label="details" style={{ "overflowWrap": "break-word"}}>
<TableHead>
<TableRow>
@@ -695,11 +699,13 @@ function DetailedPayloadInnerTable(props){
}
</TableBody>
</Table>
</TableContainer>
<Paper elevation={5} style={{backgroundColor: theme.pageHeader.main, color: theme.pageHeaderText.main,marginBottom: "5px", marginTop: "10px"}} variant={"elevation"}>
<Typography variant="h6" style={{textAlign: "left", display: "inline-block", marginLeft: "20px", color: theme.pageHeaderColor}}>
Build Steps
</Typography>
</Paper>
<TableContainer className="mythicElement">
<Table size="small" aria-label="details" style={{ "overflowWrap": "break-word"}}>
<TableHead>
<TableRow>
@@ -723,6 +729,7 @@ function DetailedPayloadInnerTable(props){
}
</TableBody>
</Table>
</TableContainer>
{ c2Profiles.map( (c2) => (
<React.Fragment key={"c2frag" + props.payload_id + c2.c2_profile}>
<Paper elevation={5} style={{backgroundColor: theme.pageHeader.main, color: theme.pageHeaderText.main,marginBottom: "5px", marginTop: "10px"}} variant={"elevation"}>
@@ -730,6 +737,7 @@ function DetailedPayloadInnerTable(props){
{c2.c2_profile}
</Typography>
</Paper>
<TableContainer className="mythicElement">
<Table size="small" aria-label="details" style={{"overflowWrap": "break-word"}}>
<TableHead>
<TableRow>
@@ -764,6 +772,7 @@ function DetailedPayloadInnerTable(props){
}
</TableBody>
</Table>
</TableContainer>
</React.Fragment>
))}
@@ -775,6 +784,7 @@ function DetailedPayloadInnerTable(props){
<Button style={{float: "right"}} variant="contained" size="small" onClick={()=>{setOpenAddRemoveCommandsDialog(true)}} >Add/Remove Commands</Button>
</Paper>
{commands.length > 0 &&
<TableContainer className="mythicElement">
<Table size="small" aria-label="details" style={{"overflowWrap": "break-word"}}>
<TableHead>
<TableRow>
@@ -803,6 +813,7 @@ function DetailedPayloadInnerTable(props){
}
</TableBody>
</Table>
</TableContainer>
}
</React.Fragment>
@@ -860,4 +871,4 @@ function DetailedPayloadInnerTable(props){
}
</React.Fragment>
)
}
}
@@ -9,6 +9,7 @@ import MythicTableCell from "../../MythicComponents/MythicTableCell";
import TableRow from '@mui/material/TableRow';
import Table from '@mui/material/Table';
import TableBody from '@mui/material/TableBody';
import TableContainer from '@mui/material/TableContainer';
import MythicTextField from "../../MythicComponents/MythicTextField";
import MenuItem from '@mui/material/MenuItem';
import FormControl from '@mui/material/FormControl';
@@ -101,6 +102,7 @@ export function HostFileDialog(props) {
<React.Fragment>
<DialogTitle id="form-dialog-title">Host File via C2 Profile</DialogTitle>
<DialogContent dividers={true}>
<TableContainer className="mythicElement">
<Table size="small" aria-label="details" style={{ "overflowWrap": "break-word"}}>
<TableBody>
<TableRow hover>
@@ -140,6 +142,7 @@ export function HostFileDialog(props) {
</TableRow>
</TableBody>
</Table>
</TableContainer>
</DialogContent>
<DialogActions>
<Button variant="contained" onClick={props.onClose} color="primary">
@@ -155,4 +158,3 @@ export function HostFileDialog(props) {
</React.Fragment>
);
}
@@ -2,13 +2,13 @@ import React from 'react';
import Table from '@mui/material/Table';
import TableBody from '@mui/material/TableBody';
import TableCell from '@mui/material/TableCell';
import TableContainer from '@mui/material/TableContainer';
import TableHead from '@mui/material/TableHead';
import TableRow from '@mui/material/TableRow';
import Paper from '@mui/material/Paper';
import Button from '@mui/material/Button';
import Typography from '@mui/material/Typography';
import { PayloadsTableRow } from './PayloadsTableRow';
import {useTheme} from '@mui/material/styles';
import {ImportPayloadConfigDialog} from './ImportPayloadConfigDialog';
import { MythicDialog } from '../../MythicComponents/MythicDialog';
import ButtonGroup from '@mui/material/ButtonGroup';
@@ -27,7 +27,6 @@ import {MythicPageHeader} from "../../MythicComponents/MythicPageHeader";
export function PayloadsTable({payload, onDeletePayload, onUpdateCallbackAlert, onRestorePayload, me,
pageData, onChangePage, onChangeShowDeleted, onChangeShowAutogenerated,
onCallbacksAllowedChanged, openBackdrop}){
const theme = useTheme();
const [showDeleted, setShowDeleted] = React.useState(false);
const [showAutogenerated, setShowAutogenerated] = React.useState(false);
const [openPayloadImport, setOpenPayloadImport] = React.useState(false);
@@ -118,13 +117,13 @@ export function PayloadsTable({payload, onDeletePayload, onUpdateCallbackAlert,
/>
}
</MythicPageHeader>
<div style={{flexGrow: 1, overflowY: "auto", height: "100%", position: "relative"}}>
<TableContainer className="mythicElement" style={{flexGrow: 1, overflowY: "auto", height: "100%", position: "relative"}}>
{openBackdrop &&
<Backdrop open={openBackdrop} style={{zIndex: 2000, position: "absolute"}}>
<CircularProgress color="inherit" disableShrink />
</Backdrop>
}
<Table stickyHeader size="small" style={{ "maxWidth": "100%", "overflow": "auto", tableLayout: "fixed"}}>
<Table stickyHeader size="small" style={{maxWidth: "100%", tableLayout: "fixed"}}>
<TableHead >
<TableRow>
<TableCell style={{width: "6rem"}}></TableCell>
@@ -151,7 +150,7 @@ export function PayloadsTable({payload, onDeletePayload, onUpdateCallbackAlert,
))}
</TableBody>
</Table>
</div>
</TableContainer>
<div style={{background: "transparent", display: "flex", justifyContent: "center", alignItems: "center", paddingTop: "5px", paddingBottom: "10px"}}>
<Pagination count={Math.ceil(pageData.totalCount / pageData.fetchLimit)} variant="outlined" color="primary" boundaryCount={1}
siblingCount={1} onChange={onChangePage} showFirstButton={true} showLastButton={true} style={{padding: "20px"}}/>
@@ -161,4 +160,3 @@ export function PayloadsTable({payload, onDeletePayload, onUpdateCallbackAlert,
)
}
@@ -13,6 +13,7 @@ import TableCell from '@mui/material/TableCell';
import TableRow from '@mui/material/TableRow';
import Table from '@mui/material/Table';
import TableBody from '@mui/material/TableBody';
import TableContainer from '@mui/material/TableContainer';
import TableHead from '@mui/material/TableHead';
import DialogContent from '@mui/material/DialogContent';
@@ -171,6 +172,7 @@ export function PayloadBuildStepStatusDialog(props) {
<React.Fragment>
<DialogTitle id="form-dialog-title">Step {props.step.step_number + 1} - {props.step.step_name}</DialogTitle>
<DialogContent>
<TableContainer className="mythicElement">
<Table size="small" style={{ maxWidth: "100%", overflow: "scroll"}}>
<TableHead>
<TableRow>
@@ -206,6 +208,7 @@ export function PayloadBuildStepStatusDialog(props) {
</TableRow>
</TableBody>
</Table>
</TableContainer>
</DialogContent>
<DialogActions>
<Button variant="contained" onClick={props.onClose} color="primary">
@@ -252,7 +252,7 @@ export function FileMetaDownloadTable(props){
<DeleteIcon />Delete Selected
</Button>
</span>
<div style={{height: "100%", overflowY: "auto"}}>
<TableContainer className="mythicElement" style={{height: "100%", overflowY: "auto"}}>
<Table stickyHeader size="small" style={{"tableLayout": "fixed", "maxWidth": "100%", "overflow": "scroll"}}>
<TableHead>
<TableRow>
@@ -284,7 +284,7 @@ export function FileMetaDownloadTable(props){
))}
</TableBody>
</Table>
</div>
</TableContainer>
</TableContainer>
)
}
@@ -639,7 +639,7 @@ export function FileMetaUploadTable(props){
<DeleteIcon />Delete Selected
</Button>
</span>
<div style={{height: "100%", overflowY: "auto"}}>
<TableContainer className="mythicElement" style={{height: "100%", overflowY: "auto"}}>
<Table stickyHeader size="small"
style={{"tableLayout": "fixed", "maxWidth": "100%", "overflow": "scroll"}}>
<TableHead>
@@ -673,7 +673,7 @@ export function FileMetaUploadTable(props){
))}
</TableBody>
</Table>
</div>
</TableContainer>
</TableContainer>
)
}
@@ -1283,7 +1283,7 @@ export function FileMetaEventingWorkflowsTable(props){
<DeleteIcon />Delete Selected
</Button>
</span>
<div style={{height: "100%", overflowY: "auto"}}>
<TableContainer className="mythicElement" style={{height: "100%", overflowY: "auto"}}>
<Table stickyHeader size="small"
style={{"tableLayout": "fixed", "maxWidth": "100%", "overflow": "scroll"}}>
<TableHead>
@@ -1316,7 +1316,7 @@ export function FileMetaEventingWorkflowsTable(props){
))}
</TableBody>
</Table>
</div>
</TableContainer>
</TableContainer>
)
}
@@ -121,7 +121,7 @@ export function SearchPayloadsTable({payloads, setPayloads, showDeleted, me}){
}
return (
<div style={{display: "flex", flexGrow: 1, overflowY: "auto"}}>
<TableContainer style={{height: "100%", overflowY: "auto"}}>
<TableContainer className="mythicElement" style={{height: "100%", overflowY: "auto"}}>
<Table stickyHeader size="small" style={{ "maxWidth": "100%", "overflow": "scroll", tableLayout: "fixed"}}>
<TableHead>
<TableRow>
@@ -153,4 +153,3 @@ export function SearchPayloadsTable({payloads, setPayloads, showDeleted, me}){
</div>
)
}
@@ -54,7 +54,7 @@ export function ProxySearchTable(props){
}
return (
<TableContainer style={{overflowY: "auto", flexGrow: 1, marginTop: "5px"}}>
<TableContainer className="mythicElement" style={{overflowY: "auto", flexGrow: 1, marginTop: "5px"}}>
<Table stickyHeader size="small" style={{tableLayout: "fixed"}}>
<TableHead>
<TableRow>
@@ -222,4 +222,3 @@ function ProxySearchTableRow(props){
</React.Fragment>
)
}
@@ -293,7 +293,7 @@ export function CreateInviteLinksDialog(props) {
<DialogContentText>
<b style={{marginLeft: "10px"}}>{"Note:"}</b> Invite links are deleted if Mythic restarts
</DialogContentText>
<TableContainer >
<TableContainer className="mythicElement">
<Table size="small" style={{ "maxWidth": "100%", "overflow": "scroll", marginRight: "10px"}}>
<TableBody>
<TableRow hover>
@@ -367,4 +367,3 @@ export function CreateInviteLinksDialog(props) {
</React.Fragment>
);
}
@@ -2,6 +2,7 @@ import React from 'react';
import Table from '@mui/material/Table';
import TableBody from '@mui/material/TableBody';
import TableCell from '@mui/material/TableCell';
import TableContainer from '@mui/material/TableContainer';
import TableHead from '@mui/material/TableHead';
import TableRow from '@mui/material/TableRow';
import {
@@ -129,7 +130,7 @@ export function SettingsOperatorTable(props){
/>
}
</MythicPageHeader>
<div style={{display: "flex", flexGrow: 1, overflowY: "auto", alignItems: "flex-start"}}>
<TableContainer className="mythicElement" style={{display: "flex", flexGrow: 1, overflowY: "auto", alignItems: "flex-start"}}>
<Table stickyHeader size="small" style={{"tableLayout": "fixed",}}>
<TableHead >
<TableRow>
@@ -163,8 +164,7 @@ export function SettingsOperatorTable(props){
))}
</TableBody>
</Table>
</div>
</TableContainer>
</>
)
}
@@ -11,7 +11,6 @@ import TableBody from '@mui/material/TableBody';
import Link from '@mui/material/Link';
import TableContainer from '@mui/material/TableContainer';
import Typography from '@mui/material/Typography';
import {HexColorInput, HexColorPicker} from 'react-colorful';
import {GetMythicSetting, useSetMythicSetting} from "../../MythicComponents/MythicSavedUserSetting";
import MenuItem from '@mui/material/MenuItem';
import Select from '@mui/material/Select';
@@ -28,6 +27,7 @@ import {copyStringToClipboard} from "../../utilities/Clipboard";
import {useLazyQuery } from '@apollo/client';
import PhoneCallbackIcon from '@mui/icons-material/PhoneCallback';
import ColorLensIcon from '@mui/icons-material/ColorLens';
import {MythicColorSwatchInput} from "../../MythicComponents/MythicColorInput";
const interactTypeOptions = [
{value: "interact", display: "Accordions"},
@@ -51,6 +51,406 @@ const isValidColor = (color) =>{
}
return true;
}
const COLOR_EDITOR_SECTIONS = [
{
title: "Application Shell",
description: "Page chrome, surfaces, typography, and borders.",
colors: [
{name: "background", display: "App Background", description: "Main page background behind views and dialogs.", preview: "surface"},
{name: "paper", display: "Panel Background", description: "Menus, dialogs, and content surfaces.", preview: "surface"},
{name: "pageHeader", display: "Page Headers", description: "Header bars at the top of major pages.", preview: "surface"},
{name: "text", display: "Text", description: "Primary readable text throughout the UI.", preview: "surface"},
{name: "borderColor", display: "Borders", description: "Outlines around panels, tables, and controls.", preview: "surface"},
],
},
{
title: "Navigation",
description: "Left navigation gradient, labels, and icons.",
colors: [
{name: "navBarColor", display: "Navigation Top", description: "Start color for the navigation background.", preview: "navigation"},
{name: "navBarBottomColor", display: "Navigation Bottom", description: "End color for the navigation background.", preview: "navigation"},
{name: "navBarIcons", display: "Navigation Icons", description: "Icon color in the navigation bar.", preview: "navigation"},
{name: "navBarText", display: "Navigation Text", description: "Text color in the navigation bar.", preview: "navigation"},
],
},
{
title: "Tables and Selection",
description: "Table headers, hover states, and selected callback emphasis.",
colors: [
{name: "tableHeader", display: "Table Header", description: "Sticky header rows in tables and data grids.", preview: "table"},
{name: "tableHover", display: "Table Hover", description: "Rows when hovered or softly emphasized.", preview: "table"},
{name: "selectedCallbackColor", display: "Active Callback", description: "Currently active callback row highlight.", preview: "table"},
{name: "selectedCallbackHierarchyColor", display: "Tree Host Highlight", description: "Current host highlight in tree views.", preview: "table"},
],
},
{
title: "Status Colors",
description: "Button, alert, tag, and status accents.",
colors: [
{name: "primary", display: "Primary", description: "Primary actions and key affordances.", preview: "status"},
{name: "secondary", display: "Secondary", description: "Secondary actions and supporting accents.", preview: "status"},
{name: "info", display: "Info", description: "Informational actions and notices.", preview: "status"},
{name: "success", display: "Success", description: "Success actions, healthy states, and confirmations.", preview: "status"},
{name: "warning", display: "Warning", description: "Warning actions and caution states.", preview: "status"},
{name: "error", display: "Error", description: "Danger actions, failed states, and errors.", preview: "status"},
],
},
{
title: "Tasking",
description: "Task prompt, context badges, and command output.",
colors: [
{name: "taskPromptTextColor", display: "Prompt Text", description: "Tasking prompt text.", preview: "task"},
{name: "taskPromptCommandTextColor", display: "Command Text", description: "Command and parameter text in tasking.", preview: "task"},
{name: "taskContextColor", display: "Context", description: "Generic tasking context labels.", preview: "task"},
{name: "taskContextImpersonationColor", display: "Impersonation Context", description: "User or impersonation tasking context labels.", preview: "task"},
{name: "taskContextExtraColor", display: "Extra Context", description: "Additional tasking context labels.", preview: "task"},
{name: "outputBackgroundColor", display: "Output Background", description: "Task output and terminal-style response background.", preview: "output"},
{name: "outputTextColor", display: "Output Text", description: "Task output and terminal-style response text.", preview: "output"},
],
},
{
title: "File Browsing",
description: "File browser empty-folder treatment.",
colors: [
{name: "emptyFolderColor", display: "Empty Folder", description: "Empty folder icon and text in file-based browsers.", preview: "file"},
],
},
];
const clonePalette = (sourcePalette) => {
const clonedPalette = {};
Object.entries(sourcePalette || {}).forEach(([key, value]) => {
clonedPalette[key] = typeof value === "object" && value !== null ? {...value} : value;
});
return clonedPalette;
}
const addAlpha = (color, alphaHex) => {
if(isValidColor(color)){
return `${color}${alphaHex}`;
}
return color;
}
const getPaletteValue = (palette, name, mode) => {
const color = palette?.[name]?.[mode];
if(isValidColor(color)){
return color;
}
const defaultColor = operatorSettingDefaults.palette?.[name]?.[mode];
if(isValidColor(defaultColor)){
return defaultColor;
}
return mode === "dark" ? "#1f2937" : "#f8fafc";
}
const getReadableTextColor = (backgroundColor) => {
if(!isValidColor(backgroundColor)){
return "#ffffff";
}
const red = parseInt(backgroundColor.slice(1, 3), 16);
const green = parseInt(backgroundColor.slice(3, 5), 16);
const blue = parseInt(backgroundColor.slice(5, 7), 16);
const brightness = (red * 299 + green * 587 + blue * 114) / 1000;
return brightness >= 140 ? "#111827" : "#ffffff";
}
const ModeColorControl = ({mode, name, color, onChange}) => (
<Box sx={{minWidth: 0}}>
<Typography variant="caption" sx={{display: "block", color: "text.secondary", mb: 0.5}}>
{mode === "dark" ? "Dark" : "Light"}
</Typography>
<MythicColorSwatchInput
color={color}
label={`${name} ${mode} color`}
onChange={(value) => onChange(name, mode, value)}
/>
</Box>
);
const PreviewLabel = ({children, color}) => (
<Typography
variant="caption"
sx={{
color,
display: "block",
lineHeight: 1.2,
whiteSpace: "nowrap",
overflow: "hidden",
textOverflow: "ellipsis",
}}
>
{children}
</Typography>
);
const ColorUsagePreview = ({option, palette, mode}) => {
const background = getPaletteValue(palette, "background", mode);
const paper = getPaletteValue(palette, "paper", mode);
const text = getPaletteValue(palette, "text", mode);
const border = getPaletteValue(palette, "borderColor", mode);
const navTop = getPaletteValue(palette, "navBarColor", mode);
const navBottom = getPaletteValue(palette, "navBarBottomColor", mode);
const navIcon = getPaletteValue(palette, "navBarIcons", mode);
const navText = getPaletteValue(palette, "navBarText", mode);
const tableHeader = getPaletteValue(palette, "tableHeader", mode);
const tableHover = getPaletteValue(palette, "tableHover", mode);
const selectedCallback = getPaletteValue(palette, "selectedCallbackColor", mode);
const selectedHierarchy = getPaletteValue(palette, "selectedCallbackHierarchyColor", mode);
const outputBackground = getPaletteValue(palette, "outputBackgroundColor", mode);
const outputText = getPaletteValue(palette, "outputTextColor", mode);
const promptText = getPaletteValue(palette, "taskPromptTextColor", mode);
const commandText = getPaletteValue(palette, "taskPromptCommandTextColor", mode);
const context = getPaletteValue(palette, "taskContextColor", mode);
const impersonation = getPaletteValue(palette, "taskContextImpersonationColor", mode);
const extra = getPaletteValue(palette, "taskContextExtraColor", mode);
const previewColor = getPaletteValue(palette, option.name, mode);
const shellSx = {
border: `1px solid ${addAlpha(border, "99")}`,
borderRadius: "6px",
overflow: "hidden",
minHeight: 74,
backgroundColor: background,
};
switch(option.preview){
case "navigation":
return (
<Box sx={{...shellSx, display: "flex"}}>
<Box sx={{width: 58, background: `linear-gradient(180deg, ${navTop}, ${navBottom})`, p: 1}}>
<PhoneCallbackIcon style={{color: navIcon, fontSize: 18}}/>
<PreviewLabel color={navText}>Tasks</PreviewLabel>
</Box>
<Box sx={{flex: 1, backgroundColor: paper, p: 1}}>
<PreviewLabel color={text}>{mode} navigation</PreviewLabel>
<Box sx={{height: 7, mt: 1, borderRadius: "4px", backgroundColor: previewColor}} />
</Box>
</Box>
);
case "table":
return (
<Box sx={shellSx}>
<Box sx={{height: 22, px: 1, display: "flex", alignItems: "center", backgroundColor: tableHeader}}>
<PreviewLabel color={text}>Table header</PreviewLabel>
</Box>
<Box sx={{height: 18, px: 1, display: "flex", alignItems: "center", borderTop: `1px solid ${addAlpha(border, "99")}`, backgroundColor: paper}}>
<PreviewLabel color={text}>Normal row</PreviewLabel>
</Box>
<Box sx={{height: 18, px: 1, display: "flex", alignItems: "center", backgroundColor: addAlpha(tableHover, "CC")}}>
<PreviewLabel color={text}>Hover row</PreviewLabel>
</Box>
<Box sx={{height: 18, display: "grid", gridTemplateColumns: "1fr 1fr"}}>
<Box sx={{px: 1, backgroundColor: addAlpha(selectedCallback, "CC")}}>
<PreviewLabel color={text}>Active</PreviewLabel>
</Box>
<Box sx={{px: 1, backgroundColor: addAlpha(selectedHierarchy, "CC")}}>
<PreviewLabel color={text}>Tree</PreviewLabel>
</Box>
</Box>
</Box>
);
case "status":
return (
<Box sx={{...shellSx, p: 1, backgroundColor: paper}}>
<Box sx={{display: "inline-flex", alignItems: "center", px: 1, py: 0.5, borderRadius: "4px", backgroundColor: previewColor, color: getReadableTextColor(previewColor), fontSize: "0.75rem", fontWeight: 700}}>
{option.display}
</Box>
<Box sx={{mt: 1, height: 10, borderRadius: "4px", backgroundColor: addAlpha(previewColor, "66")}} />
<PreviewLabel color={text}>{mode} accent</PreviewLabel>
</Box>
);
case "task":
return (
<Box sx={{...shellSx, p: 1, backgroundColor: paper}}>
<PreviewLabel color={promptText}>operator@host</PreviewLabel>
<Typography variant="caption" sx={{color: commandText, display: "block", lineHeight: 1.2}}>
shell whoami
</Typography>
<Box sx={{display: "flex", gap: 0.5, mt: 0.75, minWidth: 0}}>
{[context, impersonation, extra].map((color, index) => (
<Box key={`${mode}-${color}-${index}`} sx={{height: 12, flex: 1, borderRadius: "3px", backgroundColor: color}} />
))}
</Box>
</Box>
);
case "output":
return (
<Box sx={{...shellSx, p: 1, backgroundColor: outputBackground}}>
<Typography variant="caption" sx={{color: outputText, display: "block", fontFamily: "monospace", lineHeight: 1.25}}>
user\host
</Typography>
<Typography variant="caption" sx={{color: outputText, display: "block", fontFamily: "monospace", lineHeight: 1.25}}>
completed
</Typography>
</Box>
);
case "file":
return (
<Box sx={{...shellSx, p: 1, backgroundColor: paper}}>
<Box sx={{height: 24, borderRadius: "4px", backgroundColor: addAlpha(previewColor, "33"), border: `1px solid ${addAlpha(previewColor, "99")}`}} />
<Typography variant="caption" sx={{color: previewColor, display: "block", mt: 0.75, fontWeight: 700}}>
Empty folder
</Typography>
</Box>
);
case "surface":
default:
return (
<Box sx={{...shellSx, p: 0.75}}>
<Box sx={{height: 16, borderRadius: "4px 4px 0 0", backgroundColor: getPaletteValue(palette, "pageHeader", mode)}} />
<Box sx={{p: 0.75, backgroundColor: paper, border: `1px solid ${addAlpha(border, "99")}`, borderTop: 0, borderRadius: "0 0 4px 4px"}}>
<PreviewLabel color={text}>{mode} surface</PreviewLabel>
<Box sx={{height: 7, mt: 0.75, borderRadius: "4px", backgroundColor: previewColor}} />
</Box>
</Box>
);
}
}
const ColorTokenEditor = ({option, palette, onChange}) => (
<Box
sx={{
display: "grid",
gridTemplateColumns: {xs: "1fr", md: "minmax(170px, 0.8fr) minmax(250px, 1fr) minmax(260px, 1.1fr)"},
gap: 1.5,
alignItems: "center",
p: 1.5,
borderTop: "1px solid",
borderColor: "divider",
"&:first-of-type": {borderTop: 0},
}}
>
<Box sx={{minWidth: 0}}>
<Typography variant="body2" sx={{fontWeight: 700}}>
{option.display}
</Typography>
<Typography variant="caption" sx={{color: "text.secondary", display: "block", lineHeight: 1.3}}>
{option.description}
</Typography>
</Box>
<Box sx={{display: "grid", gridTemplateColumns: "1fr 1fr", gap: 1.5, minWidth: 0}}>
<ModeColorControl
mode="dark"
name={option.name}
color={palette?.[option.name]?.dark}
onChange={onChange}
/>
<ModeColorControl
mode="light"
name={option.name}
color={palette?.[option.name]?.light}
onChange={onChange}
/>
</Box>
<Box sx={{display: "grid", gridTemplateColumns: "1fr 1fr", gap: 1, minWidth: 0}}>
<ColorUsagePreview option={option} palette={palette} mode="dark" />
<ColorUsagePreview option={option} palette={palette} mode="light" />
</Box>
</Box>
);
const BackgroundImageEditor = ({palette, backgroundFileImageDarkRef, backgroundFileImageLightRef, onChangePaletteColor, onFileBackgroundImageChangeDark, onFileBackgroundImageChangeLight}) => (
<Box sx={{mt: 2}}>
<Box sx={{mb: 1}}>
<Typography variant="h6" sx={{fontWeight: 700}}>Background Images</Typography>
<Typography variant="caption" sx={{color: "text.secondary"}}>
Optional page background images for each theme mode.
</Typography>
</Box>
<Box
sx={{
display: "grid",
gridTemplateColumns: {xs: "1fr", md: "1fr 1fr"},
gap: 1.5,
}}
>
{[
{mode: "dark", label: "Dark", ref: backgroundFileImageDarkRef, onChange: onFileBackgroundImageChangeDark},
{mode: "light", label: "Light", ref: backgroundFileImageLightRef, onChange: onFileBackgroundImageChangeLight},
].map((imageOption) => (
<Box
key={imageOption.mode}
sx={{
border: "1px solid",
borderColor: "divider",
borderRadius: "8px",
overflow: "hidden",
backgroundColor: imageOption.mode === "dark" ? "#111827" : "#f8fafc",
}}
>
<Box sx={{display: "flex", alignItems: "center", gap: 1, p: 1}}>
<Typography variant="body2" sx={{fontWeight: 700, flexGrow: 1, color: imageOption.mode === "dark" ? "#ffffff" : "#111827"}}>
{imageOption.label}
</Typography>
<Button size="small" color="info" variant="contained" onClick={() => imageOption.ref.current.click()}>
Upload
<input ref={imageOption.ref} onChange={imageOption.onChange} type="file" hidden />
</Button>
<Button size="small" color="warning" variant="contained" onClick={() => onChangePaletteColor("backgroundImage", imageOption.mode, null)}>
Remove
</Button>
</Box>
<Box
sx={{
height: 120,
backgroundImage: palette.backgroundImage?.[imageOption.mode],
backgroundSize: "cover",
backgroundPosition: "center",
borderTop: "1px solid",
borderColor: "divider",
}}
/>
</Box>
))}
</Box>
</Box>
);
const ColorPaletteEditor = ({palette, onChangePaletteColor, backgroundFileImageDarkRef, backgroundFileImageLightRef, onFileBackgroundImageChangeDark, onFileBackgroundImageChangeLight}) => (
<Box sx={{width: "100%", py: 1}}>
<Typography variant="h4" sx={{mb: 0.5}}>
Theme Colors
</Typography>
<Typography variant="body2" sx={{color: "text.secondary", mb: 2}}>
Colors are grouped by where operators will see them, with dark and light previews shown side by side.
</Typography>
{COLOR_EDITOR_SECTIONS.map((section) => (
<Box key={section.title} sx={{mb: 2.5}}>
<Box sx={{mb: 1}}>
<Typography variant="h6" sx={{fontWeight: 700}}>{section.title}</Typography>
<Typography variant="caption" sx={{color: "text.secondary"}}>{section.description}</Typography>
</Box>
<Box
sx={{
border: "1px solid",
borderColor: "divider",
borderRadius: "8px",
overflow: "hidden",
backgroundColor: "background.paper",
}}
>
{section.colors.map((option) => (
<ColorTokenEditor
key={option.name}
option={option}
palette={palette}
onChange={onChangePaletteColor}
/>
))}
</Box>
</Box>
))}
<BackgroundImageEditor
palette={palette}
backgroundFileImageDarkRef={backgroundFileImageDarkRef}
backgroundFileImageLightRef={backgroundFileImageLightRef}
onChangePaletteColor={onChangePaletteColor}
onFileBackgroundImageChangeDark={onFileBackgroundImageChangeDark}
onFileBackgroundImageChangeLight={onFileBackgroundImageChangeLight}
/>
</Box>
);
export function SettingsOperatorUIConfigDialog(props) {
const fileInputRef = React.useRef(null);
const backgroundFileImageLightRef = React.useRef(null);
@@ -247,35 +647,8 @@ export function SettingsOperatorUIConfigDialog(props) {
light: isValidColor(initialPalette?.borderColor?.light) ? initialPalette?.borderColor?.light : operatorSettingDefaults.palette.borderColor.light,
},
});
const paletteOptionsSolidColor = [
{name: "primary", display: "Primary"},
{name: "error", display: "Error"},
{name: "warning", display: "Warning"},
{name: "info", display: "Informational"},
{name: "success", display: "Success"},
{name: "secondary", display: "Secondary"},
{name: "pageHeader", display: "Page Headers"},
{name: "taskPromptTextColor", display: "Tasking Prompt Text"},
{name: "taskPromptCommandTextColor", display: "Tasking Command and Parameter Text"}
];
const paletteOptionsTextColor = [
{name: "tableHeader", display: "Table Headers"},
{name: "tableHover", display: "Table Hover"},
{name: "selectedCallbackColor", display: "Currently active callback row highlight"},
{name: "selectedCallbackHierarchyColor", display: "Current Host highlight in tree views"},
{name: "paper", display: "Menu and Modals Background"},
{name: "background", display: "Background"},
{name: "taskContextColor", display: "Tasking Context Generic Background Color"},
{name: "taskContextImpersonationColor", display: "Tasking Context User Background Color"},
{name: "taskContextExtraColor", display: "Tasking Context Extra Info Background Color"},
{name: "emptyFolderColor", display: "Color of the empty folder icon and text in file-based browsers"},
{name: "borderColor", display: "Color of borders around elements"}
]
const [resumeNotifications, setResumeNotifications] = React.useState(false);
const [_, updateSettings, clearSettings] = useSetMythicSetting();
const onChangeFontSize = (name, value, error) => {
setFontSize(value);
}
const [, updateSettings, clearSettings] = useSetMythicSetting();
const onChangeFontFamily = (name, value, error) => {
setFontFamily(value);
}
@@ -365,7 +738,7 @@ export function SettingsOperatorUIConfigDialog(props) {
setInteractType(operatorSettingDefaults.interactType);
setUseDisplayParamsForCLIHistory(operatorSettingDefaults.useDisplayParamsForCLIHistory);
setResumeNotifications(false);
setPalette(operatorSettingDefaults.palette);
setPalette(clonePalette(operatorSettingDefaults.palette));
setTaskTimestampDisplayField(operatorSettingDefaults.taskTimestampDisplayField);
setHideTaskingContext(operatorSettingDefaults.hideTaskingContext);
setTaskingContextFields(operatorSettingDefaults.taskingContextFields);
@@ -376,9 +749,9 @@ export function SettingsOperatorUIConfigDialog(props) {
props.onClose();
}
const setColorDefaults = (mode) => {
let newPaletteOptions = {...palette};
let newPaletteOptions = clonePalette(palette);
for(const [key, value] of Object.entries(operatorSettingDefaults.palette)){
newPaletteOptions[key][mode] = value[mode];
newPaletteOptions[key] = {...newPaletteOptions[key], [mode]: value[mode]};
}
setPalette(newPaletteOptions);
}
@@ -661,242 +1034,15 @@ export function SettingsOperatorUIConfigDialog(props) {
</MythicStyledTableCell>
</TableRow>
<TableRow>
<MythicStyledTableCell></MythicStyledTableCell>
<MythicStyledTableCell>
<Typography variant={"h4"}>
Global Palette Colors
</Typography>
</MythicStyledTableCell>
</TableRow>
<TableRow hover>
<MythicStyledTableCell>Navigation Bar Color</MythicStyledTableCell>
<MythicStyledTableCell>
<div style={{display: "flex", width: "100%", paddingRight: "15px"}}>
<div style={{display: "inline-block", width: "100%"}}>
<HexColorPicker style={{width: "100%"}} color={palette?.navBarColor?.dark} onChange={(v) => onChangePaletteColor("navBarColor", "dark", v)}/>
<HexColorInput color={palette?.navBarColor?.dark} onChange={(v) => onChangePaletteColor("navBarColor", "dark", v)}/>
<Box sx={{width: "100%", height: 25, backgroundColor: palette?.navBarColor?.dark, display: "flex", alignItems: "center"}}>
<PhoneCallbackIcon style={{color: palette.navBarIcons.dark, marginRight: "5px"}}/>
<Typography style={{color: palette.navBarText.dark, display: "inline-block"}}>Dark Mode Color</Typography>
</Box>
</div>
<div style={{display: "inline-block", width: "100%"}}>
<HexColorPicker style={{width: "100%"}} color={palette?.navBarColor?.light} onChange={(v) => onChangePaletteColor("navBarColor", "light", v)}/>
<HexColorInput color={palette?.navBarColor?.light} onChange={(v) => onChangePaletteColor("navBarColor", "light", v)}/>
<Box sx={{width: "100%", height: 25, backgroundColor: palette?.navBarColor?.light, display: "flex", alignItems: "center"}}>
<PhoneCallbackIcon style={{color: palette.navBarIcons.light, marginRight: "5px"}}/>
<Typography style={{color: palette.navBarText.light, display: "inline-block"}}>Light Mode Color</Typography>
</Box>
</div>
</div>
</MythicStyledTableCell>
</TableRow>
<TableRow hover>
<MythicStyledTableCell>Navigation Bar Bottom Color</MythicStyledTableCell>
<MythicStyledTableCell>
<div style={{display: "flex", width: "100%", paddingRight: "15px"}}>
<div style={{display: "inline-block", width: "100%"}}>
<HexColorPicker style={{width: "100%"}} color={palette?.navBarBottomColor?.dark} onChange={(v) => onChangePaletteColor("navBarBottomColor", "dark", v)}/>
<HexColorInput color={palette?.navBarBottomColor?.dark} onChange={(v) => onChangePaletteColor("navBarBottomColor", "dark", v)}/>
<Box sx={{width: "100%", height: 25, backgroundColor: palette?.navBarBottomColor?.dark, display: "flex", alignItems: "center"}}>
<PhoneCallbackIcon style={{color: palette.navBarIcons.dark, marginRight: "5px"}}/>
<Typography style={{color: palette.navBarText.dark, display: "inline-block"}}>Dark Mode Color</Typography>
</Box>
</div>
<div style={{display: "inline-block", width: "100%"}}>
<HexColorPicker style={{width: "100%"}} color={palette?.navBarBottomColor?.light} onChange={(v) => onChangePaletteColor("navBarBottomColor", "light", v)}/>
<HexColorInput color={palette?.navBarBottomColor?.light} onChange={(v) => onChangePaletteColor("navBarBottomColor", "light", v)}/>
<Box sx={{width: "100%", height: 25, backgroundColor: palette?.navBarBottomColor?.light, display: "flex", alignItems: "center"}}>
<PhoneCallbackIcon style={{color: palette.navBarIcons.light, marginRight: "5px"}}/>
<Typography style={{color: palette.navBarText.light, display: "inline-block"}}>Light Mode Color</Typography>
</Box>
</div>
</div>
</MythicStyledTableCell>
</TableRow>
<TableRow hover>
<MythicStyledTableCell>Navigation Bar Icon Colors</MythicStyledTableCell>
<MythicStyledTableCell>
<div style={{display: "flex", width: "100%", paddingRight: "15px"}}>
<div style={{display: "inline-block", width: "100%"}}>
<HexColorPicker style={{width: "100%"}} color={palette?.navBarIcons?.dark} onChange={(v) => onChangePaletteColor("navBarIcons", "dark", v)}/>
<HexColorInput color={palette?.navBarIcons?.dark} onChange={(v) => onChangePaletteColor("navBarIcons", "dark", v)}/>
<Box sx={{width: "100%", height: 25, background: `linear-gradient(.25turn, ${palette?.navBarColor?.dark}, ${palette?.navBarBottomColor?.dark})`, display: "flex", alignItems: "center"}}>
<PhoneCallbackIcon style={{color: palette.navBarIcons.dark, marginRight: "5px"}}/>
<Typography style={{color: palette.navBarText.dark, display: "inline-block"}}>Dark Mode Color</Typography>
</Box>
</div>
<div style={{display: "inline-block", width: "100%"}}>
<HexColorPicker style={{width: "100%"}} color={palette?.navBarIcons?.light} onChange={(v) => onChangePaletteColor("navBarIcons", "light", v)}/>
<HexColorInput color={palette?.navBarIcons?.light} onChange={(v) => onChangePaletteColor("navBarIcons", "light", v)}/>
<Box sx={{width: "100%", height: 25, background: `linear-gradient(.25turn, ${palette?.navBarColor?.light}, ${palette?.navBarBottomColor?.light})`, display: "flex", alignItems: "center"}}>
<PhoneCallbackIcon style={{color: palette.navBarIcons.light, marginRight: "5px"}}/>
<Typography style={{color: palette.navBarText.light, display: "inline-block"}}>Light Mode Color</Typography>
</Box>
</div>
</div>
</MythicStyledTableCell>
</TableRow>
<TableRow hover>
<MythicStyledTableCell>Navigation Bar Text Color</MythicStyledTableCell>
<MythicStyledTableCell>
<div style={{display: "flex", width: "100%", paddingRight: "15px"}}>
<div style={{display: "inline-block", width: "100%"}}>
<HexColorPicker style={{width: "100%"}} color={palette?.navBarText?.dark} onChange={(v) => onChangePaletteColor("navBarText", "dark", v)}/>
<HexColorInput color={palette?.navBarText?.dark} onChange={(v) => onChangePaletteColor("navBarText", "dark", v)}/>
<Box sx={{width: "100%", height: 25, background: `linear-gradient(.25turn, ${palette?.navBarColor?.dark}, ${palette?.navBarBottomColor?.dark})`, display: "flex", alignItems: "center"}}>
<PhoneCallbackIcon style={{color: palette.navBarIcons.dark, marginRight: "5px"}}/>
<Typography style={{color: palette.navBarText.dark, display: "inline-block"}}>Dark Mode Color</Typography>
</Box>
</div>
<div style={{display: "inline-block", width: "100%"}}>
<HexColorPicker style={{width: "100%"}} color={palette?.navBarText?.light} onChange={(v) => onChangePaletteColor("navBarText", "light", v)}/>
<HexColorInput color={palette?.navBarText?.light} onChange={(v) => onChangePaletteColor("navBarText", "light", v)}/>
<Box sx={{width: "100%", height: 25, background: `linear-gradient(.25turn, ${palette?.navBarColor?.light}, ${palette?.navBarBottomColor?.light})`, display: "flex", alignItems: "center"}}>
<PhoneCallbackIcon style={{color: palette.navBarIcons.light, marginRight: "5px"}}/>
<Typography style={{color: palette.navBarText.light, display: "inline-block"}}>Light Mode Color</Typography>
</Box>
</div>
</div>
</MythicStyledTableCell>
</TableRow>
<TableRow hover>
<MythicStyledTableCell>Background Images</MythicStyledTableCell>
<MythicStyledTableCell>
<div style={{display: "flex", width: "100%", justifyContent: "space-between"}}>
<div style={{width: "100%"}}>
<Button color={"info"} variant={"contained"} onClick={()=>backgroundFileImageDarkRef.current.click()} >
Upload Dark
<input ref={backgroundFileImageDarkRef} onChange={onFileBackgroundImageChangeDark} type="file" hidden />
</Button>
<Button color={"warning"} variant={"contained"} onClick={() => onChangePaletteColor("backgroundImage", "dark", null)} >
Remove Dark
</Button>
<div style={{backgroundImage: palette.backgroundImage.dark, width: "100%", height: "300px", backgroundSize: "contain"}}>
</div>
</div>
<div style={{width: "100%"}}>
<Button color={"info"} variant={"contained"} onClick={()=>backgroundFileImageLightRef.current.click()} >
Upload Light
<input ref={backgroundFileImageLightRef} onChange={onFileBackgroundImageChangeLight} type="file" hidden />
</Button>
<Button color={"warning"} variant={"contained"} onClick={() => onChangePaletteColor("backgroundImage", "light", null)} >
Remove Light
</Button>
<div style={{backgroundImage: palette.backgroundImage.light, width: "100%", height: "300px", backgroundSize: "contain"}}>
</div>
</div>
</div>
</MythicStyledTableCell>
</TableRow>
{paletteOptionsSolidColor.map(p => (
<TableRow hover key={p.display}>
<MythicStyledTableCell>{p.display}</MythicStyledTableCell>
<MythicStyledTableCell>
<div style={{display: "flex", width: "100%", paddingRight: "15px"}}>
<div style={{display: "inline-block", width: "100%"}}>
<HexColorPicker style={{width: "100%"}} color={palette?.[p.name]?.dark} onChange={(v) => onChangePaletteColor(p.name, "dark", v)}/>
<HexColorInput color={palette?.[p.name]?.dark} onChange={(v) => onChangePaletteColor(p.name, "dark", v)}/>
<Box sx={{width: "100%", height: 25, backgroundColor: palette?.[p.name]?.dark}}>
<Typography style={{color: "white"}}>Dark Mode Color</Typography>
</Box>
</div>
<div style={{display: "inline-block", width: "100%"}}>
<HexColorPicker style={{width: "100%"}} color={palette?.[p.name]?.light} onChange={(v) => onChangePaletteColor(p.name, "light", v)}/>
<HexColorInput color={palette?.[p.name]?.light} onChange={(v) => onChangePaletteColor(p.name, "light", v)}/>
<Box sx={{width: "100%", height: 25, backgroundColor: palette?.[p.name]?.light}}>
<Typography style={{color: "black"}}>Light Mode Color</Typography>
</Box>
</div>
</div>
</MythicStyledTableCell>
</TableRow>
))}
{paletteOptionsTextColor.map(p => (
<TableRow hover key={p.display}>
<MythicStyledTableCell>{p.display}</MythicStyledTableCell>
<MythicStyledTableCell>
<div style={{display: "flex", width: "100%", paddingRight: "15px"}}>
<div style={{display: "inline-block", width: "100%"}}>
<HexColorPicker style={{width: "100%"}} color={palette?.[p.name]?.dark} onChange={(v) => onChangePaletteColor(p.name, "dark", v)}/>
<HexColorInput color={palette?.[p.name]?.dark} onChange={(v) => onChangePaletteColor(p.name, "dark", v)}/>
<Box sx={{width: "100%", height: 25, backgroundColor: palette?.[p.name]?.dark}}>
<Typography style={{color: palette.text.dark}}>Dark Mode Color</Typography>
</Box>
</div>
<div style={{display: "inline-block", width: "100%"}}>
<HexColorPicker style={{width: "100%"}} color={palette?.[p.name]?.light} onChange={(v) => onChangePaletteColor(p.name, "light", v)}/>
<HexColorInput color={palette?.[p.name]?.light} onChange={(v) => onChangePaletteColor(p.name, "light", v)}/>
<Box sx={{width: "100%", height: 25, backgroundColor: palette?.[p.name]?.light}}>
<Typography style={{color: palette.text.light}}>Light Mode Color</Typography>
</Box>
</div>
</div>
</MythicStyledTableCell>
</TableRow>
))}
<TableRow hover>
<MythicStyledTableCell>Text Color</MythicStyledTableCell>
<MythicStyledTableCell>
<div style={{display: "flex", width: "100%", paddingRight: "15px"}}>
<div style={{display: "inline-block", width: "100%"}}>
<HexColorPicker style={{width: "100%"}} color={palette?.text?.dark} onChange={(v) => onChangePaletteColor("text", "dark", v)}/>
<HexColorInput color={palette?.text?.dark} onChange={(v) => onChangePaletteColor("text", "dark", v)}/>
<Box sx={{width: "100%", height: 25, backgroundColor: palette?.background?.dark, display: "flex", alignItems: "center"}}>
<Typography style={{color: palette.text.dark, display: "inline-block"}}>Dark Mode Color</Typography>
</Box>
</div>
<div style={{display: "inline-block", width: "100%"}}>
<HexColorPicker style={{width: "100%"}} color={palette?.text?.light} onChange={(v) => onChangePaletteColor("text", "light", v)}/>
<HexColorInput color={palette?.text?.light} onChange={(v) => onChangePaletteColor("text", "light", v)}/>
<Box sx={{width: "100%", height: 25, backgroundColor: palette?.background?.light, display: "flex", alignItems: "center"}}>
<Typography style={{color: palette.text.light, display: "inline-block"}}>Light Mode Color</Typography>
</Box>
</div>
</div>
</MythicStyledTableCell>
</TableRow>
<TableRow hover>
<MythicStyledTableCell>Task Output Text Color</MythicStyledTableCell>
<MythicStyledTableCell>
<div style={{display: "flex", width: "100%", paddingRight: "15px"}}>
<div style={{display: "inline-block", width: "100%"}}>
<HexColorPicker style={{width: "100%"}} color={palette?.outputTextColor?.dark} onChange={(v) => onChangePaletteColor("outputTextColor", "dark", v)}/>
<HexColorInput color={palette?.outputTextColor?.dark} onChange={(v) => onChangePaletteColor("outputTextColor", "dark", v)}/>
<Box sx={{width: "100%", height: 25, backgroundColor: palette?.outputBackgroundColor?.dark, display: "flex", alignItems: "center"}}>
<Typography style={{color: palette.outputTextColor.dark, display: "inline-block"}}>Dark Mode Output Text Color</Typography>
</Box>
</div>
<div style={{display: "inline-block", width: "100%"}}>
<HexColorPicker style={{width: "100%"}} color={palette?.outputTextColor?.light} onChange={(v) => onChangePaletteColor("outputTextColor", "light", v)}/>
<HexColorInput color={palette?.outputTextColor?.light} onChange={(v) => onChangePaletteColor("outputTextColor", "light", v)}/>
<Box sx={{width: "100%", height: 25, backgroundColor: palette?.outputBackgroundColor?.light, display: "flex", alignItems: "center"}}>
<Typography style={{color: palette.outputTextColor.light, display: "inline-block"}}>Light Mode Output Text Color</Typography>
</Box>
</div>
</div>
</MythicStyledTableCell>
</TableRow>
<TableRow hover>
<MythicStyledTableCell>Task Output Background Color</MythicStyledTableCell>
<MythicStyledTableCell>
<div style={{display: "flex", width: "100%", paddingRight: "15px"}}>
<div style={{display: "inline-block", width: "100%"}}>
<HexColorPicker style={{width: "100%"}} color={palette?.outputBackgroundColor?.dark} onChange={(v) => onChangePaletteColor("outputBackgroundColor", "dark", v)}/>
<HexColorInput color={palette?.outputBackgroundColor?.dark} onChange={(v) => onChangePaletteColor("outputBackgroundColor", "dark", v)}/>
<Box sx={{width: "100%", height: 25, backgroundColor: palette?.outputBackgroundColor?.dark, display: "flex", alignItems: "center"}}>
<Typography style={{color: palette.outputTextColor.dark, display: "inline-block"}}>Dark Mode Output Text Color</Typography>
</Box>
</div>
<div style={{display: "inline-block", width: "100%"}}>
<HexColorPicker style={{width: "100%"}} color={palette?.outputBackgroundColor?.light} onChange={(v) => onChangePaletteColor("outputBackgroundColor", "light", v)}/>
<HexColorInput color={palette?.outputBackgroundColor?.light} onChange={(v) => onChangePaletteColor("outputBackgroundColor", "light", v)}/>
<Box sx={{width: "100%", height: 25, backgroundColor: palette?.outputBackgroundColor?.light, display: "flex", alignItems: "center"}}>
<Typography style={{color: palette.outputTextColor.light, display: "inline-block"}}>Light Mode Output Text Color</Typography>
</Box>
</div>
</div>
<MythicStyledTableCell colSpan={2} style={{paddingTop: "16px", paddingBottom: "16px"}}>
<ColorPaletteEditor
palette={palette}
onChangePaletteColor={onChangePaletteColor}
backgroundFileImageDarkRef={backgroundFileImageDarkRef}
backgroundFileImageLightRef={backgroundFileImageLightRef}
onFileBackgroundImageChangeDark={onFileBackgroundImageChangeDark}
onFileBackgroundImageChangeLight={onFileBackgroundImageChangeLight}
/>
</MythicStyledTableCell>
</TableRow>
</TableBody>
@@ -921,4 +1067,3 @@ export function SettingsOperatorUIConfigDialog(props) {
</React.Fragment>
);
}
+86 -41
View File
@@ -2,14 +2,39 @@ import { createGlobalStyle} from "styled-components"
// hex transparencies https://gist.github.com/lopspower/03fb1cc0ac9f32ef38f4
export const GlobalStyles = createGlobalStyle`
body {
margin: 0
margin: 0;
background-color: ${(props) => props.theme.palette.background.default};
color: ${(props) => props.theme.palette.text.primary};
font-family: ${(props) => props.theme.typography.fontFamily};
}
html, body, #root {
height: 100%;
width: 100%;
color-scheme: light dark;
}
* {
box-sizing: border-box;
}
::selection {
background-color: ${(props) => props.theme.palette.primary.main + "40"};
}
* {
scrollbar-color: ${(props) => props.theme.borderColor} transparent;
scrollbar-width: thin;
}
*::-webkit-scrollbar {
height: 10px;
width: 10px;
}
*::-webkit-scrollbar-thumb {
background-color: ${(props) => props.theme.borderColor};
border: 3px solid transparent;
border-radius: 999px;
background-clip: padding-box;
}
*::-webkit-scrollbar-track {
background: transparent;
}
@media screen and (max-width: 1100px) {
.hideOnSmallWidth {
display: none;
@@ -35,23 +60,27 @@ html, body, #root {
}
.MuiTableCell-head {
background-color: ${(props) => props.theme.tableHeader} !important;
font-weight: bold;
border-top: 2px solid ${(props) => props.theme.borderColor};
border-bottom: 2px solid ${(props) => props.theme.borderColor};
color: ${(props) => props.theme.palette.text.primary};
font-size: 0.76rem;
font-weight: 700;
letter-spacing: 0;
text-transform: uppercase;
border-top: 0;
border-bottom: 1px solid ${(props) => props.theme.table?.border || props.theme.borderColor};
}
tr:nth-child(even) {
background-color: ${(props) => props.theme.palette.mode === 'dark' ? props.theme.tableHover + "80" : props.theme.tableHover + "80"};
background-color: ${(props) => props.theme.table?.rowStripe || props.theme.tableHover + "66"};
}
.alternateRow {
background-color: ${(props) => props.theme.palette.mode === 'dark' ? props.theme.tableHover + "0D" : props.theme.tableHover + "80"};
background-color: ${(props) => props.theme.table?.rowStripe || props.theme.tableHover + "66"};
}
.MythicResizableGridRowHighlight {
background-color: ${(props) => props.theme.palette.mode === 'dark' ? props.theme.tableHover + "60" : props.theme.tableHover + "10"};
background-color: ${(props) => props.theme.table?.rowStripe || props.theme.tableHover + "66"};
}
.MuiTableRow-hover {
&:hover,
&--hovered {
background-color: ${(props) => props.theme.tableHover + "CC"} !important;
background-color: ${(props) => props.theme.table?.rowHover || props.theme.tableHover + "CC"} !important;
color: ${(props) => props.theme.palette.text.primary} !important;
}
}
@@ -62,7 +91,7 @@ tr:nth-child(even) {
.MuiListItem-root {
&:hover,
&--hovered {
background-color: ${(props) => props.theme.tableHover + "CC"} !important;
background-color: ${(props) => props.theme.surfaces?.hover || props.theme.palette.action.hover} !important;
color: ${(props) => props.theme.palette.text.primary} !important;
}
}
@@ -115,7 +144,7 @@ tspan {
z-index: 0 !important
}
.gutter {
background-color: ${(props) => props.theme.topAppBarColor};
background-color: ${(props) => props.theme.borderColor};
background-repeat: no-repeat;
background-position: 50%;
}
@@ -170,8 +199,8 @@ tspan {
.context-menu {
background-color: ${(props) => props.theme.palette.background.paper};
border: 1px solid ${(props) => props.theme.borderColor};
border-radius: 5px;
box-shadow: 10px 19px 20px rgba(0, 0, 0, 10%);
border-radius: ${(props) => props.theme.shape.borderRadius + 2}px;
box-shadow: ${(props) => props.theme.palette.mode === 'dark' ? "0 18px 48px rgba(0, 0, 0, 40%)" : "0 18px 48px rgba(15, 23, 42, 12%)"};
position: absolute;
z-index: 10;
}
@@ -201,21 +230,30 @@ tspan {
display: flex;
align-items: center;
position: relative;
padding: 0 0.5em;
padding: 0 8px;
box-sizing: border-box;
justify-content: space-between;
user-select: none;
border-top: 2px solid ${(props) => props.theme.borderColor};
border-bottom: 2px solid ${(props) => props.theme.borderColor};
border-right: 1px solid ${(props) => props.theme.table?.borderSoft || props.theme.borderColor};
border-bottom: 1px solid ${(props) => props.theme.table?.border || props.theme.borderColor};
background-color: ${(props) => props.theme.tableHeader} !important;
color: ${(props) => props.theme.palette.text.primary};
font-size: 0.76rem;
font-weight: 700;
letter-spacing: 0;
&:first-child-of-type {
border-left: 2px solid ${(props) => props.theme.borderColor};
border-left: 0;
}
&:hover {
background-color: ${(props) => props.theme.tableHover};
background-color: ${(props) => props.theme.table?.headerHover || props.theme.tableHover};
cursor: pointer;
}
}
.MythicResizableGrid-headerCell .MythicResizableGrid-cellInner {
font-size: 0.76rem;
font-weight: 700;
line-height: 1.2;
}
.MythicResizableGrid-headerResizeHandle {
position: absolute;
top: 0;
@@ -233,9 +271,9 @@ tspan {
right: 2px;
width: 0px;
height: 100%;
border-left: 1px solid ${(props) => props.theme.palette.text.main};
border-right: 1px solid ${(props) => props.theme.palette.text.main};
opacity: 0.85;
border-left: 1px solid ${(props) => props.theme.palette.text.secondary};
border-right: 1px solid ${(props) => props.theme.palette.text.secondary};
opacity: 0.55;
}
.MythicResizableGrid-headerResizeHandle:hover,
.MythicResizableGrid-headerResizeHandleActive {
@@ -252,15 +290,19 @@ tspan {
opacity: 1;
}
.MythicResizableGrid-hoveredRow {
background-color: ${(props) => props.theme.tableHover + "CC"};
background-color: ${(props) => props.theme.table?.rowHover || props.theme.tableHover + "CC"};
}
.MythicResizableGrid-cell {
display: flex;
align-items: center;
padding: 0 0.5em;
padding: 0 8px;
box-sizing: border-box;
font-family: monospace;
border-bottom: 1px solid ${(props) => props.theme.borderColor};
color: ${(props) => props.theme.palette.text.primary};
font-family: ${(props) => props.theme.typography.fontFamily};
font-size: 0.86rem;
font-variant-numeric: tabular-nums;
border-right: 1px solid ${(props) => props.theme.table?.borderSoft || props.theme.borderColor};
border-bottom: 1px solid ${(props) => props.theme.table?.borderSoft || props.theme.borderColor};
cursor: default !important;
}
.MythicResizableGrid-cellInner {
@@ -289,7 +331,7 @@ tspan {
}
.MuiPaper-root {
border: 1px solid ${(props) => props.theme.borderColor};
border-radius: 5px;
border-radius: ${(props) => props.theme.shape.borderRadius}px;
background-color: ${(props) => props.theme.palette.background.paper};
background-image: unset;
}
@@ -303,13 +345,13 @@ tspan {
.MuiList-root {
background-color: ${(props) => props.theme.palette.background.paper};
border: 1px solid ${(props) => props.theme.borderColor};
border-radius: 3px;
line-height: 30px;
border-radius: ${(props) => props.theme.shape.borderRadius}px;
line-height: 28px;
}
.dropdownMenuColored {
background-color: ${(props) => props.theme.palette.background.paper} !important;
border: 1px solid ${(props) => props.theme.borderColor};
border-radius: 5px;
border-radius: ${(props) => props.theme.shape.borderRadius}px;
//color: white;
}
// gets the title of the table
@@ -329,21 +371,21 @@ tspan {
min-height: 2rem;
}
.selectedCallback {
background-color: ${(props) => props.theme.selectedCallbackColor + "CC"};
background-color: ${(props) => props.theme.table?.selected || props.theme.selectedCallbackColor + "CC"};
}
.selectedCallbackHierarchy {
background-color: ${(props) => props.theme.selectedCallbackHierarchyColor + "CC"};
background-color: ${(props) => props.theme.table?.selectedHierarchy || props.theme.selectedCallbackHierarchyColor + "CC"};
}
.MuiDataGrid-row.Mui-selected {
background-color: ${(props) => props.theme.selectedCallbackColor} !important;
background-color: ${(props) => props.theme.table?.selected || props.theme.selectedCallbackColor + "CC"} !important;
}
.roundedBottomCorners {
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
}
.MuiInputLabel-root {
color: ${(props) => props.theme.borderColor} !important;
color: ${(props) => props.theme.palette.text.secondary} !important;
}
.MuiOutlinedInput-notchedOutline {
border-color: ${(props) => props.theme.borderColor} !important;
@@ -355,19 +397,22 @@ tspan {
border-color: ${(props) => props.theme.borderColor} !important;
}
.Mui-focused {
border-color: ${(props) => props.theme.borderColor} !important;
border-color: ${(props) => props.theme.palette.primary.main} !important;
}
.MuiInputBase-input {
border-color: ${(props) => props.theme.borderColor} !important;
}
.MuiInput-root::after {
border-color: ${(props) => props.theme.borderColor} !important;
border-color: ${(props) => props.theme.palette.primary.main} !important;
}
.MuiTableCell-root {
padding: 0 16px 0 16px;
padding: 6px 10px;
border-bottom: 1px solid ${(props) => props.theme.table?.borderSoft || props.theme.borderColor};
line-height: 1.35;
vertical-align: middle;
}
.MuiTabs-root {
min-height: 30px;
min-height: 34px;
}
.MuiTab-root {
min-width: unset !important;
@@ -395,11 +440,11 @@ tspan {
color: ${(props) => props.theme.outputTextColor};
}
.rounded-tab {
border-top-left-radius: 10px;
border-top-right-radius: 10px;
padding: 0 10px 0 10px;
border-top-left-radius: ${(props) => props.theme.shape.borderRadius}px;
border-top-right-radius: ${(props) => props.theme.shape.borderRadius}px;
padding: 2px 10px 0 10px;
border-top: 1px solid ${(props) => props.theme.borderColor};
border-left: 2px solid ${(props) => props.theme.borderColor};
border-left: 1px solid ${(props) => props.theme.borderColor};
border-right: 1px solid ${(props) => props.theme.borderColor};
border-bottom: 1px solid ${(props) => props.theme.borderColor};
position: relative;