From deac8346ad9c6cb6d70f1508db66982def5063f6 Mon Sep 17 00:00:00 2001 From: Rohit Kini Date: Mon, 15 Jul 2024 17:03:03 +0530 Subject: [PATCH] logger magnify demagnify functionality --- api/src/config/dev.config.ts | 4 +- api/src/config/prod.config.ts | 2 + api/src/server.ts | 13 ++- ui/src/common/assets/icons.tsx | 19 +++- ui/src/components/LogScreen/index.scss | 62 ++++++----- ui/src/components/LogScreen/index.tsx | 139 ++++++++++++++++++------- 6 files changed, 176 insertions(+), 63 deletions(-) diff --git a/api/src/config/dev.config.ts b/api/src/config/dev.config.ts index 86cf81918..00f69565a 100644 --- a/api/src/config/dev.config.ts +++ b/api/src/config/dev.config.ts @@ -10,4 +10,6 @@ export const devConfig = { AZURE_NA: "https://azure-na-app.contentstack.com/#!", AZURE_EU: "https://azure-eu-app.contentstack.com/#!", }, -}; + LOG_FILE_PATH: + process.platform === "win32" ? ".\\combine.log" : "./combine.log", // Replace with the actual path to your log file +}; \ No newline at end of file diff --git a/api/src/config/prod.config.ts b/api/src/config/prod.config.ts index 2a124479d..7a49fdbd9 100644 --- a/api/src/config/prod.config.ts +++ b/api/src/config/prod.config.ts @@ -11,4 +11,6 @@ export const prodConfig = { AZURE_NA: "https://azure-na-app.contentstack.com/#!", AZURE_EU: "https://azure-eu-app.contentstack.com/#!", }, + LOG_FILE_PATH: + process.platform === "win32" ? ".\\combine.log" : "./combine.log", // Replace with the actual path to your log file }; diff --git a/api/src/server.ts b/api/src/server.ts index 678121afd..7e9f0cf42 100644 --- a/api/src/server.ts +++ b/api/src/server.ts @@ -20,6 +20,7 @@ import chokidar from "chokidar"; import { Server } from "socket.io"; import http from "http"; import fs from "fs"; + try { const app = express(); app.use( @@ -55,9 +56,17 @@ try { logger.info(`Server listening at port ${config.PORT}`) ); // Chokidar - Watch for log file changes - const logFilePath = "/Users/sayali.joshi/Projects/migration-v2-node-server/api/combine.log"; // Replace with the actual path to your log file + const logFilePath = config.LOG_FILE_PATH; const watcher = chokidar.watch(logFilePath); // Socket.IO - Send logs to client + /** + * The Socket.IO server instance. + * + * @remarks + * This server instance is responsible for handling real-time communication between the client and the server using the Socket.IO library. + * + * @type {Server} + */ const io = new Server( server, (http, @@ -94,4 +103,4 @@ try { } catch (e) { logger.error("Error while starting the server!"); logger.error(e); -} +} \ No newline at end of file diff --git a/ui/src/common/assets/icons.tsx b/ui/src/common/assets/icons.tsx index 179668e2e..0b7f5d6c0 100644 --- a/ui/src/common/assets/icons.tsx +++ b/ui/src/common/assets/icons.tsx @@ -770,4 +770,21 @@ export const LOG_OUT = ( -); \ No newline at end of file +); + +export const MAGNIFY = ( + + + + +); + +export const DEMAGNIFY = ( + + + + + +); + + diff --git a/ui/src/components/LogScreen/index.scss b/ui/src/components/LogScreen/index.scss index 479c674b6..ae1c11f22 100644 --- a/ui/src/components/LogScreen/index.scss +++ b/ui/src/components/LogScreen/index.scss @@ -1,4 +1,7 @@ @import '../../scss/variables'; +/** + * Styles for the LogScreen component. + */ .logs-container { font-family: Arial, sans-serif; @@ -8,8 +11,13 @@ margin: 0 $px-24 $px-24; position: relative; } + .logs-wrapper { position: relative; + + /** + * Styles for the action items within the LogScreen component. + */ .action-items { position: absolute; right: 48px; @@ -17,13 +25,16 @@ } } - +/** + * Styles for each log entry within the LogScreen component. + */ .log-entry { align-items: center; background-color: $color-base-white-10; display: flex; padding: 5px 0; position: relative; + &::before { background-color: $color-base-white-5; border-right: 1px solid $color-brand-secondary-lightest; @@ -36,30 +47,33 @@ width: 50px; } - .log-number, .log-time, .log-message { + /** + * Styles for the log number within each log entry. + */ + .log-number { + text-align: center; + min-width: 50px; + color: $color-font-active; + position: relative; + } + + /** + * Styles for the log time within each log entry. + */ + .log-time { + color: $color-font-active; font-family: "IBM Plex Mono", monospace; font-size: $size-font-medium; font-weight: $font-weight-medium; + padding: 0 $px-16; } -} - -.log-number { - text-align: center; - min-width: 50px; - color: $color-font-active; - position: relative; -} - -.log-time { - color: $color-font-active; - font-family: "IBM Plex Mono", monospace; - font-size: $size-font-medium; - font-weight: $font-weight-medium; - padding: 0 $px-16; -} - -.log-message { - color: $color-black-222; - flex-grow: 1; - padding: 0 $px-16; -} + + /** + * Styles for the log message within each log entry. + */ + .log-message { + color: $color-black-222; + flex-grow: 1; + padding: 0 $px-16; + } +} \ No newline at end of file diff --git a/ui/src/components/LogScreen/index.tsx b/ui/src/components/LogScreen/index.tsx index 81a601603..66170972e 100644 --- a/ui/src/components/LogScreen/index.tsx +++ b/ui/src/components/LogScreen/index.tsx @@ -1,11 +1,13 @@ // Libraries -import React, { useEffect, useState, useRef } from 'react'; +import React, { useEffect, useState } from 'react'; import { Icon } from '@contentstack/venus-components'; import io from 'socket.io-client'; // CSS import './index.scss'; +import { MAGNIFY,DEMAGNIFY } from '../../common/assets'; + const logStyles: { [key: string]: React.CSSProperties } = { info: { backgroundColor: '#f1f1f1' }, warn: { backgroundColor: '#ffeeba', color: '#856404' }, @@ -17,61 +19,128 @@ type LogsType = { serverPath: string; } -const LogViewer = ({serverPath}: LogsType) => { +/** + * LogViewer component displays logs received from the server. + * @param {string} serverPath - The path of the server to connect to. + */ +const LogViewer = ({ serverPath }: LogsType) => { const [logs, setLogs] = useState(["Loading logs..."]); useEffect(() => { const socket = io(serverPath || ''); // Connect to the server + + /** + * Event listener for 'logUpdate' event. + * @param {string} newLogs - The new logs received from the server. + */ socket.on('logUpdate', (newLogs: string) => { - console.log("new logs", newLogs); - + // console.log("new logs", newLogs); const logArray = newLogs.split('\n'); - console.log(logArray); + // console.log(logArray); setLogs(logArray); - }); - + return () => { socket.disconnect(); // Cleanup on component unmount }; }, []); - - //SCROLL LISTENER - useEffect(() => { - window.addEventListener("scroll", handleScrollToTop); - }); - const refScrollUp = useRef(null); + /** + * Scrolls to the top of the logs container. + */ const handleScrollToTop = () => { - console.log("=============", refScrollUp, refScrollUp?.current); - - refScrollUp?.current?.scrollIntoView({ behavior: "smooth" }); + const logsContainer = document.querySelector('.logs-container'); + if (logsContainer) { + logsContainer.scrollTo({ + top: 0, + behavior: 'smooth', + }); + } + } + + /** + * Scrolls to the bottom of the logs container. + */ + const handleScrollToBottom = () => { + const logsContainer = document.querySelector('.logs-container'); + if (logsContainer) { + logsContainer.scrollTo({ + top: logsContainer.scrollHeight, + behavior: 'smooth', + }); + } } + + /** + * Copies the logs to the clipboard. + */ + const handleCopyLogs = () => { + const logsContainer = document.querySelector('.logs-container'); + if (logsContainer) { + const range = document.createRange(); + range.selectNode(logsContainer); + window.getSelection()?.removeAllRanges(); + window.getSelection()?.addRange(range); + navigator.clipboard.writeText(logsContainer.textContent || ''); + window.getSelection()?.removeAllRanges(); + } + } + + const [zoomLevel, setZoomLevel] = useState(1); + + /** + * Zooms in the logs container. + */ + const handleZoomIn = () => { + const logsContainer = document.querySelector('.logs-magnify') as HTMLElement; + if (logsContainer) { + setZoomLevel(prevZoomLevel => prevZoomLevel + 0.1); + logsContainer.style.transform = `scale(${zoomLevel})`; + } + }; + + /** + * Zooms out the logs container. + */ + const handleZoomOut = () => { + const logsContainer = document.querySelector('.logs-magnify') as HTMLElement; + if (logsContainer) { + setZoomLevel(prevZoomLevel => prevZoomLevel - 0.1); + logsContainer.style.transform = `scale(${zoomLevel})`; + } + }; + return (
- {logs?.map((log, index) => { - console.log(log); - try { - const logObject = JSON.parse(log); - const level = logObject.level; - const timestamp = logObject.timestamp; - const message = logObject.message; - return ( -
-
{index}
-
{new Date(timestamp).toTimeString().split(' ')[0]}
-
{message}
-
- ); - } catch (error) { - console.error('Invalid JSON string', error); - } - })} - +
+ {logs?.map((log, index) => { + // console.log(log); + try { + const logObject = JSON.parse(log); + const level = logObject.level; + const timestamp = logObject.timestamp; + const message = logObject.message; + return ( +
+
{index}
+
{new Date(timestamp).toTimeString().split(' ')[0]}
+
{message}
+
+ ); + } catch (error) { + console.error('Invalid JSON string', error); + } + })} +
+ + {MAGNIFY} + {DEMAGNIFY} + +
);