diff --git a/web/src/containers/Studio/editor.tsx b/web/src/containers/Studio/editor.tsx index 6a1b042..1ae758c 100644 --- a/web/src/containers/Studio/editor.tsx +++ b/web/src/containers/Studio/editor.tsx @@ -1,4 +1,4 @@ -import React, { Dispatch, SetStateAction } from 'react' +import { Dispatch, SetStateAction } from 'react' import { Backdrop, @@ -17,6 +17,8 @@ import { TabContext, TabList, TabPanel } from '@mui/lab' import FilePathInputModal from '../../components/filePathInputModal' import FileMenu from './internal/components/fileMenu' import RunMenu from './internal/components/runMenu' +import LogComponent from './internal/components/log/logComponent' +import LogTabWithIcons from './internal/components/log/logTabWithIcons' import { usePrompt } from '../../utils/hooks' import { getLanguageFromExtension } from './internal/helper' @@ -108,6 +110,8 @@ const SASjsEditor = ({ /> ) + const logWithErrorsOrWarnings = log?.errors.length || log?.warnings.length + return ( - + : '' + } + /> @@ -195,15 +205,7 @@ const SASjsEditor = ({ -
-

Log

-
-                {log}
-              
-
+ {log && }
diff --git a/web/src/containers/Studio/internal/components/log/logComponent.tsx b/web/src/containers/Studio/internal/components/log/logComponent.tsx new file mode 100644 index 0000000..2ba1079 --- /dev/null +++ b/web/src/containers/Studio/internal/components/log/logComponent.tsx @@ -0,0 +1,140 @@ +import TreeView from '@mui/lab/TreeView' +import TreeItem from '@mui/lab/TreeItem' +import { ChevronRight, ExpandMore } from '@mui/icons-material' +import { Typography } from '@mui/material' +import { ListItemText } from '@mui/material' +import { makeStyles } from '@mui/styles' +import Highlight from 'react-highlight' +import { LogObject } from '../../../../../utils' + +const useStyles: any = makeStyles((theme: any) => ({ + expansionDescription: { + backgroundColor: '#fbfbfb', + border: '1px solid #e2e2e2', + borderRadius: '3px', + minHeight: '50px', + padding: '10px', + boxSizing: 'border-box', + whiteSpace: 'pre-wrap', + fontFamily: 'Monaco, Courier, monospace', + position: 'relative', + width: '100%', + [theme.breakpoints.down('sm')]: { + fontSize: theme.typography.pxToRem(12) + }, + [theme.breakpoints.up('md')]: { + fontSize: theme.typography.pxToRem(16) + } + } +})) + +interface LogComponentProps { + log: LogObject +} + +const LogComponent = (props: LogComponentProps) => { + const { log } = props + + const classes = useStyles() + + const goToLogLine = (type: 'error' | 'warning', ind: number) => { + const line = document.getElementById(`${type}_${ind}`) + const logWrapper: HTMLDivElement | null = + document.querySelector(`#logWrapper`) + const logContainer: HTMLHeadElement | null = + document.querySelector(`#log_container`) + + if (line && logWrapper && logContainer) { + line.style.backgroundColor = '#f6e30599' + logWrapper.scrollTop = + line.offsetTop - logWrapper.offsetTop + logContainer.offsetTop + + setTimeout(() => { + line.setAttribute('style', '') + }, 3000) + } + } + + const decodeHtml = (encodedString: string) => { + const tempElement = document.createElement('textarea') + tempElement.innerHTML = encodedString + + return tempElement.value + } + + return ( +
+
+
+
+ } + defaultExpandIcon={} + > + {log?.errors.length && ( + + {`Errors (${log.errors.length})`} + + } + > + {log.errors && + log.errors.map((error, ind) => ( + } + key={`error_${ind}`} + onClick={() => goToLogLine('error', ind)} + /> + ))} + + )} + {log?.warnings.length && ( + {`Warnings (${log.warnings.length})`} + } + > + {log.warnings && + log.warnings.map((warning, ind) => ( + } + key={`warning_${ind}`} + onClick={() => goToLogLine('warning', ind)} + /> + ))} + + )} + +
+
+ + + + {decodeHtml(log?.body || '')} + + +
+ ) +} + +export default LogComponent diff --git a/web/src/containers/Studio/internal/components/log/logTabWithIcons.tsx b/web/src/containers/Studio/internal/components/log/logTabWithIcons.tsx new file mode 100644 index 0000000..d4c3779 --- /dev/null +++ b/web/src/containers/Studio/internal/components/log/logTabWithIcons.tsx @@ -0,0 +1,32 @@ +import { ErrorOutline, Warning } from '@mui/icons-material' +import { LogObject } from '../../../../../utils' + +interface LogTabProps { + log: LogObject +} + +const LogTabWithIcons = (props: LogTabProps) => { + const { errors, warnings } = props.log + + return ( +
{ + const logWrapper = document.querySelector(`#logWrapper`) + + if (logWrapper) logWrapper.scrollTop = 0 + }} + > + log + {errors.length && } + {warnings.length && }{' '} +
+ ) +} + +export default LogTabWithIcons