From 370af54d5ab11606315abd8fabcef5acc76440d9 Mon Sep 17 00:00:00 2001 From: Dave Marco Date: Tue, 24 Sep 2024 17:55:09 +0000 Subject: [PATCH 01/31] first draft --- .../src/components/Editor/index.tsx | 20 +---- .../src/components/MenuBar/NavigationBar.tsx | 10 +-- .../src/components/MenuBar/PageNumInput.tsx | 3 +- .../src/contexts/StateContextProvider.tsx | 73 ++++++++++++------- new-log-viewer/src/services/LogFileManager.ts | 30 ++++++++ new-log-viewer/src/typings/worker.ts | 14 +++- new-log-viewer/src/utils/actions.ts | 42 +---------- new-log-viewer/src/utils/math.ts | 29 -------- 8 files changed, 97 insertions(+), 124 deletions(-) diff --git a/new-log-viewer/src/components/Editor/index.tsx b/new-log-viewer/src/components/Editor/index.tsx index 88d0c46d..5c52d307 100644 --- a/new-log-viewer/src/components/Editor/index.tsx +++ b/new-log-viewer/src/components/Editor/index.tsx @@ -24,7 +24,6 @@ import {BeginLineNumToLogEventNumMap} from "../../typings/worker"; import { ACTION_NAME, EDITOR_ACTIONS, - handleAction, } from "../../utils/actions"; import { CONFIG_DEFAULT, @@ -63,7 +62,7 @@ const resetCachedPageSize = () => { const Editor = () => { const {mode, systemMode} = useColorScheme(); - const {beginLineNumToLogEventNum, logData, numEvents} = useContext(StateContext); + const {beginLineNumToLogEventNum, logData, loadPage} = useContext(StateContext); const {logEventNum} = useContext(UrlContext); const [lineNum, setLineNum] = useState(1); @@ -72,23 +71,18 @@ const Editor = () => { ); const editorRef = useRef>(null); const isMouseDownRef = useRef(false); - const logEventNumRef = useRef>(logEventNum); - const numEventsRef = useRef>(numEvents); const pageSizeRef = useRef(getConfig(CONFIG_KEY.PAGE_SIZE)); const handleEditorCustomAction = useCallback(( editor: monaco.editor.IStandaloneCodeEditor, actionName: ACTION_NAME ) => { - if (null === logEventNumRef.current || null === numEventsRef.current) { - return; - } switch (actionName) { case ACTION_NAME.FIRST_PAGE: case ACTION_NAME.PREV_PAGE: case ACTION_NAME.NEXT_PAGE: case ACTION_NAME.LAST_PAGE: - handleAction(actionName, logEventNumRef.current, numEventsRef.current); + loadPage(ACTION_NAME.LAST_PAGE); break; case ACTION_NAME.PAGE_TOP: goToPositionAndCenter(editor, {lineNumber: 1, column: 1}); @@ -162,16 +156,6 @@ const Editor = () => { beginLineNumToLogEventNumRef.current = beginLineNumToLogEventNum; }, [beginLineNumToLogEventNum]); - // Synchronize `logEventNumRef` with `logEventNum`. - useEffect(() => { - logEventNumRef.current = logEventNum; - }, [logEventNum]); - - // Synchronize `numEventsRef` with `numEvents`. - useEffect(() => { - numEventsRef.current = numEvents; - }, [numEvents]); - // On `logEventNum` update, update line number in the editor. useEffect(() => { if (null === editorRef.current || isMouseDownRef.current) { diff --git a/new-log-viewer/src/components/MenuBar/NavigationBar.tsx b/new-log-viewer/src/components/MenuBar/NavigationBar.tsx index a519af30..0edd0d3b 100644 --- a/new-log-viewer/src/components/MenuBar/NavigationBar.tsx +++ b/new-log-viewer/src/components/MenuBar/NavigationBar.tsx @@ -6,10 +6,8 @@ import SkipNext from "@mui/icons-material/SkipNext"; import SkipPrevious from "@mui/icons-material/SkipPrevious"; import {StateContext} from "../../contexts/StateContextProvider"; -import {UrlContext} from "../../contexts/UrlContextProvider"; import { ACTION_NAME, - handleAction, } from "../../utils/actions"; import PageNumInput from "./PageNumInput"; import SmallIconButton from "./SmallIconButton"; @@ -21,16 +19,12 @@ import SmallIconButton from "./SmallIconButton"; * @return */ const NavigationBar = () => { - const {numEvents} = useContext(StateContext); - const {logEventNum} = useContext(UrlContext); + const {loadPage} = useContext(StateContext); const handleNavButtonClick = (event: React.MouseEvent) => { - if (null === logEventNum) { - return; - } const {actionName} = event.currentTarget.dataset as { actionName: ACTION_NAME }; if (Object.values(ACTION_NAME).includes(actionName)) { - handleAction(actionName, logEventNum, numEvents); + loadPage(actionName); } }; diff --git a/new-log-viewer/src/components/MenuBar/PageNumInput.tsx b/new-log-viewer/src/components/MenuBar/PageNumInput.tsx index 33da7e4a..0e381d92 100644 --- a/new-log-viewer/src/components/MenuBar/PageNumInput.tsx +++ b/new-log-viewer/src/components/MenuBar/PageNumInput.tsx @@ -8,6 +8,7 @@ import React, { import {Typography} from "@mui/joy"; import Input from "@mui/joy/Input"; +import {ACTION_NAME} from "../../utils/actions"; import {StateContext} from "../../contexts/StateContextProvider"; import "./PageNumInput.css"; @@ -38,7 +39,7 @@ const PageNumInput = () => { return; } - loadPage(Number(inputRef.current.value)); + loadPage(ACTION_NAME.SPECIFIC_PAGE, Number(inputRef.current.value)); setIsEditing(false); }; diff --git a/new-log-viewer/src/contexts/StateContextProvider.tsx b/new-log-viewer/src/contexts/StateContextProvider.tsx index 5d506d2c..cb1044ce 100644 --- a/new-log-viewer/src/contexts/StateContextProvider.tsx +++ b/new-log-viewer/src/contexts/StateContextProvider.tsx @@ -15,12 +15,14 @@ import { CURSOR_CODE, CursorType, FileSrcType, + LOG_EVENT_ANCHOR, MainWorkerRespMessage, WORKER_REQ_CODE, WORKER_RESP_CODE, WorkerReq, } from "../typings/worker"; import {getConfig} from "../utils/config"; +import {ACTION_NAME} from "../utils/actions"; import { clamp, getChunkNum, @@ -33,16 +35,15 @@ import { UrlContext, } from "./UrlContextProvider"; - interface StateContextType { beginLineNumToLogEventNum: BeginLineNumToLogEventNumMap, fileName: string, loadFile: (fileSrc: FileSrcType, cursor: CursorType) => void, - loadPage: (newPageNum: number) => void, + loadPage: (action: ACTION_NAME, specificPageNum?: Nullable) => void, logData: string, numEvents: number, numPages: number, - pageNum: Nullable + pageNum: number, } const StateContext = createContext({} as StateContextType); @@ -85,22 +86,6 @@ const updateLogEventNumInUrl = ( }); }; -/** - * Gets the last log event number from a map of begin line numbers to log event numbers. - * - * @param beginLineNumToLogEventNum - * @return The last log event number. - */ -const getLastLogEventNum = (beginLineNumToLogEventNum: BeginLineNumToLogEventNumMap) => { - const allLogEventNums = Array.from(beginLineNumToLogEventNum.values()); - let lastLogEventNum = allLogEventNums.at(-1); - if ("undefined" === typeof lastLogEventNum) { - lastLogEventNum = 1; - } - - return lastLogEventNum; -}; - /** * Sends a post message to a worker with the given code and arguments. This wrapper around * `worker.postMessage()` ensures type safety for both the request code and its corresponding @@ -137,7 +122,7 @@ const StateContextProvider = ({children}: StateContextProviderProps) => { useRef(STATE_DEFAULT.beginLineNumToLogEventNum); const logEventNumRef = useRef(logEventNum); const numPagesRef = useRef(STATE_DEFAULT.numPages); - const pageNumRef = useRef>(STATE_DEFAULT.pageNum); + const pageNumRef = useRef(STATE_DEFAULT.pageNum); const mainWorkerRef = useRef(null); @@ -152,8 +137,7 @@ const StateContextProvider = ({children}: StateContextProviderProps) => { case WORKER_RESP_CODE.PAGE_DATA: { setLogData(args.logs); beginLineNumToLogEventNumRef.current = args.beginLineNumToLogEventNum; - const lastLogEventNum = getLastLogEventNum(args.beginLineNumToLogEventNum); - updateLogEventNumInUrl(lastLogEventNum, logEventNumRef.current); + updateLogEventNumInUrl(numEvents, args.newLogEventNum); break; } case WORKER_RESP_CODE.NOTIFICATION: @@ -189,14 +173,51 @@ const StateContextProvider = ({children}: StateContextProviderProps) => { handleMainWorkerResp, ]); - const loadPage = (newPageNum: number) => { + const loadPage = (action: ACTION_NAME, specificPageNum: Nullable = null) => { if (null === mainWorkerRef.current) { console.error("Unexpected null mainWorkerRef.current"); + return; + } + if (null === specificPageNum && action !== ACTION_NAME.SPECIFIC_PAGE) { + console.error(`Unexpected page number provided to page action ${action}`); return; } + + if (STATE_DEFAULT.pageNum == pageNumRef.current) { + console.error(`Page actions cannot be executed if the current page is not set.`); + return; + } + + let newPageNum: number; + let anchor: LOG_EVENT_ANCHOR = LOG_EVENT_ANCHOR.FIRST; + + switch (action) { + case ACTION_NAME.SPECIFIC_PAGE: + // specificPageNum cannot be null, since already checked during validation. + newPageNum = specificPageNum!; + break; + case ACTION_NAME.FIRST_PAGE: + newPageNum = 1; + break; + case ACTION_NAME.PREV_PAGE: + anchor = LOG_EVENT_ANCHOR.LAST + newPageNum = clamp(pageNumRef.current - 1, 1, numPagesRef.current); + break; + case ACTION_NAME.NEXT_PAGE: + newPageNum = clamp(pageNumRef.current + 1, 1, numPagesRef.current); + break; + case ACTION_NAME.LAST_PAGE: + anchor = LOG_EVENT_ANCHOR.LAST + newPageNum = numPagesRef.current; + break; + default: + console.error(`Behaviour for action ${action} is not yet defined.`); + return; + } + workerPostReq(mainWorkerRef.current, WORKER_REQ_CODE.LOAD_PAGE, { - cursor: {code: CURSOR_CODE.PAGE_NUM, args: {pageNum: newPageNum}}, + cursor: {code: CURSOR_CODE.PAGE_NUM, args: {pageNum: newPageNum, logEventAnchor: anchor}}, decoderOptions: getConfig(CONFIG_KEY.DECODER_OPTIONS), }); }; @@ -236,7 +257,7 @@ const StateContextProvider = ({children}: StateContextProviderProps) => { // NOTE: We don't need to call `updateLogEventNumInUrl()` since it's called when // handling the `WORKER_RESP_CODE.PAGE_DATA` response (the response to // `WORKER_REQ_CODE.LOAD_PAGE` requests) . - loadPage(newPageNum); + loadPage(ACTION_NAME.SPECIFIC_PAGE, newPageNum); } } @@ -262,7 +283,7 @@ const StateContextProvider = ({children}: StateContextProviderProps) => { 1 ); - cursor = {code: CURSOR_CODE.PAGE_NUM, args: {pageNum: newPageNum}}; + cursor = {code: CURSOR_CODE.PAGE_NUM, args: {pageNum: newPageNum, logEventAnchor:LOG_EVENT_ANCHOR.FIRST}}; } loadFile(filePath, cursor); }, [ diff --git a/new-log-viewer/src/services/LogFileManager.ts b/new-log-viewer/src/services/LogFileManager.ts index ea73d7fa..9f1bfc3e 100644 --- a/new-log-viewer/src/services/LogFileManager.ts +++ b/new-log-viewer/src/services/LogFileManager.ts @@ -9,6 +9,7 @@ import { CURSOR_CODE, CursorType, FileSrcType, + LOG_EVENT_ANCHOR, } from "../typings/worker"; import {getUint8ArrayFrom} from "../utils/http"; import {getChunkNum} from "../utils/math"; @@ -164,6 +165,7 @@ class LogFileManager { logs: string, beginLineNumToLogEventNum: BeginLineNumToLogEventNumMap, cursorLineNum: number + newLogEventNum: number } { console.debug(`loadPage: cursor=${JSON.stringify(cursor)}`); @@ -191,10 +193,13 @@ class LogFileManager { currentLine += msg.split("\n").length - 1; }); + const newLogEventNum: number = this.#getNewLogEventNum(cursor, beginLineNumToLogEventNum) + return { logs: messages.join(""), beginLineNumToLogEventNum: beginLineNumToLogEventNum, cursorLineNum: 1, + newLogEventNum: newLogEventNum, }; } @@ -228,6 +233,31 @@ class LogFileManager { const endLogEventNum = Math.min(this.#numEvents, beginLogEventNum + this.#pageSize - 1); return {beginLogEventNum, endLogEventNum}; } + + /** + * Gets the range of log event numbers for the page containing the given cursor. + * + * @param cursor The cursor object containing the code and arguments. + * @return The range. + * @throws {Error} if the type of cursor is not supported. + */ + #getNewLogEventNum (cursor: CursorType, beginLineNumToLogEventNum: BeginLineNumToLogEventNumMap): number { + const {code, args} = cursor; + const logEventNumOnPage: number[] = Array.from(beginLineNumToLogEventNum.values()); + let NewLogEventNum: number|undefined = logEventNumOnPage.at(0); + + if (CURSOR_CODE.PAGE_NUM === code) { + if (args.logEventAnchor = LOG_EVENT_ANCHOR.FIRST) { + NewLogEventNum = logEventNumOnPage.at(-1); + } + } + + if (NewLogEventNum === undefined) { + throw Error("Could not find Log Event on page") + } + + return NewLogEventNum + } } export default LogFileManager; diff --git a/new-log-viewer/src/typings/worker.ts b/new-log-viewer/src/typings/worker.ts index 0c88beb6..46c1705f 100644 --- a/new-log-viewer/src/typings/worker.ts +++ b/new-log-viewer/src/typings/worker.ts @@ -7,11 +7,19 @@ import {LOG_LEVEL} from "./logs"; */ type FileSrcType = string | File; +/** + * Whether returned page should be anchored to top or bottom. + */ +enum LOG_EVENT_ANCHOR { + FIRST = "first", + LAST = "last", +} + /** * Enum of cursors used for locating some log event and navigating across pages. * - LAST_EVENT: the last event * - TIMESTAMP: the first event that has a timestamp >= the given value - * - PAGE_NUM: the first event on the given page + * - PAGE_NUM: the first or last event on the given page */ enum CURSOR_CODE { LAST_EVENT = "lastEvent", @@ -22,7 +30,7 @@ enum CURSOR_CODE { type CursorArgMap = { [CURSOR_CODE.LAST_EVENT]: null; [CURSOR_CODE.TIMESTAMP]: { timestamp: number }; - [CURSOR_CODE.PAGE_NUM]: { pageNum: number }; + [CURSOR_CODE.PAGE_NUM]: { pageNum: number, logEventAnchor: LOG_EVENT_ANCHOR; }; }; type CursorType = { @@ -70,6 +78,7 @@ type WorkerRespMap = { logs: string, beginLineNumToLogEventNum: BeginLineNumToLogEventNumMap, cursorLineNum: number + newLogEventNum: number }, [WORKER_RESP_CODE.NOTIFICATION]: { logLevel: LOG_LEVEL, @@ -95,6 +104,7 @@ type MainWorkerRespMessage = { export { CURSOR_CODE, + LOG_EVENT_ANCHOR, WORKER_REQ_CODE, WORKER_RESP_CODE, }; diff --git a/new-log-viewer/src/utils/actions.ts b/new-log-viewer/src/utils/actions.ts index cded5069..c0c53d49 100644 --- a/new-log-viewer/src/utils/actions.ts +++ b/new-log-viewer/src/utils/actions.ts @@ -1,16 +1,9 @@ import * as monaco from "monaco-editor/esm/vs/editor/editor.api.js"; -import {updateWindowUrlHashParams} from "../contexts/UrlContextProvider"; import {Nullable} from "../typings/common"; -import {CONFIG_KEY} from "../typings/config"; -import {getConfig} from "./config"; -import { - getFirstItemNumInNextChunk, - getLastItemNumInPrevChunk, -} from "./math"; - enum ACTION_NAME { + SPECIFIC_PAGE = "specificPage", FIRST_PAGE = "firstPage", PREV_PAGE = "prevPage", NEXT_PAGE = "nextPage", @@ -67,42 +60,11 @@ const EDITOR_ACTIONS : ActionType[] = [ keyBindings: [monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyI], }, ]; -/* eslint-enable sort-keys */ -/** - * Handles an action based on the given action name, log event number, and total number of events. - * - * @param actionName - * @param logEventNum - * @param numEvents - */ -const handleAction = (actionName: ACTION_NAME, logEventNum: number, numEvents: number) => { - const pageSize = getConfig(CONFIG_KEY.PAGE_SIZE); - switch (actionName) { - case ACTION_NAME.FIRST_PAGE: - updateWindowUrlHashParams({logEventNum: 1}); - break; - case ACTION_NAME.PREV_PAGE: - updateWindowUrlHashParams({ - logEventNum: getLastItemNumInPrevChunk(logEventNum, pageSize), - }); - break; - case ACTION_NAME.NEXT_PAGE: - updateWindowUrlHashParams({ - logEventNum: getFirstItemNumInNextChunk(logEventNum, pageSize), - }); - break; - case ACTION_NAME.LAST_PAGE: - updateWindowUrlHashParams({logEventNum: numEvents}); - break; - default: - break; - } -}; +/* eslint-enable sort-keys */ export { ACTION_NAME, EDITOR_ACTIONS, - handleAction, }; export type {ActionType}; diff --git a/new-log-viewer/src/utils/math.ts b/new-log-viewer/src/utils/math.ts index fea1cf6d..61f4bedc 100644 --- a/new-log-viewer/src/utils/math.ts +++ b/new-log-viewer/src/utils/math.ts @@ -20,36 +20,7 @@ const clamp = (num: number, min: number, max: number) => Math.min(Math.max(num, const getChunkNum = (itemNum: number, chunkSize: number) => Math.max(1, Math.ceil(itemNum / chunkSize)); -/** - * Calculates the last item number in the previous chunk. - * - * @param itemNum - * @param chunkSize - * @return The last item number in the previous chunk. If the input item belongs - * to the first chunk, returns 1. - */ -const getLastItemNumInPrevChunk = (itemNum: number, chunkSize: number) => { - if (itemNum < chunkSize) { - return 1; - } - const prevChunkNum = getChunkNum(itemNum - chunkSize, chunkSize); - return prevChunkNum * chunkSize; -}; - -/** - * Calculates the first item number in the next chunk. - * - * @param itemNum - * @param chunkSize - * @return The first item number in the next chunk. - */ -const getFirstItemNumInNextChunk = (itemNum: number, chunkSize: number) => ( - (getChunkNum(itemNum, chunkSize) * chunkSize) + 1 -); - export { clamp, getChunkNum, - getFirstItemNumInNextChunk, - getLastItemNumInPrevChunk, }; From 96927bf4cce346edcb65146396314b1e802b9eea Mon Sep 17 00:00:00 2001 From: Dave Marco Date: Tue, 24 Sep 2024 18:58:41 +0000 Subject: [PATCH 02/31] next pass --- .../src/contexts/StateContextProvider.tsx | 38 ++++---------- new-log-viewer/src/services/LogFileManager.ts | 20 +++++--- new-log-viewer/src/services/MainWorker.ts | 2 + new-log-viewer/src/typings/worker.ts | 3 +- new-log-viewer/src/utils/actions.ts | 50 +++++++++++++++++++ 5 files changed, 77 insertions(+), 36 deletions(-) diff --git a/new-log-viewer/src/contexts/StateContextProvider.tsx b/new-log-viewer/src/contexts/StateContextProvider.tsx index cb1044ce..0e6f7f4b 100644 --- a/new-log-viewer/src/contexts/StateContextProvider.tsx +++ b/new-log-viewer/src/contexts/StateContextProvider.tsx @@ -22,7 +22,10 @@ import { WorkerReq, } from "../typings/worker"; import {getConfig} from "../utils/config"; -import {ACTION_NAME} from "../utils/actions"; +import { + getPageReqCursorArgs, + ACTION_NAME} +from "../utils/actions"; import { clamp, getChunkNum, @@ -136,8 +139,9 @@ const StateContextProvider = ({children}: StateContextProviderProps) => { break; case WORKER_RESP_CODE.PAGE_DATA: { setLogData(args.logs); + pageNumRef.current = args.pageNum beginLineNumToLogEventNumRef.current = args.beginLineNumToLogEventNum; - updateLogEventNumInUrl(numEvents, args.newLogEventNum); + updateLogEventNumInUrl(numEvents, args.logEventNum); break; } case WORKER_RESP_CODE.NOTIFICATION: @@ -179,39 +183,19 @@ const StateContextProvider = ({children}: StateContextProviderProps) => { return; } - if (null === specificPageNum && action !== ACTION_NAME.SPECIFIC_PAGE) { + if (null === specificPageNum && ACTION_NAME.SPECIFIC_PAGE !== action) { console.error(`Unexpected page number provided to page action ${action}`); return; } - if (STATE_DEFAULT.pageNum == pageNumRef.current) { + if (STATE_DEFAULT.pageNum === pageNumRef.current) { console.error(`Page actions cannot be executed if the current page is not set.`); return; } - let newPageNum: number; - let anchor: LOG_EVENT_ANCHOR = LOG_EVENT_ANCHOR.FIRST; + const [newPageNum, anchor] = getPageReqCursorArgs(action, specificPageNum!, pageNumRef.current, numPagesRef.current); - switch (action) { - case ACTION_NAME.SPECIFIC_PAGE: - // specificPageNum cannot be null, since already checked during validation. - newPageNum = specificPageNum!; - break; - case ACTION_NAME.FIRST_PAGE: - newPageNum = 1; - break; - case ACTION_NAME.PREV_PAGE: - anchor = LOG_EVENT_ANCHOR.LAST - newPageNum = clamp(pageNumRef.current - 1, 1, numPagesRef.current); - break; - case ACTION_NAME.NEXT_PAGE: - newPageNum = clamp(pageNumRef.current + 1, 1, numPagesRef.current); - break; - case ACTION_NAME.LAST_PAGE: - anchor = LOG_EVENT_ANCHOR.LAST - newPageNum = numPagesRef.current; - break; - default: + if (newPageNum === null|| anchor === null) { console.error(`Behaviour for action ${action} is not yet defined.`); return; } @@ -260,8 +244,6 @@ const StateContextProvider = ({children}: StateContextProviderProps) => { loadPage(ACTION_NAME.SPECIFIC_PAGE, newPageNum); } } - - pageNumRef.current = newPageNum; }, [ numEvents, logEventNum, diff --git a/new-log-viewer/src/services/LogFileManager.ts b/new-log-viewer/src/services/LogFileManager.ts index 9f1bfc3e..89c9cda3 100644 --- a/new-log-viewer/src/services/LogFileManager.ts +++ b/new-log-viewer/src/services/LogFileManager.ts @@ -4,6 +4,7 @@ import { LOG_EVENT_FILE_END_IDX, } from "../typings/decoders"; import {MAX_V8_STRING_LENGTH} from "../typings/js"; +import {CONFIG_KEY} from "../typings/config"; import { BeginLineNumToLogEventNumMap, CURSOR_CODE, @@ -12,6 +13,7 @@ import { LOG_EVENT_ANCHOR, } from "../typings/worker"; import {getUint8ArrayFrom} from "../utils/http"; +import {getConfig} from "../utils/config"; import {getChunkNum} from "../utils/math"; import {formatSizeInBytes} from "../utils/units"; import {getBasenameFromUrlOrDefault} from "../utils/url"; @@ -19,6 +21,8 @@ import ClpIrDecoder from "./decoders/ClpIrDecoder"; import JsonlDecoder from "./decoders/JsonlDecoder"; + + /** * Loads a file from a given source. * @@ -165,7 +169,8 @@ class LogFileManager { logs: string, beginLineNumToLogEventNum: BeginLineNumToLogEventNumMap, cursorLineNum: number - newLogEventNum: number + logEventNum: number + pageNum: number } { console.debug(`loadPage: cursor=${JSON.stringify(cursor)}`); @@ -193,13 +198,15 @@ class LogFileManager { currentLine += msg.split("\n").length - 1; }); - const newLogEventNum: number = this.#getNewLogEventNum(cursor, beginLineNumToLogEventNum) + const newLogEventNum = this.#getNewLogEventNum(cursor, beginLineNumToLogEventNum); + const newPageNum: number = getChunkNum(beginLogEventNum, getConfig(CONFIG_KEY.PAGE_SIZE)); return { logs: messages.join(""), beginLineNumToLogEventNum: beginLineNumToLogEventNum, cursorLineNum: 1, - newLogEventNum: newLogEventNum, + logEventNum: newLogEventNum, + pageNum: newPageNum, }; } @@ -235,11 +242,10 @@ class LogFileManager { } /** - * Gets the range of log event numbers for the page containing the given cursor. + * Gets the new log event number. * * @param cursor The cursor object containing the code and arguments. - * @return The range. - * @throws {Error} if the type of cursor is not supported. + * @return The new log event number. Returns null if there are no events. */ #getNewLogEventNum (cursor: CursorType, beginLineNumToLogEventNum: BeginLineNumToLogEventNumMap): number { const {code, args} = cursor; @@ -253,7 +259,7 @@ class LogFileManager { } if (NewLogEventNum === undefined) { - throw Error("Could not find Log Event on page") + throw Error("There are no log events on the page."); } return NewLogEventNum diff --git a/new-log-viewer/src/services/MainWorker.ts b/new-log-viewer/src/services/MainWorker.ts index 87a1bd89..ab0d40ad 100644 --- a/new-log-viewer/src/services/MainWorker.ts +++ b/new-log-viewer/src/services/MainWorker.ts @@ -2,7 +2,9 @@ import dayjs from "dayjs"; import dayjsTimezone from "dayjs/plugin/timezone"; import dayjsUtc from "dayjs/plugin/utc"; +import {Nullable} from "../typings/common"; import {LOG_LEVEL} from "../typings/logs"; + import { MainWorkerReqMessage, WORKER_REQ_CODE, diff --git a/new-log-viewer/src/typings/worker.ts b/new-log-viewer/src/typings/worker.ts index 46c1705f..b0bf024d 100644 --- a/new-log-viewer/src/typings/worker.ts +++ b/new-log-viewer/src/typings/worker.ts @@ -78,7 +78,8 @@ type WorkerRespMap = { logs: string, beginLineNumToLogEventNum: BeginLineNumToLogEventNumMap, cursorLineNum: number - newLogEventNum: number + logEventNum: number + pageNum: number }, [WORKER_RESP_CODE.NOTIFICATION]: { logLevel: LOG_LEVEL, diff --git a/new-log-viewer/src/utils/actions.ts b/new-log-viewer/src/utils/actions.ts index c0c53d49..e6c808fe 100644 --- a/new-log-viewer/src/utils/actions.ts +++ b/new-log-viewer/src/utils/actions.ts @@ -1,5 +1,13 @@ import * as monaco from "monaco-editor/esm/vs/editor/editor.api.js"; +import { + LOG_EVENT_ANCHOR, +} from "../typings/worker"; + +import { + clamp, +} from "../utils/math"; + import {Nullable} from "../typings/common"; enum ACTION_NAME { @@ -61,10 +69,52 @@ const EDITOR_ACTIONS : ActionType[] = [ }, ]; +/** + * Calculates the new page number and log event anchor based on the action name. + * + * @param action + * @param specificPageNum Page number for specific page action. + * @param currentPageNum + * @param numPages + * @return The new page number and the log event anchor required for the page request. Returns + * null for both if the action behaviour is not yet setup. + */ +const getPageReqCursorArgs = (action: ACTION_NAME, specificPageNum: Nullable, currentPageNum: number, numPages: number): [Nullable, Nullable] => { + let newPageNum: number; + let anchor: LOG_EVENT_ANCHOR = LOG_EVENT_ANCHOR.FIRST; + + switch (action) { + case ACTION_NAME.SPECIFIC_PAGE: + // specificPageNum cannot be null, since already checked during loadPage validation. Clamp + // is to prevent someone from non-existent page. + newPageNum = clamp(specificPageNum!, 1, numPages); + break; + case ACTION_NAME.FIRST_PAGE: + newPageNum = 1; + break; + case ACTION_NAME.PREV_PAGE: + anchor = LOG_EVENT_ANCHOR.LAST + newPageNum = clamp(currentPageNum - 1, 1, numPages); + break; + case ACTION_NAME.NEXT_PAGE: + newPageNum = clamp(currentPageNum + 1, 1, numPages); + break; + case ACTION_NAME.LAST_PAGE: + anchor = LOG_EVENT_ANCHOR.LAST + newPageNum = numPages; + break; + default: + return [null, null]; + } + return [newPageNum, anchor] +} + + /* eslint-enable sort-keys */ export { ACTION_NAME, EDITOR_ACTIONS, + getPageReqCursorArgs }; export type {ActionType}; From fcd0ee983588d11aa913b5f451c6f3341f066928 Mon Sep 17 00:00:00 2001 From: Dave Marco Date: Tue, 24 Sep 2024 19:44:49 +0000 Subject: [PATCH 03/31] fix lint --- .../src/components/Editor/index.tsx | 2 +- .../src/components/MenuBar/NavigationBar.tsx | 4 +- .../src/components/MenuBar/PageNumInput.tsx | 9 +- .../src/contexts/StateContextProvider.tsx | 44 +++++----- new-log-viewer/src/services/LogFileManager.ts | 63 +++++++------- new-log-viewer/src/services/MainWorker.ts | 2 - new-log-viewer/src/typings/worker.ts | 2 +- new-log-viewer/src/utils/actions.ts | 85 ++++++++++++------- 8 files changed, 115 insertions(+), 96 deletions(-) diff --git a/new-log-viewer/src/components/Editor/index.tsx b/new-log-viewer/src/components/Editor/index.tsx index 5c52d307..0d7a41bf 100644 --- a/new-log-viewer/src/components/Editor/index.tsx +++ b/new-log-viewer/src/components/Editor/index.tsx @@ -98,7 +98,7 @@ const Editor = () => { default: break; } - }, []); + }, [loadPage]); /** * Sets `editorRef` and configures callbacks for mouse down detection. diff --git a/new-log-viewer/src/components/MenuBar/NavigationBar.tsx b/new-log-viewer/src/components/MenuBar/NavigationBar.tsx index 0edd0d3b..6de167aa 100644 --- a/new-log-viewer/src/components/MenuBar/NavigationBar.tsx +++ b/new-log-viewer/src/components/MenuBar/NavigationBar.tsx @@ -6,9 +6,7 @@ import SkipNext from "@mui/icons-material/SkipNext"; import SkipPrevious from "@mui/icons-material/SkipPrevious"; import {StateContext} from "../../contexts/StateContextProvider"; -import { - ACTION_NAME, -} from "../../utils/actions"; +import {ACTION_NAME} from "../../utils/actions"; import PageNumInput from "./PageNumInput"; import SmallIconButton from "./SmallIconButton"; diff --git a/new-log-viewer/src/components/MenuBar/PageNumInput.tsx b/new-log-viewer/src/components/MenuBar/PageNumInput.tsx index 0e381d92..d466a31b 100644 --- a/new-log-viewer/src/components/MenuBar/PageNumInput.tsx +++ b/new-log-viewer/src/components/MenuBar/PageNumInput.tsx @@ -8,8 +8,8 @@ import React, { import {Typography} from "@mui/joy"; import Input from "@mui/joy/Input"; -import {ACTION_NAME} from "../../utils/actions"; import {StateContext} from "../../contexts/StateContextProvider"; +import {ACTION_NAME} from "../../utils/actions"; import "./PageNumInput.css"; @@ -24,9 +24,6 @@ const PAGE_NUM_INPUT_FIT_EXTRA_WIDTH = 2; */ const PageNumInput = () => { const {loadPage, numPages, pageNum} = useContext(StateContext); - const adjustedPageNum = (null === pageNum) ? - 0 : - pageNum; const [isEditing, setIsEditing] = useState(false); const inputRef = useRef(null); @@ -69,9 +66,9 @@ const PageNumInput = () => { if (null === inputRef.current) { return; } - inputRef.current.value = adjustedPageNum.toString(); + inputRef.current.value = pageNum.toString(); adjustInputWidth(); - }, [adjustedPageNum]); + }, [pageNum]); return (
{ break; case WORKER_RESP_CODE.PAGE_DATA: { setLogData(args.logs); - pageNumRef.current = args.pageNum + pageNumRef.current = args.pageNum; beginLineNumToLogEventNumRef.current = args.beginLineNumToLogEventNum; - updateLogEventNumInUrl(numEvents, args.logEventNum); + updateWindowUrlHashParams({ + logEventNum: args.logEventNum, + }); break; } case WORKER_RESP_CODE.NOTIFICATION: @@ -180,28 +183,26 @@ const StateContextProvider = ({children}: StateContextProviderProps) => { const loadPage = (action: ACTION_NAME, specificPageNum: Nullable = null) => { if (null === mainWorkerRef.current) { console.error("Unexpected null mainWorkerRef.current"); - return; - } - if (null === specificPageNum && ACTION_NAME.SPECIFIC_PAGE !== action) { - console.error(`Unexpected page number provided to page action ${action}`); return; } - if (STATE_DEFAULT.pageNum === pageNumRef.current) { - console.error(`Page actions cannot be executed if the current page is not set.`); - return; - } - - const [newPageNum, anchor] = getPageReqCursorArgs(action, specificPageNum!, pageNumRef.current, numPagesRef.current); + const [newPageNum, anchor] = getPageReqCursorArgs( + action, + specificPageNum, + pageNumRef.current, + numPagesRef.current + ); - if (newPageNum === null|| anchor === null) { + if (null === newPageNum || null === anchor) { console.error(`Behaviour for action ${action} is not yet defined.`); + return; } workerPostReq(mainWorkerRef.current, WORKER_REQ_CODE.LOAD_PAGE, { - cursor: {code: CURSOR_CODE.PAGE_NUM, args: {pageNum: newPageNum, logEventAnchor: anchor}}, + cursor: {code: CURSOR_CODE.PAGE_NUM, + args: {pageNum: newPageNum, logEventAnchor: anchor}}, decoderOptions: getConfig(CONFIG_KEY.DECODER_OPTIONS), }); }; @@ -265,7 +266,8 @@ const StateContextProvider = ({children}: StateContextProviderProps) => { 1 ); - cursor = {code: CURSOR_CODE.PAGE_NUM, args: {pageNum: newPageNum, logEventAnchor:LOG_EVENT_ANCHOR.FIRST}}; + cursor = {code: CURSOR_CODE.PAGE_NUM, + args: {pageNum: newPageNum, logEventAnchor: LOG_EVENT_ANCHOR.FIRST}}; } loadFile(filePath, cursor); }, [ @@ -291,6 +293,8 @@ const StateContextProvider = ({children}: StateContextProviderProps) => { ); }; - export default StateContextProvider; -export {StateContext}; +export { + STATE_DEFAULT, + StateContext, +}; diff --git a/new-log-viewer/src/services/LogFileManager.ts b/new-log-viewer/src/services/LogFileManager.ts index 89c9cda3..9e660700 100644 --- a/new-log-viewer/src/services/LogFileManager.ts +++ b/new-log-viewer/src/services/LogFileManager.ts @@ -1,10 +1,10 @@ +import {CONFIG_KEY} from "../typings/config"; import { Decoder, DecoderOptionsType, LOG_EVENT_FILE_END_IDX, } from "../typings/decoders"; import {MAX_V8_STRING_LENGTH} from "../typings/js"; -import {CONFIG_KEY} from "../typings/config"; import { BeginLineNumToLogEventNumMap, CURSOR_CODE, @@ -12,8 +12,8 @@ import { FileSrcType, LOG_EVENT_ANCHOR, } from "../typings/worker"; -import {getUint8ArrayFrom} from "../utils/http"; import {getConfig} from "../utils/config"; +import {getUint8ArrayFrom} from "../utils/http"; import {getChunkNum} from "../utils/math"; import {formatSizeInBytes} from "../utils/units"; import {getBasenameFromUrlOrDefault} from "../utils/url"; @@ -21,7 +21,34 @@ import ClpIrDecoder from "./decoders/ClpIrDecoder"; import JsonlDecoder from "./decoders/JsonlDecoder"; +/** + * Gets the new log event number. + * + * @param cursor The cursor object containing the code and arguments. + * @param beginLineNumToLogEventNum + * @return The new log event number. + * @throws {Error} There are no log events on the page. + */ +const getNewLogEventNum = ( + cursor: CursorType, + beginLineNumToLogEventNum: BeginLineNumToLogEventNumMap +): number => { + const {code, args} = cursor; + const logEventNumOnPage: number[] = Array.from(beginLineNumToLogEventNum.values()); + let NewLogEventNum: number|undefined = logEventNumOnPage.at(0); + + if (CURSOR_CODE.PAGE_NUM === code) { + if (LOG_EVENT_ANCHOR.FIRST === args.logEventAnchor) { + NewLogEventNum = logEventNumOnPage.at(-1); + } + } + + if (!NewLogEventNum) { + throw Error("There are no log events on the page."); + } + return NewLogEventNum; +}; /** * Loads a file from a given source. @@ -166,10 +193,10 @@ class LogFileManager { * @throws {Error} if any error occurs during decode. */ loadPage (cursor: CursorType): { - logs: string, beginLineNumToLogEventNum: BeginLineNumToLogEventNumMap, cursorLineNum: number logEventNum: number + logs: string, pageNum: number } { console.debug(`loadPage: cursor=${JSON.stringify(cursor)}`); @@ -198,14 +225,14 @@ class LogFileManager { currentLine += msg.split("\n").length - 1; }); - const newLogEventNum = this.#getNewLogEventNum(cursor, beginLineNumToLogEventNum); - const newPageNum: number = getChunkNum(beginLogEventNum, getConfig(CONFIG_KEY.PAGE_SIZE)); + const newLogEventNum = getNewLogEventNum(cursor, beginLineNumToLogEventNum); + const newPageNum: number = getChunkNum(beginLogEventNum, getConfig(CONFIG_KEY.PAGE_SIZE)); return { - logs: messages.join(""), beginLineNumToLogEventNum: beginLineNumToLogEventNum, cursorLineNum: 1, logEventNum: newLogEventNum, + logs: messages.join(""), pageNum: newPageNum, }; } @@ -240,30 +267,6 @@ class LogFileManager { const endLogEventNum = Math.min(this.#numEvents, beginLogEventNum + this.#pageSize - 1); return {beginLogEventNum, endLogEventNum}; } - - /** - * Gets the new log event number. - * - * @param cursor The cursor object containing the code and arguments. - * @return The new log event number. Returns null if there are no events. - */ - #getNewLogEventNum (cursor: CursorType, beginLineNumToLogEventNum: BeginLineNumToLogEventNumMap): number { - const {code, args} = cursor; - const logEventNumOnPage: number[] = Array.from(beginLineNumToLogEventNum.values()); - let NewLogEventNum: number|undefined = logEventNumOnPage.at(0); - - if (CURSOR_CODE.PAGE_NUM === code) { - if (args.logEventAnchor = LOG_EVENT_ANCHOR.FIRST) { - NewLogEventNum = logEventNumOnPage.at(-1); - } - } - - if (NewLogEventNum === undefined) { - throw Error("There are no log events on the page."); - } - - return NewLogEventNum - } } export default LogFileManager; diff --git a/new-log-viewer/src/services/MainWorker.ts b/new-log-viewer/src/services/MainWorker.ts index ab0d40ad..87a1bd89 100644 --- a/new-log-viewer/src/services/MainWorker.ts +++ b/new-log-viewer/src/services/MainWorker.ts @@ -2,9 +2,7 @@ import dayjs from "dayjs"; import dayjsTimezone from "dayjs/plugin/timezone"; import dayjsUtc from "dayjs/plugin/utc"; -import {Nullable} from "../typings/common"; import {LOG_LEVEL} from "../typings/logs"; - import { MainWorkerReqMessage, WORKER_REQ_CODE, diff --git a/new-log-viewer/src/typings/worker.ts b/new-log-viewer/src/typings/worker.ts index b0bf024d..1812bd19 100644 --- a/new-log-viewer/src/typings/worker.ts +++ b/new-log-viewer/src/typings/worker.ts @@ -75,10 +75,10 @@ type WorkerRespMap = { numEvents: number, }, [WORKER_RESP_CODE.PAGE_DATA]: { - logs: string, beginLineNumToLogEventNum: BeginLineNumToLogEventNumMap, cursorLineNum: number logEventNum: number + logs: string, pageNum: number }, [WORKER_RESP_CODE.NOTIFICATION]: { diff --git a/new-log-viewer/src/utils/actions.ts b/new-log-viewer/src/utils/actions.ts index e6c808fe..aee98deb 100644 --- a/new-log-viewer/src/utils/actions.ts +++ b/new-log-viewer/src/utils/actions.ts @@ -1,14 +1,10 @@ import * as monaco from "monaco-editor/esm/vs/editor/editor.api.js"; -import { - LOG_EVENT_ANCHOR, -} from "../typings/worker"; - -import { - clamp, -} from "../utils/math"; - +import {STATE_DEFAULT} from "../contexts/StateContextProvider"; import {Nullable} from "../typings/common"; +import {LOG_EVENT_ANCHOR} from "../typings/worker"; +import {clamp} from "../utils/math"; + enum ACTION_NAME { SPECIFIC_PAGE = "specificPage", @@ -79,35 +75,58 @@ const EDITOR_ACTIONS : ActionType[] = [ * @return The new page number and the log event anchor required for the page request. Returns * null for both if the action behaviour is not yet setup. */ -const getPageReqCursorArgs = (action: ACTION_NAME, specificPageNum: Nullable, currentPageNum: number, numPages: number): [Nullable, Nullable] => { +const getPageReqCursorArgs = ( + action: ACTION_NAME, + specificPageNum: Nullable, + currentPageNum: number, + numPages: number +): [Nullable, Nullable] => { let newPageNum: number; let anchor: LOG_EVENT_ANCHOR = LOG_EVENT_ANCHOR.FIRST; + + if (null === specificPageNum && ACTION_NAME.SPECIFIC_PAGE !== action) { + console.error(`Unexpected page number provided to page action ${action}`); + + return [null, + null]; + } + + if (STATE_DEFAULT.pageNum === currentPageNum) { + console.error("Page actions cannot be executed if the current page is not set."); + + return [null, + null]; + } + switch (action) { - case ACTION_NAME.SPECIFIC_PAGE: - // specificPageNum cannot be null, since already checked during loadPage validation. Clamp - // is to prevent someone from non-existent page. - newPageNum = clamp(specificPageNum!, 1, numPages); - break; - case ACTION_NAME.FIRST_PAGE: - newPageNum = 1; - break; - case ACTION_NAME.PREV_PAGE: - anchor = LOG_EVENT_ANCHOR.LAST - newPageNum = clamp(currentPageNum - 1, 1, numPages); - break; - case ACTION_NAME.NEXT_PAGE: - newPageNum = clamp(currentPageNum + 1, 1, numPages); - break; - case ACTION_NAME.LAST_PAGE: - anchor = LOG_EVENT_ANCHOR.LAST - newPageNum = numPages; - break; - default: - return [null, null]; + case ACTION_NAME.SPECIFIC_PAGE: + // specificPageNum cannot be null, since already checked during loadPage validation. + // Clamp is to prevent someone from requesting non-existent page. + newPageNum = clamp(specificPageNum as number, 1, numPages); + break; + case ACTION_NAME.FIRST_PAGE: + newPageNum = 1; + break; + case ACTION_NAME.PREV_PAGE: + anchor = LOG_EVENT_ANCHOR.LAST; + newPageNum = clamp(currentPageNum - 1, 1, numPages); + break; + case ACTION_NAME.NEXT_PAGE: + newPageNum = clamp(currentPageNum + 1, 1, numPages); + break; + case ACTION_NAME.LAST_PAGE: + anchor = LOG_EVENT_ANCHOR.LAST; + newPageNum = numPages; + break; + default: + return [null, + null]; } - return [newPageNum, anchor] -} + + return [newPageNum, + anchor]; +}; /* eslint-enable sort-keys */ @@ -115,6 +134,6 @@ const getPageReqCursorArgs = (action: ACTION_NAME, specificPageNum: Nullable Date: Tue, 24 Sep 2024 19:55:36 +0000 Subject: [PATCH 04/31] small changes --- .../src/contexts/StateContextProvider.tsx | 2 +- new-log-viewer/src/services/LogFileManager.ts | 5 +++-- new-log-viewer/src/utils/actions.ts | 20 ++++++++++++------- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/new-log-viewer/src/contexts/StateContextProvider.tsx b/new-log-viewer/src/contexts/StateContextProvider.tsx index 2bfea861..6a6e4251 100644 --- a/new-log-viewer/src/contexts/StateContextProvider.tsx +++ b/new-log-viewer/src/contexts/StateContextProvider.tsx @@ -195,7 +195,7 @@ const StateContextProvider = ({children}: StateContextProviderProps) => { ); if (null === newPageNum || null === anchor) { - console.error(`Behaviour for action ${action} is not yet defined.`); + console.error(`Error with page action ${action}.`); return; } diff --git a/new-log-viewer/src/services/LogFileManager.ts b/new-log-viewer/src/services/LogFileManager.ts index 9e660700..488d972b 100644 --- a/new-log-viewer/src/services/LogFileManager.ts +++ b/new-log-viewer/src/services/LogFileManager.ts @@ -35,11 +35,12 @@ const getNewLogEventNum = ( ): number => { const {code, args} = cursor; const logEventNumOnPage: number[] = Array.from(beginLineNumToLogEventNum.values()); - let NewLogEventNum: number|undefined = logEventNumOnPage.at(0); + // Default to last event on page. + let NewLogEventNum: number|undefined = logEventNumOnPage.at(-1); if (CURSOR_CODE.PAGE_NUM === code) { if (LOG_EVENT_ANCHOR.FIRST === args.logEventAnchor) { - NewLogEventNum = logEventNumOnPage.at(-1); + NewLogEventNum = logEventNumOnPage.at(0); } } diff --git a/new-log-viewer/src/utils/actions.ts b/new-log-viewer/src/utils/actions.ts index aee98deb..eb1ea53b 100644 --- a/new-log-viewer/src/utils/actions.ts +++ b/new-log-viewer/src/utils/actions.ts @@ -73,7 +73,7 @@ const EDITOR_ACTIONS : ActionType[] = [ * @param currentPageNum * @param numPages * @return The new page number and the log event anchor required for the page request. Returns - * null for both if the action behaviour is not yet setup. + * null if the action is not setup or there is an error validating inputs. */ const getPageReqCursorArgs = ( action: ACTION_NAME, @@ -88,15 +88,19 @@ const getPageReqCursorArgs = ( if (null === specificPageNum && ACTION_NAME.SPECIFIC_PAGE !== action) { console.error(`Unexpected page number provided to page action ${action}`); - return [null, - null]; + return [ + null, + null, + ]; } if (STATE_DEFAULT.pageNum === currentPageNum) { console.error("Page actions cannot be executed if the current page is not set."); - return [null, - null]; + return [ + null, + null, + ]; } switch (action) { @@ -120,8 +124,10 @@ const getPageReqCursorArgs = ( newPageNum = numPages; break; default: - return [null, - null]; + return [ + null, + null, + ]; } return [newPageNum, From ceb8a4d87e587d47bbcd4e58fbb4d1d94001ee4e Mon Sep 17 00:00:00 2001 From: Dave Marco Date: Tue, 24 Sep 2024 20:10:06 +0000 Subject: [PATCH 05/31] small change --- .../src/contexts/StateContextProvider.tsx | 4 ++-- new-log-viewer/src/services/LogFileManager.ts | 1 + new-log-viewer/src/typings/worker.ts | 4 ++-- new-log-viewer/src/utils/actions.ts | 20 +++++++++---------- 4 files changed, 14 insertions(+), 15 deletions(-) diff --git a/new-log-viewer/src/contexts/StateContextProvider.tsx b/new-log-viewer/src/contexts/StateContextProvider.tsx index 6a6e4251..29ca71e0 100644 --- a/new-log-viewer/src/contexts/StateContextProvider.tsx +++ b/new-log-viewer/src/contexts/StateContextProvider.tsx @@ -23,7 +23,7 @@ import { } from "../typings/worker"; import { ACTION_NAME, - getPageReqCursorArgs, + getPageNumCursorArgs, } from "../utils/actions"; import {getConfig} from "../utils/config"; import { @@ -187,7 +187,7 @@ const StateContextProvider = ({children}: StateContextProviderProps) => { return; } - const [newPageNum, anchor] = getPageReqCursorArgs( + const [newPageNum, anchor] = getPageNumCursorArgs( action, specificPageNum, pageNumRef.current, diff --git a/new-log-viewer/src/services/LogFileManager.ts b/new-log-viewer/src/services/LogFileManager.ts index 488d972b..c721d75e 100644 --- a/new-log-viewer/src/services/LogFileManager.ts +++ b/new-log-viewer/src/services/LogFileManager.ts @@ -35,6 +35,7 @@ const getNewLogEventNum = ( ): number => { const {code, args} = cursor; const logEventNumOnPage: number[] = Array.from(beginLineNumToLogEventNum.values()); + // Default to last event on page. let NewLogEventNum: number|undefined = logEventNumOnPage.at(-1); diff --git a/new-log-viewer/src/typings/worker.ts b/new-log-viewer/src/typings/worker.ts index 1812bd19..78ed2d68 100644 --- a/new-log-viewer/src/typings/worker.ts +++ b/new-log-viewer/src/typings/worker.ts @@ -8,7 +8,7 @@ import {LOG_LEVEL} from "./logs"; type FileSrcType = string | File; /** - * Whether returned page should be anchored to top or bottom. + * Input to page num cursor resulting if page is anchored to top or bottom. */ enum LOG_EVENT_ANCHOR { FIRST = "first", @@ -30,7 +30,7 @@ enum CURSOR_CODE { type CursorArgMap = { [CURSOR_CODE.LAST_EVENT]: null; [CURSOR_CODE.TIMESTAMP]: { timestamp: number }; - [CURSOR_CODE.PAGE_NUM]: { pageNum: number, logEventAnchor: LOG_EVENT_ANCHOR; }; + [CURSOR_CODE.PAGE_NUM]: { pageNum: number, logEventAnchor: LOG_EVENT_ANCHOR}; }; type CursorType = { diff --git a/new-log-viewer/src/utils/actions.ts b/new-log-viewer/src/utils/actions.ts index eb1ea53b..5638b3e7 100644 --- a/new-log-viewer/src/utils/actions.ts +++ b/new-log-viewer/src/utils/actions.ts @@ -66,7 +66,7 @@ const EDITOR_ACTIONS : ActionType[] = [ ]; /** - * Calculates the new page number and log event anchor based on the action name. + * Calculates the new page number and log event anchor. * * @param action * @param specificPageNum Page number for specific page action. @@ -75,7 +75,7 @@ const EDITOR_ACTIONS : ActionType[] = [ * @return The new page number and the log event anchor required for the page request. Returns * null if the action is not setup or there is an error validating inputs. */ -const getPageReqCursorArgs = ( +const getPageNumCursorArgs = ( action: ACTION_NAME, specificPageNum: Nullable, currentPageNum: number, @@ -84,9 +84,8 @@ const getPageReqCursorArgs = ( let newPageNum: number; let anchor: LOG_EVENT_ANCHOR = LOG_EVENT_ANCHOR.FIRST; - - if (null === specificPageNum && ACTION_NAME.SPECIFIC_PAGE !== action) { - console.error(`Unexpected page number provided to page action ${action}`); + if (null === specificPageNum && ACTION_NAME.SPECIFIC_PAGE === action) { + console.error("Specific page action missing page input"); return [ null, @@ -130,16 +129,15 @@ const getPageReqCursorArgs = ( ]; } - return [newPageNum, - anchor]; + return [ + newPageNum, + anchor, + ]; }; - -/* eslint-enable sort-keys */ - export { ACTION_NAME, EDITOR_ACTIONS, - getPageReqCursorArgs, + getPageNumCursorArgs, }; export type {ActionType}; From 4d1e70a860437dbf36f344659f0554efd6c4f7ce Mon Sep 17 00:00:00 2001 From: Dave Marco Date: Tue, 24 Sep 2024 20:18:34 +0000 Subject: [PATCH 06/31] small change after merge --- new-log-viewer/src/services/LogFileManager.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/new-log-viewer/src/services/LogFileManager.ts b/new-log-viewer/src/services/LogFileManager.ts index 43c9b7ba..57c918e6 100644 --- a/new-log-viewer/src/services/LogFileManager.ts +++ b/new-log-viewer/src/services/LogFileManager.ts @@ -38,19 +38,19 @@ const getNewLogEventNum = ( const logEventNumOnPage: number[] = Array.from(beginLineNumToLogEventNum.values()); // Default to last event on page. - let NewLogEventNum: number|undefined = logEventNumOnPage.at(-1); + let newLogEventNum: number|undefined = logEventNumOnPage.at(-1); if (CURSOR_CODE.PAGE_NUM === code) { if (LOG_EVENT_ANCHOR.FIRST === args.logEventAnchor) { - NewLogEventNum = logEventNumOnPage.at(0); + newLogEventNum = logEventNumOnPage.at(0); } } - if (!NewLogEventNum) { + if (!newLogEventNum) { throw Error("There are no log events on the page."); } - return NewLogEventNum; + return newLogEventNum; }; /** From 662619bdeeac43561d3328060e4166880abfbfd7 Mon Sep 17 00:00:00 2001 From: Dave Marco Date: Tue, 24 Sep 2024 20:26:56 +0000 Subject: [PATCH 07/31] add utils to shorten file --- new-log-viewer/src/services/MainWorker.ts | 2 +- .../{ => fileManager}/LogFileManager.ts | 86 ++++--------------- .../src/services/fileManager/utils.ts | 72 ++++++++++++++++ 3 files changed, 89 insertions(+), 71 deletions(-) rename new-log-viewer/src/services/{ => fileManager}/LogFileManager.ts (77%) create mode 100644 new-log-viewer/src/services/fileManager/utils.ts diff --git a/new-log-viewer/src/services/MainWorker.ts b/new-log-viewer/src/services/MainWorker.ts index a04d134c..56ebadcb 100644 --- a/new-log-viewer/src/services/MainWorker.ts +++ b/new-log-viewer/src/services/MainWorker.ts @@ -10,7 +10,7 @@ import { WorkerResp, } from "../typings/worker"; import {EXPORT_LOGS_CHUNK_SIZE} from "../utils/config"; -import LogFileManager from "./LogFileManager"; +import LogFileManager from "./fileManager/LogFileManager"; /* eslint-disable import/no-named-as-default-member */ diff --git a/new-log-viewer/src/services/LogFileManager.ts b/new-log-viewer/src/services/fileManager/LogFileManager.ts similarity index 77% rename from new-log-viewer/src/services/LogFileManager.ts rename to new-log-viewer/src/services/fileManager/LogFileManager.ts index 57c918e6..33e2dbda 100644 --- a/new-log-viewer/src/services/LogFileManager.ts +++ b/new-log-viewer/src/services/fileManager/LogFileManager.ts @@ -1,83 +1,29 @@ -import {CONFIG_KEY} from "../typings/config"; +import {CONFIG_KEY} from "../../typings/config"; import { Decoder, DecoderOptionsType, LOG_EVENT_FILE_END_IDX, -} from "../typings/decoders"; -import {MAX_V8_STRING_LENGTH} from "../typings/js"; +} from "../../typings/decoders"; +import {MAX_V8_STRING_LENGTH} from "../../typings/js"; import { BeginLineNumToLogEventNumMap, CURSOR_CODE, CursorType, FileSrcType, - LOG_EVENT_ANCHOR, -} from "../typings/worker"; -import {getConfig} from "../utils/config"; -import {EXPORT_LOGS_CHUNK_SIZE} from "../utils/config"; -import {getUint8ArrayFrom} from "../utils/http"; -import {getChunkNum} from "../utils/math"; -import {formatSizeInBytes} from "../utils/units"; -import {getBasenameFromUrlOrDefault} from "../utils/url"; -import ClpIrDecoder from "./decoders/ClpIrDecoder"; -import JsonlDecoder from "./decoders/JsonlDecoder"; - - -/** - * Gets the new log event number. - * - * @param cursor The cursor object containing the code and arguments. - * @param beginLineNumToLogEventNum - * @return The new log event number. - * @throws {Error} There are no log events on the page. - */ -const getNewLogEventNum = ( - cursor: CursorType, - beginLineNumToLogEventNum: BeginLineNumToLogEventNumMap -): number => { - const {code, args} = cursor; - const logEventNumOnPage: number[] = Array.from(beginLineNumToLogEventNum.values()); - - // Default to last event on page. - let newLogEventNum: number|undefined = logEventNumOnPage.at(-1); - - if (CURSOR_CODE.PAGE_NUM === code) { - if (LOG_EVENT_ANCHOR.FIRST === args.logEventAnchor) { - newLogEventNum = logEventNumOnPage.at(0); - } - } - - if (!newLogEventNum) { - throw Error("There are no log events on the page."); - } - - return newLogEventNum; -}; - -/** - * Loads a file from a given source. - * - * @param fileSrc The source of the file to load. This can be a string representing a URL, or a File - * object. - * @return A promise that resolves with an object containing the file name and file data. - * @throws {Error} If the file source type is not supported. - */ -const loadFile = async (fileSrc: FileSrcType) - : Promise<{ fileName: string, fileData: Uint8Array }> => { - let fileName: string; - let fileData: Uint8Array; - if ("string" === typeof fileSrc) { - fileName = getBasenameFromUrlOrDefault(fileSrc); - fileData = await getUint8ArrayFrom(fileSrc, () => null); - } else { - fileName = fileSrc.name; - fileData = new Uint8Array(await fileSrc.arrayBuffer()); - } +} from "../../typings/worker"; +import { + EXPORT_LOGS_CHUNK_SIZE, + getConfig, +} from "../../utils/config"; +import {getChunkNum} from "../../utils/math"; +import {formatSizeInBytes} from "../../utils/units"; +import ClpIrDecoder from "../decoders/ClpIrDecoder"; +import JsonlDecoder from "../decoders/JsonlDecoder"; +import { + getNewLogEventNum, + loadFile, +} from "./utils"; - return { - fileName, - fileData, - }; -}; /** * Class to manage the retrieval and decoding of a given log file. diff --git a/new-log-viewer/src/services/fileManager/utils.ts b/new-log-viewer/src/services/fileManager/utils.ts new file mode 100644 index 00000000..6f36d21a --- /dev/null +++ b/new-log-viewer/src/services/fileManager/utils.ts @@ -0,0 +1,72 @@ +import { + BeginLineNumToLogEventNumMap, + CURSOR_CODE, + CursorType, + FileSrcType, + LOG_EVENT_ANCHOR, +} from "../../typings/worker"; +import {getUint8ArrayFrom} from "../../utils/http"; +import {getBasenameFromUrlOrDefault} from "../../utils/url"; + + +/** + * Gets the new log event number. + * + * @param cursor The cursor object containing the code and arguments. + * @param beginLineNumToLogEventNum + * @return The new log event number. + * @throws {Error} There are no log events on the page. + */ +const getNewLogEventNum = ( + cursor: CursorType, + beginLineNumToLogEventNum: BeginLineNumToLogEventNumMap +): number => { + const {code, args} = cursor; + const logEventNumOnPage: number[] = Array.from(beginLineNumToLogEventNum.values()); + + // Default to last event on page. + let newLogEventNum: number|undefined = logEventNumOnPage.at(-1); + + if (CURSOR_CODE.PAGE_NUM === code) { + if (LOG_EVENT_ANCHOR.FIRST === args.logEventAnchor) { + newLogEventNum = logEventNumOnPage.at(0); + } + } + + if (!newLogEventNum) { + throw Error("There are no log events on the page."); + } + + return newLogEventNum; +}; + +/** + * Loads a file from a given source. + * + * @param fileSrc The source of the file to load. This can be a string representing a URL, or a File + * object. + * @return A promise that resolves with an object containing the file name and file data. + * @throws {Error} If the file source type is not supported. + */ +const loadFile = async (fileSrc: FileSrcType) + : Promise<{ fileName: string, fileData: Uint8Array }> => { + let fileName: string; + let fileData: Uint8Array; + if ("string" === typeof fileSrc) { + fileName = getBasenameFromUrlOrDefault(fileSrc); + fileData = await getUint8ArrayFrom(fileSrc, () => null); + } else { + fileName = fileSrc.name; + fileData = new Uint8Array(await fileSrc.arrayBuffer()); + } + + return { + fileName, + fileData, + }; +}; + +export { + getNewLogEventNum, + loadFile, +}; From ed2d9c448ffe776a2089a37323879b2d9779cb7e Mon Sep 17 00:00:00 2001 From: Dave Marco Date: Tue, 24 Sep 2024 20:49:03 +0000 Subject: [PATCH 08/31] fix page size error --- new-log-viewer/src/services/fileManager/LogFileManager.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/new-log-viewer/src/services/fileManager/LogFileManager.ts b/new-log-viewer/src/services/fileManager/LogFileManager.ts index 33e2dbda..01a94283 100644 --- a/new-log-viewer/src/services/fileManager/LogFileManager.ts +++ b/new-log-viewer/src/services/fileManager/LogFileManager.ts @@ -1,4 +1,4 @@ -import {CONFIG_KEY} from "../../typings/config"; + import { Decoder, DecoderOptionsType, @@ -13,7 +13,6 @@ import { } from "../../typings/worker"; import { EXPORT_LOGS_CHUNK_SIZE, - getConfig, } from "../../utils/config"; import {getChunkNum} from "../../utils/math"; import {formatSizeInBytes} from "../../utils/units"; @@ -206,7 +205,7 @@ class LogFileManager { }); const newLogEventNum = getNewLogEventNum(cursor, beginLineNumToLogEventNum); - const newPageNum: number = getChunkNum(beginLogEventNum, getConfig(CONFIG_KEY.PAGE_SIZE)); + const newPageNum: number = getChunkNum(beginLogEventNum, this.#pageSize); return { beginLineNumToLogEventNum: beginLineNumToLogEventNum, From 26a0d02279e5f06124fc4e5d028d9f1c45b4f8dd Mon Sep 17 00:00:00 2001 From: Dave Marco Date: Tue, 24 Sep 2024 21:12:28 +0000 Subject: [PATCH 09/31] fix bug with loadpage rerender --- new-log-viewer/src/contexts/StateContextProvider.tsx | 8 ++++++-- new-log-viewer/src/services/fileManager/LogFileManager.ts | 5 +---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/new-log-viewer/src/contexts/StateContextProvider.tsx b/new-log-viewer/src/contexts/StateContextProvider.tsx index 3c06b959..66538c35 100644 --- a/new-log-viewer/src/contexts/StateContextProvider.tsx +++ b/new-log-viewer/src/contexts/StateContextProvider.tsx @@ -231,7 +231,10 @@ const StateContextProvider = ({children}: StateContextProviderProps) => { handleMainWorkerResp, ]); - const loadPage = (action: ACTION_NAME, specificPageNum: Nullable = null) => { + const loadPage = useCallback(( + action: ACTION_NAME, + specificPageNum: Nullable = null + ) => { if (null === mainWorkerRef.current) { console.error("Unexpected null mainWorkerRef.current"); @@ -256,7 +259,7 @@ const StateContextProvider = ({children}: StateContextProviderProps) => { args: {pageNum: newPageNum, logEventAnchor: anchor}}, decoderOptions: getConfig(CONFIG_KEY.DECODER_OPTIONS), }); - }; + }, []); // Synchronize `logEventNumRef` with `logEventNum`. useEffect(() => { @@ -299,6 +302,7 @@ const StateContextProvider = ({children}: StateContextProviderProps) => { }, [ numEvents, logEventNum, + loadPage, ]); // On `filePath` update, load file. diff --git a/new-log-viewer/src/services/fileManager/LogFileManager.ts b/new-log-viewer/src/services/fileManager/LogFileManager.ts index 01a94283..74031b97 100644 --- a/new-log-viewer/src/services/fileManager/LogFileManager.ts +++ b/new-log-viewer/src/services/fileManager/LogFileManager.ts @@ -1,4 +1,3 @@ - import { Decoder, DecoderOptionsType, @@ -11,9 +10,7 @@ import { CursorType, FileSrcType, } from "../../typings/worker"; -import { - EXPORT_LOGS_CHUNK_SIZE, -} from "../../utils/config"; +import {EXPORT_LOGS_CHUNK_SIZE} from "../../utils/config"; import {getChunkNum} from "../../utils/math"; import {formatSizeInBytes} from "../../utils/units"; import ClpIrDecoder from "../decoders/ClpIrDecoder"; From b32c5bd485447f598cb009695c4aa6243cdcc6b4 Mon Sep 17 00:00:00 2001 From: Dave Marco Date: Tue, 24 Sep 2024 22:15:56 +0000 Subject: [PATCH 10/31] add comments describing broken behaviour until cursor done --- .../src/contexts/StateContextProvider.tsx | 23 +++++++++++++++---- new-log-viewer/src/utils/actions.ts | 6 ++--- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/new-log-viewer/src/contexts/StateContextProvider.tsx b/new-log-viewer/src/contexts/StateContextProvider.tsx index 66538c35..b0674fee 100644 --- a/new-log-viewer/src/contexts/StateContextProvider.tsx +++ b/new-log-viewer/src/contexts/StateContextProvider.tsx @@ -48,13 +48,14 @@ interface StateContextType { beginLineNumToLogEventNum: BeginLineNumToLogEventNumMap, fileName: string, exportProgress: Nullable, - exportLogs: () => void, - loadFile: (fileSrc: FileSrcType, cursor: CursorType) => void, - loadPage: (action: ACTION_NAME, specificPageNum?: Nullable) => void, logData: string, numEvents: number, numPages: number, pageNum: number, + + exportLogs: () => void, + loadFile: (fileSrc: FileSrcType, cursor: CursorType) => void, + loadPage: (action: ACTION_NAME, specificPageNum?: Nullable) => void, } const StateContext = createContext({} as StateContextType); @@ -143,7 +144,6 @@ const StateContextProvider = ({children}: StateContextProviderProps) => { const numPagesRef = useRef(STATE_DEFAULT.numPages); const pageNumRef = useRef(STATE_DEFAULT.pageNum); const logExportManagerRef = useRef(null); - const mainWorkerRef = useRef(null); const handleMainWorkerResp = useCallback((ev: MessageEvent) => { @@ -170,6 +170,10 @@ const StateContextProvider = ({children}: StateContextProviderProps) => { setLogData(args.logs); pageNumRef.current = args.pageNum; beginLineNumToLogEventNumRef.current = args.beginLineNumToLogEventNum; + + // eslint-disable-next-line no-warning-comments + // TODO: Without logEvent cursor, we cannot jump to logEvents. + // Will be fixed once logEvent cursor is merged. updateWindowUrlHashParams({ logEventNum: args.logEventNum, }); @@ -281,6 +285,10 @@ const StateContextProvider = ({children}: StateContextProviderProps) => { return; } + // eslint-disable-next-line no-warning-comments + // TODO: Remove newPageNum calc once log Event cursor complete. Instead + // we can check if in beginLineNumToLogEventNum, and if not send page request + // with logEvent cursor. const newPageNum = clamp( getChunkNum(logEventNum, getConfig(CONFIG_KEY.PAGE_SIZE)), 1, @@ -295,7 +303,10 @@ const StateContextProvider = ({children}: StateContextProviderProps) => { } else { // NOTE: We don't need to call `updateLogEventNumInUrl()` since it's called when // handling the `WORKER_RESP_CODE.PAGE_DATA` response (the response to - // `WORKER_REQ_CODE.LOAD_PAGE` requests) . + // `WORKER_REQ_CODE.LOAD_PAGE` requests). + + // eslint-disable-next-line no-warning-comments + // TODO: Replace with logEvent cursor once its complete. loadPage(ACTION_NAME.SPECIFIC_PAGE, newPageNum); } } @@ -321,6 +332,8 @@ const StateContextProvider = ({children}: StateContextProviderProps) => { 1 ); + // eslint-disable-next-line no-warning-comments + // TODO: Replace with logEvent cursor once its complete. cursor = {code: CURSOR_CODE.PAGE_NUM, args: {pageNum: newPageNum, logEventAnchor: LOG_EVENT_ANCHOR.FIRST}}; } diff --git a/new-log-viewer/src/utils/actions.ts b/new-log-viewer/src/utils/actions.ts index 5638b3e7..eee33a9e 100644 --- a/new-log-viewer/src/utils/actions.ts +++ b/new-log-viewer/src/utils/actions.ts @@ -66,13 +66,13 @@ const EDITOR_ACTIONS : ActionType[] = [ ]; /** - * Calculates the new page number and log event anchor. + * Calculates the new page number and log event anchor for the page num cursor. * * @param action * @param specificPageNum Page number for specific page action. * @param currentPageNum * @param numPages - * @return The new page number and the log event anchor required for the page request. Returns + * @return The new page number and the log event anchor required for the page num cursor. Returns * null if the action is not setup or there is an error validating inputs. */ const getPageNumCursorArgs = ( @@ -85,7 +85,7 @@ const getPageNumCursorArgs = ( let anchor: LOG_EVENT_ANCHOR = LOG_EVENT_ANCHOR.FIRST; if (null === specificPageNum && ACTION_NAME.SPECIFIC_PAGE === action) { - console.error("Specific page action missing page input"); + console.error("Specific page action missing required page input"); return [ null, From c6f1f5f8a7cfe4338f052e99f0624337ec59a541 Mon Sep 17 00:00:00 2001 From: Dave Marco Date: Tue, 24 Sep 2024 22:30:58 +0000 Subject: [PATCH 11/31] small changes --- new-log-viewer/src/typings/worker.ts | 3 ++- new-log-viewer/src/utils/actions.ts | 12 ++++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/new-log-viewer/src/typings/worker.ts b/new-log-viewer/src/typings/worker.ts index f4e3435c..da620500 100644 --- a/new-log-viewer/src/typings/worker.ts +++ b/new-log-viewer/src/typings/worker.ts @@ -8,7 +8,8 @@ import {LOG_LEVEL} from "./logs"; type FileSrcType = string | File; /** - * Input to page num cursor resulting if page is anchored to top or bottom. + * Indicates whether the log event number should be anchored to the top or bottom of the page. + * Used as input for the page number cursor. */ enum LOG_EVENT_ANCHOR { FIRST = "first", diff --git a/new-log-viewer/src/utils/actions.ts b/new-log-viewer/src/utils/actions.ts index eee33a9e..b1c6ae40 100644 --- a/new-log-viewer/src/utils/actions.ts +++ b/new-log-viewer/src/utils/actions.ts @@ -66,14 +66,14 @@ const EDITOR_ACTIONS : ActionType[] = [ ]; /** - * Calculates the new page number and log event anchor for the page num cursor. + * Calculates the new page number and log event anchor for the page number cursor. * * @param action * @param specificPageNum Page number for specific page action. * @param currentPageNum * @param numPages - * @return The new page number and the log event anchor required for the page num cursor. Returns - * null if the action is not setup or there is an error validating inputs. + * @return The new page number and the log event anchor required for the page number cursor. + * Returns null if the action is not setup or there is an error validating inputs. */ const getPageNumCursorArgs = ( action: ACTION_NAME, @@ -82,7 +82,7 @@ const getPageNumCursorArgs = ( numPages: number ): [Nullable, Nullable] => { let newPageNum: number; - let anchor: LOG_EVENT_ANCHOR = LOG_EVENT_ANCHOR.FIRST; + let anchor: LOG_EVENT_ANCHOR; if (null === specificPageNum && ACTION_NAME.SPECIFIC_PAGE === action) { console.error("Specific page action missing required page input"); @@ -104,11 +104,14 @@ const getPageNumCursorArgs = ( switch (action) { case ACTION_NAME.SPECIFIC_PAGE: + anchor = LOG_EVENT_ANCHOR.FIRST; + // specificPageNum cannot be null, since already checked during loadPage validation. // Clamp is to prevent someone from requesting non-existent page. newPageNum = clamp(specificPageNum as number, 1, numPages); break; case ACTION_NAME.FIRST_PAGE: + anchor = LOG_EVENT_ANCHOR.FIRST; newPageNum = 1; break; case ACTION_NAME.PREV_PAGE: @@ -116,6 +119,7 @@ const getPageNumCursorArgs = ( newPageNum = clamp(currentPageNum - 1, 1, numPages); break; case ACTION_NAME.NEXT_PAGE: + anchor = LOG_EVENT_ANCHOR.FIRST; newPageNum = clamp(currentPageNum + 1, 1, numPages); break; case ACTION_NAME.LAST_PAGE: From d2ed5b9ebf9a7065d47bfd1dab049a7c57019c8c Mon Sep 17 00:00:00 2001 From: Dave Marco Date: Tue, 24 Sep 2024 23:45:55 +0000 Subject: [PATCH 12/31] move newLogEvent so better placed for future PR --- .../src/contexts/StateContextProvider.tsx | 1 + .../services/fileManager/LogFileManager.ts | 47 +++++++++++----- .../src/services/fileManager/utils.ts | 53 +++++++------------ 3 files changed, 55 insertions(+), 46 deletions(-) diff --git a/new-log-viewer/src/contexts/StateContextProvider.tsx b/new-log-viewer/src/contexts/StateContextProvider.tsx index b0674fee..4e3a7eaa 100644 --- a/new-log-viewer/src/contexts/StateContextProvider.tsx +++ b/new-log-viewer/src/contexts/StateContextProvider.tsx @@ -170,6 +170,7 @@ const StateContextProvider = ({children}: StateContextProviderProps) => { setLogData(args.logs); pageNumRef.current = args.pageNum; beginLineNumToLogEventNumRef.current = args.beginLineNumToLogEventNum; + console.log(args); // eslint-disable-next-line no-warning-comments // TODO: Without logEvent cursor, we cannot jump to logEvents. diff --git a/new-log-viewer/src/services/fileManager/LogFileManager.ts b/new-log-viewer/src/services/fileManager/LogFileManager.ts index 74031b97..80bf1ba5 100644 --- a/new-log-viewer/src/services/fileManager/LogFileManager.ts +++ b/new-log-viewer/src/services/fileManager/LogFileManager.ts @@ -9,6 +9,7 @@ import { CURSOR_CODE, CursorType, FileSrcType, + LOG_EVENT_ANCHOR, } from "../../typings/worker"; import {EXPORT_LOGS_CHUNK_SIZE} from "../../utils/config"; import {getChunkNum} from "../../utils/math"; @@ -16,7 +17,7 @@ import {formatSizeInBytes} from "../../utils/units"; import ClpIrDecoder from "../decoders/ClpIrDecoder"; import JsonlDecoder from "../decoders/JsonlDecoder"; import { - getNewLogEventNum, + getRange, loadFile, } from "./utils"; @@ -177,7 +178,7 @@ class LogFileManager { } { console.debug(`loadPage: cursor=${JSON.stringify(cursor)}`); - const {beginLogEventNum, endLogEventNum} = this.#getCursorRange(cursor); + const {beginLogEventNum, endLogEventNum, newLogEventNum} = this.#getCursorData(cursor); const results = this.#decoder.decode(beginLogEventNum - 1, endLogEventNum); if (null === results) { throw new Error("Error occurred during decoding. " + @@ -201,7 +202,6 @@ class LogFileManager { currentLine += msg.split("\n").length - 1; }); - const newLogEventNum = getNewLogEventNum(cursor, beginLineNumToLogEventNum); const newPageNum: number = getChunkNum(beginLogEventNum, this.#pageSize); return { @@ -214,34 +214,57 @@ class LogFileManager { } /** - * Gets the range of log event numbers for the page containing the given cursor. + * Gets the range of log event numbers for the page and the new log event number. * * @param cursor The cursor object containing the code and arguments. - * @return The range. + * @return The range and new log event number. * @throws {Error} if the type of cursor is not supported. */ - #getCursorRange (cursor: CursorType): { beginLogEventNum: number, endLogEventNum: number } { + #getCursorData (cursor: CursorType): { + beginLogEventNum: number, endLogEventNum: + number, + newLogEventNum: number} { + let beginLogEventIdx: number = 0; + let beginLogEventNum: number = 1; + let endLogEventNum: number = 0; + let newLogEventNum: number = 1; + if (0 === this.#numEvents) { return { - beginLogEventNum: 1, - endLogEventNum: 0, + beginLogEventNum: beginLogEventNum, + endLogEventNum: endLogEventNum, + newLogEventNum: newLogEventNum, }; } - let beginLogEventIdx: number = 0; const {code, args} = cursor; if (CURSOR_CODE.PAGE_NUM === code) { beginLogEventIdx = ((args.pageNum - 1) * this.#pageSize); + [beginLogEventNum, endLogEventNum] = getRange( + this.#numEvents, + beginLogEventIdx, + this.#pageSize, + ); + if (LOG_EVENT_ANCHOR.FIRST === args.logEventAnchor) { + newLogEventNum = beginLogEventNum; + } else { + newLogEventNum = endLogEventNum; + } } if (CURSOR_CODE.LAST_EVENT === code || beginLogEventIdx > this.#numEvents) { // Set to the first event of the last page beginLogEventIdx = (getChunkNum(this.#numEvents, this.#pageSize) - 1) * this.#pageSize; + [beginLogEventNum, endLogEventNum] = getRange( + this.#numEvents, + beginLogEventIdx, + this.#pageSize, + ); + newLogEventNum = endLogEventNum; } else if (CURSOR_CODE.TIMESTAMP === code) { throw new Error(`Unsupported cursor type: ${code}`); } - const beginLogEventNum = beginLogEventIdx + 1; - const endLogEventNum = Math.min(this.#numEvents, beginLogEventNum + this.#pageSize - 1); - return {beginLogEventNum, endLogEventNum}; + + return {beginLogEventNum, endLogEventNum, newLogEventNum}; } } diff --git a/new-log-viewer/src/services/fileManager/utils.ts b/new-log-viewer/src/services/fileManager/utils.ts index 6f36d21a..308ca489 100644 --- a/new-log-viewer/src/services/fileManager/utils.ts +++ b/new-log-viewer/src/services/fileManager/utils.ts @@ -1,43 +1,28 @@ -import { - BeginLineNumToLogEventNumMap, - CURSOR_CODE, - CursorType, - FileSrcType, - LOG_EVENT_ANCHOR, -} from "../../typings/worker"; +import {FileSrcType} from "../../typings/worker"; import {getUint8ArrayFrom} from "../../utils/http"; import {getBasenameFromUrlOrDefault} from "../../utils/url"; /** - * Gets the new log event number. + * Gets the range of log events to decode based on beginning log event index. * - * @param cursor The cursor object containing the code and arguments. - * @param beginLineNumToLogEventNum - * @return The new log event number. - * @throws {Error} There are no log events on the page. + * @param numEvents + * @param beginLogEventIdx + * @param pageSize + * @return Array with beginning log event number and ending log event number. */ -const getNewLogEventNum = ( - cursor: CursorType, - beginLineNumToLogEventNum: BeginLineNumToLogEventNumMap -): number => { - const {code, args} = cursor; - const logEventNumOnPage: number[] = Array.from(beginLineNumToLogEventNum.values()); - - // Default to last event on page. - let newLogEventNum: number|undefined = logEventNumOnPage.at(-1); - - if (CURSOR_CODE.PAGE_NUM === code) { - if (LOG_EVENT_ANCHOR.FIRST === args.logEventAnchor) { - newLogEventNum = logEventNumOnPage.at(0); - } - } - - if (!newLogEventNum) { - throw Error("There are no log events on the page."); - } - - return newLogEventNum; +const getRange = ( + numEvents: number, + beginLogEventIdx: number, + pageSize: number +): [number, number] => { + const beginLogEventNum: number = beginLogEventIdx + 1; + + // Clamp ending index using total number of events. + const endLogEventNum: number = Math.min(numEvents, beginLogEventNum + pageSize - 1); + + return [beginLogEventNum, + endLogEventNum]; }; /** @@ -67,6 +52,6 @@ const loadFile = async (fileSrc: FileSrcType) }; export { - getNewLogEventNum, + getRange, loadFile, }; From 00501802347888e27e6a2dae110458e388e71237 Mon Sep 17 00:00:00 2001 From: Dave Marco Date: Tue, 24 Sep 2024 23:49:14 +0000 Subject: [PATCH 13/31] remove print --- new-log-viewer/src/contexts/StateContextProvider.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/new-log-viewer/src/contexts/StateContextProvider.tsx b/new-log-viewer/src/contexts/StateContextProvider.tsx index 4e3a7eaa..b0674fee 100644 --- a/new-log-viewer/src/contexts/StateContextProvider.tsx +++ b/new-log-viewer/src/contexts/StateContextProvider.tsx @@ -170,7 +170,6 @@ const StateContextProvider = ({children}: StateContextProviderProps) => { setLogData(args.logs); pageNumRef.current = args.pageNum; beginLineNumToLogEventNumRef.current = args.beginLineNumToLogEventNum; - console.log(args); // eslint-disable-next-line no-warning-comments // TODO: Without logEvent cursor, we cannot jump to logEvents. From a523d180a15601014f16438a1fe5be4977ac33c8 Mon Sep 17 00:00:00 2001 From: Dave Marco Date: Wed, 25 Sep 2024 21:00:07 +0000 Subject: [PATCH 14/31] added basic log event cursor and cleanup cursor switch in logFileManager --- .../src/components/Editor/index.tsx | 6 +- .../src/components/MenuBar/NavigationBar.tsx | 4 +- .../src/components/MenuBar/PageNumInput.tsx | 4 +- .../src/contexts/StateContextProvider.tsx | 118 ++++++------------ .../services/fileManager/LogFileManager.ts | 76 +++++------ .../src/services/fileManager/utils.ts | 74 ++++++++++- new-log-viewer/src/typings/worker.ts | 3 + 7 files changed, 155 insertions(+), 130 deletions(-) diff --git a/new-log-viewer/src/components/Editor/index.tsx b/new-log-viewer/src/components/Editor/index.tsx index 0d7a41bf..26cb7b3a 100644 --- a/new-log-viewer/src/components/Editor/index.tsx +++ b/new-log-viewer/src/components/Editor/index.tsx @@ -62,7 +62,7 @@ const resetCachedPageSize = () => { const Editor = () => { const {mode, systemMode} = useColorScheme(); - const {beginLineNumToLogEventNum, logData, loadPage} = useContext(StateContext); + const {beginLineNumToLogEventNum, logData, loadPageAction} = useContext(StateContext); const {logEventNum} = useContext(UrlContext); const [lineNum, setLineNum] = useState(1); @@ -82,7 +82,7 @@ const Editor = () => { case ACTION_NAME.PREV_PAGE: case ACTION_NAME.NEXT_PAGE: case ACTION_NAME.LAST_PAGE: - loadPage(ACTION_NAME.LAST_PAGE); + loadPageAction(ACTION_NAME.LAST_PAGE); break; case ACTION_NAME.PAGE_TOP: goToPositionAndCenter(editor, {lineNumber: 1, column: 1}); @@ -98,7 +98,7 @@ const Editor = () => { default: break; } - }, [loadPage]); + }, [loadPageAction]); /** * Sets `editorRef` and configures callbacks for mouse down detection. diff --git a/new-log-viewer/src/components/MenuBar/NavigationBar.tsx b/new-log-viewer/src/components/MenuBar/NavigationBar.tsx index 6de167aa..ef04fb89 100644 --- a/new-log-viewer/src/components/MenuBar/NavigationBar.tsx +++ b/new-log-viewer/src/components/MenuBar/NavigationBar.tsx @@ -17,12 +17,12 @@ import SmallIconButton from "./SmallIconButton"; * @return */ const NavigationBar = () => { - const {loadPage} = useContext(StateContext); + const {loadPageAction} = useContext(StateContext); const handleNavButtonClick = (event: React.MouseEvent) => { const {actionName} = event.currentTarget.dataset as { actionName: ACTION_NAME }; if (Object.values(ACTION_NAME).includes(actionName)) { - loadPage(actionName); + loadPageAction(actionName); } }; diff --git a/new-log-viewer/src/components/MenuBar/PageNumInput.tsx b/new-log-viewer/src/components/MenuBar/PageNumInput.tsx index d466a31b..340aeabc 100644 --- a/new-log-viewer/src/components/MenuBar/PageNumInput.tsx +++ b/new-log-viewer/src/components/MenuBar/PageNumInput.tsx @@ -23,7 +23,7 @@ const PAGE_NUM_INPUT_FIT_EXTRA_WIDTH = 2; * @return */ const PageNumInput = () => { - const {loadPage, numPages, pageNum} = useContext(StateContext); + const {loadPageAction, numPages, pageNum} = useContext(StateContext); const [isEditing, setIsEditing] = useState(false); const inputRef = useRef(null); @@ -36,7 +36,7 @@ const PageNumInput = () => { return; } - loadPage(ACTION_NAME.SPECIFIC_PAGE, Number(inputRef.current.value)); + loadPageAction(ACTION_NAME.SPECIFIC_PAGE, Number(inputRef.current.value)); setIsEditing(false); }; diff --git a/new-log-viewer/src/contexts/StateContextProvider.tsx b/new-log-viewer/src/contexts/StateContextProvider.tsx index b0674fee..c495562c 100644 --- a/new-log-viewer/src/contexts/StateContextProvider.tsx +++ b/new-log-viewer/src/contexts/StateContextProvider.tsx @@ -17,7 +17,6 @@ import { CURSOR_CODE, CursorType, FileSrcType, - LOG_EVENT_ANCHOR, MainWorkerRespMessage, WORKER_REQ_CODE, WORKER_RESP_CODE, @@ -31,10 +30,7 @@ import { EXPORT_LOGS_CHUNK_SIZE, getConfig, } from "../utils/config"; -import { - clamp, - getChunkNum, -} from "../utils/math"; +import {getChunkNum} from "../utils/math"; import { updateWindowUrlHashParams, updateWindowUrlSearchParams, @@ -55,7 +51,7 @@ interface StateContextType { exportLogs: () => void, loadFile: (fileSrc: FileSrcType, cursor: CursorType) => void, - loadPage: (action: ACTION_NAME, specificPageNum?: Nullable) => void, + loadPageAction: (action: ACTION_NAME, specificPageNum?: Nullable) => void, } const StateContext = createContext({} as StateContextType); @@ -73,34 +69,13 @@ const STATE_DEFAULT: Readonly = Object.freeze({ exportLogs: () => null, loadFile: () => null, - loadPage: () => null, + loadPageAction: () => null, }); interface StateContextProviderProps { children: React.ReactNode } -/** - * Updates the log event number in the current window's URL hash parameters. - * - * @param lastLogEventNum The last log event number value. - * @param inputLogEventNum The log event number to set. If `null`, the hash parameter log event - * number will be set to `lastLogEventNum`. If it's outside the range `[1, lastLogEventNum]`, the - * hash parameter log event number will be clamped to that range. - */ -const updateLogEventNumInUrl = ( - lastLogEventNum: number, - inputLogEventNum: Nullable -) => { - const newLogEventNum = (null === inputLogEventNum) ? - lastLogEventNum : - clamp(inputLogEventNum, 1, lastLogEventNum); - - updateWindowUrlHashParams({ - logEventNum: newLogEventNum, - }); -}; - /** * Sends a post message to a worker with the given code and arguments. This wrapper around * `worker.postMessage()` ensures type safety for both the request code and its corresponding @@ -126,7 +101,7 @@ const workerPostReq = ( * @param props.children * @return */ -// eslint-disable-next-line max-lines-per-function +// eslint-disable-next-line max-lines-per-function, max-statements const StateContextProvider = ({children}: StateContextProviderProps) => { const {filePath, logEventNum} = useContext(UrlContext); @@ -146,6 +121,7 @@ const StateContextProvider = ({children}: StateContextProviderProps) => { const logExportManagerRef = useRef(null); const mainWorkerRef = useRef(null); + // eslint-disable-next-line max-lines-per-function const handleMainWorkerResp = useCallback((ev: MessageEvent) => { const {code, args} = ev.data; console.log(`[MainWorker -> Renderer] code=${code}`); @@ -171,9 +147,8 @@ const StateContextProvider = ({children}: StateContextProviderProps) => { pageNumRef.current = args.pageNum; beginLineNumToLogEventNumRef.current = args.beginLineNumToLogEventNum; - // eslint-disable-next-line no-warning-comments - // TODO: Without logEvent cursor, we cannot jump to logEvents. - // Will be fixed once logEvent cursor is merged. + // Assume page data always provides a valid log event num. i.e. non null or + // outside range. updateWindowUrlHashParams({ logEventNum: args.logEventNum, }); @@ -236,8 +211,7 @@ const StateContextProvider = ({children}: StateContextProviderProps) => { ]); const loadPage = useCallback(( - action: ACTION_NAME, - specificPageNum: Nullable = null + cursor: CursorType, ) => { if (null === mainWorkerRef.current) { console.error("Unexpected null mainWorkerRef.current"); @@ -245,6 +219,16 @@ const StateContextProvider = ({children}: StateContextProviderProps) => { return; } + workerPostReq(mainWorkerRef.current, WORKER_REQ_CODE.LOAD_PAGE, { + cursor: cursor, + decoderOptions: getConfig(CONFIG_KEY.DECODER_OPTIONS), + }); + }, []); + + const loadPageAction = useCallback(( + action: ACTION_NAME, + specificPageNum: Nullable = null + ) => { const [newPageNum, anchor] = getPageNumCursorArgs( action, specificPageNum, @@ -258,12 +242,13 @@ const StateContextProvider = ({children}: StateContextProviderProps) => { return; } - workerPostReq(mainWorkerRef.current, WORKER_REQ_CODE.LOAD_PAGE, { - cursor: {code: CURSOR_CODE.PAGE_NUM, - args: {pageNum: newPageNum, logEventAnchor: anchor}}, - decoderOptions: getConfig(CONFIG_KEY.DECODER_OPTIONS), - }); - }, []); + const cursor: CursorType = { + code: CURSOR_CODE.PAGE_NUM, + args: {pageNum: newPageNum, logEventAnchor: anchor}, + }; + + loadPage(cursor); + }, [loadPage]); // Synchronize `logEventNumRef` with `logEventNum`. useEffect(() => { @@ -285,33 +270,22 @@ const StateContextProvider = ({children}: StateContextProviderProps) => { return; } - // eslint-disable-next-line no-warning-comments - // TODO: Remove newPageNum calc once log Event cursor complete. Instead - // we can check if in beginLineNumToLogEventNum, and if not send page request - // with logEvent cursor. - const newPageNum = clamp( - getChunkNum(logEventNum, getConfig(CONFIG_KEY.PAGE_SIZE)), - 1, - numPagesRef.current - ); - - // Request a page switch only if it's not the initial page load. - if (STATE_DEFAULT.pageNum !== pageNumRef.current) { - if (newPageNum === pageNumRef.current) { - // Don't need to switch pages so just update `logEventNum` in the URL. - updateLogEventNumInUrl(numEvents, logEventNumRef.current); - } else { - // NOTE: We don't need to call `updateLogEventNumInUrl()` since it's called when - // handling the `WORKER_RESP_CODE.PAGE_DATA` response (the response to - // `WORKER_REQ_CODE.LOAD_PAGE` requests). + const logEventNumsOnPage: number [] = + Array.from(beginLineNumToLogEventNumRef.current.values()); - // eslint-disable-next-line no-warning-comments - // TODO: Replace with logEvent cursor once its complete. - loadPage(ACTION_NAME.SPECIFIC_PAGE, newPageNum); - } + // Do nothing if log event is on the current page. There is no need to update it, since + // it was the URL change that triggered this useEffect. + if (logEventNumsOnPage.includes(logEventNum)) { + return; } + + const cursor: CursorType = { + code: CURSOR_CODE.EVENT_NUM, + args: {logEventNum: logEventNum}, + }; + + loadPage(cursor); }, [ - numEvents, logEventNum, loadPage, ]); @@ -324,18 +298,8 @@ const StateContextProvider = ({children}: StateContextProviderProps) => { let cursor: CursorType = {code: CURSOR_CODE.LAST_EVENT, args: null}; if (URL_HASH_PARAMS_DEFAULT.logEventNum !== logEventNumRef.current) { - // Set which page to load since the user specified a specific `logEventNum`. - // NOTE: Since we don't know how many pages the log file contains, we only clamp the - // minimum of the page number. - const newPageNum = Math.max( - getChunkNum(logEventNumRef.current, getConfig(CONFIG_KEY.PAGE_SIZE)), - 1 - ); - - // eslint-disable-next-line no-warning-comments - // TODO: Replace with logEvent cursor once its complete. - cursor = {code: CURSOR_CODE.PAGE_NUM, - args: {pageNum: newPageNum, logEventAnchor: LOG_EVENT_ANCHOR.FIRST}}; + cursor = {code: CURSOR_CODE.EVENT_NUM, + args: {logEventNum: logEventNumRef.current}}; } loadFile(filePath, cursor); }, [ @@ -356,7 +320,7 @@ const StateContextProvider = ({children}: StateContextProviderProps) => { exportLogs: exportLogs, loadFile: loadFile, - loadPage: loadPage, + loadPageAction: loadPageAction, }} > {children} diff --git a/new-log-viewer/src/services/fileManager/LogFileManager.ts b/new-log-viewer/src/services/fileManager/LogFileManager.ts index 80bf1ba5..7db5528f 100644 --- a/new-log-viewer/src/services/fileManager/LogFileManager.ts +++ b/new-log-viewer/src/services/fileManager/LogFileManager.ts @@ -9,7 +9,6 @@ import { CURSOR_CODE, CursorType, FileSrcType, - LOG_EVENT_ANCHOR, } from "../../typings/worker"; import {EXPORT_LOGS_CHUNK_SIZE} from "../../utils/config"; import {getChunkNum} from "../../utils/math"; @@ -17,7 +16,9 @@ import {formatSizeInBytes} from "../../utils/units"; import ClpIrDecoder from "../decoders/ClpIrDecoder"; import JsonlDecoder from "../decoders/JsonlDecoder"; import { - getRange, + getEventNumCursorData, + getLastEventCursorData, + getPageNumCursorData, loadFile, } from "./utils"; @@ -221,50 +222,37 @@ class LogFileManager { * @throws {Error} if the type of cursor is not supported. */ #getCursorData (cursor: CursorType): { - beginLogEventNum: number, endLogEventNum: - number, - newLogEventNum: number} { - let beginLogEventIdx: number = 0; - let beginLogEventNum: number = 1; - let endLogEventNum: number = 0; - let newLogEventNum: number = 1; - - if (0 === this.#numEvents) { - return { - beginLogEventNum: beginLogEventNum, - endLogEventNum: endLogEventNum, - newLogEventNum: newLogEventNum, - }; - } - + beginLogEventNum: number, + endLogEventNum: number, + newLogEventNum: number + } { const {code, args} = cursor; - if (CURSOR_CODE.PAGE_NUM === code) { - beginLogEventIdx = ((args.pageNum - 1) * this.#pageSize); - [beginLogEventNum, endLogEventNum] = getRange( - this.#numEvents, - beginLogEventIdx, - this.#pageSize, - ); - if (LOG_EVENT_ANCHOR.FIRST === args.logEventAnchor) { - newLogEventNum = beginLogEventNum; - } else { - newLogEventNum = endLogEventNum; - } - } - if (CURSOR_CODE.LAST_EVENT === code || beginLogEventIdx > this.#numEvents) { - // Set to the first event of the last page - beginLogEventIdx = (getChunkNum(this.#numEvents, this.#pageSize) - 1) * this.#pageSize; - [beginLogEventNum, endLogEventNum] = getRange( - this.#numEvents, - beginLogEventIdx, - this.#pageSize, - ); - newLogEventNum = endLogEventNum; - } else if (CURSOR_CODE.TIMESTAMP === code) { - throw new Error(`Unsupported cursor type: ${code}`); - } - return {beginLogEventNum, endLogEventNum, newLogEventNum}; + switch (code) { + case CURSOR_CODE.PAGE_NUM: + return getPageNumCursorData( + args.pageNum, + args.logEventAnchor, + this.#numEvents, + this.#pageSize + ); + + case CURSOR_CODE.LAST_EVENT: + return getLastEventCursorData( + this.#numEvents, + this.#pageSize + ); + + case CURSOR_CODE.EVENT_NUM: + return getEventNumCursorData( + args.logEventNum, + this.#numEvents, + this.#pageSize + ); + + default: + throw new Error(`Unsupported cursor type: ${code}`); + } } } diff --git a/new-log-viewer/src/services/fileManager/utils.ts b/new-log-viewer/src/services/fileManager/utils.ts index 308ca489..7a783a69 100644 --- a/new-log-viewer/src/services/fileManager/utils.ts +++ b/new-log-viewer/src/services/fileManager/utils.ts @@ -1,5 +1,12 @@ -import {FileSrcType} from "../../typings/worker"; +import { + FileSrcType, + LOG_EVENT_ANCHOR, +} from "../../typings/worker"; import {getUint8ArrayFrom} from "../../utils/http"; +import { + clamp, + getChunkNum, +} from "../../utils/math"; import {getBasenameFromUrlOrDefault} from "../../utils/url"; @@ -51,7 +58,70 @@ const loadFile = async (fileSrc: FileSrcType) }; }; +/** + * Gets range and new log event number using page number cursor + * + * @param pageNum + * @param logEventAnchor + * @param numEvents + * @param pageSize + * @return An object containing the range and the new log event number. + */ +const getPageNumCursorData = ( + pageNum: number, + logEventAnchor: LOG_EVENT_ANCHOR, + numEvents: number, + pageSize: number +): { beginLogEventNum: number; endLogEventNum: number; newLogEventNum: number } => { + const beginLogEventIdx = (pageNum - 1) * pageSize; + const [beginLogEventNum, endLogEventNum] = getRange(numEvents, beginLogEventIdx, pageSize); + const newLogEventNum = logEventAnchor === LOG_EVENT_ANCHOR.FIRST ? + beginLogEventNum : + endLogEventNum; + + return {beginLogEventNum, endLogEventNum, newLogEventNum}; +}; + +/** + * Gets range and new log event number using event number cursor. + * + * @param logEventNum + * @param numEvents + * @param pageSize + * @return An object containing the range and the new log event number. + */ +const getEventNumCursorData = ( + logEventNum: number, + numEvents: number, + pageSize: number +): { beginLogEventNum: number; endLogEventNum: number; newLogEventNum: number } => { + const validLogEventNum = clamp(logEventNum, 1, numEvents); + const beginLogEventIdx = (getChunkNum(validLogEventNum, pageSize) - 1) * pageSize; + const [beginLogEventNum, endLogEventNum] = getRange(numEvents, beginLogEventIdx, pageSize); + const newLogEventNum: number = validLogEventNum; + return {beginLogEventNum, endLogEventNum, newLogEventNum}; +}; + +/** + * Gets range and new log event number using last event cursor. + * + * @param numEvents + * @param pageSize + * @return An object containing the range and the new log event number. + */ +const getLastEventCursorData = ( + numEvents: number, + pageSize: number +): { beginLogEventNum: number; endLogEventNum: number; newLogEventNum: number } => { + const beginLogEventIdx = (getChunkNum(numEvents, pageSize) - 1) * pageSize; + const [beginLogEventNum, endLogEventNum] = getRange(numEvents, beginLogEventIdx, pageSize); + const newLogEventNum: number = endLogEventNum; + return {beginLogEventNum, endLogEventNum, newLogEventNum}; +}; + export { - getRange, + getEventNumCursorData, + getLastEventCursorData, + getPageNumCursorData, loadFile, }; diff --git a/new-log-viewer/src/typings/worker.ts b/new-log-viewer/src/typings/worker.ts index da620500..6676abca 100644 --- a/new-log-viewer/src/typings/worker.ts +++ b/new-log-viewer/src/typings/worker.ts @@ -19,17 +19,20 @@ enum LOG_EVENT_ANCHOR { /** * Enum of cursors used for locating some log event and navigating across pages. * - LAST_EVENT: the last event + * - EVENT_NUM: a specific log event number * - TIMESTAMP: the first event that has a timestamp >= the given value * - PAGE_NUM: the first or last event on the given page */ enum CURSOR_CODE { LAST_EVENT = "lastEvent", + EVENT_NUM = "eventNum", TIMESTAMP = "timestamp", PAGE_NUM = "pageNum" } type CursorArgMap = { [CURSOR_CODE.LAST_EVENT]: null; + [CURSOR_CODE.EVENT_NUM]: { logEventNum: number }; [CURSOR_CODE.TIMESTAMP]: { timestamp: number }; [CURSOR_CODE.PAGE_NUM]: { pageNum: number, logEventAnchor: LOG_EVENT_ANCHOR}; }; From cf096fa86063f9806c1bb9b6c3afd8139aa9b1f8 Mon Sep 17 00:00:00 2001 From: Dave Marco Date: Wed, 25 Sep 2024 21:08:51 +0000 Subject: [PATCH 15/31] small changes --- new-log-viewer/src/contexts/StateContextProvider.tsx | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/new-log-viewer/src/contexts/StateContextProvider.tsx b/new-log-viewer/src/contexts/StateContextProvider.tsx index c495562c..26dcf7ce 100644 --- a/new-log-viewer/src/contexts/StateContextProvider.tsx +++ b/new-log-viewer/src/contexts/StateContextProvider.tsx @@ -121,7 +121,6 @@ const StateContextProvider = ({children}: StateContextProviderProps) => { const logExportManagerRef = useRef(null); const mainWorkerRef = useRef(null); - // eslint-disable-next-line max-lines-per-function const handleMainWorkerResp = useCallback((ev: MessageEvent) => { const {code, args} = ev.data; console.log(`[MainWorker -> Renderer] code=${code}`); @@ -147,8 +146,8 @@ const StateContextProvider = ({children}: StateContextProviderProps) => { pageNumRef.current = args.pageNum; beginLineNumToLogEventNumRef.current = args.beginLineNumToLogEventNum; - // Assume page data always provides a valid log event num. i.e. non null or - // outside range. + // Assume page data always provides a valid log event num. i.e. non null and + // inside range. updateWindowUrlHashParams({ logEventNum: args.logEventNum, }); @@ -273,8 +272,10 @@ const StateContextProvider = ({children}: StateContextProviderProps) => { const logEventNumsOnPage: number [] = Array.from(beginLineNumToLogEventNumRef.current.values()); - // Do nothing if log event is on the current page. There is no need to update it, since - // it was the URL change that triggered this useEffect. + // eslint-disable-next-line no-warning-comments + // TODO: When filter is added, this will need to find the <= log event num on the page. + // If it is not the current log event, it will need to update it. However, a new request + // is not necessary. if (logEventNumsOnPage.includes(logEventNum)) { return; } From 99f40037d89e8875303ea78cc9e24b3b51736ac6 Mon Sep 17 00:00:00 2001 From: davemarco <83603688+davemarco@users.noreply.github.com> Date: Fri, 27 Sep 2024 11:24:01 -0400 Subject: [PATCH 16/31] Apply suggestions from code review Co-authored-by: kirkrodrigues <2454684+kirkrodrigues@users.noreply.github.com> --- new-log-viewer/src/components/Editor/index.tsx | 2 +- new-log-viewer/src/contexts/StateContextProvider.tsx | 3 --- new-log-viewer/src/services/fileManager/utils.ts | 6 ++++-- new-log-viewer/src/typings/worker.ts | 4 ++-- new-log-viewer/src/utils/actions.ts | 2 +- 5 files changed, 8 insertions(+), 9 deletions(-) diff --git a/new-log-viewer/src/components/Editor/index.tsx b/new-log-viewer/src/components/Editor/index.tsx index 26cb7b3a..afdb830b 100644 --- a/new-log-viewer/src/components/Editor/index.tsx +++ b/new-log-viewer/src/components/Editor/index.tsx @@ -82,7 +82,7 @@ const Editor = () => { case ACTION_NAME.PREV_PAGE: case ACTION_NAME.NEXT_PAGE: case ACTION_NAME.LAST_PAGE: - loadPageAction(ACTION_NAME.LAST_PAGE); + loadPageAction(actionName); break; case ACTION_NAME.PAGE_TOP: goToPositionAndCenter(editor, {lineNumber: 1, column: 1}); diff --git a/new-log-viewer/src/contexts/StateContextProvider.tsx b/new-log-viewer/src/contexts/StateContextProvider.tsx index 26dcf7ce..72af69cf 100644 --- a/new-log-viewer/src/contexts/StateContextProvider.tsx +++ b/new-log-viewer/src/contexts/StateContextProvider.tsx @@ -145,9 +145,6 @@ const StateContextProvider = ({children}: StateContextProviderProps) => { setLogData(args.logs); pageNumRef.current = args.pageNum; beginLineNumToLogEventNumRef.current = args.beginLineNumToLogEventNum; - - // Assume page data always provides a valid log event num. i.e. non null and - // inside range. updateWindowUrlHashParams({ logEventNum: args.logEventNum, }); diff --git a/new-log-viewer/src/services/fileManager/utils.ts b/new-log-viewer/src/services/fileManager/utils.ts index 7a783a69..1261c3c2 100644 --- a/new-log-viewer/src/services/fileManager/utils.ts +++ b/new-log-viewer/src/services/fileManager/utils.ts @@ -28,8 +28,10 @@ const getRange = ( // Clamp ending index using total number of events. const endLogEventNum: number = Math.min(numEvents, beginLogEventNum + pageSize - 1); - return [beginLogEventNum, - endLogEventNum]; + return [ + beginLogEventNum, + endLogEventNum, + ]; }; /** diff --git a/new-log-viewer/src/typings/worker.ts b/new-log-viewer/src/typings/worker.ts index 6676abca..a0ee7883 100644 --- a/new-log-viewer/src/typings/worker.ts +++ b/new-log-viewer/src/typings/worker.ts @@ -19,7 +19,7 @@ enum LOG_EVENT_ANCHOR { /** * Enum of cursors used for locating some log event and navigating across pages. * - LAST_EVENT: the last event - * - EVENT_NUM: a specific log event number + * - EVENT_NUM: a specific log event * - TIMESTAMP: the first event that has a timestamp >= the given value * - PAGE_NUM: the first or last event on the given page */ @@ -34,7 +34,7 @@ type CursorArgMap = { [CURSOR_CODE.LAST_EVENT]: null; [CURSOR_CODE.EVENT_NUM]: { logEventNum: number }; [CURSOR_CODE.TIMESTAMP]: { timestamp: number }; - [CURSOR_CODE.PAGE_NUM]: { pageNum: number, logEventAnchor: LOG_EVENT_ANCHOR}; + [CURSOR_CODE.PAGE_NUM]: { pageNum: number, logEventAnchor: LOG_EVENT_ANCHOR }; }; type CursorType = { diff --git a/new-log-viewer/src/utils/actions.ts b/new-log-viewer/src/utils/actions.ts index b1c6ae40..e36d398b 100644 --- a/new-log-viewer/src/utils/actions.ts +++ b/new-log-viewer/src/utils/actions.ts @@ -3,7 +3,7 @@ import * as monaco from "monaco-editor/esm/vs/editor/editor.api.js"; import {STATE_DEFAULT} from "../contexts/StateContextProvider"; import {Nullable} from "../typings/common"; import {LOG_EVENT_ANCHOR} from "../typings/worker"; -import {clamp} from "../utils/math"; +import {clamp} from "./math"; enum ACTION_NAME { From 78a1f8f66694c0ae4b88d6c2d74573256bd922e8 Mon Sep 17 00:00:00 2001 From: Dave Marco Date: Fri, 27 Sep 2024 19:00:06 +0000 Subject: [PATCH 17/31] kirk review --- .../src/components/Editor/index.tsx | 6 +- .../src/components/MenuBar/NavigationBar.tsx | 15 ++- .../src/components/MenuBar/PageNumInput.tsx | 7 +- .../src/contexts/StateContextProvider.tsx | 91 +++++++++++------ .../index.ts} | 4 +- .../{fileManager => LogFileManager}/utils.ts | 10 +- new-log-viewer/src/services/MainWorker.ts | 2 +- new-log-viewer/src/typings/worker.ts | 16 +-- new-log-viewer/src/utils/actions.ts | 98 ++++--------------- 9 files changed, 119 insertions(+), 130 deletions(-) rename new-log-viewer/src/services/{fileManager/LogFileManager.ts => LogFileManager/index.ts} (99%) rename new-log-viewer/src/services/{fileManager => LogFileManager}/utils.ts (93%) diff --git a/new-log-viewer/src/components/Editor/index.tsx b/new-log-viewer/src/components/Editor/index.tsx index afdb830b..fac3101a 100644 --- a/new-log-viewer/src/components/Editor/index.tsx +++ b/new-log-viewer/src/components/Editor/index.tsx @@ -62,7 +62,7 @@ const resetCachedPageSize = () => { const Editor = () => { const {mode, systemMode} = useColorScheme(); - const {beginLineNumToLogEventNum, logData, loadPageAction} = useContext(StateContext); + const {beginLineNumToLogEventNum, logData, loadPageByAction} = useContext(StateContext); const {logEventNum} = useContext(UrlContext); const [lineNum, setLineNum] = useState(1); @@ -82,7 +82,7 @@ const Editor = () => { case ACTION_NAME.PREV_PAGE: case ACTION_NAME.NEXT_PAGE: case ACTION_NAME.LAST_PAGE: - loadPageAction(actionName); + loadPageByAction({code: actionName}); break; case ACTION_NAME.PAGE_TOP: goToPositionAndCenter(editor, {lineNumber: 1, column: 1}); @@ -98,7 +98,7 @@ const Editor = () => { default: break; } - }, [loadPageAction]); + }, [loadPageByAction]); /** * Sets `editorRef` and configures callbacks for mouse down detection. diff --git a/new-log-viewer/src/components/MenuBar/NavigationBar.tsx b/new-log-viewer/src/components/MenuBar/NavigationBar.tsx index ef04fb89..9718d559 100644 --- a/new-log-viewer/src/components/MenuBar/NavigationBar.tsx +++ b/new-log-viewer/src/components/MenuBar/NavigationBar.tsx @@ -17,12 +17,19 @@ import SmallIconButton from "./SmallIconButton"; * @return */ const NavigationBar = () => { - const {loadPageAction} = useContext(StateContext); + const {loadPageByAction} = useContext(StateContext); const handleNavButtonClick = (event: React.MouseEvent) => { - const {actionName} = event.currentTarget.dataset as { actionName: ACTION_NAME }; - if (Object.values(ACTION_NAME).includes(actionName)) { - loadPageAction(actionName); + const {actionName} = event.currentTarget.dataset; + + // Makes sure actionName is a valid navigation action code with no args. + if ( + actionName === ACTION_NAME.FIRST_PAGE || + actionName === ACTION_NAME.PREV_PAGE || + actionName === ACTION_NAME.NEXT_PAGE || + actionName === ACTION_NAME.LAST_PAGE + ) { + loadPageByAction({code: actionName}); } }; diff --git a/new-log-viewer/src/components/MenuBar/PageNumInput.tsx b/new-log-viewer/src/components/MenuBar/PageNumInput.tsx index 340aeabc..9c953f29 100644 --- a/new-log-viewer/src/components/MenuBar/PageNumInput.tsx +++ b/new-log-viewer/src/components/MenuBar/PageNumInput.tsx @@ -23,7 +23,7 @@ const PAGE_NUM_INPUT_FIT_EXTRA_WIDTH = 2; * @return */ const PageNumInput = () => { - const {loadPageAction, numPages, pageNum} = useContext(StateContext); + const {loadPageByAction, numPages, pageNum} = useContext(StateContext); const [isEditing, setIsEditing] = useState(false); const inputRef = useRef(null); @@ -36,7 +36,10 @@ const PageNumInput = () => { return; } - loadPageAction(ACTION_NAME.SPECIFIC_PAGE, Number(inputRef.current.value)); + loadPageByAction({ + code: ACTION_NAME.SPECIFIC_PAGE, + args: {specificPageNum: Number(inputRef.current.value)}, + }); setIsEditing(false); }; diff --git a/new-log-viewer/src/contexts/StateContextProvider.tsx b/new-log-viewer/src/contexts/StateContextProvider.tsx index 72af69cf..0db8141c 100644 --- a/new-log-viewer/src/contexts/StateContextProvider.tsx +++ b/new-log-viewer/src/contexts/StateContextProvider.tsx @@ -16,6 +16,7 @@ import { BeginLineNumToLogEventNumMap, CURSOR_CODE, CursorType, + EVENT_POSITION, FileSrcType, MainWorkerRespMessage, WORKER_REQ_CODE, @@ -24,13 +25,16 @@ import { } from "../typings/worker"; import { ACTION_NAME, - getPageNumCursorArgs, + NavigationAction, } from "../utils/actions"; import { EXPORT_LOGS_CHUNK_SIZE, getConfig, } from "../utils/config"; -import {getChunkNum} from "../utils/math"; +import { + clamp, + getChunkNum, +} from "../utils/math"; import { updateWindowUrlHashParams, updateWindowUrlSearchParams, @@ -51,7 +55,7 @@ interface StateContextType { exportLogs: () => void, loadFile: (fileSrc: FileSrcType, cursor: CursorType) => void, - loadPageAction: (action: ACTION_NAME, specificPageNum?: Nullable) => void, + loadPageByAction: (navAction: NavigationAction) => void, } const StateContext = createContext({} as StateContextType); @@ -69,7 +73,7 @@ const STATE_DEFAULT: Readonly = Object.freeze({ exportLogs: () => null, loadFile: () => null, - loadPageAction: () => null, + loadPageByAction: () => null, }); interface StateContextProviderProps { @@ -206,7 +210,7 @@ const StateContextProvider = ({children}: StateContextProviderProps) => { handleMainWorkerResp, ]); - const loadPage = useCallback(( + const loadPageByCursor = useCallback(( cursor: CursorType, ) => { if (null === mainWorkerRef.current) { @@ -221,35 +225,64 @@ const StateContextProvider = ({children}: StateContextProviderProps) => { }); }, []); - const loadPageAction = useCallback(( - action: ACTION_NAME, - specificPageNum: Nullable = null - ) => { - const [newPageNum, anchor] = getPageNumCursorArgs( - action, - specificPageNum, - pageNumRef.current, - numPagesRef.current - ); + const getPageNumCursor = useCallback((navAction: NavigationAction): Nullable => { + let newPageNum: number; + let position: EVENT_POSITION; - if (null === newPageNum || null === anchor) { - console.error(`Error with page action ${action}.`); + if (STATE_DEFAULT.pageNum === pageNumRef.current) { + console.error("Page actions cannot be executed if the current page is not set."); - return; + return null; } - const cursor: CursorType = { + switch (navAction.code) { + case ACTION_NAME.SPECIFIC_PAGE: + position = EVENT_POSITION.TOP; + + // Clamp is to prevent someone from requesting non-existent page. + newPageNum = clamp(navAction.args.specificPageNum, 1, numPagesRef.current); + break; + case ACTION_NAME.FIRST_PAGE: + position = EVENT_POSITION.TOP; + newPageNum = 1; + break; + case ACTION_NAME.PREV_PAGE: + position = EVENT_POSITION.BOTTOM; + newPageNum = clamp(pageNumRef.current - 1, 1, numPagesRef.current); + break; + case ACTION_NAME.NEXT_PAGE: + position = EVENT_POSITION.TOP; + newPageNum = clamp(pageNumRef.current + 1, 1, numPagesRef.current); + break; + case ACTION_NAME.LAST_PAGE: + position = EVENT_POSITION.BOTTOM; + newPageNum = numPagesRef.current; + break; + default: + return null; + } + + return { code: CURSOR_CODE.PAGE_NUM, - args: {pageNum: newPageNum, logEventAnchor: anchor}, + args: {pageNum: newPageNum, eventPosition: position}, }; + }, []); - loadPage(cursor); - }, [loadPage]); + const loadPageByAction = useCallback((navAction: NavigationAction) => { + const cursor = getPageNumCursor(navAction); + + if (null === cursor) { + console.error(`Error with nav action ${navAction.code}.`); + + return; + } + + loadPageByCursor(cursor); + }, [ + getPageNumCursor, + loadPageByCursor, + ]); - // Synchronize `logEventNumRef` with `logEventNum`. - useEffect(() => { - logEventNumRef.current = logEventNum; - }, [logEventNum]); // On `numEvents` update, recalculate `numPagesRef`. useEffect(() => { @@ -282,10 +315,10 @@ const StateContextProvider = ({children}: StateContextProviderProps) => { args: {logEventNum: logEventNum}, }; - loadPage(cursor); + loadPageByCursor(cursor); }, [ logEventNum, - loadPage, + loadPageByCursor, ]); // On `filePath` update, load file. @@ -318,7 +351,7 @@ const StateContextProvider = ({children}: StateContextProviderProps) => { exportLogs: exportLogs, loadFile: loadFile, - loadPageAction: loadPageAction, + loadPageByAction: loadPageByAction, }} > {children} diff --git a/new-log-viewer/src/services/fileManager/LogFileManager.ts b/new-log-viewer/src/services/LogFileManager/index.ts similarity index 99% rename from new-log-viewer/src/services/fileManager/LogFileManager.ts rename to new-log-viewer/src/services/LogFileManager/index.ts index 7db5528f..047346c5 100644 --- a/new-log-viewer/src/services/fileManager/LogFileManager.ts +++ b/new-log-viewer/src/services/LogFileManager/index.ts @@ -180,7 +180,7 @@ class LogFileManager { console.debug(`loadPage: cursor=${JSON.stringify(cursor)}`); const {beginLogEventNum, endLogEventNum, newLogEventNum} = this.#getCursorData(cursor); - const results = this.#decoder.decode(beginLogEventNum - 1, endLogEventNum); + const results = this.#decoder.decode(beginLogEventNum - 1, endLogEventNum - 1); if (null === results) { throw new Error("Error occurred during decoding. " + `beginLogEventNum=${beginLogEventNum}, ` + @@ -232,7 +232,7 @@ class LogFileManager { case CURSOR_CODE.PAGE_NUM: return getPageNumCursorData( args.pageNum, - args.logEventAnchor, + args.eventPosition, this.#numEvents, this.#pageSize ); diff --git a/new-log-viewer/src/services/fileManager/utils.ts b/new-log-viewer/src/services/LogFileManager/utils.ts similarity index 93% rename from new-log-viewer/src/services/fileManager/utils.ts rename to new-log-viewer/src/services/LogFileManager/utils.ts index 1261c3c2..96da16c9 100644 --- a/new-log-viewer/src/services/fileManager/utils.ts +++ b/new-log-viewer/src/services/LogFileManager/utils.ts @@ -1,6 +1,6 @@ import { + EVENT_POSITION, FileSrcType, - LOG_EVENT_ANCHOR, } from "../../typings/worker"; import {getUint8ArrayFrom} from "../../utils/http"; import { @@ -26,7 +26,7 @@ const getRange = ( const beginLogEventNum: number = beginLogEventIdx + 1; // Clamp ending index using total number of events. - const endLogEventNum: number = Math.min(numEvents, beginLogEventNum + pageSize - 1); + const endLogEventNum: number = Math.min(numEvents + 1, beginLogEventNum + pageSize); return [ beginLogEventNum, @@ -64,20 +64,20 @@ const loadFile = async (fileSrc: FileSrcType) * Gets range and new log event number using page number cursor * * @param pageNum - * @param logEventAnchor + * @param eventPosition * @param numEvents * @param pageSize * @return An object containing the range and the new log event number. */ const getPageNumCursorData = ( pageNum: number, - logEventAnchor: LOG_EVENT_ANCHOR, + eventPosition: EVENT_POSITION, numEvents: number, pageSize: number ): { beginLogEventNum: number; endLogEventNum: number; newLogEventNum: number } => { const beginLogEventIdx = (pageNum - 1) * pageSize; const [beginLogEventNum, endLogEventNum] = getRange(numEvents, beginLogEventIdx, pageSize); - const newLogEventNum = logEventAnchor === LOG_EVENT_ANCHOR.FIRST ? + const newLogEventNum = eventPosition === EVENT_POSITION.TOP ? beginLogEventNum : endLogEventNum; diff --git a/new-log-viewer/src/services/MainWorker.ts b/new-log-viewer/src/services/MainWorker.ts index 56ebadcb..a04d134c 100644 --- a/new-log-viewer/src/services/MainWorker.ts +++ b/new-log-viewer/src/services/MainWorker.ts @@ -10,7 +10,7 @@ import { WorkerResp, } from "../typings/worker"; import {EXPORT_LOGS_CHUNK_SIZE} from "../utils/config"; -import LogFileManager from "./fileManager/LogFileManager"; +import LogFileManager from "./LogFileManager"; /* eslint-disable import/no-named-as-default-member */ diff --git a/new-log-viewer/src/typings/worker.ts b/new-log-viewer/src/typings/worker.ts index a0ee7883..b648a405 100644 --- a/new-log-viewer/src/typings/worker.ts +++ b/new-log-viewer/src/typings/worker.ts @@ -7,13 +7,14 @@ import {LOG_LEVEL} from "./logs"; */ type FileSrcType = string | File; + /** - * Indicates whether the log event number should be anchored to the top or bottom of the page. - * Used as input for the page number cursor. + * For a page requested by the page number `CURSOR_CODE`, this enum indicates which log event + * number (e.g., first on page, or last on page) should be returned with the page. */ -enum LOG_EVENT_ANCHOR { - FIRST = "first", - LAST = "last", +enum EVENT_POSITION { + TOP, + BOTTOM, } /** @@ -34,7 +35,7 @@ type CursorArgMap = { [CURSOR_CODE.LAST_EVENT]: null; [CURSOR_CODE.EVENT_NUM]: { logEventNum: number }; [CURSOR_CODE.TIMESTAMP]: { timestamp: number }; - [CURSOR_CODE.PAGE_NUM]: { pageNum: number, logEventAnchor: LOG_EVENT_ANCHOR }; + [CURSOR_CODE.PAGE_NUM]: { pageNum: number, eventPosition: EVENT_POSITION }; }; type CursorType = { @@ -107,6 +108,7 @@ type WorkerResp = T extends keyof WorkerRespMap ? WorkerRespMap[T] : never; + type MainWorkerReqMessage = { [T in keyof WorkerReqMap]: { code: T, args: WorkerReqMap[T] }; }[keyof WorkerReqMap]; @@ -117,7 +119,7 @@ type MainWorkerRespMessage = { export { CURSOR_CODE, - LOG_EVENT_ANCHOR, + EVENT_POSITION, WORKER_REQ_CODE, WORKER_RESP_CODE, }; diff --git a/new-log-viewer/src/utils/actions.ts b/new-log-viewer/src/utils/actions.ts index e36d398b..0db23281 100644 --- a/new-log-viewer/src/utils/actions.ts +++ b/new-log-viewer/src/utils/actions.ts @@ -1,9 +1,6 @@ import * as monaco from "monaco-editor/esm/vs/editor/editor.api.js"; -import {STATE_DEFAULT} from "../contexts/StateContextProvider"; import {Nullable} from "../typings/common"; -import {LOG_EVENT_ANCHOR} from "../typings/worker"; -import {clamp} from "./math"; enum ACTION_NAME { @@ -65,83 +62,30 @@ const EDITOR_ACTIONS : ActionType[] = [ }, ]; -/** - * Calculates the new page number and log event anchor for the page number cursor. - * - * @param action - * @param specificPageNum Page number for specific page action. - * @param currentPageNum - * @param numPages - * @return The new page number and the log event anchor required for the page number cursor. - * Returns null if the action is not setup or there is an error validating inputs. - */ -const getPageNumCursorArgs = ( - action: ACTION_NAME, - specificPageNum: Nullable, - currentPageNum: number, - numPages: number -): [Nullable, Nullable] => { - let newPageNum: number; - let anchor: LOG_EVENT_ANCHOR; - - if (null === specificPageNum && ACTION_NAME.SPECIFIC_PAGE === action) { - console.error("Specific page action missing required page input"); - - return [ - null, - null, - ]; - } - - if (STATE_DEFAULT.pageNum === currentPageNum) { - console.error("Page actions cannot be executed if the current page is not set."); - - return [ - null, - null, - ]; - } - - switch (action) { - case ACTION_NAME.SPECIFIC_PAGE: - anchor = LOG_EVENT_ANCHOR.FIRST; - - // specificPageNum cannot be null, since already checked during loadPage validation. - // Clamp is to prevent someone from requesting non-existent page. - newPageNum = clamp(specificPageNum as number, 1, numPages); - break; - case ACTION_NAME.FIRST_PAGE: - anchor = LOG_EVENT_ANCHOR.FIRST; - newPageNum = 1; - break; - case ACTION_NAME.PREV_PAGE: - anchor = LOG_EVENT_ANCHOR.LAST; - newPageNum = clamp(currentPageNum - 1, 1, numPages); - break; - case ACTION_NAME.NEXT_PAGE: - anchor = LOG_EVENT_ANCHOR.FIRST; - newPageNum = clamp(currentPageNum + 1, 1, numPages); - break; - case ACTION_NAME.LAST_PAGE: - anchor = LOG_EVENT_ANCHOR.LAST; - newPageNum = numPages; - break; - default: - return [ - null, - null, - ]; - } - - return [ - newPageNum, - anchor, - ]; +type NavigationActionsMap = { + [ACTION_NAME.SPECIFIC_PAGE]: { + specificPageNum: number, + }, + [ACTION_NAME.FIRST_PAGE]: null + , + [ACTION_NAME.PREV_PAGE]: null + , + [ACTION_NAME.NEXT_PAGE]: null + , + [ACTION_NAME.LAST_PAGE]: null }; +type NavigationAction = { + [T in keyof NavigationActionsMap]: NavigationActionsMap[T] extends object ? + {code: T, args: NavigationActionsMap[T]} : + {code: T}; + } [keyof NavigationActionsMap]; + export { ACTION_NAME, EDITOR_ACTIONS, - getPageNumCursorArgs, }; -export type {ActionType}; +export type { + ActionType, + NavigationAction, +}; From a11295adeecbced44fb98bfe8c323be0054bc87b Mon Sep 17 00:00:00 2001 From: Dave Marco Date: Fri, 27 Sep 2024 19:10:22 +0000 Subject: [PATCH 18/31] add comment --- new-log-viewer/src/utils/actions.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/new-log-viewer/src/utils/actions.ts b/new-log-viewer/src/utils/actions.ts index 0db23281..fc708cb2 100644 --- a/new-log-viewer/src/utils/actions.ts +++ b/new-log-viewer/src/utils/actions.ts @@ -75,6 +75,7 @@ type NavigationActionsMap = { [ACTION_NAME.LAST_PAGE]: null }; +// Some navigation actions supply code and args fields, and others only code field. type NavigationAction = { [T in keyof NavigationActionsMap]: NavigationActionsMap[T] extends object ? {code: T, args: NavigationActionsMap[T]} : From 18599f13e39e60e903e06b29a372019455d27230 Mon Sep 17 00:00:00 2001 From: davemarco <83603688+davemarco@users.noreply.github.com> Date: Mon, 30 Sep 2024 11:19:17 -0400 Subject: [PATCH 19/31] Apply suggestions from code review Co-authored-by: kirkrodrigues <2454684+kirkrodrigues@users.noreply.github.com> --- .../src/components/MenuBar/NavigationBar.tsx | 2 +- .../src/contexts/StateContextProvider.tsx | 8 +++--- .../src/services/LogFileManager/index.ts | 1 - .../src/services/LogFileManager/utils.ts | 25 +++++++++++++------ new-log-viewer/src/typings/worker.ts | 6 ++--- new-log-viewer/src/utils/actions.ts | 11 +++----- 6 files changed, 28 insertions(+), 25 deletions(-) diff --git a/new-log-viewer/src/components/MenuBar/NavigationBar.tsx b/new-log-viewer/src/components/MenuBar/NavigationBar.tsx index 9718d559..e09866bb 100644 --- a/new-log-viewer/src/components/MenuBar/NavigationBar.tsx +++ b/new-log-viewer/src/components/MenuBar/NavigationBar.tsx @@ -22,7 +22,7 @@ const NavigationBar = () => { const handleNavButtonClick = (event: React.MouseEvent) => { const {actionName} = event.currentTarget.dataset; - // Makes sure actionName is a valid navigation action code with no args. + // Ensure `actionName` is a valid navigation action code with no args. if ( actionName === ACTION_NAME.FIRST_PAGE || actionName === ACTION_NAME.PREV_PAGE || diff --git a/new-log-viewer/src/contexts/StateContextProvider.tsx b/new-log-viewer/src/contexts/StateContextProvider.tsx index 0db8141c..28526286 100644 --- a/new-log-viewer/src/contexts/StateContextProvider.tsx +++ b/new-log-viewer/src/contexts/StateContextProvider.tsx @@ -270,7 +270,6 @@ const StateContextProvider = ({children}: StateContextProviderProps) => { const loadPageByAction = useCallback((navAction: NavigationAction) => { const cursor = getPageNumCursor(navAction); - if (null === cursor) { console.error(`Error with nav action ${navAction.code}.`); @@ -283,7 +282,6 @@ const StateContextProvider = ({children}: StateContextProviderProps) => { loadPageByCursor, ]); - // On `numEvents` update, recalculate `numPagesRef`. useEffect(() => { if (STATE_DEFAULT.numEvents === numEvents) { @@ -329,8 +327,10 @@ const StateContextProvider = ({children}: StateContextProviderProps) => { let cursor: CursorType = {code: CURSOR_CODE.LAST_EVENT, args: null}; if (URL_HASH_PARAMS_DEFAULT.logEventNum !== logEventNumRef.current) { - cursor = {code: CURSOR_CODE.EVENT_NUM, - args: {logEventNum: logEventNumRef.current}}; + cursor = { + code: CURSOR_CODE.EVENT_NUM, + args: {logEventNum: logEventNumRef.current}, + }; } loadFile(filePath, cursor); }, [ diff --git a/new-log-viewer/src/services/LogFileManager/index.ts b/new-log-viewer/src/services/LogFileManager/index.ts index 047346c5..a7397a5d 100644 --- a/new-log-viewer/src/services/LogFileManager/index.ts +++ b/new-log-viewer/src/services/LogFileManager/index.ts @@ -227,7 +227,6 @@ class LogFileManager { newLogEventNum: number } { const {code, args} = cursor; - switch (code) { case CURSOR_CODE.PAGE_NUM: return getPageNumCursorData( diff --git a/new-log-viewer/src/services/LogFileManager/utils.ts b/new-log-viewer/src/services/LogFileManager/utils.ts index 96da16c9..0d64c27d 100644 --- a/new-log-viewer/src/services/LogFileManager/utils.ts +++ b/new-log-viewer/src/services/LogFileManager/utils.ts @@ -11,12 +11,15 @@ import {getBasenameFromUrlOrDefault} from "../../utils/url"; /** - * Gets the range of log events to decode based on beginning log event index. + * Gets the log event number range [begin, end) of the page that starts at the given log event + * index. * * @param numEvents * @param beginLogEventIdx * @param pageSize - * @return Array with beginning log event number and ending log event number. + * @return An array: + * - beginLogEventNum + * - endLogEventNum */ const getRange = ( numEvents: number, @@ -61,13 +64,15 @@ const loadFile = async (fileSrc: FileSrcType) }; /** - * Gets range and new log event number using page number cursor + * Gets the data for the `PAGE_NUM` cursor. * * @param pageNum * @param eventPosition * @param numEvents * @param pageSize - * @return An object containing the range and the new log event number. + * @return Log event numbers for: + * - the range [begin, end) of page `pageNum`. + * - the log event (on the page) indicated by `eventPosition`. */ const getPageNumCursorData = ( pageNum: number, @@ -85,12 +90,14 @@ const getPageNumCursorData = ( }; /** - * Gets range and new log event number using event number cursor. + * Gets the data for the `EVENT_NUM` cursor. * * @param logEventNum * @param numEvents * @param pageSize - * @return An object containing the range and the new log event number. + * @return Log event numbers for: + * - the range [begin, end) of the page containing `logEventNum`. + * - log event `logEventNum`. */ const getEventNumCursorData = ( logEventNum: number, @@ -105,11 +112,13 @@ const getEventNumCursorData = ( }; /** - * Gets range and new log event number using last event cursor. + * Gets the data for the `LAST` cursor. * * @param numEvents * @param pageSize - * @return An object containing the range and the new log event number. + * @return Log event numbers for: + * - the range [begin, end) of the last page. + * - the last log event on the last page. */ const getLastEventCursorData = ( numEvents: number, diff --git a/new-log-viewer/src/typings/worker.ts b/new-log-viewer/src/typings/worker.ts index b648a405..3010f30c 100644 --- a/new-log-viewer/src/typings/worker.ts +++ b/new-log-viewer/src/typings/worker.ts @@ -7,10 +7,9 @@ import {LOG_LEVEL} from "./logs"; */ type FileSrcType = string | File; - /** - * For a page requested by the page number `CURSOR_CODE`, this enum indicates which log event - * number (e.g., first on page, or last on page) should be returned with the page. + * For `CURSOR_CODE.PAGE_NUM`, this enum indicates which log event number (e.g., first/last on page) + * should be returned with the page. */ enum EVENT_POSITION { TOP, @@ -108,7 +107,6 @@ type WorkerResp = T extends keyof WorkerRespMap ? WorkerRespMap[T] : never; - type MainWorkerReqMessage = { [T in keyof WorkerReqMap]: { code: T, args: WorkerReqMap[T] }; }[keyof WorkerReqMap]; diff --git a/new-log-viewer/src/utils/actions.ts b/new-log-viewer/src/utils/actions.ts index fc708cb2..1ba3c0ef 100644 --- a/new-log-viewer/src/utils/actions.ts +++ b/new-log-viewer/src/utils/actions.ts @@ -66,13 +66,10 @@ type NavigationActionsMap = { [ACTION_NAME.SPECIFIC_PAGE]: { specificPageNum: number, }, - [ACTION_NAME.FIRST_PAGE]: null - , - [ACTION_NAME.PREV_PAGE]: null - , - [ACTION_NAME.NEXT_PAGE]: null - , - [ACTION_NAME.LAST_PAGE]: null + [ACTION_NAME.FIRST_PAGE]: null, + [ACTION_NAME.PREV_PAGE]: null, + [ACTION_NAME.NEXT_PAGE]: null, + [ACTION_NAME.LAST_PAGE]: null, }; // Some navigation actions supply code and args fields, and others only code field. From 829ba10b41f22ef92386e3fc082d7b6647d2b18d Mon Sep 17 00:00:00 2001 From: Dave Marco Date: Mon, 30 Sep 2024 17:58:18 +0000 Subject: [PATCH 20/31] kirk review 2 --- .../Editor/MonacoInstance/actions.ts | 4 +- .../Editor/MonacoInstance/index.tsx | 4 +- .../components/Editor/MonacoInstance/utils.ts | 4 +- .../src/components/MenuBar/PageNumInput.tsx | 2 +- .../src/contexts/StateContextProvider.tsx | 54 ++++---- .../src/services/LogFileManager/index.ts | 35 +++--- .../src/services/LogFileManager/utils.ts | 118 ++++++++++-------- new-log-viewer/src/typings/worker.ts | 8 +- new-log-viewer/src/utils/actions.ts | 9 +- 9 files changed, 135 insertions(+), 103 deletions(-) diff --git a/new-log-viewer/src/components/Editor/MonacoInstance/actions.ts b/new-log-viewer/src/components/Editor/MonacoInstance/actions.ts index c30dc04b..e32e93f5 100644 --- a/new-log-viewer/src/components/Editor/MonacoInstance/actions.ts +++ b/new-log-viewer/src/components/Editor/MonacoInstance/actions.ts @@ -1,7 +1,7 @@ import * as monaco from "monaco-editor/esm/vs/editor/editor.api.js"; import {Nullable} from "../../../typings/common"; -import {ActionType} from "../../../utils/actions"; +import {EditorAction} from "../../../utils/actions"; import {clamp} from "../../../utils/math"; import type { CursorExplicitPosChangeCallback, @@ -152,7 +152,7 @@ const setupMobileZoom = ( */ const setupCustomActions = ( editor: monaco.editor.IStandaloneCodeEditor, - actions: ActionType[], + actions: EditorAction[], onCustomAction: CustomActionCallback ) => { actions.forEach(({actionName, label, keyBindings}) => { diff --git a/new-log-viewer/src/components/Editor/MonacoInstance/index.tsx b/new-log-viewer/src/components/Editor/MonacoInstance/index.tsx index 0d0af05d..b23da3fc 100644 --- a/new-log-viewer/src/components/Editor/MonacoInstance/index.tsx +++ b/new-log-viewer/src/components/Editor/MonacoInstance/index.tsx @@ -5,7 +5,7 @@ import { import * as monaco from "monaco-editor/esm/vs/editor/editor.api"; -import {ActionType} from "../../../utils/actions"; +import {EditorAction} from "../../../utils/actions"; import { BeforeMountCallback, BeforeTextUpdateCallback, @@ -23,7 +23,7 @@ import "./index.css"; interface MonacoEditorProps { - actions: ActionType[], + actions: EditorAction[], lineNum: number, text: string, themeName: "dark" | "light", diff --git a/new-log-viewer/src/components/Editor/MonacoInstance/utils.ts b/new-log-viewer/src/components/Editor/MonacoInstance/utils.ts index 9ab6af59..d63d277b 100644 --- a/new-log-viewer/src/components/Editor/MonacoInstance/utils.ts +++ b/new-log-viewer/src/components/Editor/MonacoInstance/utils.ts @@ -1,6 +1,6 @@ import * as monaco from "monaco-editor/esm/vs/editor/editor.api.js"; -import {ActionType} from "../../../utils/actions"; +import {EditorAction} from "../../../utils/actions"; import { setupCursorExplicitPosChangeCallback, setupCustomActions, @@ -40,7 +40,7 @@ const goToPositionAndCenter = ( */ const createMonacoEditor = ( editorContainer: HTMLDivElement, - actions: ActionType[], + actions: EditorAction[], handlers: CustomMonacoEditorHandlers ): monaco.editor.IStandaloneCodeEditor => { setupCustomLogLanguage(); diff --git a/new-log-viewer/src/components/MenuBar/PageNumInput.tsx b/new-log-viewer/src/components/MenuBar/PageNumInput.tsx index 9c953f29..cf37059a 100644 --- a/new-log-viewer/src/components/MenuBar/PageNumInput.tsx +++ b/new-log-viewer/src/components/MenuBar/PageNumInput.tsx @@ -38,7 +38,7 @@ const PageNumInput = () => { loadPageByAction({ code: ACTION_NAME.SPECIFIC_PAGE, - args: {specificPageNum: Number(inputRef.current.value)}, + args: {pageNum: Number(inputRef.current.value)}, }); setIsEditing(false); }; diff --git a/new-log-viewer/src/contexts/StateContextProvider.tsx b/new-log-viewer/src/contexts/StateContextProvider.tsx index 28526286..dcfec568 100644 --- a/new-log-viewer/src/contexts/StateContextProvider.tsx +++ b/new-log-viewer/src/contexts/StateContextProvider.tsx @@ -16,7 +16,7 @@ import { BeginLineNumToLogEventNumMap, CURSOR_CODE, CursorType, - EVENT_POSITION, + EVENT_POSITION_ON_PAGE, FileSrcType, MainWorkerRespMessage, WORKER_REQ_CODE, @@ -226,36 +226,35 @@ const StateContextProvider = ({children}: StateContextProviderProps) => { }, []); const getPageNumCursor = useCallback((navAction: NavigationAction): Nullable => { - let newPageNum: number; - let position: EVENT_POSITION; - if (STATE_DEFAULT.pageNum === pageNumRef.current) { console.error("Page actions cannot be executed if the current page is not set."); return null; } + let newPageNum: number; + let position: EVENT_POSITION_ON_PAGE; switch (navAction.code) { case ACTION_NAME.SPECIFIC_PAGE: - position = EVENT_POSITION.TOP; + position = EVENT_POSITION_ON_PAGE.TOP; // Clamp is to prevent someone from requesting non-existent page. - newPageNum = clamp(navAction.args.specificPageNum, 1, numPagesRef.current); + newPageNum = clamp(navAction.args.pageNum, 1, numPagesRef.current); break; case ACTION_NAME.FIRST_PAGE: - position = EVENT_POSITION.TOP; + position = EVENT_POSITION_ON_PAGE.TOP; newPageNum = 1; break; case ACTION_NAME.PREV_PAGE: - position = EVENT_POSITION.BOTTOM; + position = EVENT_POSITION_ON_PAGE.BOTTOM; newPageNum = clamp(pageNumRef.current - 1, 1, numPagesRef.current); break; case ACTION_NAME.NEXT_PAGE: - position = EVENT_POSITION.TOP; + position = EVENT_POSITION_ON_PAGE.TOP; newPageNum = clamp(pageNumRef.current + 1, 1, numPagesRef.current); break; case ACTION_NAME.LAST_PAGE: - position = EVENT_POSITION.BOTTOM; + position = EVENT_POSITION_ON_PAGE.BOTTOM; newPageNum = numPagesRef.current; break; default: @@ -264,7 +263,7 @@ const StateContextProvider = ({children}: StateContextProviderProps) => { return { code: CURSOR_CODE.PAGE_NUM, - args: {pageNum: newPageNum, eventPosition: position}, + args: {pageNum: newPageNum, eventPositionOnPage: position}, }; }, []); @@ -291,6 +290,11 @@ const StateContextProvider = ({children}: StateContextProviderProps) => { numPagesRef.current = getChunkNum(numEvents, getConfig(CONFIG_KEY.PAGE_SIZE)); }, [numEvents]); + // Synchronize `logEventNumRef` with `logEventNum`. + useEffect(() => { + logEventNumRef.current = logEventNum; + }, [logEventNum]); + // On `logEventNum` update, clamp it then switch page if necessary or simply update the URL. useEffect(() => { if (URL_HASH_PARAMS_DEFAULT.logEventNum === logEventNum) { @@ -300,21 +304,31 @@ const StateContextProvider = ({children}: StateContextProviderProps) => { const logEventNumsOnPage: number [] = Array.from(beginLineNumToLogEventNumRef.current.values()); + const clampedLogEventNum = clamp(logEventNum, 1, numEvents); + // eslint-disable-next-line no-warning-comments - // TODO: When filter is added, this will need to find the <= log event num on the page. - // If it is not the current log event, it will need to update it. However, a new request - // is not necessary. - if (logEventNumsOnPage.includes(logEventNum)) { + // TODO: After filter is added, will need find the largest <= log event number on the + // current page. Once found, we update the log event number in the URL instead of sending + // a new request since the page has not changed. + + if (logEventNumsOnPage.includes(clampedLogEventNum)) { + if (clampedLogEventNum !== logEventNum) { + updateWindowUrlHashParams({ + logEventNum: clampedLogEventNum, + }); + } + return; } const cursor: CursorType = { code: CURSOR_CODE.EVENT_NUM, - args: {logEventNum: logEventNum}, + args: {eventNum: logEventNum}, }; loadPageByCursor(cursor); }, [ + numEvents, logEventNum, loadPageByCursor, ]); @@ -329,7 +343,7 @@ const StateContextProvider = ({children}: StateContextProviderProps) => { if (URL_HASH_PARAMS_DEFAULT.logEventNum !== logEventNumRef.current) { cursor = { code: CURSOR_CODE.EVENT_NUM, - args: {logEventNum: logEventNumRef.current}, + args: {eventNum: logEventNumRef.current}, }; } loadFile(filePath, cursor); @@ -359,8 +373,6 @@ const StateContextProvider = ({children}: StateContextProviderProps) => { ); }; + export default StateContextProvider; -export { - STATE_DEFAULT, - StateContext, -}; +export {StateContext}; diff --git a/new-log-viewer/src/services/LogFileManager/index.ts b/new-log-viewer/src/services/LogFileManager/index.ts index a7397a5d..36a00e33 100644 --- a/new-log-viewer/src/services/LogFileManager/index.ts +++ b/new-log-viewer/src/services/LogFileManager/index.ts @@ -179,12 +179,17 @@ class LogFileManager { } { console.debug(`loadPage: cursor=${JSON.stringify(cursor)}`); - const {beginLogEventNum, endLogEventNum, newLogEventNum} = this.#getCursorData(cursor); - const results = this.#decoder.decode(beginLogEventNum - 1, endLogEventNum - 1); + const { + pageBeginLogEventNum, + pageEndLogEventNum, + matchingLogEventNum, + } = this.#getCursorData(cursor); + + const results = this.#decoder.decode(pageBeginLogEventNum - 1, pageEndLogEventNum - 1); if (null === results) { throw new Error("Error occurred during decoding. " + - `beginLogEventNum=${beginLogEventNum}, ` + - `endLogEventNum=${endLogEventNum}`); + `pageBeginLogEventNum=${pageBeginLogEventNum}, ` + + `pageEndLogEventNum=${pageEndLogEventNum}`); } const messages: string[] = []; @@ -203,35 +208,37 @@ class LogFileManager { currentLine += msg.split("\n").length - 1; }); - const newPageNum: number = getChunkNum(beginLogEventNum, this.#pageSize); + const newPageNum: number = getChunkNum(pageBeginLogEventNum, this.#pageSize); return { beginLineNumToLogEventNum: beginLineNumToLogEventNum, cursorLineNum: 1, - logEventNum: newLogEventNum, + logEventNum: matchingLogEventNum, logs: messages.join(""), pageNum: newPageNum, }; } /** - * Gets the range of log event numbers for the page and the new log event number. + * Gets the data that corresponds to the cursor. * - * @param cursor The cursor object containing the code and arguments. - * @return The range and new log event number. + * @param cursor + * @return Log event numbers for: + * - the range [begin, end) of the page containing the matching log event. + * - the log event number that matches the cursor. * @throws {Error} if the type of cursor is not supported. */ #getCursorData (cursor: CursorType): { - beginLogEventNum: number, - endLogEventNum: number, - newLogEventNum: number + pageBeginLogEventNum: number, + pageEndLogEventNum: number, + matchingLogEventNum: number } { const {code, args} = cursor; switch (code) { case CURSOR_CODE.PAGE_NUM: return getPageNumCursorData( args.pageNum, - args.eventPosition, + args.eventPositionOnPage, this.#numEvents, this.#pageSize ); @@ -244,7 +251,7 @@ class LogFileManager { case CURSOR_CODE.EVENT_NUM: return getEventNumCursorData( - args.logEventNum, + args.eventNum, this.#numEvents, this.#pageSize ); diff --git a/new-log-viewer/src/services/LogFileManager/utils.ts b/new-log-viewer/src/services/LogFileManager/utils.ts index 0d64c27d..71537ad7 100644 --- a/new-log-viewer/src/services/LogFileManager/utils.ts +++ b/new-log-viewer/src/services/LogFileManager/utils.ts @@ -1,5 +1,5 @@ import { - EVENT_POSITION, + EVENT_POSITION_ON_PAGE, FileSrcType, } from "../../typings/worker"; import {getUint8ArrayFrom} from "../../utils/http"; @@ -14,79 +14,57 @@ import {getBasenameFromUrlOrDefault} from "../../utils/url"; * Gets the log event number range [begin, end) of the page that starts at the given log event * index. * - * @param numEvents * @param beginLogEventIdx + * @param numEvents * @param pageSize * @return An array: - * - beginLogEventNum - * - endLogEventNum + * - pageBeginLogEventNum + * - pageEndLogEventNum */ -const getRange = ( - numEvents: number, +const getPageBoundaries = ( beginLogEventIdx: number, + numEvents: number, pageSize: number ): [number, number] => { - const beginLogEventNum: number = beginLogEventIdx + 1; + const pageBeginLogEventNum: number = beginLogEventIdx + 1; // Clamp ending index using total number of events. - const endLogEventNum: number = Math.min(numEvents + 1, beginLogEventNum + pageSize); + const pageEndLogEventNum: number = Math.min(numEvents + 1, pageBeginLogEventNum + pageSize); return [ - beginLogEventNum, - endLogEventNum, + pageBeginLogEventNum, + pageEndLogEventNum, ]; }; -/** - * Loads a file from a given source. - * - * @param fileSrc The source of the file to load. This can be a string representing a URL, or a File - * object. - * @return A promise that resolves with an object containing the file name and file data. - * @throws {Error} If the file source type is not supported. - */ -const loadFile = async (fileSrc: FileSrcType) - : Promise<{ fileName: string, fileData: Uint8Array }> => { - let fileName: string; - let fileData: Uint8Array; - if ("string" === typeof fileSrc) { - fileName = getBasenameFromUrlOrDefault(fileSrc); - fileData = await getUint8ArrayFrom(fileSrc, () => null); - } else { - fileName = fileSrc.name; - fileData = new Uint8Array(await fileSrc.arrayBuffer()); - } - - return { - fileName, - fileData, - }; -}; - /** * Gets the data for the `PAGE_NUM` cursor. * * @param pageNum - * @param eventPosition + * @param eventPositionOnPage * @param numEvents * @param pageSize * @return Log event numbers for: * - the range [begin, end) of page `pageNum`. - * - the log event (on the page) indicated by `eventPosition`. + * - the log event indicated by `eventPositionOnPage`. */ const getPageNumCursorData = ( pageNum: number, - eventPosition: EVENT_POSITION, + eventPositionOnPage: EVENT_POSITION_ON_PAGE, numEvents: number, pageSize: number -): { beginLogEventNum: number; endLogEventNum: number; newLogEventNum: number } => { +): { pageBeginLogEventNum: number; pageEndLogEventNum: number; matchingLogEventNum: number } => { const beginLogEventIdx = (pageNum - 1) * pageSize; - const [beginLogEventNum, endLogEventNum] = getRange(numEvents, beginLogEventIdx, pageSize); - const newLogEventNum = eventPosition === EVENT_POSITION.TOP ? - beginLogEventNum : - endLogEventNum; + const [pageBeginLogEventNum, pageEndLogEventNum] = getPageBoundaries( + beginLogEventIdx, + numEvents, + pageSize + ); + const matchingLogEventNum = eventPositionOnPage === EVENT_POSITION_ON_PAGE.TOP ? + pageBeginLogEventNum : + pageEndLogEventNum; - return {beginLogEventNum, endLogEventNum, newLogEventNum}; + return {pageBeginLogEventNum, pageEndLogEventNum, matchingLogEventNum}; }; /** @@ -103,12 +81,16 @@ const getEventNumCursorData = ( logEventNum: number, numEvents: number, pageSize: number -): { beginLogEventNum: number; endLogEventNum: number; newLogEventNum: number } => { +): { pageBeginLogEventNum: number; pageEndLogEventNum: number; matchingLogEventNum: number } => { const validLogEventNum = clamp(logEventNum, 1, numEvents); const beginLogEventIdx = (getChunkNum(validLogEventNum, pageSize) - 1) * pageSize; - const [beginLogEventNum, endLogEventNum] = getRange(numEvents, beginLogEventIdx, pageSize); - const newLogEventNum: number = validLogEventNum; - return {beginLogEventNum, endLogEventNum, newLogEventNum}; + const [pageBeginLogEventNum, pageEndLogEventNum] = getPageBoundaries( + beginLogEventIdx, + numEvents, + pageSize + ); + const matchingLogEventNum: number = validLogEventNum; + return {pageBeginLogEventNum, pageEndLogEventNum, matchingLogEventNum}; }; /** @@ -123,11 +105,41 @@ const getEventNumCursorData = ( const getLastEventCursorData = ( numEvents: number, pageSize: number -): { beginLogEventNum: number; endLogEventNum: number; newLogEventNum: number } => { +): { pageBeginLogEventNum: number; pageEndLogEventNum: number; matchingLogEventNum: number } => { const beginLogEventIdx = (getChunkNum(numEvents, pageSize) - 1) * pageSize; - const [beginLogEventNum, endLogEventNum] = getRange(numEvents, beginLogEventIdx, pageSize); - const newLogEventNum: number = endLogEventNum; - return {beginLogEventNum, endLogEventNum, newLogEventNum}; + const [pageBeginLogEventNum, pageEndLogEventNum] = getPageBoundaries( + beginLogEventIdx, + numEvents, + pageSize + ); + const matchingLogEventNum: number = pageEndLogEventNum; + return {pageBeginLogEventNum, pageEndLogEventNum, matchingLogEventNum}; +}; + +/** + * Loads a file from a given source. + * + * @param fileSrc The source of the file to load. This can be a string representing a URL, or a File + * object. + * @return A promise that resolves with an object containing the file name and file data. + * @throws {Error} If the file source type is not supported. + */ +const loadFile = async (fileSrc: FileSrcType) + : Promise<{ fileName: string, fileData: Uint8Array }> => { + let fileName: string; + let fileData: Uint8Array; + if ("string" === typeof fileSrc) { + fileName = getBasenameFromUrlOrDefault(fileSrc); + fileData = await getUint8ArrayFrom(fileSrc, () => null); + } else { + fileName = fileSrc.name; + fileData = new Uint8Array(await fileSrc.arrayBuffer()); + } + + return { + fileName, + fileData, + }; }; export { diff --git a/new-log-viewer/src/typings/worker.ts b/new-log-viewer/src/typings/worker.ts index 3010f30c..27e188ee 100644 --- a/new-log-viewer/src/typings/worker.ts +++ b/new-log-viewer/src/typings/worker.ts @@ -11,7 +11,7 @@ type FileSrcType = string | File; * For `CURSOR_CODE.PAGE_NUM`, this enum indicates which log event number (e.g., first/last on page) * should be returned with the page. */ -enum EVENT_POSITION { +enum EVENT_POSITION_ON_PAGE { TOP, BOTTOM, } @@ -32,9 +32,9 @@ enum CURSOR_CODE { type CursorArgMap = { [CURSOR_CODE.LAST_EVENT]: null; - [CURSOR_CODE.EVENT_NUM]: { logEventNum: number }; + [CURSOR_CODE.EVENT_NUM]: { eventNum: number }; [CURSOR_CODE.TIMESTAMP]: { timestamp: number }; - [CURSOR_CODE.PAGE_NUM]: { pageNum: number, eventPosition: EVENT_POSITION }; + [CURSOR_CODE.PAGE_NUM]: { pageNum: number, eventPositionOnPage: EVENT_POSITION_ON_PAGE }; }; type CursorType = { @@ -117,7 +117,7 @@ type MainWorkerRespMessage = { export { CURSOR_CODE, - EVENT_POSITION, + EVENT_POSITION_ON_PAGE, WORKER_REQ_CODE, WORKER_RESP_CODE, }; diff --git a/new-log-viewer/src/utils/actions.ts b/new-log-viewer/src/utils/actions.ts index 1ba3c0ef..336ecaac 100644 --- a/new-log-viewer/src/utils/actions.ts +++ b/new-log-viewer/src/utils/actions.ts @@ -13,7 +13,7 @@ enum ACTION_NAME { PAGE_BOTTOM = "pageBottom" } -type ActionType = { +type EditorAction = { actionName: Nullable, label: string, keyBindings: monaco.KeyCode[], @@ -24,7 +24,7 @@ type ActionType = { * but will be displayed in a help dialog. */ /* eslint-disable sort-keys */ -const EDITOR_ACTIONS : ActionType[] = [ +const EDITOR_ACTIONS : EditorAction[] = [ { actionName: null, label: "Focus on Editor", @@ -61,10 +61,11 @@ const EDITOR_ACTIONS : ActionType[] = [ keyBindings: [monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyI], }, ]; +/* eslint-enable sort-keys */ type NavigationActionsMap = { [ACTION_NAME.SPECIFIC_PAGE]: { - specificPageNum: number, + pageNum: number, }, [ACTION_NAME.FIRST_PAGE]: null, [ACTION_NAME.PREV_PAGE]: null, @@ -84,6 +85,6 @@ export { EDITOR_ACTIONS, }; export type { - ActionType, + EditorAction, NavigationAction, }; From 1572a91a9437ff8201d94c30b2bf4e840f2e2cbb Mon Sep 17 00:00:00 2001 From: Dave Marco Date: Mon, 30 Sep 2024 19:25:31 +0000 Subject: [PATCH 21/31] new comment from kirk --- .../src/components/Editor/index.tsx | 2 +- .../src/components/MenuBar/NavigationBar.tsx | 2 +- .../src/contexts/StateContextProvider.tsx | 99 ++++++++++--------- new-log-viewer/src/utils/actions.ts | 6 +- 4 files changed, 59 insertions(+), 50 deletions(-) diff --git a/new-log-viewer/src/components/Editor/index.tsx b/new-log-viewer/src/components/Editor/index.tsx index fac3101a..71de26c4 100644 --- a/new-log-viewer/src/components/Editor/index.tsx +++ b/new-log-viewer/src/components/Editor/index.tsx @@ -82,7 +82,7 @@ const Editor = () => { case ACTION_NAME.PREV_PAGE: case ACTION_NAME.NEXT_PAGE: case ACTION_NAME.LAST_PAGE: - loadPageByAction({code: actionName}); + loadPageByAction({code: actionName, args: null}); break; case ACTION_NAME.PAGE_TOP: goToPositionAndCenter(editor, {lineNumber: 1, column: 1}); diff --git a/new-log-viewer/src/components/MenuBar/NavigationBar.tsx b/new-log-viewer/src/components/MenuBar/NavigationBar.tsx index e09866bb..da050839 100644 --- a/new-log-viewer/src/components/MenuBar/NavigationBar.tsx +++ b/new-log-viewer/src/components/MenuBar/NavigationBar.tsx @@ -29,7 +29,7 @@ const NavigationBar = () => { actionName === ACTION_NAME.NEXT_PAGE || actionName === ACTION_NAME.LAST_PAGE ) { - loadPageByAction({code: actionName}); + loadPageByAction({code: actionName, args: null}); } }; diff --git a/new-log-viewer/src/contexts/StateContextProvider.tsx b/new-log-viewer/src/contexts/StateContextProvider.tsx index dcfec568..bb38b093 100644 --- a/new-log-viewer/src/contexts/StateContextProvider.tsx +++ b/new-log-viewer/src/contexts/StateContextProvider.tsx @@ -97,6 +97,60 @@ const workerPostReq = ( worker.postMessage({code, args}); }; +/** + * Returns a cursor based on a navigation action. + * + * @param navAction Action to navigate to a new page. + * @param currentPageNum + * @param numPages + * @return `PAGE_NUM` cursor. + */ +const getPageNumCursor = ( + navAction: NavigationAction, + currentPageNum: number, + numPages: number +): Nullable => { + if (STATE_DEFAULT.pageNum === currentPageNum) { + console.error("Page actions cannot be executed if the current page is not set."); + + return null; + } + + let newPageNum: number; + let position: EVENT_POSITION_ON_PAGE; + switch (navAction.code) { + case ACTION_NAME.SPECIFIC_PAGE: + position = EVENT_POSITION_ON_PAGE.TOP; + + // Clamp is to prevent someone from requesting non-existent page. + newPageNum = clamp(navAction.args.pageNum, 1, numPages); + break; + case ACTION_NAME.FIRST_PAGE: + position = EVENT_POSITION_ON_PAGE.TOP; + newPageNum = 1; + break; + case ACTION_NAME.PREV_PAGE: + position = EVENT_POSITION_ON_PAGE.BOTTOM; + newPageNum = clamp(currentPageNum - 1, 1, numPages); + break; + case ACTION_NAME.NEXT_PAGE: + position = EVENT_POSITION_ON_PAGE.TOP; + newPageNum = clamp(currentPageNum + 1, 1, numPages); + break; + case ACTION_NAME.LAST_PAGE: + position = EVENT_POSITION_ON_PAGE.BOTTOM; + newPageNum = numPages; + break; + default: + return null; + } + + return { + code: CURSOR_CODE.PAGE_NUM, + args: {pageNum: newPageNum, eventPositionOnPage: position}, + }; +}; + /** * Provides state management for the application. This provider must be wrapped by * UrlContextProvider to function correctly. @@ -225,50 +279,8 @@ const StateContextProvider = ({children}: StateContextProviderProps) => { }); }, []); - const getPageNumCursor = useCallback((navAction: NavigationAction): Nullable => { - if (STATE_DEFAULT.pageNum === pageNumRef.current) { - console.error("Page actions cannot be executed if the current page is not set."); - - return null; - } - - let newPageNum: number; - let position: EVENT_POSITION_ON_PAGE; - switch (navAction.code) { - case ACTION_NAME.SPECIFIC_PAGE: - position = EVENT_POSITION_ON_PAGE.TOP; - - // Clamp is to prevent someone from requesting non-existent page. - newPageNum = clamp(navAction.args.pageNum, 1, numPagesRef.current); - break; - case ACTION_NAME.FIRST_PAGE: - position = EVENT_POSITION_ON_PAGE.TOP; - newPageNum = 1; - break; - case ACTION_NAME.PREV_PAGE: - position = EVENT_POSITION_ON_PAGE.BOTTOM; - newPageNum = clamp(pageNumRef.current - 1, 1, numPagesRef.current); - break; - case ACTION_NAME.NEXT_PAGE: - position = EVENT_POSITION_ON_PAGE.TOP; - newPageNum = clamp(pageNumRef.current + 1, 1, numPagesRef.current); - break; - case ACTION_NAME.LAST_PAGE: - position = EVENT_POSITION_ON_PAGE.BOTTOM; - newPageNum = numPagesRef.current; - break; - default: - return null; - } - - return { - code: CURSOR_CODE.PAGE_NUM, - args: {pageNum: newPageNum, eventPositionOnPage: position}, - }; - }, []); - const loadPageByAction = useCallback((navAction: NavigationAction) => { - const cursor = getPageNumCursor(navAction); + const cursor = getPageNumCursor(navAction, pageNumRef.current, numPagesRef.current); if (null === cursor) { console.error(`Error with nav action ${navAction.code}.`); @@ -277,7 +289,6 @@ const StateContextProvider = ({children}: StateContextProviderProps) => { loadPageByCursor(cursor); }, [ - getPageNumCursor, loadPageByCursor, ]); diff --git a/new-log-viewer/src/utils/actions.ts b/new-log-viewer/src/utils/actions.ts index 336ecaac..5f9d4ed6 100644 --- a/new-log-viewer/src/utils/actions.ts +++ b/new-log-viewer/src/utils/actions.ts @@ -73,11 +73,9 @@ type NavigationActionsMap = { [ACTION_NAME.LAST_PAGE]: null, }; -// Some navigation actions supply code and args fields, and others only code field. type NavigationAction = { - [T in keyof NavigationActionsMap]: NavigationActionsMap[T] extends object ? - {code: T, args: NavigationActionsMap[T]} : - {code: T}; + [T in keyof NavigationActionsMap]: + {code: T, args: NavigationActionsMap[T]} } [keyof NavigationActionsMap]; export { From 1e6ad3faa0fb1bb17bf4244e4cd9bd38df00a10d Mon Sep 17 00:00:00 2001 From: Dave Marco Date: Mon, 30 Sep 2024 19:42:23 +0000 Subject: [PATCH 22/31] small nit --- new-log-viewer/src/contexts/StateContextProvider.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/new-log-viewer/src/contexts/StateContextProvider.tsx b/new-log-viewer/src/contexts/StateContextProvider.tsx index bb38b093..f5fdc49f 100644 --- a/new-log-viewer/src/contexts/StateContextProvider.tsx +++ b/new-log-viewer/src/contexts/StateContextProvider.tsx @@ -98,7 +98,7 @@ const workerPostReq = ( }; /** - * Returns a cursor based on a navigation action. + * Returns a `PAGE_NUM` cursor based on a navigation action. * * @param navAction Action to navigate to a new page. * @param currentPageNum From 31012ff51682ff2ebc5a8edfdf2f9a9f24abfdba Mon Sep 17 00:00:00 2001 From: Dave Marco Date: Mon, 30 Sep 2024 20:02:25 +0000 Subject: [PATCH 23/31] fix off-by-error related to end num now exclusive --- new-log-viewer/src/services/LogFileManager/utils.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/new-log-viewer/src/services/LogFileManager/utils.ts b/new-log-viewer/src/services/LogFileManager/utils.ts index 71537ad7..2a871c02 100644 --- a/new-log-viewer/src/services/LogFileManager/utils.ts +++ b/new-log-viewer/src/services/LogFileManager/utils.ts @@ -62,7 +62,7 @@ const getPageNumCursorData = ( ); const matchingLogEventNum = eventPositionOnPage === EVENT_POSITION_ON_PAGE.TOP ? pageBeginLogEventNum : - pageEndLogEventNum; + pageEndLogEventNum - 1; return {pageBeginLogEventNum, pageEndLogEventNum, matchingLogEventNum}; }; @@ -112,7 +112,7 @@ const getLastEventCursorData = ( numEvents, pageSize ); - const matchingLogEventNum: number = pageEndLogEventNum; + const matchingLogEventNum: number = pageEndLogEventNum - 1; return {pageBeginLogEventNum, pageEndLogEventNum, matchingLogEventNum}; }; From 6200bd490038a55e1e30805933c0230d937b92f9 Mon Sep 17 00:00:00 2001 From: davemarco <83603688+davemarco@users.noreply.github.com> Date: Tue, 1 Oct 2024 14:46:54 -0400 Subject: [PATCH 24/31] Apply suggestions from code review Co-authored-by: kirkrodrigues <2454684+kirkrodrigues@users.noreply.github.com> --- new-log-viewer/src/contexts/StateContextProvider.tsx | 2 ++ new-log-viewer/src/utils/actions.ts | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/new-log-viewer/src/contexts/StateContextProvider.tsx b/new-log-viewer/src/contexts/StateContextProvider.tsx index f5fdc49f..9a0f8e5d 100644 --- a/new-log-viewer/src/contexts/StateContextProvider.tsx +++ b/new-log-viewer/src/contexts/StateContextProvider.tsx @@ -111,6 +111,8 @@ const getPageNumCursor = ( numPages: number ): Nullable => { if (STATE_DEFAULT.pageNum === currentPageNum) { + // TODO This shouldn't be possible, but currently, the page nav buttons remain enabled + // even when a file hasn't been loaded. console.error("Page actions cannot be executed if the current page is not set."); return null; diff --git a/new-log-viewer/src/utils/actions.ts b/new-log-viewer/src/utils/actions.ts index 5f9d4ed6..edc2d0e5 100644 --- a/new-log-viewer/src/utils/actions.ts +++ b/new-log-viewer/src/utils/actions.ts @@ -75,8 +75,8 @@ type NavigationActionsMap = { type NavigationAction = { [T in keyof NavigationActionsMap]: - {code: T, args: NavigationActionsMap[T]} - } [keyof NavigationActionsMap]; + { code: T, args: NavigationActionsMap[T] } +} [keyof NavigationActionsMap]; export { ACTION_NAME, From 6f43e7f1291f373f0e270b94df3c26b03f4995cf Mon Sep 17 00:00:00 2001 From: Dave Marco Date: Tue, 1 Oct 2024 18:49:04 +0000 Subject: [PATCH 25/31] move function and other --- .../src/contexts/StateContextProvider.tsx | 49 ++++++++++--------- 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/new-log-viewer/src/contexts/StateContextProvider.tsx b/new-log-viewer/src/contexts/StateContextProvider.tsx index 9a0f8e5d..0132dd18 100644 --- a/new-log-viewer/src/contexts/StateContextProvider.tsx +++ b/new-log-viewer/src/contexts/StateContextProvider.tsx @@ -111,7 +111,8 @@ const getPageNumCursor = ( numPages: number ): Nullable => { if (STATE_DEFAULT.pageNum === currentPageNum) { - // TODO This shouldn't be possible, but currently, the page nav buttons remain enabled + // eslint-disable-next-line no-warning-comments + // TODO: This shouldn't be possible, but currently, the page nav buttons remain enabled // even when a file hasn't been loaded. console.error("Page actions cannot be executed if the current page is not set."); @@ -153,6 +154,28 @@ const getPageNumCursor = ( }; }; +/** + * Submits a `LOAD_PAGE` request to a worker. + * + * @param worker + * @param cursor + */ +const loadPageByCursor = ( + worker: Nullable, + cursor: CursorType, +) => { + if (null === worker) { + console.error("Unexpected null worker"); + + return; + } + + workerPostReq(worker, WORKER_REQ_CODE.LOAD_PAGE, { + cursor: cursor, + decoderOptions: getConfig(CONFIG_KEY.DECODER_OPTIONS), + }); +}; + /** * Provides state management for the application. This provider must be wrapped by * UrlContextProvider to function correctly. @@ -266,20 +289,6 @@ const StateContextProvider = ({children}: StateContextProviderProps) => { handleMainWorkerResp, ]); - const loadPageByCursor = useCallback(( - cursor: CursorType, - ) => { - if (null === mainWorkerRef.current) { - console.error("Unexpected null mainWorkerRef.current"); - - return; - } - - workerPostReq(mainWorkerRef.current, WORKER_REQ_CODE.LOAD_PAGE, { - cursor: cursor, - decoderOptions: getConfig(CONFIG_KEY.DECODER_OPTIONS), - }); - }, []); const loadPageByAction = useCallback((navAction: NavigationAction) => { const cursor = getPageNumCursor(navAction, pageNumRef.current, numPagesRef.current); @@ -288,11 +297,8 @@ const StateContextProvider = ({children}: StateContextProviderProps) => { return; } - - loadPageByCursor(cursor); - }, [ - loadPageByCursor, - ]); + loadPageByCursor(mainWorkerRef.current, cursor); + }, []); // On `numEvents` update, recalculate `numPagesRef`. useEffect(() => { @@ -339,11 +345,10 @@ const StateContextProvider = ({children}: StateContextProviderProps) => { args: {eventNum: logEventNum}, }; - loadPageByCursor(cursor); + loadPageByCursor(mainWorkerRef.current, cursor); }, [ numEvents, logEventNum, - loadPageByCursor, ]); // On `filePath` update, load file. From d266ce7c9bca24c9f21153bb359f10923a4cb937 Mon Sep 17 00:00:00 2001 From: Dave Marco Date: Tue, 1 Oct 2024 21:39:02 +0000 Subject: [PATCH 26/31] move null check --- .../src/contexts/StateContextProvider.tsx | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/new-log-viewer/src/contexts/StateContextProvider.tsx b/new-log-viewer/src/contexts/StateContextProvider.tsx index 0132dd18..cb834af3 100644 --- a/new-log-viewer/src/contexts/StateContextProvider.tsx +++ b/new-log-viewer/src/contexts/StateContextProvider.tsx @@ -161,15 +161,9 @@ const getPageNumCursor = ( * @param cursor */ const loadPageByCursor = ( - worker: Nullable, + worker: Worker, cursor: CursorType, ) => { - if (null === worker) { - console.error("Unexpected null worker"); - - return; - } - workerPostReq(worker, WORKER_REQ_CODE.LOAD_PAGE, { cursor: cursor, decoderOptions: getConfig(CONFIG_KEY.DECODER_OPTIONS), @@ -291,6 +285,11 @@ const StateContextProvider = ({children}: StateContextProviderProps) => { const loadPageByAction = useCallback((navAction: NavigationAction) => { + if (null === mainWorkerRef.current) { + console.error("Unexpected null mainWorkerRef.current"); + + return; + } const cursor = getPageNumCursor(navAction, pageNumRef.current, numPagesRef.current); if (null === cursor) { console.error(`Error with nav action ${navAction.code}.`); @@ -316,6 +315,12 @@ const StateContextProvider = ({children}: StateContextProviderProps) => { // On `logEventNum` update, clamp it then switch page if necessary or simply update the URL. useEffect(() => { + if (null === mainWorkerRef.current) { + console.error("Unexpected null mainWorkerRef.current"); + + return; + } + if (URL_HASH_PARAMS_DEFAULT.logEventNum === logEventNum) { return; } From 041955271dd39d7285fef4f77a32cbd1181c9ff4 Mon Sep 17 00:00:00 2001 From: Dave Marco Date: Tue, 1 Oct 2024 21:41:36 +0000 Subject: [PATCH 27/31] add more lines --- new-log-viewer/src/contexts/StateContextProvider.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/new-log-viewer/src/contexts/StateContextProvider.tsx b/new-log-viewer/src/contexts/StateContextProvider.tsx index cb834af3..33c24444 100644 --- a/new-log-viewer/src/contexts/StateContextProvider.tsx +++ b/new-log-viewer/src/contexts/StateContextProvider.tsx @@ -1,4 +1,4 @@ -/* eslint max-lines: ["error", 400] */ +/* eslint max-lines: ["error", 450] */ import React, { createContext, useCallback, @@ -320,7 +320,7 @@ const StateContextProvider = ({children}: StateContextProviderProps) => { return; } - + if (URL_HASH_PARAMS_DEFAULT.logEventNum === logEventNum) { return; } From 3887f769febc216d47b9e6a82da030697cd5224c Mon Sep 17 00:00:00 2001 From: Kirk Rodrigues <2454684+kirkrodrigues@users.noreply.github.com> Date: Tue, 1 Oct 2024 17:51:37 -0400 Subject: [PATCH 28/31] Remove log. --- new-log-viewer/src/contexts/StateContextProvider.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/new-log-viewer/src/contexts/StateContextProvider.tsx b/new-log-viewer/src/contexts/StateContextProvider.tsx index 33c24444..e5b03a9f 100644 --- a/new-log-viewer/src/contexts/StateContextProvider.tsx +++ b/new-log-viewer/src/contexts/StateContextProvider.tsx @@ -316,8 +316,6 @@ const StateContextProvider = ({children}: StateContextProviderProps) => { // On `logEventNum` update, clamp it then switch page if necessary or simply update the URL. useEffect(() => { if (null === mainWorkerRef.current) { - console.error("Unexpected null mainWorkerRef.current"); - return; } From 808a7e12ea56047b0e91831edb60b4228e54e383 Mon Sep 17 00:00:00 2001 From: Kirk Rodrigues <2454684+kirkrodrigues@users.noreply.github.com> Date: Tue, 1 Oct 2024 17:58:36 -0400 Subject: [PATCH 29/31] Remove extra newline. --- new-log-viewer/src/contexts/StateContextProvider.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/new-log-viewer/src/contexts/StateContextProvider.tsx b/new-log-viewer/src/contexts/StateContextProvider.tsx index e5b03a9f..797c8463 100644 --- a/new-log-viewer/src/contexts/StateContextProvider.tsx +++ b/new-log-viewer/src/contexts/StateContextProvider.tsx @@ -283,7 +283,6 @@ const StateContextProvider = ({children}: StateContextProviderProps) => { handleMainWorkerResp, ]); - const loadPageByAction = useCallback((navAction: NavigationAction) => { if (null === mainWorkerRef.current) { console.error("Unexpected null mainWorkerRef.current"); From d8b32ea7d4e97f63c0c95816b4111aa0e666152c Mon Sep 17 00:00:00 2001 From: Dave Marco Date: Tue, 1 Oct 2024 23:13:39 +0000 Subject: [PATCH 30/31] small wording change so i am last pusher --- new-log-viewer/src/contexts/StateContextProvider.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/new-log-viewer/src/contexts/StateContextProvider.tsx b/new-log-viewer/src/contexts/StateContextProvider.tsx index 33c24444..0b16b62e 100644 --- a/new-log-viewer/src/contexts/StateContextProvider.tsx +++ b/new-log-viewer/src/contexts/StateContextProvider.tsx @@ -331,7 +331,7 @@ const StateContextProvider = ({children}: StateContextProviderProps) => { const clampedLogEventNum = clamp(logEventNum, 1, numEvents); // eslint-disable-next-line no-warning-comments - // TODO: After filter is added, will need find the largest <= log event number on the + // TODO: After filter is added, will need to find the largest <= log event number on the // current page. Once found, we update the log event number in the URL instead of sending // a new request since the page has not changed. From c26459d0f573167811d0f2a23793880a6c1128dd Mon Sep 17 00:00:00 2001 From: Dave Marco Date: Tue, 1 Oct 2024 23:16:12 +0000 Subject: [PATCH 31/31] small change so last pusher --- new-log-viewer/src/contexts/StateContextProvider.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/new-log-viewer/src/contexts/StateContextProvider.tsx b/new-log-viewer/src/contexts/StateContextProvider.tsx index a5e0b0bc..bf65ca90 100644 --- a/new-log-viewer/src/contexts/StateContextProvider.tsx +++ b/new-log-viewer/src/contexts/StateContextProvider.tsx @@ -329,8 +329,8 @@ const StateContextProvider = ({children}: StateContextProviderProps) => { // eslint-disable-next-line no-warning-comments // TODO: After filter is added, will need to find the largest <= log event number on the - // current page. Once found, we update the log event number in the URL instead of sending - // a new request since the page has not changed. + // current page. Once found, we update the event number in the URL instead of sending a new + // request since the page has not changed. if (logEventNumsOnPage.includes(clampedLogEventNum)) { if (clampedLogEventNum !== logEventNum) {