diff --git a/packages/ui/src/components/JobCard/Details/Details.module.css b/packages/ui/src/components/JobCard/Details/Details.module.css index d4107131..013faa79 100644 --- a/packages/ui/src/components/JobCard/Details/Details.module.css +++ b/packages/ui/src/components/JobCard/Details/Details.module.css @@ -19,10 +19,7 @@ flex: 1; max-width: calc(100% - 80px); overflow: hidden; -} - -.tabContent.logs { - overflow: visible; + position: relative; } .tabContent :global(.error) { diff --git a/packages/ui/src/components/JobCard/Details/Details.tsx b/packages/ui/src/components/JobCard/Details/Details.tsx index 7cd7f32c..0d9afb2e 100644 --- a/packages/ui/src/components/JobCard/Details/Details.tsx +++ b/packages/ui/src/components/JobCard/Details/Details.tsx @@ -29,11 +29,7 @@ export const Details = ({ status, job, actions }: DetailsProps) => { ))} -
+
diff --git a/packages/ui/src/components/JobCard/Details/DetailsContent/JobLogs/JobLogs.module.css b/packages/ui/src/components/JobCard/Details/DetailsContent/JobLogs/JobLogs.module.css index fbb95b0e..8e2dd65c 100644 --- a/packages/ui/src/components/JobCard/Details/DetailsContent/JobLogs/JobLogs.module.css +++ b/packages/ui/src/components/JobCard/Details/DetailsContent/JobLogs/JobLogs.module.css @@ -1,37 +1,35 @@ .jobLogs { - margin: 0 10px 0 0; - color: #000; + margin: 0; + overflow: hidden; position: relative; - border-radius: 4px; + background: #fff; } .preWrapper { - padding: 0 15px; - padding-top: 20px; + padding: 40px 1rem 1rem; max-height: 100%; overflow: auto; height: 330px; - background: #FFF; } -.preWrapper span { +.preWrapper ol { display: block; white-space: pre-wrap; word-break: break-all; } -.preWrapper span i { - color: #999; - font-style: normal; +.preWrapper ol li::marker { + color: #a0aec0; + content: attr(data-line-number); } .preWrapper::-webkit-scrollbar { - width: 0.35rem; + width: 0.5rem; } .preWrapper::-webkit-scrollbar-track { padding: 2px; - margin-top: 15px; + background: rgba(255, 255, 255, 0.2); } .preWrapper::-webkit-scrollbar-thumb { @@ -39,68 +37,43 @@ border-radius: 4px; } -.jobLogs:fullscreen .preWrapper { - height: 100%; - padding-top: 55px; - padding-bottom: 10px; -} - -.jobLogs:fullscreen .preWrapper::-webkit-scrollbar { - width: 0.55rem; -} - .toolbar { position: absolute; - top: -30px; - right: 0px; - width: 100%; - background: rgba(255, 255, 255, 0.5); - padding-bottom: 3px; - text-align: right; - z-index: 9; + top: 0; + left: 15px; + right: 15px; + background: rgba(255, 255, 255, 0.85); backdrop-filter: blur(4px); + padding: 0 0 1rem; + margin: 0; + list-style: none; + text-align: right; + z-index: 1; display: flex; } -.jobLogs:fullscreen .toolbar { - position: fixed; - top: 0; - width: 100%; - padding-bottom: 15px; +.toolbar > li:first-child { + flex: 1; } -.toolbar form { - display: inline-block ; +.toolbar > li button { + height: 100%; } -.toolbar button { - margin-left: 1rem; - font-size: 1rem; - padding: 0.65rem; +.toolbar > li + li { + margin-left: 0.5rem; } -.toolbar form { - flex: 1; - text-align: left; -} - -.toolbar .searchBar { - padding: 5px 15px; - border-radius: 4px; - border-bottom-right-radius: 0; - border: none; - outline: none; - width: 100%; - box-shadow: none !important; - border-bottom: 1px solid #e0e7eb; +.jobLogs:fullscreen .toolbar { + position: fixed; + padding: 1rem 0; } -.jobLogs:fullscreen .toolbar .searchBar { - padding: 10px 15px; - font-size: 1.25rem; +.jobLogs:fullscreen .preWrapper { + height: 100%; + padding-top: 1rem !important; } -.toolbar button svg { - width: 0.6rem; - height: 0.6rem; +.toolbar .searchBar { + width: 100%; } diff --git a/packages/ui/src/components/JobCard/Details/DetailsContent/JobLogs/JobLogs.tsx b/packages/ui/src/components/JobCard/Details/DetailsContent/JobLogs/JobLogs.tsx index ca6b8807..856d2988 100644 --- a/packages/ui/src/components/JobCard/Details/DetailsContent/JobLogs/JobLogs.tsx +++ b/packages/ui/src/components/JobCard/Details/DetailsContent/JobLogs/JobLogs.tsx @@ -1,11 +1,11 @@ -/* eslint-disable no-console */ -import React, { SyntheticEvent, useEffect, useState, useRef } from 'react'; import { AppJob } from '@bull-board/api/typings/app'; -import { Button } from '../../../Button/Button'; +import React, { SyntheticEvent, useEffect, useRef, useState } from 'react'; +import { useInterval } from '../../../../../hooks/useInterval'; +import { InputField } from '../../../../Form/InputField/InputField'; import { FullscreenIcon } from '../../../../Icons/Fullscreen'; -import { PlayIcon } from '../../../../Icons/Play'; import { PauseIcon } from '../../../../Icons/Pause'; -import { useInterval } from '../../../../../hooks/useInterval'; +import { PlayIcon } from '../../../../Icons/Play'; +import { Button } from '../../../Button/Button'; import s from './JobLogs.module.css'; interface JobLogsProps { @@ -16,13 +16,13 @@ interface JobLogsProps { } interface LogType { - lineNumber: number; message: string; + lineNumber: number; } -const getLogType = ({ message }: LogType) => { - const msgType = message?.match(/((info|warn|error)?):/i)?.[1] || ''; - return msgType.toLowerCase(); +const getLogType = (log: LogType) => { + const msgType = log.message?.match(/((info|warn|error)?):/i)?.[1]; + return msgType?.toLowerCase(); }; const onClickFullScreen = (el: HTMLElement | null) => async () => { @@ -34,12 +34,9 @@ const shouldShow = (log: LogType, keyword = '') => { return !keyword || new RegExp(`${keyword}`, 'i').test(log.message); }; -const formatLogs = (logs: string[]): LogType[] => { - return logs.map((message, lineNumber) => ({ - message, - lineNumber: lineNumber + 1, - })); -}; +function formatLogs(logs: string[]) { + return logs.map((message, i) => ({ message, lineNumber: i + 1 })); +} export const JobLogs = ({ actions, job }: JobLogsProps) => { const [logs, setLogs] = useState([]); @@ -73,12 +70,14 @@ export const JobLogs = ({ actions, job }: JobLogsProps) => { liveLogs ? 2500 : null ); - const onClickLiveLogsButton = () => { + const toggleLiveLogsButton = () => { setLiveLogs(!liveLogs); }; const onSearch = (event: SyntheticEvent) => { - if (!!!event.currentTarget?.value) setKeyword(''); + if (!event.currentTarget?.value) { + setKeyword(''); + } }; const onSearchSubmit = (event: SyntheticEvent) => { @@ -88,36 +87,47 @@ export const JobLogs = ({ actions, job }: JobLogsProps) => { return (
-
-
- -
+
    +
  • +
    + + +
  • + {!job.finishedOn && ( - +
  • + +
  • )} - -
+
  • + +
  • +
    -          {logs
    -            .filter((log) => shouldShow(log, keyword))
    -            .map((log) => (
    -              
    -                {log.lineNumber} {log.message}
    -              
    -            ))}
    +          
      + {logs + .filter((log) => shouldShow(log, keyword)) + .map((log) => ( +
    1. + {log.message} +
    2. + ))} +