From 7b12591595cdd5144d9311ffa06a80c5dab79364 Mon Sep 17 00:00:00 2001 From: Yury Shkoda Date: Tue, 11 Apr 2023 14:18:42 +0300 Subject: [PATCH] feat(log): use improved log for SAS run time only --- web/src/containers/Studio/editor.tsx | 16 +- .../internal/components/log/logComponent.tsx | 154 ++++++++++-------- .../components/log/logTabWithIcons.tsx | 13 +- .../Studio/internal/hooks/useEditor.ts | 33 +++- web/src/utils/log.ts | 4 +- 5 files changed, 134 insertions(+), 86 deletions(-) diff --git a/web/src/containers/Studio/editor.tsx b/web/src/containers/Studio/editor.tsx index 1ae758c..a65b94d 100644 --- a/web/src/containers/Studio/editor.tsx +++ b/web/src/containers/Studio/editor.tsx @@ -23,6 +23,7 @@ import LogTabWithIcons from './internal/components/log/logTabWithIcons' import { usePrompt } from '../../utils/hooks' import { getLanguageFromExtension } from './internal/helper' import useEditor from './internal/hooks/useEditor' +import { RunTimeType } from '../../context/appContext' const StyledTabPanel = styled(TabPanel)(() => ({ padding: '10px' @@ -110,7 +111,11 @@ const SASjsEditor = ({ /> ) - const logWithErrorsOrWarnings = log?.errors.length || log?.warnings.length + // INFO: variable indicating if selected run type is SAS if there are any errors or warnings in the log + const logWithErrorsOrWarnings = + selectedRunTime === RunTimeType.SAS && + log && + (log?.errors.length !== 0 || log?.warnings.length !== 0) return ( @@ -155,6 +160,11 @@ const SASjsEditor = ({ icon={ logWithErrorsOrWarnings ? : '' } + onClick={() => { + const logWrapper = document.querySelector(`#logWrapper`) + + if (logWrapper) logWrapper.scrollTop = 0 + }} /> - {log && } + {log && ( + + )}
diff --git a/web/src/containers/Studio/internal/components/log/logComponent.tsx b/web/src/containers/Studio/internal/components/log/logComponent.tsx index 2ba1079..4581912 100644 --- a/web/src/containers/Studio/internal/components/log/logComponent.tsx +++ b/web/src/containers/Studio/internal/components/log/logComponent.tsx @@ -6,6 +6,7 @@ import { ListItemText } from '@mui/material' import { makeStyles } from '@mui/styles' import Highlight from 'react-highlight' import { LogObject } from '../../../../../utils' +import { RunTimeType } from '../../../../../context/appContext' const useStyles: any = makeStyles((theme: any) => ({ expansionDescription: { @@ -30,10 +31,11 @@ const useStyles: any = makeStyles((theme: any) => ({ interface LogComponentProps { log: LogObject + selectedRunTime: RunTimeType } const LogComponent = (props: LogComponentProps) => { - const { log } = props + const { log, selectedRunTime } = props const classes = useStyles() @@ -63,77 +65,91 @@ const LogComponent = (props: LogComponentProps) => { } return ( -
-
+ <> + {selectedRunTime === RunTimeType.SAS ? (
-
- } - defaultExpandIcon={} - > - {log?.errors.length && ( - - {`Errors (${log.errors.length})`} - - } + id="logWrapper" + style={{ overflowY: 'auto', maxHeight: 'calc(100vh - 130px)' }} + > +
+
+
+ } + defaultExpandIcon={} > - {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)} - /> - ))} - - )} - -
-
+ {log?.errors.length !== 0 && ( + + {`Errors (${log.errors.length})`} + + } + > + {log.errors && + log.errors.map((error, ind) => ( + } + key={`error_${ind}`} + onClick={() => goToLogLine('error', ind)} + /> + ))} + + )} + {log?.warnings.length !== 0 && ( + {`Warnings (${log.warnings.length})`} + } + > + {log.warnings && + log.warnings.map((warning, ind) => ( + } + key={`warning_${ind}`} + onClick={() => goToLogLine('warning', ind)} + /> + ))} + + )} +
+
+
- - - {decodeHtml(log?.body || '')} - - -
+ + + {decodeHtml(log?.body || '')} + + +
+ ) : ( +
+

Log

+
+            {log}
+          
+
+ )} + ) } diff --git a/web/src/containers/Studio/internal/components/log/logTabWithIcons.tsx b/web/src/containers/Studio/internal/components/log/logTabWithIcons.tsx index d4c3779..8b825fe 100644 --- a/web/src/containers/Studio/internal/components/log/logTabWithIcons.tsx +++ b/web/src/containers/Studio/internal/components/log/logTabWithIcons.tsx @@ -16,15 +16,14 @@ const LogTabWithIcons = (props: LogTabProps) => { gap: 6, alignItems: 'center' }} - onClick={() => { - const logWrapper = document.querySelector(`#logWrapper`) - - if (logWrapper) logWrapper.scrollTop = 0 - }} > log - {errors.length && } - {warnings.length && }{' '} + {errors.length !== 0 && ( + + )} + {warnings.length !== 0 && ( + + )}{' '} ) } diff --git a/web/src/containers/Studio/internal/hooks/useEditor.ts b/web/src/containers/Studio/internal/hooks/useEditor.ts index 43bcba2..d135982 100644 --- a/web/src/containers/Studio/internal/hooks/useEditor.ts +++ b/web/src/containers/Studio/internal/hooks/useEditor.ts @@ -18,6 +18,7 @@ import { useSnackbar, useStateWithCallback } from '../../../../utils/hooks' +import { parseErrorsAndWarnings, LogObject } from '../../../../utils' const SASJS_LOGS_SEPARATOR = 'SASJS_LOGS_SEPARATOR_163ee17b6ff24f028928972d80a26784' @@ -41,10 +42,12 @@ const useEditor = ({ const [prevFileContent, setPrevFileContent] = useStateWithCallback('') const [fileContent, setFileContent] = useState('') - const [log, setLog] = useState('') + const [log, setLog] = useState() const [webout, setWebout] = useState('') const [runTimes, setRunTimes] = useState([]) - const [selectedRunTime, setSelectedRunTime] = useState('') + const [selectedRunTime, setSelectedRunTime] = useState( + RunTimeType.SAS + ) const [selectedFileExtension, setSelectedFileExtension] = useState('') const [openFilePathInputModal, setOpenFilePathInputModal] = useState(false) const [showDiff, setShowDiff] = useState(false) @@ -150,6 +153,13 @@ const useEditor = ({ const runCode = useCallback( (code: string) => { setIsLoading(true) + + // Scroll to bottom of log + const logElement = document.getElementById('log') + if (logElement) logElement.scrollTop = logElement.scrollHeight + + setIsLoading(false) + axios .post(`/SASjsApi/code/execute`, { code: programPathInjection( @@ -160,8 +170,18 @@ const useEditor = ({ runTime: selectedRunTime }) .then((res: any) => { + const { errors, warnings, logLines } = parseErrorsAndWarnings( + res.data.split(SASJS_LOGS_SEPARATOR)[1] + ) + + const log: LogObject = { + body: logLines.join(`\n`), + errors, + warnings + } + setWebout(res.data.split(SASJS_LOGS_SEPARATOR)[0] ?? '') - setLog(res.data.split(SASJS_LOGS_SEPARATOR)[1] ?? '') + setLog(log) setTab('log') // Scroll to bottom of log @@ -249,7 +269,7 @@ const useEditor = ({ }, [appContext.runTimes]) useEffect(() => { - if (runTimes.length) setSelectedRunTime(runTimes[0]) + if (runTimes.length) setSelectedRunTime(runTimes[0] as RunTimeType) }, [runTimes]) useEffect(() => { @@ -280,7 +300,6 @@ const useEditor = ({ const content = localStorage.getItem('fileContent') ?? '' setFileContent(content) } - setLog('') setWebout('') setTab('code') // eslint-disable-next-line react-hooks/exhaustive-deps @@ -294,7 +313,9 @@ const useEditor = ({ useEffect(() => { const fileExtension = selectedFileExtension.toLowerCase() - if (runTimes.includes(fileExtension)) setSelectedRunTime(fileExtension) + + if (runTimes.includes(fileExtension)) + setSelectedRunTime(fileExtension as RunTimeType) }, [selectedFileExtension, runTimes]) return { diff --git a/web/src/utils/log.ts b/web/src/utils/log.ts index a69ffe4..4b8cc59 100644 --- a/web/src/utils/log.ts +++ b/web/src/utils/log.ts @@ -15,7 +15,7 @@ export const parseErrorsAndWarnings = (log: string) => { errorLines.push(line) logLines[index] = - `` + + `` + logLines[index] + '' } @@ -31,7 +31,7 @@ export const parseErrorsAndWarnings = (log: string) => { warningLines.push(line) logLines[index] = - `` + + `` + logLines[index] + '' }