mirror of
https://github.com/its-a-feature/Mythic
synced 2026-06-08 14:55:38 +00:00
more detailed color settings
This commit is contained in:
@@ -130,6 +130,14 @@ export const operatorSettingDefaults = {
|
||||
dark: '#161b22',
|
||||
light: '#ffffff'
|
||||
},
|
||||
surfaceRaised: {
|
||||
dark: '#1b222c',
|
||||
light: '#ffffff'
|
||||
},
|
||||
surfaceMuted: {
|
||||
dark: '#121820',
|
||||
light: '#eef2f6'
|
||||
},
|
||||
tableHeader: {
|
||||
dark: '#484848',
|
||||
light: '#c4c4c4'
|
||||
@@ -142,10 +150,94 @@ export const operatorSettingDefaults = {
|
||||
dark: '#171d25',
|
||||
light: '#ffffff'
|
||||
},
|
||||
pageHeaderText: {
|
||||
dark: "#e5e7eb",
|
||||
light: "#111827",
|
||||
},
|
||||
sectionHeaderAccent: {
|
||||
dark: "#8ab4f8",
|
||||
light: "#2563eb",
|
||||
},
|
||||
sectionHeaderGradientStart: {
|
||||
dark: "#374760",
|
||||
light: "#d8e3fb",
|
||||
},
|
||||
sectionHeaderGradientMiddle: {
|
||||
dark: "#253040",
|
||||
light: "#edf3fe",
|
||||
},
|
||||
sectionHeaderGradientEnd: {
|
||||
dark: "#242a31",
|
||||
light: "#f5f6f7",
|
||||
},
|
||||
subtleAccentGradientStart: {
|
||||
dark: "#1d2b3f",
|
||||
light: "#edf4ff",
|
||||
},
|
||||
subtleAccentGradientEnd: {
|
||||
dark: "#161b22",
|
||||
light: "#ffffff",
|
||||
},
|
||||
graphGroupColor: {
|
||||
dark: "#394c5d",
|
||||
light: "#d3d7e8",
|
||||
},
|
||||
speedDialAction: {
|
||||
dark: "#495054",
|
||||
light: "#ffffff",
|
||||
},
|
||||
chartSeries1: {
|
||||
dark: "#09bdff",
|
||||
light: "#09bdff",
|
||||
},
|
||||
chartSeries2: {
|
||||
dark: "#39b86f",
|
||||
light: "#39b86f",
|
||||
},
|
||||
chartSeries3: {
|
||||
dark: "#d69d2d",
|
||||
light: "#d69d2d",
|
||||
},
|
||||
chartSeries4: {
|
||||
dark: "#d65c6b",
|
||||
light: "#d65c6b",
|
||||
},
|
||||
chartSeries5: {
|
||||
dark: "#7b6fd6",
|
||||
light: "#7b6fd6",
|
||||
},
|
||||
chartSeries6: {
|
||||
dark: "#24a3a3",
|
||||
light: "#24a3a3",
|
||||
},
|
||||
chartSeries7: {
|
||||
dark: "#9c6ade",
|
||||
light: "#9c6ade",
|
||||
},
|
||||
chartSeries8: {
|
||||
dark: "#d47f38",
|
||||
light: "#d47f38",
|
||||
},
|
||||
chartSeries9: {
|
||||
dark: "#4e7ad7",
|
||||
light: "#4e7ad7",
|
||||
},
|
||||
chartSeries10: {
|
||||
dark: "#90a955",
|
||||
light: "#90a955",
|
||||
},
|
||||
text: {
|
||||
dark: "#e5e7eb",
|
||||
light: "#111827",
|
||||
},
|
||||
textSecondary: {
|
||||
dark: "#9ca3af",
|
||||
light: "#475569",
|
||||
},
|
||||
textDisabled: {
|
||||
dark: "#6b7280",
|
||||
light: "#94a3b8",
|
||||
},
|
||||
selectedCallbackColor: {
|
||||
dark: '#1e3a5f',
|
||||
light: '#dbeafe',
|
||||
@@ -198,6 +290,10 @@ export const operatorSettingDefaults = {
|
||||
dark: '#94a3b8',
|
||||
light: '#64748b'
|
||||
},
|
||||
folderColor: {
|
||||
dark: '#f1d592',
|
||||
light: '#f1d592'
|
||||
},
|
||||
outputBackgroundColor: {
|
||||
dark: '#0b1017',
|
||||
light: '#f8fafc'
|
||||
|
||||
@@ -62,6 +62,22 @@ query getUserSettings {
|
||||
}
|
||||
`;
|
||||
|
||||
const normalizeBackgroundImageValue = (value) => {
|
||||
if(typeof value !== "string" || value.length === 0){
|
||||
return null;
|
||||
}
|
||||
if(value.startsWith("data:image/")){
|
||||
return `url("${value}")`;
|
||||
}
|
||||
if(value.startsWith("url(\"data:image/") && !value.endsWith("\")")){
|
||||
return `${value}")`;
|
||||
}
|
||||
if(value.startsWith("url(data:image/") && !value.endsWith(")")){
|
||||
return `${value})`;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
const getModernThemeAdditions = (themeMode, preferences = operatorSettingDefaults) => {
|
||||
const isDark = themeMode === "dark";
|
||||
const mode = isDark ? "dark" : "light";
|
||||
@@ -76,15 +92,24 @@ const getModernThemeAdditions = (themeMode, preferences = operatorSettingDefault
|
||||
return color;
|
||||
};
|
||||
const textPrimary = getColor("text");
|
||||
const textSecondary = isDark ? "#9ca3af" : "#475569";
|
||||
const textSecondary = getColor("textSecondary");
|
||||
const borderColor = getColor("borderColor");
|
||||
const backgroundDefault = getColor("background");
|
||||
const backgroundPaper = getColor("paper");
|
||||
const surfaceRaised = getColor("surfaceRaised");
|
||||
const surfaceMuted = getColor("surfaceMuted");
|
||||
const navBackground = getColor("navBarColor");
|
||||
const navAccent = getColor("navBarBottomColor");
|
||||
const navText = getColor("navBarText");
|
||||
const navIcon = getColor("navBarIcons");
|
||||
const primary = getColor("primary");
|
||||
const sectionHeaderAccent = getColor("sectionHeaderAccent");
|
||||
const sectionHeaderGradientStart = getColor("sectionHeaderGradientStart");
|
||||
const sectionHeaderGradientMiddle = getColor("sectionHeaderGradientMiddle");
|
||||
const sectionHeaderGradientEnd = getColor("sectionHeaderGradientEnd");
|
||||
const subtleAccentGradientStart = getColor("subtleAccentGradientStart");
|
||||
const subtleAccentGradientEnd = getColor("subtleAccentGradientEnd");
|
||||
const chartSeriesColors = Array.from({length: 10}, (_, index) => getColor(`chartSeries${index + 1}`));
|
||||
const tableHeaderColor = getColor("tableHeader");
|
||||
const tableHoverColor = getColor("tableHover");
|
||||
const tableRowStripeColor = withAlpha(tableHoverColor, isDark ? "55" : "66");
|
||||
@@ -99,7 +124,12 @@ const getModernThemeAdditions = (themeMode, preferences = operatorSettingDefault
|
||||
borderRadius: 6,
|
||||
},
|
||||
pageHeaderText: {
|
||||
main: textPrimary,
|
||||
main: getColor("pageHeaderText"),
|
||||
},
|
||||
gradients: {
|
||||
sectionHeader: `linear-gradient(90deg, ${sectionHeaderGradientStart} 0%, ${sectionHeaderGradientMiddle} 48%, ${sectionHeaderGradientEnd} 100%)`,
|
||||
subtleAccent: `linear-gradient(135deg, ${subtleAccentGradientStart} 0%, ${subtleAccentGradientEnd} 62%)`,
|
||||
subtleAccentHorizontal: `linear-gradient(90deg, ${subtleAccentGradientStart} 0%, ${subtleAccentGradientEnd} 100%)`,
|
||||
},
|
||||
navigation: {
|
||||
background: `linear-gradient(180deg, ${navBackground}, ${navAccent})`,
|
||||
@@ -112,11 +142,18 @@ const getModernThemeAdditions = (themeMode, preferences = operatorSettingDefault
|
||||
muted: withAlpha(navText, "B3"),
|
||||
accent: navAccent,
|
||||
},
|
||||
sectionHeader: {
|
||||
accent: sectionHeaderAccent,
|
||||
gradientStart: sectionHeaderGradientStart,
|
||||
gradientMiddle: sectionHeaderGradientMiddle,
|
||||
gradientEnd: sectionHeaderGradientEnd,
|
||||
},
|
||||
chartSeriesColors,
|
||||
surfaces: {
|
||||
app: backgroundDefault,
|
||||
paper: backgroundPaper,
|
||||
raised: isDark ? "#1b222c" : "#ffffff",
|
||||
muted: isDark ? withAlpha(backgroundDefault, "DD") : withAlpha(backgroundDefault, "EE"),
|
||||
raised: surfaceRaised,
|
||||
muted: surfaceMuted,
|
||||
hover: tableRowHoverColor,
|
||||
selected: tableSelectedColor,
|
||||
},
|
||||
@@ -639,27 +676,35 @@ export function App(props) {
|
||||
preferences?.palette?.background?.light || operatorSettingDefaults.palette.background.light,
|
||||
paper: themeMode === "dark" ? preferences?.palette?.paper?.dark || operatorSettingDefaults.palette.paper.dark :
|
||||
preferences?.palette?.paper?.light || operatorSettingDefaults.palette.paper.light,
|
||||
image: themeMode === "dark" ? preferences?.palette?.backgroundImage?.dark || operatorSettingDefaults.palette.backgroundImage.dark :
|
||||
preferences?.palette?.backgroundImage?.light || operatorSettingDefaults.palette.backgroundImage.light,
|
||||
image: normalizeBackgroundImageValue(themeMode === "dark" ? preferences?.palette?.backgroundImage?.dark || operatorSettingDefaults.palette.backgroundImage.dark :
|
||||
preferences?.palette?.backgroundImage?.light || operatorSettingDefaults.palette.backgroundImage.light),
|
||||
},
|
||||
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',
|
||||
secondary: themeMode === 'dark' ? preferences?.palette?.textSecondary?.dark || operatorSettingDefaults.palette.textSecondary.dark :
|
||||
preferences?.palette?.textSecondary?.light || operatorSettingDefaults.palette.textSecondary.light,
|
||||
disabled: themeMode === 'dark' ? preferences?.palette?.textDisabled?.dark || operatorSettingDefaults.palette.textDisabled.dark :
|
||||
preferences?.palette?.textDisabled?.light || operatorSettingDefaults.palette.textDisabled.light,
|
||||
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)',
|
||||
hover: themeMode === 'dark' ? `${preferences?.palette?.tableHover?.dark || operatorSettingDefaults.palette.tableHover.dark}CC` :
|
||||
`${preferences?.palette?.tableHover?.light || operatorSettingDefaults.palette.tableHover.light}CC`,
|
||||
selected: themeMode === 'dark' ? `${preferences?.palette?.selectedCallbackColor?.dark || operatorSettingDefaults.palette.selectedCallbackColor.dark}99` :
|
||||
`${preferences?.palette?.selectedCallbackColor?.light || operatorSettingDefaults.palette.selectedCallbackColor.light}99`,
|
||||
focus: themeMode === 'dark' ? `${preferences?.palette?.primary?.dark || operatorSettingDefaults.palette.primary.dark}55` :
|
||||
`${preferences?.palette?.primary?.light || operatorSettingDefaults.palette.primary.light}33`,
|
||||
},
|
||||
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',
|
||||
graphGroupRGBA: themeMode === 'dark' ? `${preferences?.palette?.graphGroupColor?.dark || operatorSettingDefaults.palette.graphGroupColor.dark}80` :
|
||||
`${preferences?.palette?.graphGroupColor?.light || operatorSettingDefaults.palette.graphGroupColor.light}80`,
|
||||
speedDialAction: themeMode === 'dark' ? preferences?.palette?.speedDialAction?.dark || operatorSettingDefaults.palette.speedDialAction.dark :
|
||||
preferences?.palette?.speedDialAction?.light || operatorSettingDefaults.palette.speedDialAction.light,
|
||||
},
|
||||
folderColor: '#f1d592',
|
||||
folderColor: themeMode === 'dark' ? preferences?.palette?.folderColor?.dark || operatorSettingDefaults.palette.folderColor.dark :
|
||||
preferences?.palette?.folderColor?.light || operatorSettingDefaults.palette.folderColor.light,
|
||||
tableHeader: themeMode === 'dark' ? preferences?.palette?.tableHeader?.dark || operatorSettingDefaults.palette.tableHeader.dark :
|
||||
preferences?.palette?.tableHeader?.light || operatorSettingDefaults.palette.tableHeader.light,
|
||||
selectedCallbackColor: themeMode === 'dark' ? preferences?.palette?.selectedCallbackColor?.dark || operatorSettingDefaults.palette.selectedCallbackColor.dark :
|
||||
@@ -677,8 +722,8 @@ export function App(props) {
|
||||
preferences?.palette?.pageHeader?.light || operatorSettingDefaults.palette.pageHeader.light,
|
||||
},
|
||||
pageHeaderText: {
|
||||
main: themeMode === 'dark' ? preferences?.palette?.text?.dark || operatorSettingDefaults.palette.text.dark :
|
||||
preferences?.palette?.text?.light || operatorSettingDefaults.palette.text.light,
|
||||
main: themeMode === 'dark' ? preferences?.palette?.pageHeaderText?.dark || operatorSettingDefaults.palette.pageHeaderText.dark :
|
||||
preferences?.palette?.pageHeaderText?.light || operatorSettingDefaults.palette.pageHeaderText.light,
|
||||
},
|
||||
topAppBarColor: themeMode === 'dark' ? (preferences?.palette?.navBarColor?.dark || operatorSettingDefaults.palette.navBarColor.dark) :
|
||||
(preferences?.palette?.navBarColor?.light || operatorSettingDefaults.palette.navBarColor.light),
|
||||
@@ -751,27 +796,35 @@ export function App(props) {
|
||||
operatorSettingDefaults.palette.background.light,
|
||||
paper: themeMode === "dark" ? operatorSettingDefaults.palette.paper.dark :
|
||||
operatorSettingDefaults.palette.paper.light,
|
||||
image: themeMode === "dark" ? operatorSettingDefaults.palette.backgroundImage.dark :
|
||||
operatorSettingDefaults.palette.backgroundImage.light,
|
||||
image: normalizeBackgroundImageValue(themeMode === "dark" ? operatorSettingDefaults.palette.backgroundImage.dark :
|
||||
operatorSettingDefaults.palette.backgroundImage.light),
|
||||
},
|
||||
text: {
|
||||
primary: themeMode === 'dark' ? operatorSettingDefaults.palette.text.dark :
|
||||
operatorSettingDefaults.palette.text.light,
|
||||
secondary: themeMode === 'dark' ? '#9ca3af' : '#475569',
|
||||
disabled: themeMode === 'dark' ? '#6b7280' : '#94a3b8',
|
||||
secondary: themeMode === 'dark' ? operatorSettingDefaults.palette.textSecondary.dark :
|
||||
operatorSettingDefaults.palette.textSecondary.light,
|
||||
disabled: themeMode === 'dark' ? operatorSettingDefaults.palette.textDisabled.dark :
|
||||
operatorSettingDefaults.palette.textDisabled.light,
|
||||
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)',
|
||||
hover: themeMode === 'dark' ? `${operatorSettingDefaults.palette.tableHover.dark}CC` :
|
||||
`${operatorSettingDefaults.palette.tableHover.light}CC`,
|
||||
selected: themeMode === 'dark' ? `${operatorSettingDefaults.palette.selectedCallbackColor.dark}99` :
|
||||
`${operatorSettingDefaults.palette.selectedCallbackColor.light}99`,
|
||||
focus: themeMode === 'dark' ? `${operatorSettingDefaults.palette.primary.dark}55` :
|
||||
`${operatorSettingDefaults.palette.primary.light}33`,
|
||||
},
|
||||
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',
|
||||
graphGroupRGBA: themeMode === 'dark' ? `${operatorSettingDefaults.palette.graphGroupColor.dark}80` :
|
||||
`${operatorSettingDefaults.palette.graphGroupColor.light}80`,
|
||||
speedDialAction: themeMode === 'dark' ? operatorSettingDefaults.palette.speedDialAction.dark :
|
||||
operatorSettingDefaults.palette.speedDialAction.light,
|
||||
},
|
||||
folderColor: '#f1d592',
|
||||
folderColor: themeMode === 'dark' ? operatorSettingDefaults.palette.folderColor.dark :
|
||||
operatorSettingDefaults.palette.folderColor.light,
|
||||
tableHeader: themeMode === 'dark' ? operatorSettingDefaults.palette.tableHeader.dark :
|
||||
operatorSettingDefaults.palette.tableHeader.light,
|
||||
selectedCallbackColor: themeMode === 'dark' ? operatorSettingDefaults.palette.selectedCallbackColor.dark :
|
||||
@@ -789,8 +842,8 @@ export function App(props) {
|
||||
operatorSettingDefaults.palette.pageHeader.light,
|
||||
},
|
||||
pageHeaderText: {
|
||||
main: themeMode === 'dark' ? operatorSettingDefaults.palette.text.dark :
|
||||
operatorSettingDefaults.palette.text.light,
|
||||
main: themeMode === 'dark' ? operatorSettingDefaults.palette.pageHeaderText.dark :
|
||||
operatorSettingDefaults.palette.pageHeaderText.light,
|
||||
},
|
||||
topAppBarColor: themeMode === 'dark' ? operatorSettingDefaults.palette.navBarColor.dark :
|
||||
operatorSettingDefaults.palette.navBarColor.light,
|
||||
|
||||
@@ -249,10 +249,7 @@ export const MythicSectionHeader = ({
|
||||
}) => {
|
||||
const theme = useTheme();
|
||||
const headerTextColor = theme.pageHeaderText?.main || theme.palette.text.primary;
|
||||
const sectionAccentColor = theme.palette.primary.main;
|
||||
const sectionOverlayStart = alpha(sectionAccentColor, theme.palette.mode === "dark" ? 0.28 : 0.18);
|
||||
const sectionOverlayMiddle = alpha(sectionAccentColor, theme.palette.mode === "dark" ? 0.12 : 0.08);
|
||||
const sectionOverlayEnd = alpha(headerTextColor, theme.palette.mode === "dark" ? 0.055 : 0.04);
|
||||
const sectionAccentColor = theme.sectionHeader?.accent || theme.palette.primary.main;
|
||||
return (
|
||||
<MythicPageHeader
|
||||
actions={actions}
|
||||
@@ -261,7 +258,7 @@ export const MythicSectionHeader = ({
|
||||
subtitle={subtitle}
|
||||
title={title}
|
||||
sx={{
|
||||
backgroundImage: `linear-gradient(90deg, ${sectionOverlayStart} 0%, ${sectionOverlayMiddle} 48%, ${sectionOverlayEnd} 100%)`,
|
||||
backgroundImage: theme.gradients?.sectionHeader,
|
||||
borderColor: alpha(sectionAccentColor, theme.palette.mode === "dark" ? 0.55 : 0.38),
|
||||
boxShadow: `inset 0 1px 0 ${alpha(headerTextColor, 0.22)}, 0 2px 6px ${alpha(theme.palette.common.black, theme.palette.mode === "dark" ? 0.28 : 0.12)}`,
|
||||
mb: 0.5,
|
||||
|
||||
@@ -59,7 +59,7 @@ const Root = styled('div')((
|
||||
|
||||
[`& .${classes.checkIcon}`]: {
|
||||
fontSize: 20,
|
||||
color: '#b3b3b3',
|
||||
color: theme.palette.text.secondary,
|
||||
paddingRight: 4,
|
||||
},
|
||||
|
||||
@@ -83,4 +83,4 @@ export const MythicSnackDownload = (props) => {
|
||||
</React.Fragment>
|
||||
</Root>
|
||||
);
|
||||
};
|
||||
};
|
||||
|
||||
@@ -24,8 +24,8 @@ export const StyledDivider = styled(Divider)((
|
||||
}
|
||||
) => ({
|
||||
[`&.${classes.divider}`]: {
|
||||
backgroundColor: "rgb(100, 170, 204)",
|
||||
border: "2px solid rgba(100, 170, 204)"
|
||||
backgroundColor: theme.palette.primary.main,
|
||||
border: `2px solid ${theme.palette.primary.main}`
|
||||
}
|
||||
}));
|
||||
export const StyledButton = styled(Button)((
|
||||
|
||||
@@ -881,7 +881,7 @@ export function TopAppBarVertical(props) {
|
||||
<StyledListItem className={classes.listSubHeader} style={{display: me?.user?.current_operation_id === 0 ? "" : "none"}}>
|
||||
<ListItemText primary={
|
||||
<>
|
||||
<Link style={{display: "inline-flex", alignItems: "center", paddingRight: "10px", color: "#f84d4d",
|
||||
<Link style={{display: "inline-flex", alignItems: "center", paddingRight: "10px", color: theme.palette.error.main,
|
||||
fontWeight: "bold",}} to="/new/operations">
|
||||
{"CLICK TO SET OPERATION!"}
|
||||
</Link>
|
||||
|
||||
+6
-6
@@ -791,9 +791,9 @@ export const CallbacksTabsCustomFileBasedBrowserTable = (props) => {
|
||||
left: "35%",
|
||||
top: "40%",
|
||||
borderRadius: "4px",
|
||||
border: "1px solid black",
|
||||
border: `1px solid ${theme.palette.divider}`,
|
||||
padding: "5px",
|
||||
backgroundColor: "rgba(37,37,37,0.92)", color: "white",
|
||||
backgroundColor: theme.palette.background.contrast, color: theme.palette.text.contrast,
|
||||
}}>
|
||||
{"Only PARTIAL data has been collected for this path. "}<br/>
|
||||
{"Task this callback to list the contents"}
|
||||
@@ -812,9 +812,9 @@ export const CallbacksTabsCustomFileBasedBrowserTable = (props) => {
|
||||
left: "35%",
|
||||
top: "40%",
|
||||
borderRadius: "4px",
|
||||
border: "1px solid black",
|
||||
border: `1px solid ${theme.palette.divider}`,
|
||||
padding: "5px",
|
||||
backgroundColor: "rgba(37,37,37,0.92)", color: "white",
|
||||
backgroundColor: theme.palette.background.contrast, color: theme.palette.text.contrast,
|
||||
}}>
|
||||
{"Some data exists for this path, but isn't loaded into the UI. "}
|
||||
<br/>
|
||||
@@ -829,9 +829,9 @@ export const CallbacksTabsCustomFileBasedBrowserTable = (props) => {
|
||||
left: "35%",
|
||||
top: "40%",
|
||||
borderRadius: "4px",
|
||||
border: "1px solid black",
|
||||
border: `1px solid ${theme.palette.divider}`,
|
||||
padding: "5px",
|
||||
backgroundColor: "rgba(37,37,37,0.92)", color: "white",
|
||||
backgroundColor: theme.palette.background.contrast, color: theme.palette.text.contrast,
|
||||
}}>
|
||||
{"No data has been collected for this path. "}
|
||||
<div style={{display: "flex", alignItems: "center"}}>
|
||||
|
||||
@@ -95,6 +95,7 @@ const columnDefaults = [
|
||||
{ name: 'Comment', type: 'string', key: 'comment', width: 200, visible: false },
|
||||
];
|
||||
export const CallbacksTabsFileBrowserTable = (props) => {
|
||||
const theme = useTheme();
|
||||
const [updateSetting] = useSetMythicSetting();
|
||||
const [loading, setLoading] = React.useState(true);
|
||||
const [allData, setAllData] = React.useState([]);
|
||||
@@ -682,9 +683,9 @@ export const CallbacksTabsFileBrowserTable = (props) => {
|
||||
left: "35%",
|
||||
top: "40%",
|
||||
borderRadius: "4px",
|
||||
border: "1px solid black",
|
||||
border: `1px solid ${theme.palette.divider}`,
|
||||
padding: "5px",
|
||||
backgroundColor: "rgba(37,37,37,0.92)", color: "white",
|
||||
backgroundColor: theme.palette.background.contrast, color: theme.palette.text.contrast,
|
||||
}}>
|
||||
{"Only PARTIAL data has been collected for this path. "}<br/>
|
||||
{"Task this callback to list the contents"}
|
||||
@@ -703,9 +704,9 @@ export const CallbacksTabsFileBrowserTable = (props) => {
|
||||
left: "35%",
|
||||
top: "40%",
|
||||
borderRadius: "4px",
|
||||
border: "1px solid black",
|
||||
border: `1px solid ${theme.palette.divider}`,
|
||||
padding: "5px",
|
||||
backgroundColor: "rgba(37,37,37,0.92)", color: "white",
|
||||
backgroundColor: theme.palette.background.contrast, color: theme.palette.text.contrast,
|
||||
}}>
|
||||
{"Some data exists for this path, but isn't loaded into the UI. "}
|
||||
<br/>
|
||||
@@ -720,9 +721,9 @@ export const CallbacksTabsFileBrowserTable = (props) => {
|
||||
left: "35%",
|
||||
top: "40%",
|
||||
borderRadius: "4px",
|
||||
border: "1px solid black",
|
||||
border: `1px solid ${theme.palette.divider}`,
|
||||
padding: "5px",
|
||||
backgroundColor: "rgba(37,37,37,0.92)", color: "white",
|
||||
backgroundColor: theme.palette.background.contrast, color: theme.palette.text.contrast,
|
||||
}}>
|
||||
{"No data has been collected for this path. "}
|
||||
<div style={{display: "flex", alignItems: "center"}}>
|
||||
|
||||
@@ -142,6 +142,7 @@ export function CallbacksTabsProcessBrowserLabel(props){
|
||||
)
|
||||
}
|
||||
export const CallbacksTabsProcessBrowserPanel = ({index, value, tabInfo, me, setNewDataForTab}) =>{
|
||||
const theme = useTheme();
|
||||
const fromNow = React.useRef((new Date()));
|
||||
const [backdropOpen, setBackdropOpen] = React.useState(false);
|
||||
const [expandOrCollapseAll, setExpandOrCollapseAll] = React.useState(false);
|
||||
@@ -410,9 +411,9 @@ export const CallbacksTabsProcessBrowserPanel = ({index, value, tabInfo, me, set
|
||||
<Backdrop open={backdropOpen} style={{zIndex: 2, position: "absolute",}} invisible={false}>
|
||||
<div style={{
|
||||
borderRadius: "4px",
|
||||
border: "1px solid black",
|
||||
border: `1px solid ${theme.palette.divider}`,
|
||||
padding: "5px",
|
||||
backgroundColor: "rgba(37,37,37,0.92)", color: "white",
|
||||
backgroundColor: theme.palette.background.contrast, color: theme.palette.text.contrast,
|
||||
alignItems: "center",
|
||||
display: "flex", flexDirection: "column"}}>
|
||||
<CircularProgress color="inherit" />
|
||||
|
||||
@@ -142,13 +142,16 @@ const handleTerminalCodes = (response) => {
|
||||
return output;
|
||||
}
|
||||
export const GetOutputFormatAll = ({data, useASNIColor, messagesEndRef, showTaskStatus, wrapText, autoScroll=false}) => {
|
||||
const theme = useTheme();
|
||||
const errorOutputBackground = theme.palette.error.main + (theme.palette.mode === "dark" ? "33" : "22");
|
||||
const outputTextColor = theme.outputTextColor;
|
||||
const [dataElement, setDataElement] = React.useState(null);
|
||||
React.useEffect( () => {
|
||||
const elements = data.map( d => {
|
||||
if(d.response !== undefined) {
|
||||
// we're looking at response output
|
||||
if(d.is_error){
|
||||
return (<pre id={"response" + d.timestamp + d.id} style={{display: "inline",backgroundColor: "#311717", color: "white", margin: "0 0 0 0",
|
||||
return (<pre id={"response" + d.timestamp + d.id} style={{display: "inline", backgroundColor: errorOutputBackground, color: outputTextColor, margin: "0 0 0 0",
|
||||
wordBreak: wrapText ? "break-all" : "",
|
||||
whiteSpace: wrapText ? "pre-wrap" : ""}} key={d.timestamp + d.id}>
|
||||
{d.response}
|
||||
@@ -186,7 +189,7 @@ export const GetOutputFormatAll = ({data, useASNIColor, messagesEndRef, showTask
|
||||
}
|
||||
})
|
||||
setDataElement(elements);
|
||||
}, [data, useASNIColor, showTaskStatus, wrapText]);
|
||||
}, [data, useASNIColor, showTaskStatus, wrapText, errorOutputBackground, outputTextColor]);
|
||||
React.useLayoutEffect( () => {
|
||||
if(autoScroll){
|
||||
messagesEndRef?.current?.scrollIntoView({ behavior: "auto", block: "nearest" });
|
||||
@@ -1080,9 +1083,9 @@ export const ResponseDisplayInteractive = (props) =>{
|
||||
<Backdrop open={backdropOpen} style={{zIndex: 2, position: "absolute",}} invisible={false}>
|
||||
<div style={{
|
||||
borderRadius: "4px",
|
||||
border: "1px solid black",
|
||||
border: `1px solid ${theme.palette.divider}`,
|
||||
padding: "5px",
|
||||
backgroundColor: "rgba(37,37,37,0.92)", color: "white",
|
||||
backgroundColor: theme.palette.background.contrast, color: theme.palette.text.contrast,
|
||||
alignItems: "center",
|
||||
display: "flex", flexDirection: "column"}}>
|
||||
<CircularProgress color="inherit" />
|
||||
|
||||
@@ -24,7 +24,7 @@ export function ResponseDisplayScreenshotModal({onClose, images, startIndex}) {
|
||||
return (
|
||||
< >
|
||||
<DialogContent dividers={true} style={{padding: 0}} >
|
||||
<div style={{height: "calc(80vh)", display: zoom ? "" : "flex", alignItems: zoom ? "" : "flex-start" , background: theme.palette.mode === "dark" ? "rgb(44, 52, 60)" : "grey"}}>
|
||||
<div style={{height: "calc(80vh)", display: zoom ? "" : "flex", alignItems: zoom ? "" : "flex-start" , background: theme.surfaces?.muted || theme.palette.background.default}}>
|
||||
<img onClick={toggleZoom} src={"/api/v1.4/files/screencaptures/" + images[activeStep]}
|
||||
style={{width: zoom ? "" : "100%", cursor: zoom ? "zoom-out" : "zoom-in", overflow: "auto"}} />
|
||||
</div>
|
||||
@@ -59,4 +59,4 @@ export function ResponseDisplayScreenshotModal({onClose, images, startIndex}) {
|
||||
</DialogActions>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -623,7 +623,7 @@ const TaskActionsToolbarGeneric = ({toggleViewBrowserScript, toggleSelectAllOutp
|
||||
}
|
||||
<Paper className="mythic-response-actions-toolbar" elevation={0} sx={{
|
||||
alignItems: "center",
|
||||
backgroundColor: theme.palette.mode === "dark" ? "rgba(255,255,255,0.03)" : "rgba(0,0,0,0.02)",
|
||||
backgroundColor: theme.surfaces?.muted || theme.palette.background.default,
|
||||
borderLeft: 0,
|
||||
borderRight: 0,
|
||||
borderTop: 0,
|
||||
|
||||
@@ -64,7 +64,7 @@ const StyledMythicDialog = styled(MythicDialog)((
|
||||
|
||||
[`& .${classes.checkIcon}`]: {
|
||||
fontSize: 20,
|
||||
color: '#b3b3b3',
|
||||
color: theme.palette.text.secondary,
|
||||
paddingRight: 4,
|
||||
},
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ import DialogTitle from '@mui/material/DialogTitle';
|
||||
import ToggleButton from '@mui/material/ToggleButton';
|
||||
import ToggleButtonGroup from '@mui/material/ToggleButtonGroup';
|
||||
import Popover from '@mui/material/Popover';
|
||||
import {CallbackDataCard, DashboardEmptyCard, GaugeCard, LineTimeMultiChartCard, PieChartCard, TableDataCard} from './DashboardComponents';
|
||||
import {CallbackDataCard, DashboardEmptyCard, GaugeCard, getDashboardColors, LineTimeMultiChartCard, PieChartCard, TableDataCard} from './DashboardComponents';
|
||||
import {MythicAgentSVGIcon} from "../../MythicComponents/MythicAgentSVGIcon";
|
||||
import {MythicStyledTooltip} from "../../MythicComponents/MythicStyledTooltip";
|
||||
import {b64DecodeUnicode} from "../Callbacks/ResponseDisplay";
|
||||
@@ -226,19 +226,6 @@ function getNormalizedTaskStatusColor (theme, taskStatus) {
|
||||
}
|
||||
// Hour in milliseconds
|
||||
const ONE_HOUR = 60 * 60 * 1000;
|
||||
const errorColors = [
|
||||
"#de1212",
|
||||
"#d56b6b",
|
||||
"#de6012",
|
||||
"#de126e",
|
||||
"#d712de",
|
||||
"#e06597",
|
||||
"#de7d54",
|
||||
"#640909",
|
||||
"#7e0a86",
|
||||
"#832f0b",
|
||||
];
|
||||
|
||||
const dashboardOptions = ["operator", "lead", "custom"];
|
||||
const dashboardElementGridSpans = {
|
||||
"Activity Timeline": 2,
|
||||
@@ -1204,6 +1191,7 @@ const MyOperationsDashboardElement = ({me, data, reloadDashboard, editing, remov
|
||||
)
|
||||
}
|
||||
const Top10CommandErrorStatsDashboardElement = ({me, data, editing, removeElement}) => {
|
||||
const theme = useTheme();
|
||||
const navigate = useNavigate();
|
||||
const [commands, setCommands] = React.useState([]);
|
||||
const handleErrorTaskClick = (event, item) => {
|
||||
@@ -1231,14 +1219,15 @@ const Top10CommandErrorStatsDashboardElement = ({me, data, editing, removeElemen
|
||||
value: value
|
||||
})
|
||||
}
|
||||
const chartColors = getDashboardColors(theme);
|
||||
commandErrorArrayOptions = commandErrorArrayOptions.sort((a, b) => b.value - a.value).slice(0, 10).map( (c, i) => {
|
||||
return {
|
||||
...c,
|
||||
color: errorColors[i]
|
||||
color: chartColors[(i + 3) % chartColors.length]
|
||||
}
|
||||
})
|
||||
setCommands(commandErrorArrayOptions);
|
||||
}, [data]);
|
||||
}, [data, theme]);
|
||||
return (
|
||||
<PieChartCard data={commands} onClick={handleErrorTaskClick}
|
||||
title={"Top 10 Command Error Stats"} hidden={false}
|
||||
@@ -1363,6 +1352,7 @@ const TaskStatusDashboardElement = ({me, data, editing, removeElement}) => {
|
||||
)
|
||||
}
|
||||
const ActivityPerDayDashboardElement = ({me, data, editing, removeElement}) => {
|
||||
const theme = useTheme();
|
||||
const [tasksPerDay, setTasksPerDay] = React.useState({x: [], y: []});
|
||||
React.useEffect( () => {
|
||||
let callbackData = {};
|
||||
@@ -1448,7 +1438,7 @@ const ActivityPerDayDashboardElement = ({me, data, editing, removeElement}) => {
|
||||
highlighted: "series",
|
||||
faded: "global",
|
||||
},
|
||||
color: '#44b636',
|
||||
color: theme.palette.success.main,
|
||||
yAxisId: "callbackAxis",
|
||||
})
|
||||
}
|
||||
@@ -1464,7 +1454,7 @@ const ActivityPerDayDashboardElement = ({me, data, editing, removeElement}) => {
|
||||
})
|
||||
}
|
||||
setTasksPerDay({x: taskDayArrayOptions, y: taskDayArrayOperatorOptions});
|
||||
}, [data]);
|
||||
}, [data, theme.palette.success.main]);
|
||||
return (
|
||||
<LineTimeMultiChartCard data={tasksPerDay} view_utc_time={me?.user?.view_utc_time} editing={editing}
|
||||
removeElement={removeElement}/>
|
||||
|
||||
@@ -16,27 +16,14 @@ import VisibilityIcon from '@mui/icons-material/Visibility';
|
||||
import Paper from "@mui/material/Paper";
|
||||
import {MythicEmptyState} from "../../MythicComponents/MythicStateDisplay";
|
||||
|
||||
const fallbackDashboardColors = [
|
||||
'#09bdff',
|
||||
'#39b86f',
|
||||
'#d69d2d',
|
||||
'#d65c6b',
|
||||
'#7b6fd6',
|
||||
'#24a3a3',
|
||||
'#9c6ade',
|
||||
'#d47f38',
|
||||
'#4e7ad7',
|
||||
'#90a955',
|
||||
];
|
||||
|
||||
const getDashboardColors = (theme) => [
|
||||
export const getDashboardColors = (theme) => [
|
||||
theme.palette.info.main,
|
||||
theme.palette.success.main,
|
||||
theme.palette.warning.main,
|
||||
theme.palette.error.main,
|
||||
theme.palette.secondary.main,
|
||||
theme.palette.primary.main,
|
||||
...fallbackDashboardColors,
|
||||
...(theme.chartSeriesColors || []),
|
||||
];
|
||||
|
||||
const DashboardCard = ({
|
||||
|
||||
@@ -14,6 +14,7 @@ import { MythicDisplayTextDialog} from '../../MythicComponents/MythicDisplayText
|
||||
import { MythicDialog } from '../../MythicComponents/MythicDialog';
|
||||
import { SelectPayloadTypeDialog } from './SelectPayloadTypeDialog';
|
||||
import {MythicPageHeader, MythicPageHeaderChip} from "../../MythicComponents/MythicPageHeader";
|
||||
import {useTheme} from "@mui/material/styles";
|
||||
|
||||
|
||||
export function MitreGrid({entries, onGetCommands, onGetTasks, onGetCommandsFiltered, onGetTasksFiltered, onFilterByTags, showCountGrouping}){
|
||||
@@ -56,6 +57,7 @@ export function MitreGrid({entries, onGetCommands, onGetTasks, onGetCommandsFilt
|
||||
}
|
||||
|
||||
function PoperDropdown({onGetCommands, onGetTasks, onGetCommandsFiltered, onGetTasksFiltered, onFilterByTags, setBackdropOpen, entries, showCountGrouping}){
|
||||
const theme = useTheme();
|
||||
const dropdownAnchorRef = React.useRef(null);
|
||||
const [dropdownOpen, setDropdownOpen] = React.useState(false);
|
||||
const [openLicense, setOpenLicense] = React.useState(false);
|
||||
@@ -164,9 +166,9 @@ function PoperDropdown({onGetCommands, onGetTasks, onGetCommandsFiltered, onGetT
|
||||
],
|
||||
"gradient": {
|
||||
"colors": [
|
||||
"#ff6666ff",
|
||||
"#ffe766ff",
|
||||
"#8ec843ff"
|
||||
theme.palette.error.main,
|
||||
theme.palette.warning.main,
|
||||
theme.palette.success.main
|
||||
],
|
||||
"minValue": 0,
|
||||
"maxValue": 100
|
||||
@@ -175,7 +177,7 @@ function PoperDropdown({onGetCommands, onGetTasks, onGetCommandsFiltered, onGetT
|
||||
"metadata": [],
|
||||
"links": [],
|
||||
"showTacticRowBackground": false,
|
||||
"tacticRowBackground": "#dddddd",
|
||||
"tacticRowBackground": theme.tableHeader,
|
||||
"selectTechniquesAcrossTactics": true,
|
||||
"selectSubtechniquesWithParent": false
|
||||
};
|
||||
@@ -190,7 +192,7 @@ function PoperDropdown({onGetCommands, onGetTasks, onGetCommandsFiltered, onGetT
|
||||
{
|
||||
"techniqueID": entries[key].rows[i].t_num,
|
||||
"tactic": key.replaceAll(" ", "-").toLowerCase(),
|
||||
"color": "#bc3b24",
|
||||
"color": theme.palette.error.main,
|
||||
"enabled": true,
|
||||
"comment": "",
|
||||
"metadata": [],
|
||||
@@ -206,7 +208,7 @@ function PoperDropdown({onGetCommands, onGetTasks, onGetCommandsFiltered, onGetT
|
||||
{
|
||||
"techniqueID": entries[key].rows[i].t_num,
|
||||
"tactic": key.replaceAll(" ", "-").toLowerCase(),
|
||||
"color": "#bc3b24",
|
||||
"color": theme.palette.error.main,
|
||||
"enabled": true,
|
||||
"comment": "",
|
||||
"metadata": [],
|
||||
|
||||
@@ -3,8 +3,10 @@ import Button from '@mui/material/Button';
|
||||
import { Box } from '@mui/material';
|
||||
import { MythicDialog } from '../../MythicComponents/MythicDialog';
|
||||
import { MitreMapDisplayDialog } from './MitreMapDisplayDialog';
|
||||
import {useTheme} from "@mui/material/styles";
|
||||
|
||||
export function MitreGridRow({row, showCountGrouping}){
|
||||
const theme = useTheme();
|
||||
const [buttonColor, setButtonColor] = React.useState({});
|
||||
const [openDisplay, setOpenDisplay] = React.useState(false);
|
||||
React.useEffect( () => {
|
||||
@@ -14,24 +16,24 @@ export function MitreGridRow({row, showCountGrouping}){
|
||||
break;
|
||||
case "command":
|
||||
if(row.commands.length > 0){
|
||||
setButtonColor({color: "white", backgroundColor: "rgb(188, 58, 36)"});
|
||||
setButtonColor({color: theme.palette.error.contrastText, backgroundColor: theme.palette.error.main});
|
||||
}else{
|
||||
setButtonColor({});
|
||||
}
|
||||
break;
|
||||
case "task":
|
||||
if(row.tasks.length > 0){
|
||||
setButtonColor({color: "white", backgroundColor: "rgb(188, 58, 36)"});
|
||||
setButtonColor({color: theme.palette.error.contrastText, backgroundColor: theme.palette.error.main});
|
||||
}else{
|
||||
setButtonColor({});
|
||||
}
|
||||
}
|
||||
}, [row.commands, row.tasks, showCountGrouping])
|
||||
}, [row.commands, row.tasks, showCountGrouping, theme.palette.error.contrastText, theme.palette.error.main])
|
||||
return (
|
||||
<div style={{display: "flex", flexDirection: "row", alignItems: "center"}}>
|
||||
{row?.t_num?.includes(".") ?
|
||||
(
|
||||
<Box width={"50px"} height={"1px"} style={{border: "1px dashed grey"}} />
|
||||
<Box width={"50px"} height={"1px"} style={{border: `1px dashed ${theme.palette.text.secondary}`}} />
|
||||
) : null}
|
||||
<Button style={{
|
||||
width: "100%",
|
||||
@@ -54,4 +56,3 @@ export function MitreGridRow({row, showCountGrouping}){
|
||||
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
+10
-6
@@ -19,6 +19,7 @@ import {CustomBrowserRow} from "./CustomBrowserCard";
|
||||
import {MythicPageBody} from "../../MythicComponents/MythicPageBody";
|
||||
import {MythicPageHeader, MythicPageHeaderChip} from "../../MythicComponents/MythicPageHeader";
|
||||
import {MythicToolbarToggle} from "../../MythicComponents/MythicTableToolbar";
|
||||
import {useTheme} from "@mui/material/styles";
|
||||
|
||||
const SUB_Payload_Types = gql`
|
||||
subscription getPayloadTypesSubscription {
|
||||
@@ -415,6 +416,7 @@ const ContainersTabBrowsersLabel = (props) => {
|
||||
|
||||
|
||||
const ContainersTabPayloadTypesPanel = (props) => {
|
||||
const theme = useTheme();
|
||||
const getEmptyServiceListMessage = () => {
|
||||
let message = "";
|
||||
switch(props.type){
|
||||
@@ -453,9 +455,9 @@ A few examples are github.com/MythicAgents/bloodhound and github.com/MythicAgent
|
||||
left: "35%",
|
||||
top: "40%",
|
||||
borderRadius: "4px",
|
||||
border: "1px solid black",
|
||||
border: `1px solid ${theme.palette.divider}`,
|
||||
padding: "5px",
|
||||
backgroundColor: "rgba(37,37,37,0.92)", color: "white",
|
||||
backgroundColor: theme.palette.background.contrast, color: theme.palette.text.contrast,
|
||||
whiteSpace: "pre-wrap"
|
||||
}}>
|
||||
{message}
|
||||
@@ -492,6 +494,7 @@ A few examples are github.com/MythicAgents/bloodhound and github.com/MythicAgent
|
||||
)
|
||||
}
|
||||
const ContainersTabConsumingServicesPanel = (props) => {
|
||||
const theme = useTheme();
|
||||
const getEmptyServiceListMessage = () => {
|
||||
let message = "";
|
||||
switch(props.type){
|
||||
@@ -522,9 +525,9 @@ You can extend this auth capability to support your own LDAP, SSO, or otherwise
|
||||
left: "35%",
|
||||
top: "40%",
|
||||
borderRadius: "4px",
|
||||
border: "1px solid black",
|
||||
border: `1px solid ${theme.palette.divider}`,
|
||||
padding: "5px",
|
||||
backgroundColor: "rgba(37,37,37,0.92)", color: "white",
|
||||
backgroundColor: theme.palette.background.contrast, color: theme.palette.text.contrast,
|
||||
whiteSpace: "pre-wrap"
|
||||
}}>
|
||||
{message}
|
||||
@@ -558,6 +561,7 @@ You can extend this auth capability to support your own LDAP, SSO, or otherwise
|
||||
)
|
||||
}
|
||||
const ContainersTabCustomBrowsersPanel = (props) => {
|
||||
const theme = useTheme();
|
||||
const getEmptyServiceListMessage = () => {
|
||||
let message = "";
|
||||
switch(props.type){
|
||||
@@ -572,9 +576,9 @@ const ContainersTabCustomBrowsersPanel = (props) => {
|
||||
left: "35%",
|
||||
top: "40%",
|
||||
borderRadius: "4px",
|
||||
border: "1px solid black",
|
||||
border: `1px solid ${theme.palette.divider}`,
|
||||
padding: "5px",
|
||||
backgroundColor: "rgba(37,37,37,0.92)", color: "white",
|
||||
backgroundColor: theme.palette.background.contrast, color: theme.palette.text.contrast,
|
||||
whiteSpace: "pre-wrap"
|
||||
}}>
|
||||
{message}
|
||||
|
||||
@@ -29,6 +29,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 RestartAltIcon from '@mui/icons-material/RestartAlt';
|
||||
import {MythicColorSwatchInput} from "../../MythicComponents/MythicColorInput";
|
||||
import VisibilityOffIcon from '@mui/icons-material/VisibilityOff';
|
||||
import VisibilityIcon from '@mui/icons-material/Visibility';
|
||||
@@ -270,11 +271,36 @@ const COLOR_EDITOR_SECTIONS = [
|
||||
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: "surfaceRaised", display: "Raised Surface", description: "Elevated cards, menus, and popover-like surfaces.", preview: "surface"},
|
||||
{name: "surfaceMuted", display: "Muted Surface", description: "Quiet section backgrounds and low-emphasis containers.", preview: "surface"},
|
||||
{name: "text", display: "Primary Text", description: "Primary readable text throughout the UI.", preview: "typography"},
|
||||
{name: "textSecondary", display: "Secondary Text", description: "Muted helper text, labels, metadata, and quiet icon states.", preview: "typography"},
|
||||
{name: "textDisabled", display: "Disabled Text", description: "Disabled controls, empty counts, and intentionally de-emphasized values.", preview: "typography"},
|
||||
{name: "borderColor", display: "Borders", description: "Outlines around panels, tables, and controls.", preview: "surface"},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Headers and Gradients",
|
||||
description: "Page headers, section headers, and the subtle accent gradients used on modern cards.",
|
||||
colors: [
|
||||
{name: "pageHeader", display: "Page Header Surface", description: "Base surface for page and section headers.", preview: "headerGradient"},
|
||||
{name: "pageHeaderText", display: "Page Header Text", description: "Text and action icon color inside page and section headers.", preview: "headerGradient"},
|
||||
{name: "sectionHeaderAccent", display: "Section Accent", description: "The colored strip and border accent on section headers.", preview: "headerGradient"},
|
||||
{name: "sectionHeaderGradientStart", display: "Header Gradient Start", description: "The left side of section header gradients.", preview: "headerGradient"},
|
||||
{name: "sectionHeaderGradientMiddle", display: "Header Gradient Middle", description: "The middle stop of section header gradients.", preview: "headerGradient"},
|
||||
{name: "sectionHeaderGradientEnd", display: "Header Gradient End", description: "The right side of section header gradients.", preview: "headerGradient"},
|
||||
{name: "subtleAccentGradientStart", display: "Subtle Gradient Start", description: "The visible edge of soft dashboard, overview, and option-card gradients.", preview: "subtleGradient"},
|
||||
{name: "subtleAccentGradientEnd", display: "Subtle Gradient End", description: "The fade-out side of soft dashboard, overview, and option-card gradients.", preview: "subtleGradient"},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Graphs and Floating Controls",
|
||||
description: "Graph grouping surfaces and legacy floating action controls.",
|
||||
colors: [
|
||||
{name: "graphGroupColor", display: "Graph Group", description: "Grouped node backgrounds in graph-style views.", preview: "graph"},
|
||||
{name: "speedDialAction", display: "Floating Action", description: "Floating action buttons where SpeedDial controls are still used.", preview: "floatingAction"},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Navigation",
|
||||
description: "Left navigation gradient, labels, and icons.",
|
||||
@@ -307,6 +333,22 @@ const COLOR_EDITOR_SECTIONS = [
|
||||
{name: "error", display: "Error", description: "Danger actions, failed states, and errors.", preview: "status"},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Data Visualization",
|
||||
description: "Additional chart colors used when dashboard visualizations need more series than the status palette provides.",
|
||||
colors: [
|
||||
{name: "chartSeries1", display: "Chart Series 1", description: "Dashboard chart fallback color 1.", preview: "chart"},
|
||||
{name: "chartSeries2", display: "Chart Series 2", description: "Dashboard chart fallback color 2.", preview: "chart"},
|
||||
{name: "chartSeries3", display: "Chart Series 3", description: "Dashboard chart fallback color 3.", preview: "chart"},
|
||||
{name: "chartSeries4", display: "Chart Series 4", description: "Dashboard chart fallback color 4.", preview: "chart"},
|
||||
{name: "chartSeries5", display: "Chart Series 5", description: "Dashboard chart fallback color 5.", preview: "chart"},
|
||||
{name: "chartSeries6", display: "Chart Series 6", description: "Dashboard chart fallback color 6.", preview: "chart"},
|
||||
{name: "chartSeries7", display: "Chart Series 7", description: "Dashboard chart fallback color 7.", preview: "chart"},
|
||||
{name: "chartSeries8", display: "Chart Series 8", description: "Dashboard chart fallback color 8.", preview: "chart"},
|
||||
{name: "chartSeries9", display: "Chart Series 9", description: "Dashboard chart fallback color 9.", preview: "chart"},
|
||||
{name: "chartSeries10", display: "Chart Series 10", description: "Dashboard chart fallback color 10.", preview: "chart"},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Tasking",
|
||||
description: "Task prompt, context badges, and command output.",
|
||||
@@ -322,8 +364,9 @@ const COLOR_EDITOR_SECTIONS = [
|
||||
},
|
||||
{
|
||||
title: "File Browsing",
|
||||
description: "File browser empty-folder treatment.",
|
||||
description: "File browser folder and empty-folder treatment.",
|
||||
colors: [
|
||||
{name: "folderColor", display: "Folder", description: "Normal folder icon color in file browser trees.", preview: "file"},
|
||||
{name: "emptyFolderColor", display: "Empty Folder", description: "Empty folder icon and text in file-based browsers.", preview: "file"},
|
||||
],
|
||||
},
|
||||
@@ -356,6 +399,39 @@ const getPaletteValue = (palette, name, mode) => {
|
||||
return mode === "dark" ? "#1f2937" : "#f8fafc";
|
||||
}
|
||||
|
||||
const normalizeBackgroundImageValue = (value) => {
|
||||
if(typeof value !== "string" || value.length === 0){
|
||||
return null;
|
||||
}
|
||||
if(value.startsWith("data:image/")){
|
||||
return `url("${value}")`;
|
||||
}
|
||||
if(value.startsWith("url(\"data:image/") && !value.endsWith("\")")){
|
||||
return `${value}")`;
|
||||
}
|
||||
if(value.startsWith("url(data:image/") && !value.endsWith(")")){
|
||||
return `${value})`;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
const buildInitialPalette = (initialPalette) => {
|
||||
return Object.entries(operatorSettingDefaults.palette).reduce((newPalette, [name, defaultValue]) => {
|
||||
if(name === "backgroundImage"){
|
||||
newPalette[name] = {
|
||||
dark: normalizeBackgroundImageValue(initialPalette?.[name]?.dark || defaultValue.dark),
|
||||
light: normalizeBackgroundImageValue(initialPalette?.[name]?.light || defaultValue.light),
|
||||
};
|
||||
return newPalette;
|
||||
}
|
||||
newPalette[name] = {
|
||||
dark: isValidColor(initialPalette?.[name]?.dark) ? initialPalette[name].dark : defaultValue.dark,
|
||||
light: isValidColor(initialPalette?.[name]?.light) ? initialPalette[name].light : defaultValue.light,
|
||||
};
|
||||
return newPalette;
|
||||
}, {});
|
||||
}
|
||||
|
||||
const getReadableTextColor = (backgroundColor) => {
|
||||
if(!isValidColor(backgroundColor)){
|
||||
return "#ffffff";
|
||||
@@ -367,18 +443,45 @@ const getReadableTextColor = (backgroundColor) => {
|
||||
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 ModeColorControl = ({mode, name, display, color, defaultColor, onChange}) => {
|
||||
const modeLabel = mode === "dark" ? "Dark" : "Light";
|
||||
const resetDisabled = defaultColor === undefined || color === defaultColor;
|
||||
return (
|
||||
<Box sx={{minWidth: 0}}>
|
||||
<Box sx={{alignItems: "center", display: "flex", gap: 0.75, justifyContent: "space-between", mb: 0.5}}>
|
||||
<Typography variant="caption" sx={{display: "block", color: "text.secondary"}}>
|
||||
{modeLabel}
|
||||
</Typography>
|
||||
<MythicStyledTooltip title={`Reset ${display} ${modeLabel.toLowerCase()} color to default`}>
|
||||
<span>
|
||||
<IconButton
|
||||
aria-label={`Reset ${display} ${modeLabel.toLowerCase()} color to default`}
|
||||
disabled={resetDisabled}
|
||||
onClick={() => onChange(name, mode, defaultColor)}
|
||||
size="small"
|
||||
sx={{
|
||||
color: resetDisabled ? "text.disabled" : "text.secondary",
|
||||
height: 24,
|
||||
width: 24,
|
||||
"&:hover": {
|
||||
color: "warning.main",
|
||||
backgroundColor: "action.hover",
|
||||
},
|
||||
}}
|
||||
>
|
||||
<RestartAltIcon sx={{fontSize: "1rem"}} />
|
||||
</IconButton>
|
||||
</span>
|
||||
</MythicStyledTooltip>
|
||||
</Box>
|
||||
<MythicColorSwatchInput
|
||||
color={color}
|
||||
label={`${name} ${mode} color`}
|
||||
onChange={(value) => onChange(name, mode, value)}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
const PreviewLabel = ({children, color}) => (
|
||||
<Typography
|
||||
@@ -399,8 +502,23 @@ const PreviewLabel = ({children, color}) => (
|
||||
const ColorUsagePreview = ({option, palette, mode}) => {
|
||||
const background = getPaletteValue(palette, "background", mode);
|
||||
const paper = getPaletteValue(palette, "paper", mode);
|
||||
const surfaceRaised = getPaletteValue(palette, "surfaceRaised", mode);
|
||||
const surfaceMuted = getPaletteValue(palette, "surfaceMuted", mode);
|
||||
const text = getPaletteValue(palette, "text", mode);
|
||||
const textSecondary = getPaletteValue(palette, "textSecondary", mode);
|
||||
const textDisabled = getPaletteValue(palette, "textDisabled", mode);
|
||||
const border = getPaletteValue(palette, "borderColor", mode);
|
||||
const pageHeader = getPaletteValue(palette, "pageHeader", mode);
|
||||
const pageHeaderText = getPaletteValue(palette, "pageHeaderText", mode);
|
||||
const sectionHeaderAccent = getPaletteValue(palette, "sectionHeaderAccent", mode);
|
||||
const sectionHeaderGradientStart = getPaletteValue(palette, "sectionHeaderGradientStart", mode);
|
||||
const sectionHeaderGradientMiddle = getPaletteValue(palette, "sectionHeaderGradientMiddle", mode);
|
||||
const sectionHeaderGradientEnd = getPaletteValue(palette, "sectionHeaderGradientEnd", mode);
|
||||
const subtleAccentGradientStart = getPaletteValue(palette, "subtleAccentGradientStart", mode);
|
||||
const subtleAccentGradientEnd = getPaletteValue(palette, "subtleAccentGradientEnd", mode);
|
||||
const graphGroup = getPaletteValue(palette, "graphGroupColor", mode);
|
||||
const speedDialAction = getPaletteValue(palette, "speedDialAction", mode);
|
||||
const chartSeriesColors = Array.from({length: 10}, (_, index) => getPaletteValue(palette, `chartSeries${index + 1}`, mode));
|
||||
const navTop = getPaletteValue(palette, "navBarColor", mode);
|
||||
const navBottom = getPaletteValue(palette, "navBarBottomColor", mode);
|
||||
const navIcon = getPaletteValue(palette, "navBarIcons", mode);
|
||||
@@ -416,6 +534,8 @@ const ColorUsagePreview = ({option, palette, mode}) => {
|
||||
const context = getPaletteValue(palette, "taskContextColor", mode);
|
||||
const impersonation = getPaletteValue(palette, "taskContextImpersonationColor", mode);
|
||||
const extra = getPaletteValue(palette, "taskContextExtraColor", mode);
|
||||
const folder = getPaletteValue(palette, "folderColor", mode);
|
||||
const emptyFolder = getPaletteValue(palette, "emptyFolderColor", mode);
|
||||
const previewColor = getPaletteValue(palette, option.name, mode);
|
||||
const shellSx = {
|
||||
border: `1px solid ${addAlpha(border, "99")}`,
|
||||
@@ -424,6 +544,8 @@ const ColorUsagePreview = ({option, palette, mode}) => {
|
||||
minHeight: 74,
|
||||
backgroundColor: background,
|
||||
};
|
||||
const sectionHeaderGradient = `linear-gradient(90deg, ${sectionHeaderGradientStart} 0%, ${sectionHeaderGradientMiddle} 48%, ${sectionHeaderGradientEnd} 100%)`;
|
||||
const subtleAccentGradient = `linear-gradient(135deg, ${subtleAccentGradientStart} 0%, ${subtleAccentGradientEnd} 62%)`;
|
||||
switch(option.preview){
|
||||
case "navigation":
|
||||
return (
|
||||
@@ -470,6 +592,75 @@ const ColorUsagePreview = ({option, palette, mode}) => {
|
||||
<PreviewLabel color={text}>{mode} accent</PreviewLabel>
|
||||
</Box>
|
||||
);
|
||||
case "typography":
|
||||
return (
|
||||
<Box sx={{...shellSx, p: 1, backgroundColor: paper}}>
|
||||
<Typography variant="caption" sx={{color: text, display: "block", fontWeight: option.name === "text" ? 800 : 600, lineHeight: 1.25}}>
|
||||
Primary task title
|
||||
</Typography>
|
||||
<Typography variant="caption" sx={{color: textSecondary, display: "block", fontWeight: option.name === "textSecondary" ? 800 : 500, lineHeight: 1.25}}>
|
||||
Secondary metadata and helper text
|
||||
</Typography>
|
||||
<Typography variant="caption" sx={{color: textDisabled, display: "block", fontWeight: option.name === "textDisabled" ? 800 : 500, lineHeight: 1.25}}>
|
||||
Disabled or unavailable action
|
||||
</Typography>
|
||||
<Box sx={{height: 5, mt: 0.75, borderRadius: "4px", backgroundColor: previewColor}} />
|
||||
</Box>
|
||||
);
|
||||
case "headerGradient":
|
||||
return (
|
||||
<Box sx={{...shellSx, p: 0.75, backgroundColor: background}}>
|
||||
<Box sx={{height: 22, borderRadius: "4px", backgroundColor: pageHeader, color: pageHeaderText, px: 0.75, display: "flex", alignItems: "center", border: `1px solid ${addAlpha(pageHeaderText, "33")}`}}>
|
||||
<PreviewLabel color={pageHeaderText}>Page header</PreviewLabel>
|
||||
</Box>
|
||||
<Box sx={{height: 30, mt: 0.65, borderRadius: "4px", backgroundColor: pageHeader, backgroundImage: sectionHeaderGradient, border: `1px solid ${addAlpha(sectionHeaderAccent, "99")}`, color: pageHeaderText, display: "flex", alignItems: "center", overflow: "hidden"}}>
|
||||
<Box sx={{alignSelf: "stretch", width: 5, backgroundColor: sectionHeaderAccent, mr: 0.75}} />
|
||||
<PreviewLabel color={pageHeaderText}>Section header</PreviewLabel>
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
case "subtleGradient":
|
||||
return (
|
||||
<Box sx={{...shellSx, p: 0.75, backgroundColor: surfaceMuted}}>
|
||||
<Box sx={{height: 48, borderRadius: "5px", backgroundColor: surfaceRaised, backgroundImage: subtleAccentGradient, border: `1px solid ${addAlpha(border, "99")}`, p: 0.75}}>
|
||||
<PreviewLabel color={text}>Dashboard card</PreviewLabel>
|
||||
<Box sx={{height: 6, mt: 1, width: "68%", borderRadius: "3px", backgroundColor: previewColor}} />
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
case "graph":
|
||||
return (
|
||||
<Box sx={{...shellSx, p: 0.75, backgroundColor: paper}}>
|
||||
<Box sx={{height: 48, borderRadius: "5px", backgroundColor: addAlpha(graphGroup, "80"), border: `1px solid ${border}`, display: "grid", placeItems: "center"}}>
|
||||
<Box sx={{height: 18, width: 58, borderRadius: "4px", backgroundColor: surfaceRaised, border: `1px solid ${addAlpha(border, "99")}`}} />
|
||||
</Box>
|
||||
<PreviewLabel color={textSecondary}>Grouped graph node</PreviewLabel>
|
||||
</Box>
|
||||
);
|
||||
case "floatingAction":
|
||||
return (
|
||||
<Box sx={{...shellSx, p: 0.75, backgroundColor: surfaceMuted, display: "flex", alignItems: "center", justifyContent: "center"}}>
|
||||
<Box sx={{height: 34, width: 34, borderRadius: "50%", backgroundColor: speedDialAction, border: `1px solid ${addAlpha(border, "99")}`, boxShadow: `0 4px 10px ${addAlpha(text, "33")}`}} />
|
||||
</Box>
|
||||
);
|
||||
case "chart":
|
||||
return (
|
||||
<Box sx={{...shellSx, p: 0.75, backgroundColor: paper}}>
|
||||
<Box sx={{alignItems: "end", display: "grid", gap: 0.35, gridTemplateColumns: "repeat(10, 1fr)", height: 48}}>
|
||||
{chartSeriesColors.map((color, index) => (
|
||||
<Box
|
||||
key={`${mode}-chart-${index}`}
|
||||
sx={{
|
||||
backgroundColor: color,
|
||||
borderRadius: "3px 3px 0 0",
|
||||
height: `${18 + ((index % 5) * 6)}px`,
|
||||
opacity: option.name === `chartSeries${index + 1}` ? 1 : 0.5,
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
case "task":
|
||||
return (
|
||||
<Box sx={{...shellSx, p: 1, backgroundColor: paper}}>
|
||||
@@ -498,9 +689,22 @@ const ColorUsagePreview = ({option, palette, mode}) => {
|
||||
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
|
||||
<Box sx={{display: "grid", gap: 0.5}}>
|
||||
<Box sx={{alignItems: "center", display: "flex", gap: 0.5}}>
|
||||
<Box sx={{height: 16, width: 20, borderRadius: "3px", backgroundColor: folder}} />
|
||||
<Typography variant="caption" sx={{color: text, fontWeight: option.name === "folderColor" ? 800 : 600}}>
|
||||
Folder with files
|
||||
</Typography>
|
||||
</Box>
|
||||
<Box sx={{alignItems: "center", display: "flex", gap: 0.5}}>
|
||||
<Box sx={{height: 16, width: 20, borderRadius: "3px", backgroundColor: addAlpha(emptyFolder, "66"), border: `1px solid ${emptyFolder}`}} />
|
||||
<Typography variant="caption" sx={{color: option.name === "emptyFolderColor" ? emptyFolder : textSecondary, fontWeight: option.name === "emptyFolderColor" ? 800 : 600}}>
|
||||
Empty folder
|
||||
</Typography>
|
||||
</Box>
|
||||
</Box>
|
||||
<Typography variant="caption" sx={{color: textSecondary, display: "block", mt: 0.75}}>
|
||||
File browser tree
|
||||
</Typography>
|
||||
</Box>
|
||||
);
|
||||
@@ -508,10 +712,16 @@ const ColorUsagePreview = ({option, palette, mode}) => {
|
||||
default:
|
||||
return (
|
||||
<Box sx={{...shellSx, p: 0.75}}>
|
||||
<Box sx={{height: 16, borderRadius: "4px 4px 0 0", backgroundColor: getPaletteValue(palette, "pageHeader", mode)}} />
|
||||
<Box sx={{height: 20, borderRadius: "4px 4px 0 0", backgroundColor: pageHeader, color: pageHeaderText, px: 0.75, display: "flex", alignItems: "center"}}>
|
||||
<PreviewLabel color={pageHeaderText}>Page header</PreviewLabel>
|
||||
</Box>
|
||||
<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}} />
|
||||
<PreviewLabel color={option.name === "textSecondary" ? textSecondary : text}>{mode} surface</PreviewLabel>
|
||||
<Box sx={{display: "grid", gap: 0.4, gridTemplateColumns: "1fr 1fr", mt: 0.75}}>
|
||||
<Box sx={{height: 9, borderRadius: "4px", backgroundColor: surfaceRaised, border: `1px solid ${addAlpha(border, "66")}`}} />
|
||||
<Box sx={{height: 9, borderRadius: "4px", backgroundColor: surfaceMuted, border: `1px solid ${addAlpha(border, "66")}`}} />
|
||||
</Box>
|
||||
<Box sx={{height: 6, mt: 0.55, borderRadius: "4px", backgroundColor: previewColor}} />
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
@@ -543,13 +753,17 @@ const ColorTokenEditor = ({option, palette, onChange}) => (
|
||||
<ModeColorControl
|
||||
mode="dark"
|
||||
name={option.name}
|
||||
display={option.display}
|
||||
color={palette?.[option.name]?.dark}
|
||||
defaultColor={operatorSettingDefaults.palette?.[option.name]?.dark}
|
||||
onChange={onChange}
|
||||
/>
|
||||
<ModeColorControl
|
||||
mode="light"
|
||||
name={option.name}
|
||||
display={option.display}
|
||||
color={palette?.[option.name]?.light}
|
||||
defaultColor={operatorSettingDefaults.palette?.[option.name]?.light}
|
||||
onChange={onChange}
|
||||
/>
|
||||
</Box>
|
||||
@@ -735,120 +949,7 @@ export function SettingsOperatorUIConfigDialog(props) {
|
||||
const [showOPSECBypassUsername, setShowOPSECBypassUsername] = React.useState(initialShowOPSECBypassUsername);
|
||||
|
||||
const initialPalette = GetMythicSetting({setting_name: 'palette', default_value: operatorSettingDefaults.palette});
|
||||
const [palette, setPalette] = React.useState({
|
||||
primary: {
|
||||
dark: isValidColor(initialPalette?.primary?.dark) ? initialPalette?.primary?.dark : operatorSettingDefaults.palette.primary.dark,
|
||||
light: isValidColor(initialPalette?.primary?.light) ? initialPalette?.primary?.light : operatorSettingDefaults.palette.primary.light,
|
||||
},
|
||||
error: {
|
||||
dark: isValidColor(initialPalette?.error?.dark) ? initialPalette?.error?.dark : operatorSettingDefaults.palette.error.dark,
|
||||
light: isValidColor(initialPalette?.error?.light) ? initialPalette?.error?.light : operatorSettingDefaults.palette.error.light,
|
||||
},
|
||||
success: {
|
||||
dark: isValidColor(initialPalette?.success?.dark) ? initialPalette?.success?.dark : operatorSettingDefaults.palette.success.dark,
|
||||
light: isValidColor(initialPalette?.success?.light) ? initialPalette?.success?.light : operatorSettingDefaults.palette.success.light,
|
||||
},
|
||||
info: {
|
||||
dark: isValidColor(initialPalette?.info?.dark) ? initialPalette?.info?.dark : operatorSettingDefaults.palette.info.dark,
|
||||
light: isValidColor(initialPalette?.info?.light) ? initialPalette?.info?.light : operatorSettingDefaults.palette.info.light,
|
||||
},
|
||||
warning: {
|
||||
dark: isValidColor(initialPalette?.warning?.dark) ? initialPalette?.warning?.dark : operatorSettingDefaults.palette.warning.dark,
|
||||
light: isValidColor(initialPalette?.warning?.light) ? initialPalette?.warning?.light : operatorSettingDefaults.palette.warning.light,
|
||||
},
|
||||
secondary: {
|
||||
dark: isValidColor(initialPalette?.secondary?.dark) ? initialPalette?.secondary?.dark : operatorSettingDefaults.palette.secondary.dark,
|
||||
light: isValidColor(initialPalette?.secondary?.light) ? initialPalette?.secondary?.light : operatorSettingDefaults.palette.secondary.light,
|
||||
},
|
||||
background: {
|
||||
dark: isValidColor(initialPalette?.background?.dark) ? initialPalette?.background?.dark : operatorSettingDefaults.palette.background.dark,
|
||||
light: isValidColor(initialPalette?.background?.light) ? initialPalette?.background?.light : operatorSettingDefaults.palette.background.light,
|
||||
},
|
||||
tableHeader: {
|
||||
dark: isValidColor(initialPalette?.tableHeader?.dark) ? initialPalette?.tableHeader?.dark : operatorSettingDefaults.palette.tableHeader.dark,
|
||||
light: isValidColor(initialPalette?.tableHeader?.light) ? initialPalette?.tableHeader?.light : operatorSettingDefaults.palette.tableHeader.light,
|
||||
},
|
||||
tableHover: {
|
||||
dark: isValidColor(initialPalette?.tableHover?.dark) ? initialPalette?.tableHover?.dark : operatorSettingDefaults.palette.tableHover.dark,
|
||||
light: isValidColor(initialPalette?.tableHover?.light) ? initialPalette?.tableHover?.light : operatorSettingDefaults.palette.tableHover.light,
|
||||
},
|
||||
pageHeader: {
|
||||
dark: isValidColor(initialPalette?.pageHeader?.dark) ? initialPalette?.pageHeader?.dark : operatorSettingDefaults.palette.pageHeader.dark,
|
||||
light: isValidColor(initialPalette?.pageHeader?.light) ? initialPalette?.pageHeader?.light : operatorSettingDefaults.palette.pageHeader.light,
|
||||
},
|
||||
text: {
|
||||
dark: isValidColor(initialPalette?.text?.dark) ? initialPalette?.text?.dark : operatorSettingDefaults.palette.text.dark,
|
||||
light: isValidColor(initialPalette?.text?.light) ? initialPalette?.text?.light : operatorSettingDefaults.palette.text.light,
|
||||
},
|
||||
paper: {
|
||||
dark: isValidColor(initialPalette?.paper?.dark) ? initialPalette?.paper?.dark : operatorSettingDefaults.palette.paper.dark,
|
||||
light: isValidColor(initialPalette?.paper?.light) ? initialPalette?.paper?.light : operatorSettingDefaults.palette.paper.light,
|
||||
},
|
||||
selectedCallbackColor: {
|
||||
dark: isValidColor(initialPalette?.selectedCallbackColor?.dark) ? initialPalette?.selectedCallbackColor?.dark : operatorSettingDefaults.palette.selectedCallbackColor.dark,
|
||||
light: isValidColor(initialPalette?.selectedCallbackColor?.light) ? initialPalette?.selectedCallbackColor?.light : operatorSettingDefaults.palette.selectedCallbackColor.light,
|
||||
},
|
||||
selectedCallbackHierarchyColor: {
|
||||
dark: isValidColor(initialPalette?.selectedCallbackHierarchyColor?.dark) ? initialPalette?.selectedCallbackHierarchyColor?.dark : operatorSettingDefaults.palette.selectedCallbackHierarchyColor.dark,
|
||||
light: isValidColor(initialPalette?.selectedCallbackHierarchyColor?.light) ? initialPalette?.selectedCallbackHierarchyColor?.light : operatorSettingDefaults.palette.selectedCallbackHierarchyColor.light,
|
||||
},
|
||||
backgroundImage: {
|
||||
dark: initialPalette?.backgroundImage?.dark || operatorSettingDefaults.palette.backgroundImage.dark,
|
||||
light: initialPalette?.backgroundImage?.light || operatorSettingDefaults.palette.backgroundImage.light,
|
||||
},
|
||||
navBarIcons: {
|
||||
dark: isValidColor(initialPalette?.navBarIcons?.dark) ? initialPalette?.navBarIcons?.dark : operatorSettingDefaults.palette.navBarIcons.dark,
|
||||
light: isValidColor(initialPalette?.navBarIcons?.light) ? initialPalette?.navBarIcons?.light : operatorSettingDefaults.palette.navBarIcons.light,
|
||||
},
|
||||
navBarText: {
|
||||
dark: isValidColor(initialPalette?.navBarText?.dark) ? initialPalette?.navBarText?.dark : operatorSettingDefaults.palette.navBarText.dark,
|
||||
light: isValidColor(initialPalette?.navBarText?.light) ? initialPalette?.navBarText?.light : operatorSettingDefaults.palette.navBarText.light,
|
||||
},
|
||||
navBarColor: {
|
||||
dark: isValidColor(initialPalette?.navBarColor?.dark) ? initialPalette?.navBarColor?.dark : operatorSettingDefaults.palette.navBarColor.dark,
|
||||
light: isValidColor(initialPalette?.navBarColor?.light) ? initialPalette?.navBarColor?.light : operatorSettingDefaults.palette.navBarColor.light,
|
||||
},
|
||||
navBarBottomColor: {
|
||||
dark: isValidColor(initialPalette?.navBarBottomColor?.dark) ? initialPalette?.navBarBottomColor?.dark : operatorSettingDefaults.palette.navBarBottomColor.dark,
|
||||
light: isValidColor(initialPalette?.navBarBottomColor?.light) ? initialPalette?.navBarBottomColor?.light : operatorSettingDefaults.palette.navBarBottomColor.light,
|
||||
},
|
||||
taskPromptTextColor: {
|
||||
dark: isValidColor(initialPalette?.taskPromptTextColor?.dark) ? initialPalette?.taskPromptTextColor?.dark : operatorSettingDefaults.palette.taskPromptTextColor.dark,
|
||||
light: isValidColor(initialPalette?.taskPromptTextColor?.light) ? initialPalette?.taskPromptTextColor?.light : operatorSettingDefaults.palette.taskPromptTextColor.light,
|
||||
},
|
||||
taskPromptCommandTextColor: {
|
||||
dark: isValidColor(initialPalette?.taskPromptCommandTextColor?.dark) ? initialPalette?.taskPromptCommandTextColor?.dark : operatorSettingDefaults.palette.taskPromptCommandTextColor.dark,
|
||||
light: isValidColor(initialPalette?.taskPromptCommandTextColor?.light) ? initialPalette?.taskPromptCommandTextColor?.light : operatorSettingDefaults.palette.taskPromptCommandTextColor.light,
|
||||
},
|
||||
taskContextColor: {
|
||||
dark: isValidColor(initialPalette?.taskContextColor?.dark) ? initialPalette?.taskContextColor?.dark : operatorSettingDefaults.palette.taskContextColor.dark,
|
||||
light: isValidColor(initialPalette?.taskContextColor?.light) ? initialPalette?.taskContextColor?.light : operatorSettingDefaults.palette.taskContextColor.light,
|
||||
},
|
||||
taskContextImpersonationColor: {
|
||||
dark: isValidColor(initialPalette?.taskContextImpersonationColor?.dark) ? initialPalette?.taskContextImpersonationColor?.dark : operatorSettingDefaults.palette.taskContextImpersonationColor.dark,
|
||||
light: isValidColor(initialPalette?.taskContextImpersonationColor?.light) ? initialPalette?.taskContextImpersonationColor?.light : operatorSettingDefaults.palette.taskContextImpersonationColor.light,
|
||||
},
|
||||
taskContextExtraColor: {
|
||||
dark: isValidColor(initialPalette?.taskContextExtraColor?.dark) ? initialPalette?.taskContextExtraColor?.dark : operatorSettingDefaults.palette.taskContextExtraColor.dark,
|
||||
light: isValidColor(initialPalette?.taskContextExtraColor?.light) ? initialPalette?.taskContextExtraColor?.light : operatorSettingDefaults.palette.taskContextExtraColor.light,
|
||||
},
|
||||
emptyFolderColor: {
|
||||
dark: isValidColor(initialPalette?.emptyFolderColor?.dark) ? initialPalette?.emptyFolderColor?.dark : operatorSettingDefaults.palette.emptyFolderColor.dark,
|
||||
light: isValidColor(initialPalette?.emptyFolderColor?.light) ? initialPalette?.emptyFolderColor?.light : operatorSettingDefaults.palette.emptyFolderColor.light,
|
||||
},
|
||||
outputBackgroundColor: {
|
||||
dark: isValidColor(initialPalette?.outputBackgroundColor?.dark) ? initialPalette?.outputBackgroundColor?.dark : operatorSettingDefaults.palette.outputBackgroundColor.dark,
|
||||
light: isValidColor(initialPalette?.outputBackgroundColor?.light) ? initialPalette?.outputBackgroundColor?.light : operatorSettingDefaults.palette.outputBackgroundColor.light,
|
||||
},
|
||||
outputTextColor: {
|
||||
dark: isValidColor(initialPalette?.outputTextColor?.dark) ? initialPalette?.outputTextColor?.dark : operatorSettingDefaults.palette.outputTextColor.dark,
|
||||
light: isValidColor(initialPalette?.outputTextColor?.light) ? initialPalette?.outputTextColor?.light : operatorSettingDefaults.palette.outputTextColor.light,
|
||||
},
|
||||
borderColor: {
|
||||
dark: isValidColor(initialPalette?.borderColor?.dark) ? initialPalette?.borderColor?.dark : operatorSettingDefaults.palette.borderColor.dark,
|
||||
light: isValidColor(initialPalette?.borderColor?.light) ? initialPalette?.borderColor?.light : operatorSettingDefaults.palette.borderColor.light,
|
||||
},
|
||||
});
|
||||
const [palette, setPalette] = React.useState(() => buildInitialPalette(initialPalette));
|
||||
const [resumeNotifications, setResumeNotifications] = React.useState(false);
|
||||
const [, updateSettings, clearSettings] = useSetMythicSetting();
|
||||
const onChangeFontFamily = (name, value, error) => {
|
||||
@@ -972,24 +1073,28 @@ export function SettingsOperatorUIConfigDialog(props) {
|
||||
reader.readAsBinaryString(evt.target.files[0]);
|
||||
}
|
||||
const onFileBackgroundImageChangeLight = async (evt) => {
|
||||
const file = evt.target.files?.[0];
|
||||
if(!file){
|
||||
return;
|
||||
}
|
||||
const reader = new FileReader();
|
||||
const filenameExtension = evt.target.files[0].name.split(".")[1];
|
||||
reader.onload = (e) => {
|
||||
const contents = e.target.result;
|
||||
let backgroundImage = `url("data:image/${filenameExtension};base64,${btoa(contents)}`;
|
||||
let backgroundImage = normalizeBackgroundImageValue(e.target.result);
|
||||
setPalette({...palette, backgroundImage: {...palette.backgroundImage, light: backgroundImage}});
|
||||
}
|
||||
reader.readAsBinaryString(evt.target.files[0]);
|
||||
reader.readAsDataURL(file);
|
||||
}
|
||||
const onFileBackgroundImageChangeDark = async (evt) => {
|
||||
const file = evt.target.files?.[0];
|
||||
if(!file){
|
||||
return;
|
||||
}
|
||||
const reader = new FileReader();
|
||||
const filenameExtension = evt.target.files[0].name.split(".")[1];
|
||||
reader.onload = (e) => {
|
||||
const contents = e.target.result;
|
||||
let backgroundImage = `url("data:image/${filenameExtension};base64,${btoa(contents)}`;
|
||||
let backgroundImage = normalizeBackgroundImageValue(e.target.result);
|
||||
setPalette({...palette, backgroundImage: {...palette.backgroundImage, dark: backgroundImage}});
|
||||
}
|
||||
reader.readAsBinaryString(evt.target.files[0]);
|
||||
reader.readAsDataURL(file);
|
||||
}
|
||||
|
||||
const getCurrentPreferences = () => {
|
||||
|
||||
@@ -1,6 +1,19 @@
|
||||
import { createGlobalStyle} from "styled-components"
|
||||
import {alpha} from "@mui/material/styles";
|
||||
// hex transparencies https://gist.github.com/lopspower/03fb1cc0ac9f32ef38f4
|
||||
const getSectionHeaderAccent = (props) => props.theme.sectionHeader?.accent || props.theme.palette.primary.main;
|
||||
const getSectionHeaderGradient = (props) => {
|
||||
if(props.theme.gradients?.sectionHeader){
|
||||
return props.theme.gradients.sectionHeader;
|
||||
}
|
||||
const headerTextColor = props.theme.pageHeaderText?.main || props.theme.palette.text.primary;
|
||||
return `linear-gradient(90deg, ${alpha(props.theme.palette.primary.main, props.theme.palette.mode === "dark" ? 0.28 : 0.18)} 0%, ${alpha(props.theme.palette.primary.main, props.theme.palette.mode === "dark" ? 0.12 : 0.08)} 48%, ${alpha(headerTextColor, props.theme.palette.mode === "dark" ? 0.055 : 0.04)} 100%)`;
|
||||
};
|
||||
const getSubtleAccentGradient = (props) => props.theme.gradients?.subtleAccent ||
|
||||
`linear-gradient(135deg, ${alpha(props.theme.palette.primary.main, props.theme.palette.mode === "dark" ? 0.13 : 0.075)} 0%, ${alpha(props.theme.palette.background.paper, 0)} 62%)`;
|
||||
const getSubtleAccentHorizontalGradient = (props) => props.theme.gradients?.subtleAccentHorizontal ||
|
||||
`linear-gradient(90deg, ${alpha(props.theme.palette.primary.main, props.theme.palette.mode === "dark" ? 0.12 : 0.07)} 0%, ${alpha(props.theme.palette.background.paper, 0)} 100%)`;
|
||||
|
||||
export const GlobalStyles = createGlobalStyle`
|
||||
body {
|
||||
margin: 0;
|
||||
@@ -183,7 +196,7 @@ tspan {
|
||||
}
|
||||
|
||||
.resizer.isResizing {
|
||||
background: blue;
|
||||
background: ${(props) => props.theme.sectionHeader?.accent || props.theme.palette.primary.main};
|
||||
opacity: 1;
|
||||
}
|
||||
.groupNode {
|
||||
@@ -608,9 +621,9 @@ tspan {
|
||||
}
|
||||
.mythic-grid-filter-dialog-title {
|
||||
background-color: ${(props) => props.theme.pageHeader?.main || props.theme.surfaces?.muted || props.theme.palette.background.default};
|
||||
background-image: ${(props) => `linear-gradient(90deg, ${alpha(props.theme.palette.primary.main, props.theme.palette.mode === "dark" ? 0.18 : 0.1)} 0%, ${alpha(props.theme.palette.text.primary, props.theme.palette.mode === "dark" ? 0.045 : 0.035)} 100%)`};
|
||||
background-image: ${getSectionHeaderGradient};
|
||||
border-bottom: 1px solid ${(props) => props.theme.table?.borderSoft || props.theme.borderColor};
|
||||
color: ${(props) => props.theme.palette.text.primary};
|
||||
color: ${(props) => props.theme.pageHeaderText?.main || props.theme.palette.text.primary};
|
||||
font-size: 0.98rem !important;
|
||||
font-weight: 850 !important;
|
||||
line-height: 1.2 !important;
|
||||
@@ -1839,11 +1852,8 @@ tspan {
|
||||
.mythic-detail-section-header {
|
||||
align-items: center;
|
||||
background-color: ${(props) => props.theme.pageHeader.main};
|
||||
background-image: ${(props) => {
|
||||
const headerTextColor = props.theme.pageHeaderText?.main || props.theme.palette.text.primary;
|
||||
return `linear-gradient(90deg, ${alpha(props.theme.palette.primary.main, props.theme.palette.mode === "dark" ? 0.28 : 0.18)} 0%, ${alpha(props.theme.palette.primary.main, props.theme.palette.mode === "dark" ? 0.12 : 0.08)} 48%, ${alpha(headerTextColor, props.theme.palette.mode === "dark" ? 0.055 : 0.04)} 100%)`;
|
||||
}};
|
||||
border: 1px solid ${(props) => alpha(props.theme.palette.primary.main, props.theme.palette.mode === "dark" ? 0.55 : 0.38)};
|
||||
background-image: ${getSectionHeaderGradient};
|
||||
border: 1px solid ${(props) => alpha(getSectionHeaderAccent(props), props.theme.palette.mode === "dark" ? 0.55 : 0.38)};
|
||||
border-radius: ${(props) => props.theme.shape.borderRadius}px;
|
||||
box-shadow: inset 0 1px 0 ${(props) => alpha(props.theme.pageHeaderText?.main || props.theme.palette.text.primary, 0.22)}, 0 2px 6px ${(props) => alpha(props.theme.palette.common.black, props.theme.palette.mode === "dark" ? 0.28 : 0.12)};
|
||||
color: ${(props) => props.theme.pageHeaderText?.main || props.theme.palette.text.primary};
|
||||
@@ -1860,7 +1870,7 @@ tspan {
|
||||
width: 100%;
|
||||
}
|
||||
.mythic-detail-section-header::before {
|
||||
background-color: ${(props) => props.theme.palette.primary.main};
|
||||
background-color: ${getSectionHeaderAccent};
|
||||
bottom: 0;
|
||||
box-shadow: 0 0 0 1px ${(props) => alpha(props.theme.pageHeaderText?.main || props.theme.palette.text.primary, 0.2)};
|
||||
content: "";
|
||||
@@ -1870,18 +1880,15 @@ tspan {
|
||||
width: 6px;
|
||||
}
|
||||
.mythic-section-header {
|
||||
background-image: ${(props) => {
|
||||
const headerTextColor = props.theme.pageHeaderText?.main || props.theme.palette.text.primary;
|
||||
return `linear-gradient(90deg, ${alpha(props.theme.palette.primary.main, props.theme.palette.mode === "dark" ? 0.28 : 0.18)} 0%, ${alpha(props.theme.palette.primary.main, props.theme.palette.mode === "dark" ? 0.12 : 0.08)} 48%, ${alpha(headerTextColor, props.theme.palette.mode === "dark" ? 0.055 : 0.04)} 100%)`;
|
||||
}} !important;
|
||||
border-color: ${(props) => alpha(props.theme.palette.primary.main, props.theme.palette.mode === "dark" ? 0.55 : 0.38)} !important;
|
||||
background-image: ${getSectionHeaderGradient} !important;
|
||||
border-color: ${(props) => alpha(getSectionHeaderAccent(props), props.theme.palette.mode === "dark" ? 0.55 : 0.38)} !important;
|
||||
box-shadow: inset 0 1px 0 ${(props) => alpha(props.theme.pageHeaderText?.main || props.theme.palette.text.primary, 0.22)}, 0 2px 6px ${(props) => alpha(props.theme.palette.common.black, props.theme.palette.mode === "dark" ? 0.28 : 0.12)} !important;
|
||||
overflow: hidden !important;
|
||||
padding-left: 1rem !important;
|
||||
position: relative !important;
|
||||
}
|
||||
.mythic-section-header::before {
|
||||
background-color: ${(props) => props.theme.palette.primary.main};
|
||||
background-color: ${getSectionHeaderAccent};
|
||||
bottom: 0;
|
||||
box-shadow: 0 0 0 1px ${(props) => alpha(props.theme.pageHeaderText?.main || props.theme.palette.text.primary, 0.2)};
|
||||
content: "";
|
||||
@@ -3490,10 +3497,7 @@ tspan {
|
||||
min-width: 0;
|
||||
}
|
||||
.mythic-create-parameter-group-header {
|
||||
background-image: ${(props) => {
|
||||
const headerTextColor = props.theme.pageHeaderText?.main || props.theme.palette.text.primary;
|
||||
return `linear-gradient(90deg, ${alpha(props.theme.palette.primary.main, props.theme.palette.mode === "dark" ? 0.18 : 0.1)} 0%, ${alpha(headerTextColor, props.theme.palette.mode === "dark" ? 0.055 : 0.04)} 100%)`;
|
||||
}};
|
||||
background-image: ${getSectionHeaderGradient};
|
||||
border: 1px solid ${(props) => props.theme.table?.borderSoft || props.theme.borderColor};
|
||||
border-radius: ${(props) => props.theme.shape.borderRadius}px;
|
||||
color: ${(props) => props.theme.pageHeaderText?.main || props.theme.palette.text.primary};
|
||||
@@ -3508,10 +3512,7 @@ tspan {
|
||||
min-width: 0;
|
||||
}
|
||||
.mythic-create-summary-group-header {
|
||||
background-image: ${(props) => {
|
||||
const headerTextColor = props.theme.pageHeaderText?.main || props.theme.palette.text.primary;
|
||||
return `linear-gradient(90deg, ${alpha(props.theme.palette.primary.main, props.theme.palette.mode === "dark" ? 0.18 : 0.1)} 0%, ${alpha(headerTextColor, props.theme.palette.mode === "dark" ? 0.055 : 0.04)} 100%)`;
|
||||
}};
|
||||
background-image: ${getSectionHeaderGradient};
|
||||
border: 1px solid ${(props) => props.theme.table?.borderSoft || props.theme.borderColor};
|
||||
border-radius: ${(props) => props.theme.shape.borderRadius}px;
|
||||
color: ${(props) => props.theme.palette.text.primary};
|
||||
@@ -3741,11 +3742,8 @@ tspan {
|
||||
.mythic-dashboard-card-header {
|
||||
align-items: center;
|
||||
background-color: ${(props) => props.theme.surfaces?.muted || props.theme.palette.background.default};
|
||||
background-image: ${(props) => {
|
||||
const headerTextColor = props.theme.pageHeaderText?.main || props.theme.palette.text.primary;
|
||||
return `linear-gradient(90deg, ${alpha(props.theme.palette.primary.main, props.theme.palette.mode === "dark" ? 0.16 : 0.09)} 0%, ${alpha(headerTextColor, props.theme.palette.mode === "dark" ? 0.05 : 0.035)} 100%)`;
|
||||
}};
|
||||
border-bottom: 1px solid ${(props) => alpha(props.theme.palette.primary.main, props.theme.palette.mode === "dark" ? 0.34 : 0.2)};
|
||||
background-image: ${getSectionHeaderGradient};
|
||||
border-bottom: 1px solid ${(props) => alpha(getSectionHeaderAccent(props), props.theme.palette.mode === "dark" ? 0.34 : 0.2)};
|
||||
display: flex;
|
||||
flex: 0 0 auto;
|
||||
gap: 0.65rem;
|
||||
@@ -3757,7 +3755,7 @@ tspan {
|
||||
position: relative;
|
||||
}
|
||||
.mythic-dashboard-card-header::before {
|
||||
background-color: ${(props) => props.theme.palette.primary.main};
|
||||
background-color: ${getSectionHeaderAccent};
|
||||
bottom: 0;
|
||||
content: "";
|
||||
left: 0;
|
||||
@@ -3874,7 +3872,7 @@ tspan {
|
||||
}
|
||||
.mythic-dashboard-chart-canvas {
|
||||
background-color: ${(props) => props.theme.palette.mode === "dark" ? alpha(props.theme.palette.common.white, 0.028) : alpha(props.theme.palette.common.black, 0.014)};
|
||||
background-image: ${(props) => `linear-gradient(135deg, ${alpha(props.theme.palette.primary.main, props.theme.palette.mode === "dark" ? 0.1 : 0.055)} 0%, ${alpha(props.theme.palette.background.paper, 0)} 62%)`};
|
||||
background-image: ${getSubtleAccentGradient};
|
||||
border: 1px solid ${(props) => props.theme.table?.borderSoft || props.theme.borderColor};
|
||||
border-radius: ${(props) => props.theme.shape.borderRadius}px;
|
||||
display: flex;
|
||||
@@ -4202,7 +4200,7 @@ tspan {
|
||||
.mythic-dashboard-callback-kpi,
|
||||
.mythic-dashboard-service-kpi {
|
||||
background-color: ${(props) => props.theme.palette.mode === "dark" ? alpha(props.theme.palette.common.white, 0.035) : alpha(props.theme.palette.common.black, 0.018)};
|
||||
background-image: ${(props) => `linear-gradient(135deg, ${alpha(props.theme.palette.primary.main, props.theme.palette.mode === "dark" ? 0.13 : 0.075)} 0%, ${alpha(props.theme.palette.background.paper, 0)} 58%)`};
|
||||
background-image: ${getSubtleAccentGradient};
|
||||
border: 1px solid ${(props) => props.theme.table?.borderSoft || props.theme.borderColor};
|
||||
border-radius: ${(props) => props.theme.shape.borderRadius}px;
|
||||
display: flex;
|
||||
@@ -4412,12 +4410,9 @@ tspan {
|
||||
}
|
||||
.mythic-dashboard-edit-toolbar {
|
||||
align-items: center;
|
||||
background-color: ${(props) => {
|
||||
const headerSurface = props.theme.pageHeader?.main || props.theme.surfaces?.muted || props.theme.palette.background.paper;
|
||||
return props.theme.palette.mode === "dark" ? headerSurface : alpha(props.theme.palette.primary.main, 0.16);
|
||||
}} !important;
|
||||
background-image: ${(props) => `linear-gradient(90deg, ${alpha(props.theme.palette.primary.main, props.theme.palette.mode === "dark" ? 0.44 : 0.32)} 0%, ${alpha(props.theme.palette.primary.main, props.theme.palette.mode === "dark" ? 0.22 : 0.22)} 42%, ${alpha(props.theme.palette.primary.main, props.theme.palette.mode === "dark" ? 0.08 : 0.12)} 100%)`} !important;
|
||||
border: 1px solid ${(props) => alpha(props.theme.palette.primary.main, props.theme.palette.mode === "dark" ? 0.55 : 0.38)};
|
||||
background-color: ${(props) => props.theme.pageHeader?.main || props.theme.surfaces?.muted || props.theme.palette.background.paper} !important;
|
||||
background-image: ${getSectionHeaderGradient} !important;
|
||||
border: 1px solid ${(props) => alpha(getSectionHeaderAccent(props), props.theme.palette.mode === "dark" ? 0.55 : 0.38)};
|
||||
border-radius: ${(props) => props.theme.shape.borderRadius}px;
|
||||
box-shadow: inset 0 1px 0 ${(props) => alpha(props.theme.pageHeaderText?.main || props.theme.palette.text.primary, 0.22)}, 0 2px 6px ${(props) => alpha(props.theme.palette.common.black, props.theme.palette.mode === "dark" ? 0.24 : 0.1)};
|
||||
color: ${(props) => props.theme.pageHeaderText?.main || props.theme.palette.text.primary};
|
||||
@@ -4432,7 +4427,7 @@ tspan {
|
||||
position: relative;
|
||||
}
|
||||
.mythic-dashboard-edit-toolbar::before {
|
||||
background-color: ${(props) => props.theme.palette.primary.main};
|
||||
background-color: ${getSectionHeaderAccent};
|
||||
bottom: 0;
|
||||
box-shadow: 0 0 0 1px ${(props) => alpha(props.theme.pageHeaderText?.main || props.theme.palette.text.primary, 0.2)};
|
||||
content: "";
|
||||
@@ -4483,10 +4478,7 @@ tspan {
|
||||
.mythic-dashboard-widget-dialog-header {
|
||||
align-items: center;
|
||||
background-color: ${(props) => props.theme.surfaces?.raised || props.theme.palette.background.paper};
|
||||
background-image: ${(props) => {
|
||||
const headerTextColor = props.theme.palette.text.primary;
|
||||
return `linear-gradient(90deg, ${alpha(props.theme.palette.primary.main, props.theme.palette.mode === "dark" ? 0.12 : 0.07)} 0%, ${alpha(headerTextColor, props.theme.palette.mode === "dark" ? 0.045 : 0.035)} 100%)`;
|
||||
}};
|
||||
background-image: ${getSectionHeaderGradient};
|
||||
border: 1px solid ${(props) => props.theme.table?.borderSoft || props.theme.borderColor};
|
||||
border-radius: ${(props) => props.theme.shape.borderRadius}px;
|
||||
display: flex;
|
||||
@@ -4537,7 +4529,7 @@ tspan {
|
||||
outline: none;
|
||||
}
|
||||
.mythic-dashboard-widget-option-selected {
|
||||
background-image: ${(props) => `linear-gradient(135deg, ${alpha(props.theme.palette.primary.main, props.theme.palette.mode === "dark" ? 0.18 : 0.1)} 0%, ${alpha(props.theme.palette.background.paper, 0)} 60%)`};
|
||||
background-image: ${getSubtleAccentGradient};
|
||||
border-color: ${(props) => alpha(props.theme.palette.primary.main, props.theme.palette.mode === "dark" ? 0.68 : 0.48)};
|
||||
}
|
||||
.mythic-dashboard-widget-option-top {
|
||||
@@ -5704,10 +5696,7 @@ tspan {
|
||||
overflow: hidden;
|
||||
}
|
||||
.mythic-eventing-step-config-section-header {
|
||||
background-image: ${(props) => {
|
||||
const headerTextColor = props.theme.pageHeaderText?.main || props.theme.palette.text.primary;
|
||||
return `linear-gradient(90deg, ${alpha(props.theme.palette.primary.main, props.theme.palette.mode === "dark" ? 0.12 : 0.07)} 0%, ${alpha(headerTextColor, props.theme.palette.mode === "dark" ? 0.045 : 0.035)} 100%)`;
|
||||
}};
|
||||
background-image: ${getSectionHeaderGradient};
|
||||
border-bottom: 1px solid ${(props) => props.theme.table?.borderSoft || props.theme.borderColor};
|
||||
padding: 0.62rem 0.7rem 0.55rem;
|
||||
}
|
||||
@@ -6150,7 +6139,7 @@ tspan {
|
||||
}
|
||||
.mythic-eventing-workflow-overview {
|
||||
background-color: ${(props) => props.theme.surfaces?.raised || props.theme.palette.background.paper};
|
||||
background-image: ${(props) => `linear-gradient(90deg, ${alpha(props.theme.palette.primary.main, props.theme.palette.mode === "dark" ? 0.12 : 0.06)} 0%, ${alpha(props.theme.palette.background.paper, 0)} 48%)`};
|
||||
background-image: ${getSubtleAccentHorizontalGradient};
|
||||
border: 1px solid ${(props) => props.theme.table?.borderSoft || props.theme.borderColor};
|
||||
border-radius: ${(props) => props.theme.shape.borderRadius}px;
|
||||
box-shadow: ${(props) => props.theme.palette.mode === "dark" ? "inset 0 1px 0 rgba(255,255,255,0.055)" : "inset 0 1px 0 rgba(255,255,255,0.78)"};
|
||||
|
||||
Reference in New Issue
Block a user