diff --git a/frontend/package.json b/frontend/package.json index 6141cbf94..6b401f0ea 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -14,6 +14,8 @@ "@fortawesome/react-fontawesome": "^0.1.16", "@monaco-editor/react": "^4.3.1", "@mui/material": "^5.2.3", + "@opuscapita/react-filemanager": "^1.1.11", + "@opuscapita/react-filemanager-connector-node-v1": "^1.1.11", "@testing-library/jest-dom": "^5.11.4", "@testing-library/react": "^11.1.0", "@testing-library/user-event": "^12.1.10", @@ -33,6 +35,7 @@ "react-flow-renderer": "^9.7.3", "react-hook-form": "^7.21.2", "react-idle-timer": "^4.6.4", + "react-lazylog": "^4.5.3", "react-lottie": "^1.2.3", "react-router-dom": "5.2.0", "react-scripts": "5.0.0", diff --git a/frontend/src/App.js b/frontend/src/App.js index 70f7f0b8e..ff912f105 100644 --- a/frontend/src/App.js +++ b/frontend/src/App.js @@ -27,9 +27,11 @@ import Settings from './pages/Settings'; import TeamDetail from './pages/TeamDetail'; import TeamGroup from './pages/TeamGroup'; import Teams from './pages/Teams'; +import PipelineEditor from './pages/Editor'; import RemoveLogs from './pages/RemoveLogs'; import PipelinesPermission from './pages/PipelinesPermission'; import createCustomTheme from './theme'; +import UseCheckTheme from './hooks/useCheckTheme'; export const ColorModeContext = React.createContext({ toggleColorMode: () => {}, @@ -92,6 +94,7 @@ function App() { + @@ -109,6 +112,10 @@ function App() { + + + + { + return ( + + } /> + + ); +}; + +export default LogsDrawer; diff --git a/frontend/src/components/DrawerContent/ShowYAMLCodeDrawer/index.jsx b/frontend/src/components/DrawerContent/ShowYAMLCodeDrawer/index.jsx index fed289bfc..f487687a2 100644 --- a/frontend/src/components/DrawerContent/ShowYAMLCodeDrawer/index.jsx +++ b/frontend/src/components/DrawerContent/ShowYAMLCodeDrawer/index.jsx @@ -72,6 +72,9 @@ const ShowYAMLCodeDrawer = ({ handleClose }) => { path={file.name} defaultLanguage={file.language} defaultValue={file.value} + options={{ + automaticLayout: true, + }} /> diff --git a/frontend/src/components/ThemeToggle/index.jsx b/frontend/src/components/ThemeToggle/index.jsx index a2dea1d9f..1376b9158 100644 --- a/frontend/src/components/ThemeToggle/index.jsx +++ b/frontend/src/components/ThemeToggle/index.jsx @@ -83,18 +83,6 @@ const ThemeToggle = (props) => { const theme = useTheme(); const colorMode = React.useContext(ColorModeContext); - // Retrieve color mode on load - React.useEffect(() => { - const themeData = localStorage.getItem('theme'); - - if (themeData) { - if (themeData !== theme.palette.mode) { - colorMode.toggleColorMode(); - } - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); - // Toggle color mode on click async function handleClick() { const color = theme.palette.mode === 'light' ? 'dark' : 'light'; diff --git a/frontend/src/hooks/useCheckTheme.jsx b/frontend/src/hooks/useCheckTheme.jsx new file mode 100644 index 000000000..c213bb2f7 --- /dev/null +++ b/frontend/src/hooks/useCheckTheme.jsx @@ -0,0 +1,25 @@ +import { useTheme } from '@mui/material'; +import { useEffect } from 'react'; +import { useContext } from 'react'; +import { ColorModeContext } from '../App'; + +const CheckTheme = () => { + const theme = useTheme(); + const colorMode = useContext(ColorModeContext); + + useEffect(() => { + const themeData = localStorage.getItem('theme'); + + if (themeData) { + if (themeData !== theme.palette.mode) { + colorMode.toggleColorMode(); + } + } + + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + return null; +}; + +export default CheckTheme; diff --git a/frontend/src/pages/Editor.jsx b/frontend/src/pages/Editor.jsx new file mode 100644 index 000000000..43686e467 --- /dev/null +++ b/frontend/src/pages/Editor.jsx @@ -0,0 +1,216 @@ +import { faPlayCircle } from '@fortawesome/free-regular-svg-icons'; +import { faCaretDown } from '@fortawesome/free-solid-svg-icons'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import Editor from '@monaco-editor/react'; +import { AppBar, Box, Button, Chip, Drawer, FormControl, Grid, InputLabel, MenuItem, Select, Toolbar, Typography, useTheme } from '@mui/material'; +import Navbar from '../components/Navbar'; +import { FileManager, FileNavigator } from '@opuscapita/react-filemanager'; +import connectorNodeV1 from '@opuscapita/react-filemanager-connector-node-v1'; +import { useContext, useRef, useState } from 'react'; +import LogsDrawer from '../components/DrawerContent/LogsDrawer'; +import customDrawerStyles from '../utils/drawerStyles'; +import { ColorModeContext } from '../App'; + +const drawerWidth = 240; +const apiOptions = { + ...connectorNodeV1.apiOptions, + apiRoot: `https://demo.core.dev.opuscapita.com/filemanager/master`, // Or you local Server Node V1 installation. +}; + +const PipelineEditor = () => { + // States + const [isOpenLogs, setIsOpenLogs] = useState(false); + const [selectedFile, setSelectedFile] = useState(FILE_MANAGER_MOCK['1']); + const [locations, setLocations] = useState([]); + + // Ref + const editorRef = useRef(null); + + // Hooks + const theme = useTheme(); + const colorMode = useContext(ColorModeContext); + + // Functions + const handleThemeSelect = (e) => { + const color = e.target.value; + localStorage.setItem('theme', color); + colorMode.toggleColorMode(); + }; + + const handleEditorOnMount = (editor) => { + editorRef.current = editor; + + window.addEventListener('resize', () => { + editor.layout({ + width: 'auto', + height: 'auto', + }); + }); + }; + + return ( + + theme.zIndex.drawer, background: (theme) => theme.palette.background.secondary, borderBottom: 1, borderColor: 'divider' }}> + + + + + + + + + + Theme + + + + + Dev worker + + + + + Draft + + + + + + setLocations(resourceLocation)} + onResourceItemDoubleClick={({ event, number, rowData }) => console.log(rowData)} + onResourceItemClick={({ event, number, rowData }) => setSelectedFile({ rowData, ...FILE_MANAGER_MOCK[rowData.id] })} + /> + + + + + + + + + + + + Pipeline permissions {'>'} Remove Logs {'>'} Clear the logs + + + /{locations.map((loc, idx) => `${idx !== 0 ? '/' : ''}${loc.name}`)} /{selectedFile && selectedFile.name} + + + + + + + + + + + + } + label="Play" + sx={{ mr: 0, bgcolor: 'primary.main', color: '#fff', fontWeight: 600 }} + /> + + + + + + + + + + setIsOpenLogs(!isOpenLogs)} sx={customDrawerStyles}> + + + + ); +}; + +const PYTHON_CODE_EXAMPLE = `import banana + + + class Monkey: + # Bananas the monkey can eat + capacity = 10 + def eat(self, n): + """Make the monkey eat n bananas!""" + self.capacity -= n * banana.size + + def feeding_frenzy(self): + self.eat(9.25) + return "Yum yum" + +`; + +const FILE_MANAGER_MOCK = { + 1: { + language: 'python', + name: 'monkey.py', + content: PYTHON_CODE_EXAMPLE, + }, + L2hlbGxvLXdvcmxkLmpz: { + language: 'javascript', + name: 'hello_world.js', + content: ` + const message = 'Hello world'; + + console.log(message) + `, + }, +}; + +export default PipelineEditor; diff --git a/frontend/src/theme.js b/frontend/src/theme.js index e829e6b16..507405048 100644 --- a/frontend/src/theme.js +++ b/frontend/src/theme.js @@ -51,6 +51,9 @@ const createCustomTheme = (mode) => ({ pipelineOnline: '#72B842', pipelineOnlineText: '#2E6707', }, + editorPageBg: { + main: '#F4F6F9', + }, } : { success: { @@ -96,6 +99,9 @@ const createCustomTheme = (mode) => ({ pipelineOnline: '#72B842', pipelineOnlineText: '#72B842', }, + editorPageBg: { + main: 'rgba(14, 25, 40, 1)', + }, }), }, breakpoints: { @@ -125,6 +131,9 @@ const createCustomTheme = (mode) => ({ fontWeight: 900, fontSize: '1.0625rem', }, + h4: { + fontSize: '1.25rem', + }, subtitle1: { fontSize: '.75rem', },