Merge pull request #148 from AmitChauhan63390/ui-fix
feat: dark theme support
This commit is contained in:
23
src/App.tsx
23
src/App.tsx
@@ -4,6 +4,7 @@ import { ThemeProvider, createTheme } from "@mui/material/styles";
|
|||||||
import { GlobalInfoProvider } from "./context/globalInfo";
|
import { GlobalInfoProvider } from "./context/globalInfo";
|
||||||
import { PageWrapper } from "./pages/PageWrappper";
|
import { PageWrapper } from "./pages/PageWrappper";
|
||||||
import i18n from "./i18n";
|
import i18n from "./i18n";
|
||||||
|
import ThemeModeProvider from './context/theme-provider';
|
||||||
|
|
||||||
|
|
||||||
const theme = createTheme({
|
const theme = createTheme({
|
||||||
@@ -85,15 +86,23 @@ const theme = createTheme({
|
|||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
return (
|
return (
|
||||||
<ThemeProvider theme={theme}>
|
<ThemeModeProvider>
|
||||||
|
<GlobalInfoProvider>
|
||||||
|
<Routes>
|
||||||
|
<Route path="/*" element={<PageWrapper />} />
|
||||||
|
</Routes>
|
||||||
|
</GlobalInfoProvider>
|
||||||
|
</ThemeModeProvider>
|
||||||
|
|
||||||
|
// <ThemeProvider theme={theme}>
|
||||||
|
|
||||||
<GlobalInfoProvider>
|
// <GlobalInfoProvider>
|
||||||
<Routes>
|
// <Routes>
|
||||||
<Route path="/*" element={<PageWrapper />} />
|
// <Route path="/*" element={<PageWrapper />} />
|
||||||
</Routes>
|
// </Routes>
|
||||||
</GlobalInfoProvider>
|
// </GlobalInfoProvider>
|
||||||
|
|
||||||
</ThemeProvider>
|
// </ThemeProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,14 @@
|
|||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import { Stack } from "@mui/material";
|
import { Stack } from "@mui/material";
|
||||||
|
import { useThemeMode } from "../../context/theme-provider";
|
||||||
|
|
||||||
interface LoaderProps {
|
interface LoaderProps {
|
||||||
text: string;
|
text: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Loader: React.FC<LoaderProps> = ({ text }) => {
|
export const Loader: React.FC<LoaderProps> = ({ text }) => {
|
||||||
|
const { darkMode } = useThemeMode();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack direction="column" sx={{ margin: "30px 0px", alignItems: "center" }}>
|
<Stack direction="column" sx={{ margin: "30px 0px", alignItems: "center" }}>
|
||||||
<DotsContainer>
|
<DotsContainer>
|
||||||
@@ -14,15 +17,19 @@ export const Loader: React.FC<LoaderProps> = ({ text }) => {
|
|||||||
<Dot />
|
<Dot />
|
||||||
<Dot />
|
<Dot />
|
||||||
</DotsContainer>
|
</DotsContainer>
|
||||||
<StyledParagraph>{text}</StyledParagraph>
|
<StyledParagraph darkMode={darkMode}>{text}</StyledParagraph>
|
||||||
</Stack>
|
</Stack>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const StyledParagraph = styled.p`
|
interface StyledParagraphProps {
|
||||||
|
darkMode: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const StyledParagraph = styled.p<StyledParagraphProps>`
|
||||||
font-size: large;
|
font-size: large;
|
||||||
font-family: inherit;
|
font-family: inherit;
|
||||||
color: #333;
|
color: ${({ darkMode }) => (darkMode ? 'white' : '#333')};
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ export const RecordingIcon = () => {
|
|||||||
textIndent: 0,
|
textIndent: 0,
|
||||||
textTransform: 'none',
|
textTransform: 'none',
|
||||||
}}
|
}}
|
||||||
fill="white"
|
fill="black"
|
||||||
d="m82.048,962.36c-0.18271-0.003-0.35147-0.001-0.53125,0.0312-0.69633,0.12662-1.3353,0.54943-1.7812,1.1562l-0.03125-0.0312-0.03125,0.0625-18.031,22.125h-44.438c-2.809,0-5.0938,2.2847-5.0938,5.0938v35.531c0,2.8091,2.2847,5.125,5.0938,5.125h20.562l-1.3125,4.5938h-0.71875c-1.1137,0-2.0312,0.9175-2.0312,2.0312v2.2188c0,1.1137,0.91751,2.0625,2.0312,2.0625h19.938c1.1137,0,2.0312-0.9488,2.0312-2.0625v-2.2188c0-1.1137-0.91751-2.0312-2.0312-2.0312h-0.71875l-1.3438-4.5938h20.438c2.809,0,5.0938-2.3159,5.0938-5.125v-35.531c0-1.7706-0.90663-3.3369-2.2812-4.25l10.531-17.625,0.03125-0.0625c0.84234-1.2783,0.51486-3.0308-0.75-3.9062l-3.0312-2.0938c-0.48208-0.33338-1.0456-0.49073-1.5938-0.5zm-0.21875,1.6875c0.28723-0.0523,0.57635,0.0338,0.84375,0.21875l3.0312,2.0938c0.53421,0.36973,0.65504,1.0569,0.28125,1.5938a0.85008,0.85008,0,0,0,-0.03125,0.0312l-17.906,30.062-9.0938-6.3125,22.094-27.125a0.85008,0.85008,0,0,0,0.03125,-0.0625c0.18694-0.26873,0.46277-0.4477,0.75-0.5zm-64.625,23.344,43.062,0-2.3438,2.9062-40.688,0c-0.0312-0.002-0.06255-0.002-0.09375,0-0.0312-0.002-0.06255-0.002-0.09375,0-0.38644,0.0753-0.69183,0.45007-0.6875,0.84375v34.844c0.003,0.4514,0.42377,0.857,0.875,0.8437h56.781c0.44088,0,0.84048-0.4028,0.84375-0.8437v-34.844c-0.008-0.25538-0.13841-0.50419-0.34375-0.65625l1.5-2.5c0.87419,0.61342,1.4375,1.6512,1.4375,2.8125v35.531c0,1.8967-1.5096,3.4063-3.4062,3.4063h-56.844c-1.8966,0-3.4062-1.5096-3.4062-3.4063v-35.531c0-1.8966,1.5096-3.4062,3.4062-3.4062zm0.875,4.5938,38.469,0-1.0312,1.25,0,0.0312c-0.48971,0.60518-0.64056,1.3922-0.5,2.0312,0.14234,0.64722,0.49536,1.1659,0.84375,1.6562a0.85008,0.85008,0,0,0,0.1875,0.21875l1.2812,0.875c-1.0387,0.79518-2.0706,1.1661-3.2188,1.6562-1.4337,0.61212-3.0045,1.4512-4.3438,3.375-1.1451,1.6448-1.0525,3.5446-0.78125,5.3437,0.27121,1.7991,0.70152,3.5802,0.5625,5.2188a0.85008,0.85008,0,0,0,1.2188,0.8437c1.4928-0.7039,3.3085-0.9361,5.0938-1.3125s3.6049-0.9489,4.75-2.5937c1.34-1.9249,1.5559-3.6628,1.625-5.2188,0.05552-1.2502,0.05447-2.363,0.4375-3.625l1.2812,0.875c1.2744,0.8814,3.0499,0.4785,3.8438-0.8437l0.03125-0.031,1.125-1.9063a0.85008,0.85008,0,0,0,0.03125,-0.0312l0.03125-0.0312a0.85008,0.85008,0,0,0,0.09375,-0.21875l4.0625-6.8125v32.406h-55.094v-33.156zm39.812,1.0625,9.3125,6.4375-0.84375,1.4062a0.85008,0.85008,0,0,0,-0.03125,0c-0.33037,0.5726-0.86691,0.7168-1.4062,0.3438l-2.1875-1.5-0.1875-0.15625-0.65625-0.4375-1.8438-1.2812-0.84375-0.59375-0.0625-0.0312-1.9688-1.3438c-0.25075-0.36937-0.4494-0.7387-0.5-0.96875-0.0558-0.25371-0.0497-0.34572,0.15625-0.59375l1.0625-1.2812zm0.84375,5.9688,0.34375,0.25,1.8438,1.25,0.375,0.25c-0.60662,1.6994-0.69236,3.2017-0.75,4.5-0.0657,1.481-0.18871,2.7295-1.3125,4.3438-0.76502,1.0988-2.0465,1.5537-3.7188,1.9062-1.3283,0.2801-2.854,0.5618-4.3438,1.0625-0.0521-1.5631-0.29881-3.0716-0.5-4.4062-0.25388-1.6841-0.29624-3.0262,0.46875-4.125,1.1246-1.6154,2.2602-2.1673,3.625-2.75,1.1932-0.5094,2.5901-1.1274,3.9688-2.2813zm-30.5,2.5313c-1.6815,0-3.0625,1.4119-3.0625,3.0937s1.381,3.0313,3.0625,3.0313,3.0625-1.3495,3.0625-3.0313-1.381-3.0937-3.0625-3.0937zm0,1.7187c0.76283,0,1.375,0.612,1.375,1.375s-0.61217,1.3438-1.375,1.3438-1.3438-0.5808-1.3438-1.3438,0.58092-1.375,1.3438-1.375zm8,5.6563c-3.3379,0.1812-7.1915,2.4749-10.344,4.6875-3.1522,2.2126-5.5625,4.4062-5.5625,4.4062-0.3273,0.3027-0.36527,0.8915-0.0625,1.2188,0.30273,0.3272,0.89151,0.334,1.2188,0.031,0,0,2.3185-2.1046,5.375-4.25s6.8989-4.2667,9.4688-4.4063c1.6177-0.088,4.3314,1.0381,6.5312,2.25,2.1999,1.212,3.9375,2.4375,3.9375,2.4375,0.35264,0.3353,1.001,0.2728,1.2812-0.125,0.28024-0.3977,0.12188-1.0307-0.3125-1.25,0,0-1.7602-1.2941-4.0625-2.5625-2.3024-1.2684-5.0831-2.567-7.4688-2.4375zm3.2812,22.562,12.344,0,1.3438,4.5312-15,0,1.3125-4.5312zm-3.7812,6.25,19.938,0c0.20135,0,0.3125,0.1424,0.3125,0.3437v2.2188c0,0.2013-0.11115,0.3437-0.3125,0.3437h-19.938c-0.20135,0-0.34375-0.1424-0.34375-0.3437v-2.2188c0-0.2013,0.1424-0.3437,0.34375-0.3437z" />
|
d="m82.048,962.36c-0.18271-0.003-0.35147-0.001-0.53125,0.0312-0.69633,0.12662-1.3353,0.54943-1.7812,1.1562l-0.03125-0.0312-0.03125,0.0625-18.031,22.125h-44.438c-2.809,0-5.0938,2.2847-5.0938,5.0938v35.531c0,2.8091,2.2847,5.125,5.0938,5.125h20.562l-1.3125,4.5938h-0.71875c-1.1137,0-2.0312,0.9175-2.0312,2.0312v2.2188c0,1.1137,0.91751,2.0625,2.0312,2.0625h19.938c1.1137,0,2.0312-0.9488,2.0312-2.0625v-2.2188c0-1.1137-0.91751-2.0312-2.0312-2.0312h-0.71875l-1.3438-4.5938h20.438c2.809,0,5.0938-2.3159,5.0938-5.125v-35.531c0-1.7706-0.90663-3.3369-2.2812-4.25l10.531-17.625,0.03125-0.0625c0.84234-1.2783,0.51486-3.0308-0.75-3.9062l-3.0312-2.0938c-0.48208-0.33338-1.0456-0.49073-1.5938-0.5zm-0.21875,1.6875c0.28723-0.0523,0.57635,0.0338,0.84375,0.21875l3.0312,2.0938c0.53421,0.36973,0.65504,1.0569,0.28125,1.5938a0.85008,0.85008,0,0,0,-0.03125,0.0312l-17.906,30.062-9.0938-6.3125,22.094-27.125a0.85008,0.85008,0,0,0,0.03125,-0.0625c0.18694-0.26873,0.46277-0.4477,0.75-0.5zm-64.625,23.344,43.062,0-2.3438,2.9062-40.688,0c-0.0312-0.002-0.06255-0.002-0.09375,0-0.0312-0.002-0.06255-0.002-0.09375,0-0.38644,0.0753-0.69183,0.45007-0.6875,0.84375v34.844c0.003,0.4514,0.42377,0.857,0.875,0.8437h56.781c0.44088,0,0.84048-0.4028,0.84375-0.8437v-34.844c-0.008-0.25538-0.13841-0.50419-0.34375-0.65625l1.5-2.5c0.87419,0.61342,1.4375,1.6512,1.4375,2.8125v35.531c0,1.8967-1.5096,3.4063-3.4062,3.4063h-56.844c-1.8966,0-3.4062-1.5096-3.4062-3.4063v-35.531c0-1.8966,1.5096-3.4062,3.4062-3.4062zm0.875,4.5938,38.469,0-1.0312,1.25,0,0.0312c-0.48971,0.60518-0.64056,1.3922-0.5,2.0312,0.14234,0.64722,0.49536,1.1659,0.84375,1.6562a0.85008,0.85008,0,0,0,0.1875,0.21875l1.2812,0.875c-1.0387,0.79518-2.0706,1.1661-3.2188,1.6562-1.4337,0.61212-3.0045,1.4512-4.3438,3.375-1.1451,1.6448-1.0525,3.5446-0.78125,5.3437,0.27121,1.7991,0.70152,3.5802,0.5625,5.2188a0.85008,0.85008,0,0,0,1.2188,0.8437c1.4928-0.7039,3.3085-0.9361,5.0938-1.3125s3.6049-0.9489,4.75-2.5937c1.34-1.9249,1.5559-3.6628,1.625-5.2188,0.05552-1.2502,0.05447-2.363,0.4375-3.625l1.2812,0.875c1.2744,0.8814,3.0499,0.4785,3.8438-0.8437l0.03125-0.031,1.125-1.9063a0.85008,0.85008,0,0,0,0.03125,-0.0312l0.03125-0.0312a0.85008,0.85008,0,0,0,0.09375,-0.21875l4.0625-6.8125v32.406h-55.094v-33.156zm39.812,1.0625,9.3125,6.4375-0.84375,1.4062a0.85008,0.85008,0,0,0,-0.03125,0c-0.33037,0.5726-0.86691,0.7168-1.4062,0.3438l-2.1875-1.5-0.1875-0.15625-0.65625-0.4375-1.8438-1.2812-0.84375-0.59375-0.0625-0.0312-1.9688-1.3438c-0.25075-0.36937-0.4494-0.7387-0.5-0.96875-0.0558-0.25371-0.0497-0.34572,0.15625-0.59375l1.0625-1.2812zm0.84375,5.9688,0.34375,0.25,1.8438,1.25,0.375,0.25c-0.60662,1.6994-0.69236,3.2017-0.75,4.5-0.0657,1.481-0.18871,2.7295-1.3125,4.3438-0.76502,1.0988-2.0465,1.5537-3.7188,1.9062-1.3283,0.2801-2.854,0.5618-4.3438,1.0625-0.0521-1.5631-0.29881-3.0716-0.5-4.4062-0.25388-1.6841-0.29624-3.0262,0.46875-4.125,1.1246-1.6154,2.2602-2.1673,3.625-2.75,1.1932-0.5094,2.5901-1.1274,3.9688-2.2813zm-30.5,2.5313c-1.6815,0-3.0625,1.4119-3.0625,3.0937s1.381,3.0313,3.0625,3.0313,3.0625-1.3495,3.0625-3.0313-1.381-3.0937-3.0625-3.0937zm0,1.7187c0.76283,0,1.375,0.612,1.375,1.375s-0.61217,1.3438-1.375,1.3438-1.3438-0.5808-1.3438-1.3438,0.58092-1.375,1.3438-1.375zm8,5.6563c-3.3379,0.1812-7.1915,2.4749-10.344,4.6875-3.1522,2.2126-5.5625,4.4062-5.5625,4.4062-0.3273,0.3027-0.36527,0.8915-0.0625,1.2188,0.30273,0.3272,0.89151,0.334,1.2188,0.031,0,0,2.3185-2.1046,5.375-4.25s6.8989-4.2667,9.4688-4.4063c1.6177-0.088,4.3314,1.0381,6.5312,2.25,2.1999,1.212,3.9375,2.4375,3.9375,2.4375,0.35264,0.3353,1.001,0.2728,1.2812-0.125,0.28024-0.3977,0.12188-1.0307-0.3125-1.25,0,0-1.7602-1.2941-4.0625-2.5625-2.3024-1.2684-5.0831-2.567-7.4688-2.4375zm3.2812,22.562,12.344,0,1.3438,4.5312-15,0,1.3125-4.5312zm-3.7812,6.25,19.938,0c0.20135,0,0.3125,0.1424,0.3125,0.3437v2.2188c0,0.2013-0.11115,0.3437-0.3125,0.3437h-19.938c-0.20135,0-0.34375-0.1424-0.34375-0.3437v-2.2188c0-0.2013,0.1424-0.3437,0.34375-0.3437z" />
|
||||||
</g>
|
</g>
|
||||||
</g>
|
</g>
|
||||||
|
|||||||
@@ -1,26 +1,23 @@
|
|||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
|
import { useThemeMode } from '../../../context/theme-provider';
|
||||||
|
|
||||||
export const NavBarButton = styled.button<{ disabled: boolean }>`
|
|
||||||
|
|
||||||
|
export const NavBarButton = styled.button<{ disabled: boolean, mode: 'light' | 'dark' }>`
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
margin-right: 5px;
|
margin-right: 5px;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
border: none;
|
border: none;
|
||||||
background-color: transparent;
|
background-color: ${mode => mode ? '#333' : '#ffffff'};
|
||||||
cursor: ${({ disabled }) => disabled ? 'default' : 'pointer'};
|
cursor: ${({ disabled }) => disabled ? 'default' : 'pointer'};
|
||||||
width: 24px;
|
width: 24px;
|
||||||
height: 24px;
|
height: 24px;
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
outline: none;
|
outline: none;
|
||||||
color: ${({ disabled }) => disabled ? '#999' : '#333'};
|
color: ${mode => mode ? '#ffffff' : '#333333'};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
${({ disabled }) => disabled ? null : `
|
|
||||||
&:hover {
|
|
||||||
background-color: #ddd;
|
|
||||||
}
|
|
||||||
&:active {
|
|
||||||
background-color: #d0d0d0;
|
|
||||||
}
|
|
||||||
`};
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const UrlFormButton = styled.button`
|
export const UrlFormButton = styled.button`
|
||||||
|
|||||||
@@ -5,19 +5,24 @@ import { useActionContext } from '../../context/browserActions';
|
|||||||
import MaxunLogo from "../../assets/maxunlogo.png";
|
import MaxunLogo from "../../assets/maxunlogo.png";
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
const CustomBoxContainer = styled.div`
|
interface CustomBoxContainerProps {
|
||||||
|
isDarkMode: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const CustomBoxContainer = styled.div<CustomBoxContainerProps>`
|
||||||
position: relative;
|
position: relative;
|
||||||
min-width: 250px;
|
min-width: 250px;
|
||||||
width: auto;
|
width: auto;
|
||||||
min-height: 100px;
|
min-height: 100px;
|
||||||
height: auto;
|
height: auto;
|
||||||
// border: 2px solid #ff00c3;
|
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
background-color: white;
|
background-color: ${({ isDarkMode }) => (isDarkMode ? '#313438' : 'white')};
|
||||||
|
color: ${({ isDarkMode }) => (isDarkMode ? 'white' : 'black')};
|
||||||
margin: 80px 13px 25px 13px;
|
margin: 80px 13px 25px 13px;
|
||||||
|
box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.1);
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Triangle = styled.div`
|
const Triangle = styled.div<CustomBoxContainerProps>`
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: -15px;
|
top: -15px;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
@@ -26,7 +31,7 @@ const Triangle = styled.div`
|
|||||||
height: 0;
|
height: 0;
|
||||||
border-left: 20px solid transparent;
|
border-left: 20px solid transparent;
|
||||||
border-right: 20px solid transparent;
|
border-right: 20px solid transparent;
|
||||||
border-bottom: 20px solid white;
|
border-bottom: 20px solid ${({ isDarkMode }) => (isDarkMode ? '#313438' : 'white')};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Logo = styled.img`
|
const Logo = styled.img`
|
||||||
@@ -44,7 +49,8 @@ const Content = styled.div`
|
|||||||
text-align: left;
|
text-align: left;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const ActionDescriptionBox = () => {
|
|
||||||
|
const ActionDescriptionBox = ({ isDarkMode }: { isDarkMode: boolean }) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { getText, getScreenshot, getList, captureStage } = useActionContext() as {
|
const { getText, getScreenshot, getList, captureStage } = useActionContext() as {
|
||||||
getText: boolean;
|
getText: boolean;
|
||||||
@@ -93,9 +99,19 @@ const ActionDescriptionBox = () => {
|
|||||||
<Checkbox
|
<Checkbox
|
||||||
checked={index < currentStageIndex}
|
checked={index < currentStageIndex}
|
||||||
disabled
|
disabled
|
||||||
|
sx={{
|
||||||
|
color: isDarkMode ? 'white' : 'default',
|
||||||
|
'&.Mui-checked': {
|
||||||
|
color: isDarkMode ? '#90caf9' : '#1976d2',
|
||||||
|
},
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
label={<Typography variant="body2" gutterBottom>{text}</Typography>}
|
label={
|
||||||
|
<Typography variant="body2" gutterBottom color={isDarkMode ? 'white' : 'textPrimary'}>
|
||||||
|
{text}
|
||||||
|
</Typography>
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</Box>
|
</Box>
|
||||||
@@ -112,9 +128,9 @@ const ActionDescriptionBox = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CustomBoxContainer>
|
<CustomBoxContainer isDarkMode={isDarkMode}>
|
||||||
<Logo src={MaxunLogo} alt='maxun_logo' />
|
<Logo src={MaxunLogo} alt="Maxun Logo" />
|
||||||
<Triangle />
|
<Triangle isDarkMode={isDarkMode} />
|
||||||
<Content>
|
<Content>
|
||||||
{renderActionDescription()}
|
{renderActionDescription()}
|
||||||
</Content>
|
</Content>
|
||||||
|
|||||||
@@ -1,16 +1,15 @@
|
|||||||
import React, { useRef } from 'react';
|
import React, { useRef } from 'react';
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import { Button } from "@mui/material";
|
import { Button } from "@mui/material";
|
||||||
//import { ActionDescription } from "../organisms/RightSidePanel";
|
|
||||||
import * as Settings from "./action-settings";
|
import * as Settings from "./action-settings";
|
||||||
import { useSocketStore } from "../../context/socket";
|
import { useSocketStore } from "../../context/socket";
|
||||||
|
|
||||||
interface ActionSettingsProps {
|
interface ActionSettingsProps {
|
||||||
action: string;
|
action: string;
|
||||||
|
darkMode?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ActionSettings = ({ action }: ActionSettingsProps) => {
|
export const ActionSettings = ({ action, darkMode = false }: ActionSettingsProps) => {
|
||||||
|
|
||||||
const settingsRef = useRef<{ getSettings: () => object }>(null);
|
const settingsRef = useRef<{ getSettings: () => object }>(null);
|
||||||
const { socket } = useSocketStore();
|
const { socket } = useSocketStore();
|
||||||
|
|
||||||
@@ -20,30 +19,27 @@ export const ActionSettings = ({ action }: ActionSettingsProps) => {
|
|||||||
return <Settings.ScreenshotSettings ref={settingsRef} />;
|
return <Settings.ScreenshotSettings ref={settingsRef} />;
|
||||||
case 'scroll':
|
case 'scroll':
|
||||||
return <Settings.ScrollSettings ref={settingsRef} />;
|
return <Settings.ScrollSettings ref={settingsRef} />;
|
||||||
case 'scrape':
|
case 'scrape':
|
||||||
return <Settings.ScrapeSettings ref={settingsRef} />;
|
return <Settings.ScrapeSettings ref={settingsRef} />;
|
||||||
case 'scrapeSchema':
|
case 'scrapeSchema':
|
||||||
return <Settings.ScrapeSchemaSettings ref={settingsRef} />;
|
return <Settings.ScrapeSchemaSettings ref={settingsRef} />;
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
const handleSubmit = (event: React.SyntheticEvent) => {
|
const handleSubmit = (event: React.SyntheticEvent) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
//get the data from settings
|
|
||||||
const settings = settingsRef.current?.getSettings();
|
const settings = settingsRef.current?.getSettings();
|
||||||
//Send notification to the server and generate the pair
|
|
||||||
socket?.emit(`action`, {
|
socket?.emit(`action`, {
|
||||||
action,
|
action,
|
||||||
settings
|
settings
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{/* <ActionDescription>Action settings:</ActionDescription> */}
|
<ActionSettingsWrapper action={action} darkMode={darkMode}>
|
||||||
<ActionSettingsWrapper action={action}>
|
|
||||||
<form onSubmit={handleSubmit}>
|
<form onSubmit={handleSubmit}>
|
||||||
<DisplaySettings />
|
<DisplaySettings />
|
||||||
<Button
|
<Button
|
||||||
@@ -64,10 +60,13 @@ export const ActionSettings = ({ action }: ActionSettingsProps) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const ActionSettingsWrapper = styled.div<{ action: string }>`
|
// Ensure that the Wrapper accepts the darkMode prop for styling adjustments.
|
||||||
|
const ActionSettingsWrapper = styled.div<{ action: string; darkMode: boolean }>`
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: ${({ action }) => action === 'script' ? 'stretch' : 'center'};;
|
align-items: ${({ action }) => (action === 'script' ? 'stretch' : 'center')};
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
|
background-color: ${({ darkMode }) => (darkMode ? '#1E1E1E' : 'white')};
|
||||||
|
color: ${({ darkMode }) => (darkMode ? 'white' : 'black')};
|
||||||
`;
|
`;
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
import type {
|
import type { FC } from 'react';
|
||||||
FC,
|
|
||||||
} from 'react';
|
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
|
|
||||||
import ReplayIcon from '@mui/icons-material/Replay';
|
import ReplayIcon from '@mui/icons-material/Replay';
|
||||||
@@ -13,15 +11,26 @@ import { useCallback, useEffect, useState } from "react";
|
|||||||
import { useSocketStore } from "../../context/socket";
|
import { useSocketStore } from "../../context/socket";
|
||||||
import { getCurrentUrl } from "../../api/recording";
|
import { getCurrentUrl } from "../../api/recording";
|
||||||
import { useGlobalInfoStore } from '../../context/globalInfo';
|
import { useGlobalInfoStore } from '../../context/globalInfo';
|
||||||
|
import { useThemeMode } from '../../context/theme-provider';
|
||||||
|
|
||||||
const StyledNavBar = styled.div<{ browserWidth: number }>`
|
const StyledNavBar = styled.div<{ browserWidth: number; isDarkMode: boolean }>`
|
||||||
display: flex;
|
display: flex;
|
||||||
padding: 12px 0px;
|
padding: 12px 0px;
|
||||||
background-color: #f6f6f6;
|
background-color: ${({ isDarkMode }) => (isDarkMode ? '#2C2F33' : '#f6f6f6')};
|
||||||
width: ${({ browserWidth }) => browserWidth}px;
|
width: ${({ browserWidth }) => browserWidth}px;
|
||||||
border-radius: 0px 5px 0px 0px;
|
border-radius: 0px 5px 0px 0px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const IconButton = styled(NavBarButton)<{ mode: string }>`
|
||||||
|
background-color: ${({ mode }) => (mode === 'dark' ? '#2C2F33' : '#f6f6f6')};
|
||||||
|
transition: background-color 0.3s ease, transform 0.1s ease;
|
||||||
|
color: ${({ mode }) => (mode === 'dark' ? '#FFFFFF' : '#333')};
|
||||||
|
cursor: pointer;
|
||||||
|
&:hover {
|
||||||
|
background-color: ${({ mode }) => (mode === 'dark' ? '#586069' : '#D0D0D0')};
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
interface NavBarProps {
|
interface NavBarProps {
|
||||||
browserWidth: number;
|
browserWidth: number;
|
||||||
handleUrlChanged: (url: string) => void;
|
handleUrlChanged: (url: string) => void;
|
||||||
@@ -31,6 +40,7 @@ const BrowserNavBar: FC<NavBarProps> = ({
|
|||||||
browserWidth,
|
browserWidth,
|
||||||
handleUrlChanged,
|
handleUrlChanged,
|
||||||
}) => {
|
}) => {
|
||||||
|
const isDarkMode = useThemeMode().darkMode;
|
||||||
|
|
||||||
const { socket } = useSocketStore();
|
const { socket } = useSocketStore();
|
||||||
const { recordingUrl, setRecordingUrl } = useGlobalInfoStore();
|
const { recordingUrl, setRecordingUrl } = useGlobalInfoStore();
|
||||||
@@ -67,7 +77,7 @@ const BrowserNavBar: FC<NavBarProps> = ({
|
|||||||
socket.off('urlChanged', handleCurrentUrlChange);
|
socket.off('urlChanged', handleCurrentUrlChange);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [socket, handleCurrentUrlChange])
|
}, [socket, handleCurrentUrlChange]);
|
||||||
|
|
||||||
const addAddress = (address: string) => {
|
const addAddress = (address: string) => {
|
||||||
if (socket) {
|
if (socket) {
|
||||||
@@ -78,38 +88,41 @@ const BrowserNavBar: FC<NavBarProps> = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledNavBar browserWidth={900}>
|
<StyledNavBar browserWidth={browserWidth} isDarkMode={isDarkMode}>
|
||||||
<NavBarButton
|
<IconButton
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
socket?.emit('input:back');
|
socket?.emit('input:back');
|
||||||
}}
|
}}
|
||||||
disabled={false}
|
disabled={false}
|
||||||
|
mode={isDarkMode ? 'dark' : 'light'}
|
||||||
>
|
>
|
||||||
<ArrowBackIcon />
|
<ArrowBackIcon />
|
||||||
</NavBarButton>
|
</IconButton>
|
||||||
|
|
||||||
<NavBarButton
|
<IconButton
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
socket?.emit('input:forward');
|
socket?.emit('input:forward');
|
||||||
}}
|
}}
|
||||||
disabled={false}
|
disabled={false}
|
||||||
|
mode={isDarkMode ? 'dark' : 'light'}
|
||||||
>
|
>
|
||||||
<ArrowForwardIcon />
|
<ArrowForwardIcon />
|
||||||
</NavBarButton>
|
</IconButton>
|
||||||
|
|
||||||
<NavBarButton
|
<IconButton
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (socket) {
|
if (socket) {
|
||||||
handleRefresh()
|
handleRefresh();
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
disabled={false}
|
disabled={false}
|
||||||
|
mode={isDarkMode ? 'dark' : 'light'}
|
||||||
>
|
>
|
||||||
<ReplayIcon />
|
<ReplayIcon />
|
||||||
</NavBarButton>
|
</IconButton>
|
||||||
|
|
||||||
<UrlForm
|
<UrlForm
|
||||||
currentAddress={recordingUrl}
|
currentAddress={recordingUrl}
|
||||||
|
|||||||
@@ -31,14 +31,26 @@ const BrowserRecordingSave = () => {
|
|||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
background: '#ff00c3',
|
background: '#ff00c3',
|
||||||
border: 'none',
|
border: 'none',
|
||||||
borderRadius: '5px',
|
borderRadius: '0px 0px 8px 8px',
|
||||||
padding: '7.5px',
|
padding: '7.5px',
|
||||||
width: 'calc(100% - 20px)',
|
width: 'calc(100% - 20px)',
|
||||||
overflow: 'hidden',
|
overflow: 'hidden',
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
justifyContent: 'space-between',
|
justifyContent: 'space-between',
|
||||||
|
height:"48px"
|
||||||
}}>
|
}}>
|
||||||
<Button onClick={() => setOpenModal(true)} variant="outlined" style={{ marginLeft: "25px" }} size="small" color="error">
|
<Button
|
||||||
|
onClick={() => setOpenModal(true)}
|
||||||
|
variant="outlined"
|
||||||
|
color="error"
|
||||||
|
sx={{
|
||||||
|
marginLeft: '25px',
|
||||||
|
color: 'red !important',
|
||||||
|
borderColor: 'red !important',
|
||||||
|
backgroundColor: 'whitesmoke !important',
|
||||||
|
}}
|
||||||
|
size="small"
|
||||||
|
>
|
||||||
{t('right_panel.buttons.discard')}
|
{t('right_panel.buttons.discard')}
|
||||||
</Button>
|
</Button>
|
||||||
<GenericModal isOpen={openModal} onClose={() => setOpenModal(false)} modalStyle={modalStyle}>
|
<GenericModal isOpen={openModal} onClose={() => setOpenModal(false)} modalStyle={modalStyle}>
|
||||||
@@ -48,7 +60,14 @@ const BrowserRecordingSave = () => {
|
|||||||
<Button onClick={goToMainMenu} variant="contained" color="error">
|
<Button onClick={goToMainMenu} variant="contained" color="error">
|
||||||
{t('right_panel.buttons.discard')}
|
{t('right_panel.buttons.discard')}
|
||||||
</Button>
|
</Button>
|
||||||
<Button onClick={() => setOpenModal(false)} variant="outlined">
|
<Button
|
||||||
|
onClick={() => setOpenModal(false)}
|
||||||
|
variant="outlined"
|
||||||
|
sx={{
|
||||||
|
color: '#ff00c3 !important',
|
||||||
|
borderColor: '#ff00c3 !important',
|
||||||
|
backgroundColor: 'whitesmoke !important',
|
||||||
|
}} >
|
||||||
{t('right_panel.buttons.cancel')}
|
{t('right_panel.buttons.cancel')}
|
||||||
</Button>
|
</Button>
|
||||||
</Box>
|
</Box>
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { Box, IconButton, Tab, Tabs } from "@mui/material";
|
import { Box, IconButton, Tab, Tabs } from "@mui/material";
|
||||||
import { AddButton } from "../atoms/buttons/AddButton";
|
|
||||||
import { useBrowserDimensionsStore } from "../../context/browserDimensions";
|
import { useBrowserDimensionsStore } from "../../context/browserDimensions";
|
||||||
import { Close } from "@mui/icons-material";
|
import { Close } from "@mui/icons-material";
|
||||||
|
import { useThemeMode } from '../../context/theme-provider';
|
||||||
|
|
||||||
interface BrowserTabsProp {
|
interface BrowserTabsProp {
|
||||||
tabs: string[],
|
tabs: string[],
|
||||||
@@ -28,15 +28,16 @@ export const BrowserTabs = (
|
|||||||
handleChangeIndex(newValue);
|
handleChangeIndex(newValue);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
const isDarkMode = useThemeMode().darkMode;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box sx={{
|
<Box sx={{
|
||||||
width: 800,
|
width: 800, // Fixed width
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
overflow: 'auto',
|
overflow: 'auto',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
}}>
|
}}>
|
||||||
<Box sx={{ borderBottom: 1, borderColor: 'divider' }}>
|
<Box sx={{ borderBottom: 1, borderColor: 'divider' }}> {/* Synced border color */}
|
||||||
<Tabs
|
<Tabs
|
||||||
value={tabIndex}
|
value={tabIndex}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
@@ -48,7 +49,11 @@ export const BrowserTabs = (
|
|||||||
id={`tab-${index}`}
|
id={`tab-${index}`}
|
||||||
sx={{
|
sx={{
|
||||||
background: 'white',
|
background: 'white',
|
||||||
borderRadius: '5px 5px 0px 0px'
|
borderRadius: '5px 5px 0px 0px',
|
||||||
|
'&.Mui-selected': {
|
||||||
|
backgroundColor:` ${isDarkMode?"#2a2a2a":"#f5f5f5"}`, // Synced selected tab color
|
||||||
|
color: '#ff00c3', // Slightly lighter text when selected
|
||||||
|
},
|
||||||
}}
|
}}
|
||||||
icon={<CloseButton closeTab={() => {
|
icon={<CloseButton closeTab={() => {
|
||||||
tabWasClosed = true;
|
tabWasClosed = true;
|
||||||
@@ -60,8 +65,7 @@ export const BrowserTabs = (
|
|||||||
if (!tabWasClosed) {
|
if (!tabWasClosed) {
|
||||||
handleTabChange(index)
|
handleTabChange(index)
|
||||||
}
|
}
|
||||||
}
|
}}
|
||||||
}
|
|
||||||
label={tab}
|
label={tab}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import { apiUrl } from "../../apiConfig.js";
|
|||||||
import Cookies from 'js-cookie';
|
import Cookies from 'js-cookie';
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
|
|
||||||
interface IntegrationProps {
|
interface IntegrationProps {
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
handleStart: (data: IntegrationSettings) => void;
|
handleStart: (data: IntegrationSettings) => void;
|
||||||
@@ -29,6 +30,20 @@ export interface IntegrationSettings {
|
|||||||
data: string;
|
data: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Helper functions to replace js-cookie functionality
|
||||||
|
const getCookie = (name: string): string | null => {
|
||||||
|
const value = `; ${document.cookie}`;
|
||||||
|
const parts = value.split(`; ${name}=`);
|
||||||
|
if (parts.length === 2) {
|
||||||
|
return parts.pop()?.split(';').shift() || null;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const removeCookie = (name: string): void => {
|
||||||
|
document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/`;
|
||||||
|
};
|
||||||
|
|
||||||
export const IntegrationSettingsModal = ({
|
export const IntegrationSettingsModal = ({
|
||||||
isOpen,
|
isOpen,
|
||||||
handleStart,
|
handleStart,
|
||||||
@@ -141,14 +156,14 @@ export const IntegrationSettingsModal = ({
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// Check if there is a success message in cookies
|
// Check if there is a success message in cookies
|
||||||
const status = Cookies.get("robot_auth_status");
|
const status = getCookie("robot_auth_status");
|
||||||
const message = Cookies.get("robot_auth_message");
|
const message = getCookie("robot_auth_message");
|
||||||
|
|
||||||
if (status === "success" && message) {
|
if (status === "success" && message) {
|
||||||
notify("success", message);
|
notify("success", message);
|
||||||
// Clear the cookies after reading
|
// Clear the cookies after reading
|
||||||
Cookies.remove("robot_auth_status");
|
removeCookie("robot_auth_status");
|
||||||
Cookies.remove("robot_auth_message");
|
removeCookie("robot_auth_message");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if we're on the callback URL
|
// Check if we're on the callback URL
|
||||||
@@ -309,4 +324,4 @@ export const modalStyle = {
|
|||||||
height: "fit-content",
|
height: "fit-content",
|
||||||
display: "block",
|
display: "block",
|
||||||
padding: "20px",
|
padding: "20px",
|
||||||
};
|
};
|
||||||
@@ -17,6 +17,7 @@ import StorageIcon from '@mui/icons-material/Storage';
|
|||||||
import ArrowUpwardIcon from '@mui/icons-material/ArrowUpward';
|
import ArrowUpwardIcon from '@mui/icons-material/ArrowUpward';
|
||||||
import { SidePanelHeader } from './SidePanelHeader';
|
import { SidePanelHeader } from './SidePanelHeader';
|
||||||
import { useGlobalInfoStore } from '../../context/globalInfo';
|
import { useGlobalInfoStore } from '../../context/globalInfo';
|
||||||
|
import { useThemeMode } from '../../context/theme-provider';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
interface InterpretationLogProps {
|
interface InterpretationLogProps {
|
||||||
@@ -124,6 +125,8 @@ export const InterpretationLog: React.FC<InterpretationLogProps> = ({ isOpen, se
|
|||||||
}
|
}
|
||||||
}, [hasScrapeListAction, hasScrapeSchemaAction, hasScreenshotAction, setIsOpen]);
|
}, [hasScrapeListAction, hasScrapeSchemaAction, hasScreenshotAction, setIsOpen]);
|
||||||
|
|
||||||
|
const { darkMode} = useThemeMode();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Grid container>
|
<Grid container>
|
||||||
<Grid item xs={12} md={9} lg={9}>
|
<Grid item xs={12} md={9} lg={9}>
|
||||||
@@ -132,7 +135,7 @@ export const InterpretationLog: React.FC<InterpretationLogProps> = ({ isOpen, se
|
|||||||
variant="contained"
|
variant="contained"
|
||||||
color="primary"
|
color="primary"
|
||||||
sx={{
|
sx={{
|
||||||
marginTop: '10px',
|
marginTop: '10px',
|
||||||
color: 'white',
|
color: 'white',
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
background: '#ff00c3',
|
background: '#ff00c3',
|
||||||
@@ -157,8 +160,8 @@ export const InterpretationLog: React.FC<InterpretationLogProps> = ({ isOpen, se
|
|||||||
onOpen={toggleDrawer(true)}
|
onOpen={toggleDrawer(true)}
|
||||||
PaperProps={{
|
PaperProps={{
|
||||||
sx: {
|
sx: {
|
||||||
background: 'white',
|
background: `${darkMode ? '#1e2124' : 'white'}`,
|
||||||
color: 'black',
|
color: `${darkMode ? 'white' : 'black'}`,
|
||||||
padding: '10px',
|
padding: '10px',
|
||||||
height: 500,
|
height: 500,
|
||||||
width: width - 10,
|
width: width - 10,
|
||||||
|
|||||||
@@ -4,17 +4,17 @@ import axios from 'axios';
|
|||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import { stopRecording } from "../../api/recording";
|
import { stopRecording } from "../../api/recording";
|
||||||
import { useGlobalInfoStore } from "../../context/globalInfo";
|
import { useGlobalInfoStore } from "../../context/globalInfo";
|
||||||
import { IconButton, Menu, MenuItem, Typography, Chip, Button, Modal, Tabs, Tab, Box, Snackbar } from "@mui/material";
|
import { IconButton, Menu, MenuItem, Typography, Chip, Button, Modal, Tabs, Tab, Box, Snackbar, Tooltip } from "@mui/material";
|
||||||
import { AccountCircle, Logout, Clear, YouTube, X, Update, Close, Language } from "@mui/icons-material";
|
import { AccountCircle, Logout, Clear, YouTube, X, Update, Close, Language, Brightness7, Brightness4 } from "@mui/icons-material";
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import { AuthContext } from '../../context/auth';
|
import { AuthContext } from '../../context/auth';
|
||||||
import { SaveRecording } from '../molecules/SaveRecording';
|
import { SaveRecording } from '../molecules/SaveRecording';
|
||||||
import DiscordIcon from '../atoms/DiscordIcon';
|
import DiscordIcon from '../atoms/DiscordIcon';
|
||||||
import { apiUrl } from '../../apiConfig';
|
import { apiUrl } from '../../apiConfig';
|
||||||
import MaxunLogo from "../../assets/maxunlogo.png";
|
import MaxunLogo from "../../assets/maxunlogo.png";
|
||||||
|
import { useThemeMode } from '../../context/theme-provider';
|
||||||
import packageJson from "../../../package.json"
|
import packageJson from "../../../package.json"
|
||||||
|
|
||||||
|
|
||||||
interface NavBarProps {
|
interface NavBarProps {
|
||||||
recordingName: string;
|
recordingName: string;
|
||||||
isRecording: boolean;
|
isRecording: boolean;
|
||||||
@@ -28,6 +28,7 @@ export const NavBar: React.FC<NavBarProps> = ({
|
|||||||
const { state, dispatch } = useContext(AuthContext);
|
const { state, dispatch } = useContext(AuthContext);
|
||||||
const { user } = state;
|
const { user } = state;
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
const { darkMode, toggleTheme } = useThemeMode();
|
||||||
const { t, i18n } = useTranslation();
|
const { t, i18n } = useTranslation();
|
||||||
|
|
||||||
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
|
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
|
||||||
@@ -102,6 +103,22 @@ export const NavBar: React.FC<NavBarProps> = ({
|
|||||||
localStorage.setItem("language", lang);
|
localStorage.setItem("language", lang);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const renderThemeToggle = () => (
|
||||||
|
<Tooltip title="Toggle light/dark theme">
|
||||||
|
<IconButton
|
||||||
|
onClick={toggleTheme}
|
||||||
|
sx={{
|
||||||
|
color: darkMode ? '#ffffff' : '#333333',
|
||||||
|
'&:hover': {
|
||||||
|
color: '#ff00c3'
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{darkMode ? <Brightness7 /> : <Brightness4 />}
|
||||||
|
</IconButton>
|
||||||
|
</Tooltip>
|
||||||
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const checkForUpdates = async () => {
|
const checkForUpdates = async () => {
|
||||||
const latestVersion = await fetchLatestVersion();
|
const latestVersion = await fetchLatestVersion();
|
||||||
@@ -158,13 +175,13 @@ export const NavBar: React.FC<NavBarProps> = ({
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<NavBarWrapper>
|
<NavBarWrapper mode={darkMode ? 'dark' : 'light'}>
|
||||||
<div style={{
|
<div style={{
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
justifyContent: 'flex-start',
|
justifyContent: 'flex-start',
|
||||||
}}>
|
}}>
|
||||||
<img src={MaxunLogo} width={45} height={40} style={{ borderRadius: '5px', margin: '5px 0px 5px 15px' }} />
|
<img src={MaxunLogo} width={45} height={40} style={{ borderRadius: '5px', margin: '5px 0px 5px 15px' }} />
|
||||||
<div style={{ padding: '11px' }}><ProjectName>{t('navbar.project_name')}</ProjectName></div>
|
<div style={{ padding: '11px' }}><ProjectName mode={darkMode ? 'dark' : 'light'}>{t('navbar.project_name')}</ProjectName></div>
|
||||||
<Chip
|
<Chip
|
||||||
label={`${currentVersion}`}
|
label={`${currentVersion}`}
|
||||||
color="primary"
|
color="primary"
|
||||||
@@ -288,7 +305,6 @@ export const NavBar: React.FC<NavBarProps> = ({
|
|||||||
borderRadius: '5px',
|
borderRadius: '5px',
|
||||||
padding: '8px',
|
padding: '8px',
|
||||||
marginRight: '10px',
|
marginRight: '10px',
|
||||||
'&:hover': { backgroundColor: 'white', color: '#ff00c3' }
|
|
||||||
}}>
|
}}>
|
||||||
<AccountCircle sx={{ marginRight: '5px' }} />
|
<AccountCircle sx={{ marginRight: '5px' }} />
|
||||||
<Typography variant="body1">{user.email}</Typography>
|
<Typography variant="body1">{user.email}</Typography>
|
||||||
@@ -383,6 +399,7 @@ export const NavBar: React.FC<NavBarProps> = ({
|
|||||||
</MenuItem>
|
</MenuItem>
|
||||||
</Menu>
|
</Menu>
|
||||||
</Menu>
|
</Menu>
|
||||||
|
{renderThemeToggle()}
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
@@ -402,14 +419,15 @@ export const NavBar: React.FC<NavBarProps> = ({
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<><IconButton
|
<NavBarRight>
|
||||||
|
<IconButton
|
||||||
onClick={handleLangMenuOpen}
|
onClick={handleLangMenuOpen}
|
||||||
sx={{
|
sx={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
borderRadius: "5px",
|
borderRadius: "5px",
|
||||||
padding: "8px",
|
padding: "8px",
|
||||||
marginRight: "10px",
|
marginRight: "8px",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Language sx={{ marginRight: '5px' }} /><Typography variant="body1">{t("Language")}</Typography>
|
<Language sx={{ marginRight: '5px' }} /><Typography variant="body1">{t("Language")}</Typography>
|
||||||
@@ -467,23 +485,34 @@ export const NavBar: React.FC<NavBarProps> = ({
|
|||||||
>
|
>
|
||||||
Deutsch
|
Deutsch
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
</Menu></>
|
</Menu>
|
||||||
)}
|
{renderThemeToggle()}
|
||||||
|
</NavBarRight>
|
||||||
|
)}
|
||||||
</NavBarWrapper>
|
</NavBarWrapper>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const NavBarWrapper = styled.div`
|
// Styled Components
|
||||||
|
const NavBarWrapper = styled.div<{ mode: 'light' | 'dark' }>`
|
||||||
grid-area: navbar;
|
grid-area: navbar;
|
||||||
background-color: white;
|
background-color: ${({ mode }) => (mode === 'dark' ? '#1e2124' : '#ffffff')};
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
border-bottom: 1px solid #e0e0e0;
|
border-bottom: 1px solid ${({ mode }) => (mode === 'dark' ? '#333' : '#e0e0e0')};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const ProjectName = styled.b`
|
const ProjectName = styled.b<{ mode: 'light' | 'dark' }>`
|
||||||
color: #3f4853;
|
color: ${({ mode }) => (mode === 'dark' ? '#ffffff' : '#3f4853')};
|
||||||
font-size: 1.3em;
|
font-size: 1.3em;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const NavBarRight = styled.div`
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-end;
|
||||||
|
margin-left: auto;
|
||||||
|
`;
|
||||||
|
|
||||||
|
|||||||
@@ -152,7 +152,16 @@ export const RobotDuplicationModal = ({ isOpen, handleStart, handleClose, initia
|
|||||||
<Button variant="contained" color="primary" onClick={handleSave}>
|
<Button variant="contained" color="primary" onClick={handleSave}>
|
||||||
{t('robot_duplication.buttons.duplicate')}
|
{t('robot_duplication.buttons.duplicate')}
|
||||||
</Button>
|
</Button>
|
||||||
<Button onClick={handleClose} color="primary" variant="outlined" style={{ marginLeft: '10px' }}>
|
<Button
|
||||||
|
onClick={handleClose}
|
||||||
|
color="primary"
|
||||||
|
variant="outlined"
|
||||||
|
style={{ marginLeft: '10px' }}
|
||||||
|
sx={{
|
||||||
|
color: '#ff00c3 !important',
|
||||||
|
borderColor: '#ff00c3 !important',
|
||||||
|
backgroundColor: 'whitesmoke !important',
|
||||||
|
}} >
|
||||||
{t('robot_duplication.buttons.cancel')}
|
{t('robot_duplication.buttons.cancel')}
|
||||||
</Button>
|
</Button>
|
||||||
</Box>
|
</Box>
|
||||||
|
|||||||
@@ -179,7 +179,11 @@ export const RobotEditModal = ({ isOpen, handleStart, handleClose, initialSettin
|
|||||||
color="primary"
|
color="primary"
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
style={{ marginLeft: '10px' }}
|
style={{ marginLeft: '10px' }}
|
||||||
>
|
sx={{
|
||||||
|
color: '#ff00c3 !important',
|
||||||
|
borderColor: '#ff00c3 !important',
|
||||||
|
backgroundColor: 'whitesmoke !important',
|
||||||
|
}}>
|
||||||
{t('robot_edit.cancel')}
|
{t('robot_edit.cancel')}
|
||||||
</Button>
|
</Button>
|
||||||
</Box>
|
</Box>
|
||||||
|
|||||||
@@ -77,10 +77,50 @@ export const RunContent = ({ row, currentLog, interpretationInProgress, logEndRe
|
|||||||
<Box sx={{ width: '100%' }}>
|
<Box sx={{ width: '100%' }}>
|
||||||
<TabContext value={tab}>
|
<TabContext value={tab}>
|
||||||
<Box sx={{ borderBottom: 1, borderColor: 'divider' }}>
|
<Box sx={{ borderBottom: 1, borderColor: 'divider' }}>
|
||||||
<Tabs value={tab} onChange={(e, newTab) => setTab(newTab)} aria-label="run-content-tabs">
|
<Tabs
|
||||||
<Tab label={t('run_content.tabs.output_data')} value='output' />
|
value={tab}
|
||||||
<Tab label={t('run_content.tabs.log')} value='log' />
|
onChange={(e, newTab) => setTab(newTab)}
|
||||||
</Tabs>
|
aria-label="run-content-tabs"
|
||||||
|
sx={{
|
||||||
|
// Remove the default blue indicator
|
||||||
|
'& .MuiTabs-indicator': {
|
||||||
|
backgroundColor: '#FF00C3', // Change to pink
|
||||||
|
},
|
||||||
|
// Remove default transition effects
|
||||||
|
'& .MuiTab-root': {
|
||||||
|
'&.Mui-selected': {
|
||||||
|
color: '#FF00C3',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Tab
|
||||||
|
label={t('run_content.tabs.output_data')}
|
||||||
|
value='output'
|
||||||
|
sx={{
|
||||||
|
color: (theme) => theme.palette.mode === 'dark' ? '#fff' : '#000',
|
||||||
|
'&:hover': {
|
||||||
|
color: '#FF00C3'
|
||||||
|
},
|
||||||
|
'&.Mui-selected': {
|
||||||
|
color: '#FF00C3',
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Tab
|
||||||
|
label={t('run_content.tabs.log')}
|
||||||
|
value='log'
|
||||||
|
sx={{
|
||||||
|
color: (theme) => theme.palette.mode === 'dark' ? '#fff' : '#000',
|
||||||
|
'&:hover': {
|
||||||
|
color: '#FF00C3'
|
||||||
|
},
|
||||||
|
'&.Mui-selected': {
|
||||||
|
color: '#FF00C3',
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Tabs>
|
||||||
</Box>
|
</Box>
|
||||||
<TabPanel value='log'>
|
<TabPanel value='log'>
|
||||||
<Box sx={{
|
<Box sx={{
|
||||||
@@ -161,6 +201,7 @@ export const RunContent = ({ row, currentLog, interpretationInProgress, logEndRe
|
|||||||
background: 'rgba(0,0,0,0.06)',
|
background: 'rgba(0,0,0,0.06)',
|
||||||
maxHeight: '300px',
|
maxHeight: '300px',
|
||||||
overflow: 'scroll',
|
overflow: 'scroll',
|
||||||
|
backgroundColor: '#19171c'
|
||||||
}}>
|
}}>
|
||||||
<pre>
|
<pre>
|
||||||
{JSON.stringify(row.serializableOutput, null, 2)}
|
{JSON.stringify(row.serializableOutput, null, 2)}
|
||||||
|
|||||||
@@ -77,7 +77,21 @@ export const SaveRecording = ({ fileName }: SaveRecordingProps) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Button onClick={() => setOpenModal(true)} variant="outlined" sx={{ marginRight: '20px' }} size="small" color="success">
|
{/* <Button onClick={() => setOpenModal(true)} variant='contained' sx={{ marginRight: '20px',backgroundColor: '#ff00c3',color: 'white' }} size="small" color="success">
|
||||||
|
Finish */}
|
||||||
|
|
||||||
|
<Button
|
||||||
|
onClick={() => setOpenModal(true)}
|
||||||
|
variant="outlined"
|
||||||
|
color="success"
|
||||||
|
sx={{
|
||||||
|
marginRight: '20px',
|
||||||
|
color: '#00c853 !important',
|
||||||
|
borderColor: '#00c853 !important',
|
||||||
|
backgroundColor: 'whitesmoke !important',
|
||||||
|
}}
|
||||||
|
size="small"
|
||||||
|
>
|
||||||
{t('right_panel.buttons.finish')}
|
{t('right_panel.buttons.finish')}
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
|
|||||||
@@ -273,7 +273,16 @@ export const ScheduleSettingsModal = ({ isOpen, handleStart, handleClose, initia
|
|||||||
<Button onClick={() => handleStart(settings)} variant="contained" color="primary">
|
<Button onClick={() => handleStart(settings)} variant="contained" color="primary">
|
||||||
{t('schedule_settings.buttons.save_schedule')}
|
{t('schedule_settings.buttons.save_schedule')}
|
||||||
</Button>
|
</Button>
|
||||||
<Button onClick={handleClose} color="primary" variant="outlined" style={{ marginLeft: '10px' }}>
|
<Button
|
||||||
|
onClick={handleClose}
|
||||||
|
color="primary"
|
||||||
|
variant="outlined"
|
||||||
|
style={{ marginLeft: '10px' }}
|
||||||
|
sx={{
|
||||||
|
color: '#ff00c3 !important',
|
||||||
|
borderColor: '#ff00c3 !important',
|
||||||
|
backgroundColor: 'whitesmoke !important',
|
||||||
|
}}>
|
||||||
{t('schedule_settings.buttons.cancel')}
|
{t('schedule_settings.buttons.cancel')}
|
||||||
</Button>
|
</Button>
|
||||||
</Box>
|
</Box>
|
||||||
|
|||||||
@@ -152,8 +152,9 @@ export const BrowserContent = () => {
|
|||||||
// todo: use width from browser dimension once fixed
|
// todo: use width from browser dimension once fixed
|
||||||
browserWidth={900}
|
browserWidth={900}
|
||||||
handleUrlChanged={handleUrlChanged}
|
handleUrlChanged={handleUrlChanged}
|
||||||
|
|
||||||
/>
|
/>
|
||||||
<BrowserWindow />
|
<BrowserWindow />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -403,6 +403,11 @@ export const BrowserWindow = () => {
|
|||||||
overflow: 'hidden',
|
overflow: 'hidden',
|
||||||
padding: '5px 10px',
|
padding: '5px 10px',
|
||||||
}}
|
}}
|
||||||
|
sx={{
|
||||||
|
color: '#ff00c3 !important',
|
||||||
|
borderColor: '#ff00c3 !important',
|
||||||
|
backgroundColor: 'whitesmoke !important',
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<span style={{
|
<span style={{
|
||||||
display: 'block',
|
display: 'block',
|
||||||
|
|||||||
@@ -1,41 +1,61 @@
|
|||||||
import * as React from 'react';
|
import React from 'react';
|
||||||
import Tabs from '@mui/material/Tabs';
|
import Tabs from '@mui/material/Tabs';
|
||||||
import Tab from '@mui/material/Tab';
|
import Tab from '@mui/material/Tab';
|
||||||
import Box from '@mui/material/Box';
|
import Box from '@mui/material/Box';
|
||||||
import { Paper, Button } from "@mui/material";
|
|
||||||
import { AutoAwesome, FormatListBulleted, VpnKey, Usb, CloudQueue, Code } from "@mui/icons-material";
|
import { Paper, Button, useTheme } from "@mui/material";
|
||||||
|
import { AutoAwesome, FormatListBulleted, VpnKey, Usb, Article, CloudQueue,Code, } from "@mui/icons-material";
|
||||||
|
|
||||||
|
|
||||||
import { apiUrl } from "../../apiConfig";
|
import { apiUrl } from "../../apiConfig";
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import i18n from '../../i18n';
|
import i18n from '../../i18n';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
interface MainMenuProps {
|
interface MainMenuProps {
|
||||||
value: string;
|
value: string;
|
||||||
handleChangeContent: (newValue: string) => void;
|
handleChangeContent: (newValue: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const MainMenu = ({ value = 'recordings', handleChangeContent }: MainMenuProps) => {
|
export const MainMenu = ({ value = 'recordings', handleChangeContent }: MainMenuProps) => {
|
||||||
|
const theme = useTheme();
|
||||||
const {t} = useTranslation();
|
const {t} = useTranslation();
|
||||||
|
|
||||||
const handleChange = (event: React.SyntheticEvent, newValue: string) => {
|
const handleChange = (event: React.SyntheticEvent, newValue: string) => {
|
||||||
handleChangeContent(newValue);
|
handleChangeContent(newValue);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Define colors based on theme mode
|
||||||
|
const defaultcolor = theme.palette.mode === 'light' ? 'black' : 'white';
|
||||||
|
|
||||||
|
const buttonStyles = {
|
||||||
|
justifyContent: 'flex-start',
|
||||||
|
textAlign: 'left',
|
||||||
|
fontSize: 'medium',
|
||||||
|
padding: '6px 16px 6px 22px',
|
||||||
|
minHeight: '48px',
|
||||||
|
minWidth: '100%',
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
textTransform: 'none',
|
||||||
|
color: theme.palette.mode === 'light' ? '#6C6C6C' : 'inherit',
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Paper
|
<Paper
|
||||||
sx={{
|
sx={{
|
||||||
height: 'auto',
|
height: 'auto',
|
||||||
width: '250px',
|
width: '250px',
|
||||||
backgroundColor: 'white',
|
backgroundColor: theme.palette.background.paper,
|
||||||
paddingTop: '0.5rem',
|
paddingTop: '0.5rem',
|
||||||
|
color: defaultcolor,
|
||||||
}}
|
}}
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
square
|
square
|
||||||
>
|
>
|
||||||
<Box sx={{
|
<Box sx={{ width: '100%', paddingBottom: '1rem' }}>
|
||||||
width: '100%',
|
|
||||||
paddingBottom: '1rem',
|
|
||||||
}}>
|
|
||||||
<Tabs
|
<Tabs
|
||||||
value={value}
|
value={value}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
@@ -101,17 +121,4 @@ export const MainMenu = ({ value = 'recordings', handleChangeContent }: MainMenu
|
|||||||
</Box>
|
</Box>
|
||||||
</Paper>
|
</Paper>
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
const buttonStyles = {
|
|
||||||
justifyContent: 'flex-start',
|
|
||||||
textAlign: 'left',
|
|
||||||
fontSize: 'medium',
|
|
||||||
padding: '6px 16px 6px 22px',
|
|
||||||
minHeight: '48px',
|
|
||||||
minWidth: '100%',
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
textTransform: 'none',
|
|
||||||
color: '#6C6C6C !important',
|
|
||||||
};
|
};
|
||||||
@@ -1,8 +1,27 @@
|
|||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import { styled } from '@mui/system';
|
import { styled } from '@mui/system';
|
||||||
import { Alert, AlertTitle, TextField, Button, Switch, FormControlLabel, Box, Typography, Tabs, Tab, Table, TableContainer, TableHead, TableRow, TableBody, TableCell, Paper } from '@mui/material';
|
import {
|
||||||
|
Alert,
|
||||||
|
AlertTitle,
|
||||||
|
TextField,
|
||||||
|
Button,
|
||||||
|
Switch,
|
||||||
|
FormControlLabel,
|
||||||
|
Box,
|
||||||
|
Typography,
|
||||||
|
Tabs,
|
||||||
|
Tab,
|
||||||
|
Table,
|
||||||
|
TableContainer,
|
||||||
|
TableHead,
|
||||||
|
TableRow,
|
||||||
|
TableBody,
|
||||||
|
TableCell,
|
||||||
|
Paper
|
||||||
|
} from '@mui/material';
|
||||||
import { sendProxyConfig, getProxyConfig, testProxyConfig, deleteProxyConfig } from '../../api/proxy';
|
import { sendProxyConfig, getProxyConfig, testProxyConfig, deleteProxyConfig } from '../../api/proxy';
|
||||||
import { useGlobalInfoStore } from '../../context/globalInfo';
|
import { useGlobalInfoStore } from '../../context/globalInfo';
|
||||||
|
import { useThemeMode } from '../../context/theme-provider';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
const FormContainer = styled(Box)({
|
const FormContainer = styled(Box)({
|
||||||
@@ -134,16 +153,20 @@ const ProxyForm: React.FC = () => {
|
|||||||
fetchProxyConfig();
|
fetchProxyConfig();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const theme = useThemeMode();
|
||||||
|
const isDarkMode = theme.darkMode;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<FormContainer>
|
<FormContainer>
|
||||||
<Typography variant="h6" gutterBottom component="div" style={{ marginTop: '20px' }}>
|
<Typography variant="h6" gutterBottom component="div" style={{ marginTop: '20px' }}>
|
||||||
{t('proxy.title')}
|
{t('proxy.title')}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Tabs value={tabIndex} onChange={handleTabChange}>
|
<Tabs value={tabIndex} onChange={handleTabChange}>
|
||||||
<Tab label={t('proxy.tab_standard')} />
|
<Tab label={t('proxy.tab_standard')} />
|
||||||
<Tab label={t('proxy.tab_rotation')} />
|
<Tab label={t('proxy.tab_rotation')} />
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
|
||||||
{tabIndex === 0 && (
|
{tabIndex === 0 && (
|
||||||
isProxyConfigured ? (
|
isProxyConfigured ? (
|
||||||
<Box sx={{ maxWidth: 600, width: '100%', marginTop: '5px' }}>
|
<Box sx={{ maxWidth: 600, width: '100%', marginTop: '5px' }}>
|
||||||
@@ -236,13 +259,19 @@ const ProxyForm: React.FC = () => {
|
|||||||
<Typography variant="body1" gutterBottom component="div">
|
<Typography variant="body1" gutterBottom component="div">
|
||||||
{t('proxy.coming_soon')}
|
{t('proxy.coming_soon')}
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|
||||||
|
{/* <Button variant="contained" color="primary" sx={{ marginTop: '20px',backgroundColor: '#ff00c3' }}>
|
||||||
|
<a style={{ color: 'white', textDecoration: 'none' }} href="https://forms.gle/hXjgqDvkEhPcaBW76">Join Maxun Cloud Waitlist</a> */}
|
||||||
|
|
||||||
<Button variant="contained" color="primary" sx={{ marginTop: '20px' }}>
|
<Button variant="contained" color="primary" sx={{ marginTop: '20px' }}>
|
||||||
<a style={{ color: 'white', textDecoration: 'none' }} href="https://forms.gle/hXjgqDvkEhPcaBW76">{t('proxy.join_waitlist')}</a>
|
<a style={{ color: 'white', textDecoration: 'none' }} href="https://forms.gle/hXjgqDvkEhPcaBW76">{t('proxy.join_waitlist')}</a>
|
||||||
|
|
||||||
</Button>
|
</Button>
|
||||||
</>
|
</>
|
||||||
</Box>
|
</Box>
|
||||||
)}
|
)}
|
||||||
</FormContainer>
|
</FormContainer>
|
||||||
|
|
||||||
<Alert severity="info" sx={{ marginTop: '80px', marginLeft: '50px', height: '230px', width: '450px', border: '1px solid #ff00c3' }}>
|
<Alert severity="info" sx={{ marginTop: '80px', marginLeft: '50px', height: '230px', width: '450px', border: '1px solid #ff00c3' }}>
|
||||||
<AlertTitle>{t('proxy.alert.title')}</AlertTitle>
|
<AlertTitle>{t('proxy.alert.title')}</AlertTitle>
|
||||||
<br />
|
<br />
|
||||||
@@ -257,6 +286,7 @@ const ProxyForm: React.FC = () => {
|
|||||||
<br />
|
<br />
|
||||||
<b>{t('proxy.alert.wrong_way')}</b>
|
<b>{t('proxy.alert.wrong_way')}</b>
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
{t('proxy.alert.proxy_url')} http://myusername:mypassword@proxy.com:1337
|
{t('proxy.alert.proxy_url')} http://myusername:mypassword@proxy.com:1337
|
||||||
</Alert>
|
</Alert>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import { emptyWorkflow } from "../../shared/constants";
|
|||||||
import { getActiveWorkflow } from "../../api/workflow";
|
import { getActiveWorkflow } from "../../api/workflow";
|
||||||
import DeleteIcon from '@mui/icons-material/Delete';
|
import DeleteIcon from '@mui/icons-material/Delete';
|
||||||
import ActionDescriptionBox from '../molecules/ActionDescriptionBox';
|
import ActionDescriptionBox from '../molecules/ActionDescriptionBox';
|
||||||
|
import { useThemeMode } from '../../context/theme-provider';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
const fetchWorkflow = (id: string, callback: (response: WorkflowFile) => void) => {
|
const fetchWorkflow = (id: string, callback: (response: WorkflowFile) => void) => {
|
||||||
@@ -461,15 +462,18 @@ export const RightSidePanel: React.FC<RightSidePanelProps> = ({ onFinishCapture
|
|||||||
// Disable the button if there are no valid list selectors or if there are unconfirmed list text fields
|
// Disable the button if there are no valid list selectors or if there are unconfirmed list text fields
|
||||||
return !hasValidListSelector || hasUnconfirmedListTextFields;
|
return !hasValidListSelector || hasUnconfirmedListTextFields;
|
||||||
}, [captureStage, browserSteps, hasUnconfirmedListTextFields]);
|
}, [captureStage, browserSteps, hasUnconfirmedListTextFields]);
|
||||||
|
|
||||||
|
const theme = useThemeMode();
|
||||||
|
const isDarkMode = theme.darkMode;
|
||||||
return (
|
return (
|
||||||
<Paper sx={{ height: '520px', width: 'auto', alignItems: "center", background: 'inherit' }} id="browser-actions" elevation={0}>
|
<Paper sx={{ height: '520px', width: 'auto', alignItems: "center", background: 'inherit' }} id="browser-actions" elevation={0}>
|
||||||
{/* <SimpleBox height={60} width='100%' background='lightGray' radius='0%'>
|
{/* <SimpleBox height={60} width='100%' background='lightGray' radius='0%'>
|
||||||
<Typography sx={{ padding: '10px' }}>Last action: {` ${lastAction}`}</Typography>
|
<Typography sx={{ padding: '10px' }}>Last action: {` ${lastAction}`}</Typography>
|
||||||
</SimpleBox> */}
|
</SimpleBox> */}
|
||||||
<ActionDescriptionBox />
|
<ActionDescriptionBox isDarkMode={isDarkMode} />
|
||||||
<Box display="flex" flexDirection="column" gap={2} style={{ margin: '13px' }}>
|
<Box display="flex" flexDirection="column" gap={2} style={{ margin: '13px' }}>
|
||||||
{!getText && !getScreenshot && !getList && showCaptureList && <Button variant="contained" onClick={startGetList}>{t('right_panel.buttons.capture_list')}</Button>}
|
{!getText && !getScreenshot && !getList && showCaptureList && <Button variant="contained" onClick={startGetList}>{t('right_panel.buttons.capture_list')}</Button>}
|
||||||
|
|
||||||
{getList && (
|
{getList && (
|
||||||
<>
|
<>
|
||||||
<Box display="flex" justifyContent="space-between" gap={2} style={{ margin: '15px' }}>
|
<Box display="flex" justifyContent="space-between" gap={2} style={{ margin: '15px' }}>
|
||||||
@@ -477,6 +481,11 @@ export const RightSidePanel: React.FC<RightSidePanelProps> = ({ onFinishCapture
|
|||||||
<Button
|
<Button
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
onClick={handleBackCaptureList}
|
onClick={handleBackCaptureList}
|
||||||
|
sx={{
|
||||||
|
color: '#ff00c3 !important',
|
||||||
|
borderColor: '#ff00c3 !important',
|
||||||
|
backgroundColor: 'whitesmoke !important',
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{t('right_panel.buttons.back')}
|
{t('right_panel.buttons.back')}
|
||||||
</Button>
|
</Button>
|
||||||
@@ -485,13 +494,26 @@ export const RightSidePanel: React.FC<RightSidePanelProps> = ({ onFinishCapture
|
|||||||
variant="outlined"
|
variant="outlined"
|
||||||
onClick={handleConfirmListCapture}
|
onClick={handleConfirmListCapture}
|
||||||
disabled={captureStage === 'initial' ? isConfirmCaptureDisabled : hasUnconfirmedListTextFields}
|
disabled={captureStage === 'initial' ? isConfirmCaptureDisabled : hasUnconfirmedListTextFields}
|
||||||
|
sx={{
|
||||||
|
color: '#ff00c3 !important',
|
||||||
|
borderColor: '#ff00c3 !important',
|
||||||
|
backgroundColor: 'whitesmoke !important',
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{captureStage === 'initial' ? t('right_panel.buttons.confirm_capture') :
|
{captureStage === 'initial' ? t('right_panel.buttons.confirm_capture') :
|
||||||
captureStage === 'pagination' ? t('right_panel.buttons.confirm_pagination') :
|
captureStage === 'pagination' ? t('right_panel.buttons.confirm_pagination') :
|
||||||
captureStage === 'limit' ? t('right_panel.buttons.confirm_limit') :
|
captureStage === 'limit' ? t('right_panel.buttons.confirm_limit') :
|
||||||
t('right_panel.buttons.finish_capture')}
|
t('right_panel.buttons.finish_capture')}
|
||||||
</Button>
|
</Button>
|
||||||
<Button variant="outlined" color="error" onClick={discardGetList}>
|
<Button
|
||||||
|
variant="outlined"
|
||||||
|
color="error"
|
||||||
|
onClick={discardGetList}
|
||||||
|
sx={{
|
||||||
|
color: 'red !important',
|
||||||
|
borderColor: 'red !important',
|
||||||
|
backgroundColor: 'whitesmoke !important',
|
||||||
|
}} >
|
||||||
{t('right_panel.buttons.discard')}
|
{t('right_panel.buttons.discard')}
|
||||||
</Button>
|
</Button>
|
||||||
</Box>
|
</Box>
|
||||||
@@ -500,11 +522,55 @@ export const RightSidePanel: React.FC<RightSidePanelProps> = ({ onFinishCapture
|
|||||||
{showPaginationOptions && (
|
{showPaginationOptions && (
|
||||||
<Box display="flex" flexDirection="column" gap={2} style={{ margin: '13px' }}>
|
<Box display="flex" flexDirection="column" gap={2} style={{ margin: '13px' }}>
|
||||||
<Typography>{t('right_panel.pagination.title')}</Typography>
|
<Typography>{t('right_panel.pagination.title')}</Typography>
|
||||||
<Button variant={paginationType === 'clickNext' ? "contained" : "outlined"} onClick={() => handlePaginationSettingSelect('clickNext')}>{t('right_panel.pagination.click_next')}</Button>
|
<Button
|
||||||
<Button variant={paginationType === 'clickLoadMore' ? "contained" : "outlined"} onClick={() => handlePaginationSettingSelect('clickLoadMore')}>{t('right_panel.pagination.click_load_more')}</Button>
|
variant={paginationType === 'clickNext' ? "contained" : "outlined"}
|
||||||
<Button variant={paginationType === 'scrollDown' ? "contained" : "outlined"} onClick={() => handlePaginationSettingSelect('scrollDown')}>{t('right_panel.pagination.scroll_down')}</Button>
|
onClick={() => handlePaginationSettingSelect('clickNext')}
|
||||||
<Button variant={paginationType === 'scrollUp' ? "contained" : "outlined"} onClick={() => handlePaginationSettingSelect('scrollUp')}>{t('right_panel.pagination.scroll_up')}</Button>
|
sx={{
|
||||||
<Button variant={paginationType === 'none' ? "contained" : "outlined"} onClick={() => handlePaginationSettingSelect('none')}>{t('right_panel.pagination.none')}</Button>
|
color: paginationType === 'clickNext' ? 'whitesmoke !important' : '#ff00c3 !important',
|
||||||
|
borderColor: '#ff00c3 !important',
|
||||||
|
backgroundColor: paginationType === 'clickNext' ? '#ff00c3 !important' : 'whitesmoke !important',
|
||||||
|
}}>
|
||||||
|
{t('right_panel.pagination.click_next')}
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant={paginationType === 'clickLoadMore' ? "contained" : "outlined"}
|
||||||
|
onClick={() => handlePaginationSettingSelect('clickLoadMore')}
|
||||||
|
sx={{
|
||||||
|
color: paginationType === 'clickLoadMore' ? 'whitesmoke !important' : '#ff00c3 !important',
|
||||||
|
borderColor: '#ff00c3 !important',
|
||||||
|
backgroundColor: paginationType === 'clickLoadMore' ? '#ff00c3 !important' : 'whitesmoke !important',
|
||||||
|
}}>
|
||||||
|
{t('right_panel.pagination.click_load_more')}
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant={paginationType === 'scrollDown' ? "contained" : "outlined"}
|
||||||
|
onClick={() => handlePaginationSettingSelect('scrollDown')}
|
||||||
|
sx={{
|
||||||
|
color: paginationType === 'scrollDown' ? 'whitesmoke !important' : '#ff00c3 !important',
|
||||||
|
borderColor: '#ff00c3 !important',
|
||||||
|
backgroundColor: paginationType === 'scrollDown' ? '#ff00c3 !important' : 'whitesmoke !important',
|
||||||
|
}}>
|
||||||
|
{t('right_panel.pagination.scroll_down')}
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant={paginationType === 'scrollUp' ? "contained" : "outlined"}
|
||||||
|
onClick={() => handlePaginationSettingSelect('scrollUp')}
|
||||||
|
sx={{
|
||||||
|
color: paginationType === 'scrollUp' ? 'whitesmoke !important' : '#ff00c3 !important',
|
||||||
|
borderColor: '#ff00c3 !important',
|
||||||
|
backgroundColor: paginationType === 'scrollUp' ? '#ff00c3 !important' : 'whitesmoke !important',
|
||||||
|
}}>
|
||||||
|
{t('right_panel.pagination.scroll_up')}
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant={paginationType === 'none' ? "contained" : "outlined"}
|
||||||
|
onClick={() => handlePaginationSettingSelect('none')}
|
||||||
|
sx={{
|
||||||
|
color: paginationType === 'none' ? 'whitesmoke !important' : '#ff00c3 !important',
|
||||||
|
borderColor: '#ff00c3 !important',
|
||||||
|
backgroundColor: paginationType === 'none' ? '#ff00c3 !important' : 'whitesmoke !important',
|
||||||
|
}}>
|
||||||
|
{t('right_panel.pagination.none')}</Button>
|
||||||
</Box>
|
</Box>
|
||||||
)}
|
)}
|
||||||
{showLimitOptions && (
|
{showLimitOptions && (
|
||||||
@@ -550,9 +616,11 @@ export const RightSidePanel: React.FC<RightSidePanelProps> = ({ onFinishCapture
|
|||||||
marginLeft: '10px',
|
marginLeft: '10px',
|
||||||
'& input': {
|
'& input': {
|
||||||
padding: '10px',
|
padding: '10px',
|
||||||
background: 'white',
|
|
||||||
},
|
},
|
||||||
width: '150px', // Ensure the text field does not go outside the panel
|
width: '150px',
|
||||||
|
background: isDarkMode ? "#1E2124" : 'white',
|
||||||
|
color: isDarkMode ? "white" : 'black', // Ensure the text field does not go outside the panel
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
@@ -560,27 +628,59 @@ export const RightSidePanel: React.FC<RightSidePanelProps> = ({ onFinishCapture
|
|||||||
</RadioGroup>
|
</RadioGroup>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
)}
|
)}
|
||||||
|
{/* {!getText && !getScreenshot && !getList && showCaptureText && <Button variant="contained" sx={{backgroundColor:"#ff00c3",color:`${isDarkMode?'white':'black'}`}} onClick={startGetText}>{t('right_panel.buttons.capture_text')}</Button>} */}
|
||||||
|
|
||||||
{!getText && !getScreenshot && !getList && showCaptureText && <Button variant="contained" onClick={handleStartGetText}>{t('right_panel.buttons.capture_text')}</Button>}
|
{!getText && !getScreenshot && !getList && showCaptureText && <Button variant="contained" onClick={handleStartGetText}>{t('right_panel.buttons.capture_text')}</Button>}
|
||||||
{getText &&
|
{getText &&
|
||||||
<>
|
<>
|
||||||
<Box display="flex" justifyContent="space-between" gap={2} style={{ margin: '15px' }}>
|
<Box display="flex" justifyContent="space-between" gap={2} style={{ margin: '15px' }}>
|
||||||
<Button variant="outlined" onClick={stopCaptureAndEmitGetTextSettings} >{t('right_panel.buttons.confirm')}</Button>
|
<Button
|
||||||
<Button variant="outlined" color="error" onClick={discardGetText} >{t('right_panel.buttons.discard')}</Button>
|
variant="outlined"
|
||||||
|
onClick={stopCaptureAndEmitGetTextSettings}
|
||||||
|
sx={{
|
||||||
|
color: '#ff00c3 !important',
|
||||||
|
borderColor: '#ff00c3 !important',
|
||||||
|
backgroundColor: 'whitesmoke !important',
|
||||||
|
}}>
|
||||||
|
{t('right_panel.buttons.confirm')}
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant="outlined"
|
||||||
|
color="error"
|
||||||
|
onClick={discardGetText}
|
||||||
|
sx={{
|
||||||
|
color: '#ff00c3 !important',
|
||||||
|
borderColor: '#ff00c3 !important',
|
||||||
|
backgroundColor: 'whitesmoke !important',
|
||||||
|
}}>
|
||||||
|
{t('right_panel.buttons.discard')}
|
||||||
|
</Button>
|
||||||
</Box>
|
</Box>
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
|
{/* {!getText && !getScreenshot && !getList && showCaptureScreenshot && <Button variant="contained" sx={{backgroundColor:"#ff00c3",color:`${isDarkMode?'white':'black'}`}} onClick={startGetScreenshot}>{t('right_panel.buttons.capture_screenshot')}</Button>} */}
|
||||||
{!getText && !getScreenshot && !getList && showCaptureScreenshot && <Button variant="contained" onClick={startGetScreenshot}>{t('right_panel.buttons.capture_screenshot')}</Button>}
|
{!getText && !getScreenshot && !getList && showCaptureScreenshot && <Button variant="contained" onClick={startGetScreenshot}>{t('right_panel.buttons.capture_screenshot')}</Button>}
|
||||||
{getScreenshot && (
|
{getScreenshot && (
|
||||||
<Box display="flex" flexDirection="column" gap={2}>
|
<Box display="flex" flexDirection="column" gap={2}>
|
||||||
<Button variant="contained" onClick={() => captureScreenshot(true)}>{t('right_panel.screenshot.capture_fullpage')}</Button>
|
<Button variant="contained" onClick={() => captureScreenshot(true)}>{t('right_panel.screenshot.capture_fullpage')}</Button>
|
||||||
<Button variant="contained" onClick={() => captureScreenshot(false)}>{t('right_panel.screenshot.capture_visible')}</Button>
|
<Button variant="contained" onClick={() => captureScreenshot(false)}>{t('right_panel.screenshot.capture_visible')}</Button>
|
||||||
<Button variant="outlined" color="error" onClick={stopGetScreenshot}>{t('right_panel.buttons.discard')}</Button>
|
<Button
|
||||||
|
variant="outlined"
|
||||||
|
color="error"
|
||||||
|
onClick={stopGetScreenshot}
|
||||||
|
sx={{
|
||||||
|
color: '#ff00c3 !important',
|
||||||
|
borderColor: '#ff00c3 !important',
|
||||||
|
backgroundColor: 'whitesmoke !important',
|
||||||
|
}}>
|
||||||
|
{t('right_panel.buttons.discard')}
|
||||||
|
</Button>
|
||||||
</Box>
|
</Box>
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
<Box>
|
<Box>
|
||||||
{browserSteps.map(step => (
|
{browserSteps.map(step => (
|
||||||
<Box key={step.id} onMouseEnter={() => handleMouseEnter(step.id)} onMouseLeave={() => handleMouseLeave(step.id)} sx={{ padding: '10px', margin: '11px', borderRadius: '5px', position: 'relative', background: 'white' }}>
|
<Box key={step.id} onMouseEnter={() => handleMouseEnter(step.id)} onMouseLeave={() => handleMouseLeave(step.id)} sx={{ padding: '10px', margin: '11px', borderRadius: '5px', position: 'relative', background: isDarkMode ? "#1E2124" : 'white', color: isDarkMode ? "white" : 'black' }}>
|
||||||
{
|
{
|
||||||
step.type === 'text' && (
|
step.type === 'text' && (
|
||||||
<>
|
<>
|
||||||
@@ -601,6 +701,7 @@ export const RightSidePanel: React.FC<RightSidePanelProps> = ({ onFinishCapture
|
|||||||
</InputAdornment>
|
</InputAdornment>
|
||||||
)
|
)
|
||||||
}}
|
}}
|
||||||
|
sx={{ background: isDarkMode ? "#1E2124" : 'white', color: isDarkMode ? "white" : 'black' }}
|
||||||
/>
|
/>
|
||||||
<TextField
|
<TextField
|
||||||
label={t('right_panel.fields.data')}
|
label={t('right_panel.fields.data')}
|
||||||
@@ -615,6 +716,7 @@ export const RightSidePanel: React.FC<RightSidePanelProps> = ({ onFinishCapture
|
|||||||
</InputAdornment>
|
</InputAdornment>
|
||||||
)
|
)
|
||||||
}}
|
}}
|
||||||
|
|
||||||
/>
|
/>
|
||||||
{!confirmedTextSteps[step.id] ? (
|
{!confirmedTextSteps[step.id] ? (
|
||||||
<Box display="flex" justifyContent="space-between" gap={2}>
|
<Box display="flex" justifyContent="space-between" gap={2}>
|
||||||
@@ -648,7 +750,7 @@ export const RightSidePanel: React.FC<RightSidePanelProps> = ({ onFinishCapture
|
|||||||
<>
|
<>
|
||||||
<Typography>{t('right_panel.messages.list_selected')}</Typography>
|
<Typography>{t('right_panel.messages.list_selected')}</Typography>
|
||||||
{Object.entries(step.fields).map(([key, field]) => (
|
{Object.entries(step.fields).map(([key, field]) => (
|
||||||
<Box key={key}>
|
<Box key={key} sx={{background: `${isDarkMode ? "#1E2124" : 'white'}` }}>
|
||||||
<TextField
|
<TextField
|
||||||
label={t('right_panel.fields.field_label')}
|
label={t('right_panel.fields.field_label')}
|
||||||
value={field.label || ''}
|
value={field.label || ''}
|
||||||
@@ -662,7 +764,7 @@ export const RightSidePanel: React.FC<RightSidePanelProps> = ({ onFinishCapture
|
|||||||
<EditIcon />
|
<EditIcon />
|
||||||
</InputAdornment>
|
</InputAdornment>
|
||||||
)
|
)
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<TextField
|
<TextField
|
||||||
label={t('right_panel.fields.field_data')}
|
label={t('right_panel.fields.field_data')}
|
||||||
@@ -677,6 +779,7 @@ export const RightSidePanel: React.FC<RightSidePanelProps> = ({ onFinishCapture
|
|||||||
</InputAdornment>
|
</InputAdornment>
|
||||||
)
|
)
|
||||||
}}
|
}}
|
||||||
|
|
||||||
/>
|
/>
|
||||||
{!confirmedListTextFields[step.id]?.[key] ? (
|
{!confirmedListTextFields[step.id]?.[key] ? (
|
||||||
<Box display="flex" justifyContent="space-between" gap={2}>
|
<Box display="flex" justifyContent="space-between" gap={2}>
|
||||||
|
|||||||
256
src/context/theme-provider.tsx
Normal file
256
src/context/theme-provider.tsx
Normal file
@@ -0,0 +1,256 @@
|
|||||||
|
import React, { createContext, useContext, useState, useEffect } from 'react';
|
||||||
|
import { ThemeProvider, createTheme } from '@mui/material/styles';
|
||||||
|
import CssBaseline from '@mui/material/CssBaseline';
|
||||||
|
|
||||||
|
const lightTheme = createTheme({
|
||||||
|
palette: {
|
||||||
|
primary: {
|
||||||
|
main: "#ff00c3",
|
||||||
|
contrastText: "#ffffff",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
MuiButton: {
|
||||||
|
styleOverrides: {
|
||||||
|
root: {
|
||||||
|
// Default styles for all buttons (optional)
|
||||||
|
textTransform: "none",
|
||||||
|
},
|
||||||
|
containedPrimary: {
|
||||||
|
// Styles for 'contained' variant with 'primary' color
|
||||||
|
"&:hover": {
|
||||||
|
backgroundColor: "#ff66d9",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
outlined: {
|
||||||
|
// Apply white background for all 'outlined' variant buttons
|
||||||
|
backgroundColor: "#ffffff",
|
||||||
|
"&:hover": {
|
||||||
|
backgroundColor: "#f0f0f0", // Optional lighter background on hover
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
MuiLink: {
|
||||||
|
styleOverrides: {
|
||||||
|
root: {
|
||||||
|
"&:hover": {
|
||||||
|
color: "#ff00c3",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
MuiIconButton: {
|
||||||
|
styleOverrides: {
|
||||||
|
root: {
|
||||||
|
// '&:hover': {
|
||||||
|
// color: "#ff66d9",
|
||||||
|
// },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
MuiTab: {
|
||||||
|
styleOverrides: {
|
||||||
|
root: {
|
||||||
|
textTransform: "none",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
MuiAlert: {
|
||||||
|
styleOverrides: {
|
||||||
|
standardInfo: {
|
||||||
|
backgroundColor: "#fce1f4",
|
||||||
|
color: "#ff00c3",
|
||||||
|
"& .MuiAlert-icon": {
|
||||||
|
color: "#ff00c3",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
MuiAlertTitle: {
|
||||||
|
styleOverrides: {
|
||||||
|
root: {
|
||||||
|
"& .MuiAlert-icon": {
|
||||||
|
color: "#ffffff",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const darkTheme = createTheme({
|
||||||
|
palette: {
|
||||||
|
mode: 'dark',
|
||||||
|
primary: {
|
||||||
|
main: "#ff00c3",
|
||||||
|
contrastText: "#ffffff",
|
||||||
|
},
|
||||||
|
background: {
|
||||||
|
default: '#121212',
|
||||||
|
paper: '#1e1e1e',
|
||||||
|
},
|
||||||
|
text: {
|
||||||
|
primary: '#ffffff',
|
||||||
|
secondary: '#b3b3b3',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
MuiButton: {
|
||||||
|
styleOverrides: {
|
||||||
|
root: {
|
||||||
|
textTransform: "none",
|
||||||
|
color: '#ffffff',
|
||||||
|
'&.MuiButton-outlined': {
|
||||||
|
borderColor: '#ffffff',
|
||||||
|
color: '#ffffff',
|
||||||
|
"&:hover": {
|
||||||
|
borderColor: '#ffffff',
|
||||||
|
backgroundColor: 'rgba(255, 255, 255, 0.08)',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
containedPrimary: {
|
||||||
|
"&:hover": {
|
||||||
|
backgroundColor: "#ff66d9",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
outlined: {
|
||||||
|
// Dark mode outlined buttons
|
||||||
|
backgroundColor: '#1e1e1e',
|
||||||
|
borderColor: '#ff00c3',
|
||||||
|
color: '#ff00c3',
|
||||||
|
"&:hover": {
|
||||||
|
backgroundColor: 'rgba(255, 0, 195, 0.08)',
|
||||||
|
borderColor: '#ff66d9',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
MuiLink: {
|
||||||
|
styleOverrides: {
|
||||||
|
root: {
|
||||||
|
color: '#ff66d9',
|
||||||
|
"&:hover": {
|
||||||
|
color: "#ff00c3",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
MuiIconButton: {
|
||||||
|
styleOverrides: {
|
||||||
|
root: {
|
||||||
|
color: '#ffffff',
|
||||||
|
"&:hover": {
|
||||||
|
backgroundColor: 'rgba(255, 0, 195, 0.08)',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
MuiTab: {
|
||||||
|
styleOverrides: {
|
||||||
|
root: {
|
||||||
|
textTransform: "none",
|
||||||
|
color: '#ffffff',
|
||||||
|
"&.Mui-selected": {
|
||||||
|
color: '#ff00c3',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
MuiAlert: {
|
||||||
|
styleOverrides: {
|
||||||
|
standardInfo: {
|
||||||
|
backgroundColor: "rgba(255, 0, 195, 0.15)",
|
||||||
|
color: "#ff66d9",
|
||||||
|
"& .MuiAlert-icon": {
|
||||||
|
color: "#ff66d9",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
MuiAlertTitle: {
|
||||||
|
styleOverrides: {
|
||||||
|
root: {
|
||||||
|
"& .MuiAlert-icon": {
|
||||||
|
color: "#ff66d9",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// Additional dark mode specific components
|
||||||
|
MuiPaper: {
|
||||||
|
styleOverrides: {
|
||||||
|
root: {
|
||||||
|
backgroundColor: '#1e1e1e',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
MuiAppBar: {
|
||||||
|
styleOverrides: {
|
||||||
|
root: {
|
||||||
|
backgroundColor: '#121212',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
MuiDrawer: {
|
||||||
|
styleOverrides: {
|
||||||
|
paper: {
|
||||||
|
backgroundColor: '#121212',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
MuiTableCell: {
|
||||||
|
styleOverrides: {
|
||||||
|
root: {
|
||||||
|
borderBottom: '1px solid rgba(255, 255, 255, 0.12)',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
MuiDivider: {
|
||||||
|
styleOverrides: {
|
||||||
|
root: {
|
||||||
|
borderColor: 'rgba(255, 255, 255, 0.12)',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const ThemeModeContext = createContext({
|
||||||
|
toggleTheme: () => {},
|
||||||
|
darkMode: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
export const useThemeMode = () => useContext(ThemeModeContext);
|
||||||
|
|
||||||
|
const ThemeModeProvider = ({ children }: { children: React.ReactNode }) => {
|
||||||
|
// Load saved mode from localStorage or default to light mode
|
||||||
|
const [darkMode, setDarkMode] = useState(() => {
|
||||||
|
const savedMode = localStorage.getItem('darkMode');
|
||||||
|
return savedMode ? JSON.parse(savedMode) : false;
|
||||||
|
});
|
||||||
|
|
||||||
|
const toggleTheme = () => {
|
||||||
|
setDarkMode((prevMode: any) => {
|
||||||
|
const newMode = !prevMode;
|
||||||
|
localStorage.setItem('darkMode', JSON.stringify(newMode)); // Save new mode to localStorage
|
||||||
|
return newMode;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
localStorage.setItem('darkMode', JSON.stringify(darkMode)); // Save initial mode
|
||||||
|
}, [darkMode]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ThemeModeContext.Provider value={{ toggleTheme, darkMode }}>
|
||||||
|
<ThemeProvider theme={darkMode ? darkTheme : lightTheme}>
|
||||||
|
<CssBaseline />
|
||||||
|
{children}
|
||||||
|
</ThemeProvider>
|
||||||
|
</ThemeModeContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ThemeModeProvider;
|
||||||
@@ -11,6 +11,7 @@ body {
|
|||||||
padding: 0;
|
padding: 0;
|
||||||
scrollbar-gutter: stable;
|
scrollbar-gutter: stable;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
html {
|
html {
|
||||||
@@ -43,6 +44,7 @@ code {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#browser-content {
|
#browser-content {
|
||||||
@@ -54,6 +56,11 @@ code {
|
|||||||
transform-origin: top left; /* Keep the position fixed */
|
transform-origin: top left; /* Keep the position fixed */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#browser {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#browser-window {
|
#browser-window {
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import { useState, useContext, useEffect, FormEvent } from "react";
|
import { useState, useContext, useEffect } from "react";
|
||||||
import { useNavigate, Link } from "react-router-dom";
|
import { useNavigate, Link } from "react-router-dom";
|
||||||
import { AuthContext } from "../context/auth";
|
import { AuthContext } from "../context/auth";
|
||||||
import { Box, Typography, TextField, Button, CircularProgress, Grid } from "@mui/material";
|
import { Box, Typography, TextField, Button, CircularProgress } from "@mui/material";
|
||||||
import { useGlobalInfoStore } from "../context/globalInfo";
|
import { useGlobalInfoStore } from "../context/globalInfo";
|
||||||
import { apiUrl } from "../apiConfig";
|
import { apiUrl } from "../apiConfig";
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import i18n from '../i18n';
|
import i18n from '../i18n';
|
||||||
|
import { useThemeMode } from "../context/theme-provider";
|
||||||
|
|
||||||
const Login = () => {
|
const Login = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@@ -17,12 +18,14 @@ const Login = () => {
|
|||||||
email: "",
|
email: "",
|
||||||
password: "",
|
password: "",
|
||||||
});
|
});
|
||||||
|
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const { notify } = useGlobalInfoStore();
|
const { notify } = useGlobalInfoStore();
|
||||||
const { email, password } = form;
|
const { email, password } = form;
|
||||||
|
|
||||||
const { state, dispatch } = useContext(AuthContext);
|
const { state, dispatch } = useContext(AuthContext);
|
||||||
const { user } = state;
|
const { user } = state;
|
||||||
|
const { darkMode } = useThemeMode();
|
||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
@@ -41,10 +44,11 @@ const Login = () => {
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
try {
|
try {
|
||||||
const { data } = await axios.post(`${apiUrl}/auth/login`, {
|
const { data } = await axios.post(
|
||||||
email,
|
`${apiUrl}/auth/login`,
|
||||||
password,
|
{ email, password },
|
||||||
});
|
{ withCredentials: true }
|
||||||
|
);
|
||||||
dispatch({ type: "LOGIN", payload: data });
|
dispatch({ type: "LOGIN", payload: data });
|
||||||
notify("success", t('login.welcome_notification'));
|
notify("success", t('login.welcome_notification'));
|
||||||
window.localStorage.setItem("user", JSON.stringify(data));
|
window.localStorage.setItem("user", JSON.stringify(data));
|
||||||
@@ -64,6 +68,7 @@ const Login = () => {
|
|||||||
maxHeight: "100vh",
|
maxHeight: "100vh",
|
||||||
mt: 6,
|
mt: 6,
|
||||||
padding: 4,
|
padding: 4,
|
||||||
|
backgroundColor: darkMode ? "#121212" : "#ffffff",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Box
|
<Box
|
||||||
@@ -71,14 +76,15 @@ const Login = () => {
|
|||||||
onSubmit={submitForm}
|
onSubmit={submitForm}
|
||||||
sx={{
|
sx={{
|
||||||
textAlign: "center",
|
textAlign: "center",
|
||||||
backgroundColor: "#ffffff",
|
backgroundColor: darkMode ? "#1e1e1e" : "#ffffff",
|
||||||
|
color: darkMode ? "#ffffff" : "#333333",
|
||||||
padding: 6,
|
padding: 6,
|
||||||
borderRadius: 5,
|
borderRadius: 5,
|
||||||
boxShadow: "0px 20px 40px rgba(0, 0, 0, 0.2), 0px -5px 10px rgba(0, 0, 0, 0.15)",
|
boxShadow: "0px 20px 40px rgba(0, 0, 0, 0.2), 0px -5px 10px rgba(0, 0, 0, 0.15)",
|
||||||
display: "flex",
|
display: "flex",
|
||||||
flexDirection: "column",
|
flexDirection: "column",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
maxWidth: 400,
|
maxWidth: 500,
|
||||||
width: "100%",
|
width: "100%",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@@ -112,7 +118,10 @@ const Login = () => {
|
|||||||
fullWidth
|
fullWidth
|
||||||
variant="contained"
|
variant="contained"
|
||||||
color="primary"
|
color="primary"
|
||||||
sx={{ mt: 2, mb: 2 }}
|
sx={{
|
||||||
|
mt: 2,
|
||||||
|
mb: 2,
|
||||||
|
}}
|
||||||
disabled={loading || !email || !password}
|
disabled={loading || !email || !password}
|
||||||
>
|
>
|
||||||
{loading ? (
|
{loading ? (
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import Login from './Login';
|
|||||||
import Register from './Register';
|
import Register from './Register';
|
||||||
import UserRoute from '../routes/userRoute';
|
import UserRoute from '../routes/userRoute';
|
||||||
import { Routes, Route, useNavigate } from 'react-router-dom';
|
import { Routes, Route, useNavigate } from 'react-router-dom';
|
||||||
|
import { AppBar } from '@mui/material';
|
||||||
|
|
||||||
export const PageWrapper = () => {
|
export const PageWrapper = () => {
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
@@ -50,7 +51,9 @@ export const PageWrapper = () => {
|
|||||||
<AuthProvider>
|
<AuthProvider>
|
||||||
<SocketProvider>
|
<SocketProvider>
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
|
|
||||||
{!browserId && <NavBar recordingName={recordingName} isRecording={!!browserId} />}
|
{!browserId && <NavBar recordingName={recordingName} isRecording={!!browserId} />}
|
||||||
|
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route element={<UserRoute />}>
|
<Route element={<UserRoute />}>
|
||||||
<Route path="/" element={<MainPage handleEditRecording={handleEditRecording} />} />
|
<Route path="/" element={<MainPage handleEditRecording={handleEditRecording} />} />
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import { editRecordingFromStorage } from "../api/storage";
|
|||||||
import { WhereWhatPair } from "maxun-core";
|
import { WhereWhatPair } from "maxun-core";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import BrowserRecordingSave from '../components/molecules/BrowserRecordingSave';
|
import BrowserRecordingSave from '../components/molecules/BrowserRecordingSave';
|
||||||
|
import { useThemeMode } from '../context/theme-provider';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
interface RecordingPageProps {
|
interface RecordingPageProps {
|
||||||
@@ -27,6 +28,7 @@ export interface PairForEdit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const RecordingPage = ({ recordingName }: RecordingPageProps) => {
|
export const RecordingPage = ({ recordingName }: RecordingPageProps) => {
|
||||||
|
const { darkMode } = useThemeMode();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [isLoaded, setIsLoaded] = React.useState(false);
|
const [isLoaded, setIsLoaded] = React.useState(false);
|
||||||
const [hasScrollbar, setHasScrollbar] = React.useState(false);
|
const [hasScrollbar, setHasScrollbar] = React.useState(false);
|
||||||
@@ -34,6 +36,7 @@ export const RecordingPage = ({ recordingName }: RecordingPageProps) => {
|
|||||||
pair: null,
|
pair: null,
|
||||||
index: 0,
|
index: 0,
|
||||||
});
|
});
|
||||||
|
|
||||||
const [showOutputData, setShowOutputData] = useState(false);
|
const [showOutputData, setShowOutputData] = useState(false);
|
||||||
|
|
||||||
const browserContentRef = React.useRef<HTMLDivElement>(null);
|
const browserContentRef = React.useRef<HTMLDivElement>(null);
|
||||||
@@ -57,15 +60,20 @@ export const RecordingPage = ({ recordingName }: RecordingPageProps) => {
|
|||||||
useEffect(() => changeBrowserDimensions(), [isLoaded])
|
useEffect(() => changeBrowserDimensions(), [isLoaded])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
document.body.style.background = 'radial-gradient(circle, rgba(255, 255, 255, 1) 0%, rgba(232, 191, 222, 1) 100%, rgba(255, 255, 255, 1) 100%)';
|
if (darkMode) {
|
||||||
document.body.style.filter = 'progid:DXImageTransform.Microsoft.gradient(startColorstr="#ffffff",endColorstr="#ffffff",GradientType=1);'
|
|
||||||
|
document.body.style.background = 'rgba(18,18,18,1)';
|
||||||
|
|
||||||
|
} else {
|
||||||
|
document.body.style.background = 'radial-gradient(circle, rgba(255, 255, 255, 1) 0%, rgba(232, 191, 222, 1) 100%, rgba(255, 255, 255, 1) 100%)';
|
||||||
|
document.body.style.filter = 'progid:DXImageTransform.Microsoft.gradient(startColorstr="#ffffff",endColorstr="#ffffff",GradientType=1);'
|
||||||
|
}
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
// Cleanup the background when leaving the page
|
|
||||||
document.body.style.background = '';
|
document.body.style.background = '';
|
||||||
document.body.style.filter = '';
|
document.body.style.filter = '';
|
||||||
};
|
};
|
||||||
}, []);
|
}, [darkMode]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let isCancelled = false;
|
let isCancelled = false;
|
||||||
|
|||||||
@@ -5,11 +5,11 @@ import { AuthContext } from "../context/auth";
|
|||||||
import { Box, Typography, TextField, Button, CircularProgress } from "@mui/material";
|
import { Box, Typography, TextField, Button, CircularProgress } from "@mui/material";
|
||||||
import { useGlobalInfoStore } from "../context/globalInfo";
|
import { useGlobalInfoStore } from "../context/globalInfo";
|
||||||
import { apiUrl } from "../apiConfig";
|
import { apiUrl } from "../apiConfig";
|
||||||
|
import { useThemeMode } from "../context/theme-provider";
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import i18n from '../i18n';
|
import i18n from '../i18n';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const Register = () => {
|
const Register = () => {
|
||||||
const {t} = useTranslation();
|
const {t} = useTranslation();
|
||||||
const [form, setForm] = useState({
|
const [form, setForm] = useState({
|
||||||
@@ -22,6 +22,7 @@ const Register = () => {
|
|||||||
|
|
||||||
const { state, dispatch } = useContext(AuthContext);
|
const { state, dispatch } = useContext(AuthContext);
|
||||||
const { user } = state;
|
const { user } = state;
|
||||||
|
const { darkMode } = useThemeMode();
|
||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
@@ -40,18 +41,14 @@ const Register = () => {
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
try {
|
try {
|
||||||
const { data } = await axios.post(`${apiUrl}/auth/register`, {
|
const { data } = await axios.post(`${apiUrl}/auth/register`, { email, password });
|
||||||
email,
|
console.log(data);
|
||||||
password,
|
|
||||||
});
|
|
||||||
dispatch({ type: "LOGIN", payload: data });
|
dispatch({ type: "LOGIN", payload: data });
|
||||||
notify("success", t('register.welcome_notification'));
|
notify("success", t('register.welcome_notification'));
|
||||||
window.localStorage.setItem("user", JSON.stringify(data));
|
window.localStorage.setItem("user", JSON.stringify(data));
|
||||||
navigate("/");
|
navigate("/");
|
||||||
} catch (error:any) {
|
} catch (error:any) {
|
||||||
|
|
||||||
notify("error", error.response.data || t('register.error_notification'));
|
notify("error", error.response.data || t('register.error_notification'));
|
||||||
|
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -65,25 +62,38 @@ const Register = () => {
|
|||||||
maxHeight: "100vh",
|
maxHeight: "100vh",
|
||||||
mt: 6,
|
mt: 6,
|
||||||
padding: 4,
|
padding: 4,
|
||||||
|
backgroundColor: darkMode ? "#121212" : "#ffffff",
|
||||||
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Box
|
<Box
|
||||||
component="form"
|
component="form"
|
||||||
onSubmit={submitForm}
|
onSubmit={submitForm}
|
||||||
sx={{
|
sx={{
|
||||||
textAlign: "center",
|
textAlign: "center",
|
||||||
backgroundColor: "#ffffff",
|
backgroundColor: darkMode ? "#1e1e1e" : "#ffffff",
|
||||||
padding: 6,
|
color: darkMode ? "#ffffff" : "#333333",
|
||||||
borderRadius: 5,
|
padding: 6,
|
||||||
boxShadow: "0px 20px 40px rgba(0, 0, 0, 0.2), 0px -5px 10px rgba(0, 0, 0, 0.15)",
|
borderRadius: 5,
|
||||||
display: "flex",
|
boxShadow: "0px 20px 40px rgba(0, 0, 0, 0.2), 0px -5px 10px rgba(0, 0, 0, 0.15)",
|
||||||
flexDirection: "column",
|
display: "flex",
|
||||||
alignItems: "center",
|
flexDirection: "column",
|
||||||
maxWidth: 400,
|
alignItems: "center",
|
||||||
width: "100%",
|
maxWidth: 500,
|
||||||
}}
|
width: "100%",
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<img src="../src/assets/maxunlogo.png" alt="logo" height={55} width={60} style={{ marginBottom: 20, borderRadius: "20%", alignItems: "center" }} />
|
<img
|
||||||
|
src="../src/assets/maxunlogo.png"
|
||||||
|
alt="logo"
|
||||||
|
height={55}
|
||||||
|
width={60}
|
||||||
|
style={{
|
||||||
|
marginBottom: 20,
|
||||||
|
borderRadius: "20%",
|
||||||
|
alignItems: "center",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
<Typography variant="h4" gutterBottom>
|
<Typography variant="h4" gutterBottom>
|
||||||
{t('register.title')}
|
{t('register.title')}
|
||||||
</Typography>
|
</Typography>
|
||||||
@@ -113,7 +123,10 @@ const Register = () => {
|
|||||||
fullWidth
|
fullWidth
|
||||||
variant="contained"
|
variant="contained"
|
||||||
color="primary"
|
color="primary"
|
||||||
sx={{ mt: 2, mb: 2 }}
|
sx={{
|
||||||
|
mt: 2,
|
||||||
|
mb: 2,
|
||||||
|
}}
|
||||||
disabled={loading || !email || !password}
|
disabled={loading || !email || !password}
|
||||||
>
|
>
|
||||||
{loading ? (
|
{loading ? (
|
||||||
@@ -125,10 +138,9 @@ const Register = () => {
|
|||||||
t('register.button')
|
t('register.button')
|
||||||
)}
|
)}
|
||||||
</Button>
|
</Button>
|
||||||
<Typography variant="body2" align="center">
|
<Typography variant="body2" align="center" sx={{ color: darkMode ? "#ffffff" : "#333333" }}>
|
||||||
{t('register.register_prompt')}{" "}
|
{t('register.register_prompt')}{" "}
|
||||||
<Link to="/login" style={{ textDecoration: "none", color: "#ff33cc" }}>
|
<Link to="/login" style={{ textDecoration: "none", color: "#ff33cc" }}>
|
||||||
|
|
||||||
{t('register.login_link')}
|
{t('register.login_link')}
|
||||||
</Link>
|
</Link>
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|||||||
Reference in New Issue
Block a user