From 4099ba64051e046811ad108d08aa48f31df3ac13 Mon Sep 17 00:00:00 2001 From: BrunoQuaresma Date: Tue, 12 Mar 2024 13:46:19 +0000 Subject: [PATCH 1/8] Refact log components --- site/src/components/Logs/LogLine.tsx | 90 +++++++++ site/src/components/Logs/Logs.stories.tsx | 20 ++ site/src/components/Logs/Logs.tsx | 53 ++++++ site/src/modules/resources/AgentLogLine.tsx | 60 ++++++ site/src/modules/resources/AgentLogs.tsx | 10 +- site/src/modules/resources/AgentRow.tsx | 7 +- .../workspaces/WorkspaceBuildLogs/Logs.tsx | 179 ------------------ .../WorkspaceBuildLogs/WorkspaceBuildLogs.tsx | 2 +- 8 files changed, 230 insertions(+), 191 deletions(-) create mode 100644 site/src/components/Logs/LogLine.tsx create mode 100644 site/src/components/Logs/Logs.stories.tsx create mode 100644 site/src/components/Logs/Logs.tsx create mode 100644 site/src/modules/resources/AgentLogLine.tsx delete mode 100644 site/src/modules/workspaces/WorkspaceBuildLogs/Logs.tsx diff --git a/site/src/components/Logs/LogLine.tsx b/site/src/components/Logs/LogLine.tsx new file mode 100644 index 0000000000000..c410d032bb99a --- /dev/null +++ b/site/src/components/Logs/LogLine.tsx @@ -0,0 +1,90 @@ +import type { Interpolation, Theme } from "@emotion/react"; +import type { FC, HTMLAttributes } from "react"; +import type { LogLevel } from "api/typesGenerated"; +import { MONOSPACE_FONT_FAMILY } from "theme/constants"; + +export const DEFAULT_LOG_LINE_SIDE_PADDING = 24; +export const LOG_LINE_HEIGHT = 20; + +export interface Line { + time: string; + output: string; + level: LogLevel; + source_id: string; +} + +type LogLineProps = { + level: LogLevel; +} & HTMLAttributes; + +export const LogLine: FC = ({ level, ...divProps }) => { + return ( +
+ ); +}; + +export const LogLinePrefix: FC> = (props) => { + return ; +}; + +export const LogLineSpace: FC = () => { + return ; +}; + +const styles = { + line: (theme) => ({ + wordBreak: "break-all", + display: "flex", + alignItems: "center", + fontSize: 13, + color: theme.palette.text.primary, + fontFamily: MONOSPACE_FONT_FAMILY, + height: LOG_LINE_HEIGHT, + // Whitespace is significant in terminal output for alignment + whiteSpace: "pre", + padding: `0 var(--log-line-side-padding, ${DEFAULT_LOG_LINE_SIDE_PADDING}px)`, + + "&.error": { + backgroundColor: theme.roles.error.background, + color: theme.roles.error.text, + + "& .dashed-line": { + backgroundColor: theme.roles.error.outline, + }, + }, + + "&.debug": { + backgroundColor: theme.roles.info.background, + color: theme.roles.info.text, + + "& .dashed-line": { + backgroundColor: theme.roles.info.outline, + }, + }, + + "&.warn": { + backgroundColor: theme.roles.warning.background, + color: theme.roles.warning.text, + + "& .dashed-line": { + backgroundColor: theme.roles.warning.outline, + }, + }, + }), + space: { + userSelect: "none", + width: 24, + display: "block", + flexShrink: 0, + }, + prefix: (theme) => ({ + userSelect: "none", + whiteSpace: "pre", + display: "inline-block", + color: theme.palette.text.secondary, + }), +} satisfies Record>; diff --git a/site/src/components/Logs/Logs.stories.tsx b/site/src/components/Logs/Logs.stories.tsx new file mode 100644 index 0000000000000..b63c01cc5f901 --- /dev/null +++ b/site/src/components/Logs/Logs.stories.tsx @@ -0,0 +1,20 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { chromatic } from "testHelpers/chromatic"; +import { MockWorkspaceBuildLogs } from "testHelpers/entities"; +import { WorkspaceBuildLogs } from "../../modules/workspaces/WorkspaceBuildLogs/WorkspaceBuildLogs"; + +const meta: Meta = { + title: "modules/workspaces/WorkspaceBuildLogs", + parameters: { chromatic }, + component: WorkspaceBuildLogs, +}; + +export default meta; + +type Story = StoryObj; + +export const InProgress: Story = { + args: { + logs: MockWorkspaceBuildLogs.slice(0, 20), + }, +}; diff --git a/site/src/components/Logs/Logs.tsx b/site/src/components/Logs/Logs.tsx new file mode 100644 index 0000000000000..1870709356b39 --- /dev/null +++ b/site/src/components/Logs/Logs.tsx @@ -0,0 +1,53 @@ +import type { Interpolation, Theme } from "@emotion/react"; +import dayjs from "dayjs"; +import type { FC } from "react"; +import { LogLinePrefix, LogLineSpace, LogLine, type Line } from "./LogLine"; + +export const DEFAULT_LOG_LINE_SIDE_PADDING = 24; + +export interface LogsProps { + lines: Line[]; + hideTimestamps?: boolean; + className?: string; +} + +export const Logs: FC = ({ + hideTimestamps, + lines, + className = "", +}) => { + return ( +
+
+ {lines.map((line, idx) => ( + + {!hideTimestamps && ( + <> + + {dayjs(line.time).format(`HH:mm:ss.SSS`)} + + + + )} + {line.output} + + ))} +
+
+ ); +}; + +const styles = { + root: (theme) => ({ + minHeight: 156, + padding: "8px 0", + borderRadius: 8, + overflowX: "auto", + background: theme.palette.background.default, + + "&:not(:last-child)": { + borderBottom: `1px solid ${theme.palette.divider}`, + borderRadius: 0, + }, + }), +} satisfies Record>; diff --git a/site/src/modules/resources/AgentLogLine.tsx b/site/src/modules/resources/AgentLogLine.tsx new file mode 100644 index 0000000000000..fdbed192117d7 --- /dev/null +++ b/site/src/modules/resources/AgentLogLine.tsx @@ -0,0 +1,60 @@ +import type { Interpolation, Theme } from "@emotion/react"; +import AnsiToHTML from "ansi-to-html"; +import { type FC, type ReactNode, useMemo } from "react"; +import { + type Line, + LogLine, + LogLinePrefix, + LogLineSpace, +} from "components/Logs/LogLine"; + +const convert = new AnsiToHTML(); + +interface AgentLogLineProps { + line: Line; + number: number; + style: React.CSSProperties; + sourceIcon: ReactNode; + maxNumber: number; +} + +export const AgentLogLine: FC = ({ + line, + number, + maxNumber, + sourceIcon, + style, +}) => { + const output = useMemo(() => { + return convert.toHtml(line.output.split(/\r/g).pop() as string); + }, [line.output]); + + return ( + + {sourceIcon} + + {number} + + + + + ); +}; + +const styles = { + number: (theme) => ({ + width: 32, + textAlign: "right", + flexShrink: 0, + color: theme.palette.text.disabled, + }), +} satisfies Record>; diff --git a/site/src/modules/resources/AgentLogs.tsx b/site/src/modules/resources/AgentLogs.tsx index 16515efb7c04e..669ecde90d9ac 100644 --- a/site/src/modules/resources/AgentLogs.tsx +++ b/site/src/modules/resources/AgentLogs.tsx @@ -10,10 +10,8 @@ import { import { FixedSizeList as List } from "react-window"; import * as API from "api/api"; import type { WorkspaceAgentLogSource } from "api/typesGenerated"; -import { - LogLine, - logLineHeight, -} from "modules/workspaces/WorkspaceBuildLogs/Logs"; +import { LOG_LINE_HEIGHT } from "components/Logs/LogLine"; +import { AgentLogLine } from "./AgentLogLine"; import type { LineWithID } from "./AgentRow"; type AgentLogsProps = Omit< @@ -39,7 +37,7 @@ export const AgentLogs = forwardRef( ref={ref} css={styles.logs} itemCount={logs.length} - itemSize={logLineHeight} + itemSize={LOG_LINE_HEIGHT} {...listProps} > {({ index, style }) => { @@ -149,7 +147,7 @@ export const AgentLogs = forwardRef( } return ( - = ({ const distanceFromBottom = logListDivRef.current.scrollHeight - (props.scrollOffset + parent.clientHeight); - setBottomOfLogs(distanceFromBottom < logLineHeight); + setBottomOfLogs(distanceFromBottom < LOG_LINE_HEIGHT); }, [logListDivRef], ); diff --git a/site/src/modules/workspaces/WorkspaceBuildLogs/Logs.tsx b/site/src/modules/workspaces/WorkspaceBuildLogs/Logs.tsx deleted file mode 100644 index 6d253e2055261..0000000000000 --- a/site/src/modules/workspaces/WorkspaceBuildLogs/Logs.tsx +++ /dev/null @@ -1,179 +0,0 @@ -import type { Interpolation, Theme } from "@emotion/react"; -import AnsiToHTML from "ansi-to-html"; -import dayjs from "dayjs"; -import { type FC, type ReactNode, useMemo } from "react"; -import type { LogLevel } from "api/typesGenerated"; -import { MONOSPACE_FONT_FAMILY } from "theme/constants"; - -export const DEFAULT_LOG_LINE_SIDE_PADDING = 24; - -const convert = new AnsiToHTML(); - -export interface Line { - time: string; - output: string; - level: LogLevel; - source_id: string; -} - -export interface LogsProps { - lines: Line[]; - hideTimestamps?: boolean; - className?: string; - children?: ReactNode; -} - -export const Logs: FC = ({ - hideTimestamps, - lines, - className = "", -}) => { - return ( -
-
- {lines.map((line, idx) => ( -
- {!hideTimestamps && ( - <> - - {dayjs(line.time).format(`HH:mm:ss.SSS`)} - - - - )} - {line.output} -
- ))} -
-
- ); -}; - -export const logLineHeight = 20; - -interface LogLineProps { - line: Line; - hideTimestamp?: boolean; - number?: number; - style?: React.CSSProperties; - sourceIcon?: ReactNode; - maxNumber?: number; -} - -export const LogLine: FC = ({ - line, - hideTimestamp, - number, - maxNumber, - sourceIcon, - style, -}) => { - const output = useMemo(() => { - return convert.toHtml(line.output.split(/\r/g).pop() as string); - }, [line.output]); - const isUsingLineNumber = number !== undefined; - - return ( -
- {sourceIcon} - {!hideTimestamp && ( - <> - - {number ? number : dayjs(line.time).format(`HH:mm:ss.SSS`)} - - - - )} - -
- ); -}; - -const styles = { - root: (theme) => ({ - minHeight: 156, - padding: "8px 0", - borderRadius: 8, - overflowX: "auto", - background: theme.palette.background.default, - - "&:not(:last-child)": { - borderBottom: `1px solid ${theme.palette.divider}`, - borderRadius: 0, - }, - }), - line: (theme) => ({ - wordBreak: "break-all", - display: "flex", - alignItems: "center", - fontSize: 13, - color: theme.palette.text.primary, - fontFamily: MONOSPACE_FONT_FAMILY, - height: "auto", - // Whitespace is significant in terminal output for alignment - whiteSpace: "pre", - padding: `0 var(--log-line-side-padding, ${DEFAULT_LOG_LINE_SIDE_PADDING}px)`, - - "&.error": { - backgroundColor: theme.roles.error.background, - color: theme.roles.error.text, - - "& .dashed-line": { - backgroundColor: theme.roles.error.outline, - }, - }, - - "&.debug": { - backgroundColor: theme.roles.info.background, - color: theme.roles.info.text, - - "& .dashed-line": { - backgroundColor: theme.roles.info.outline, - }, - }, - - "&.warn": { - backgroundColor: theme.roles.warning.background, - color: theme.roles.warning.text, - - "& .dashed-line": { - backgroundColor: theme.roles.warning.outline, - }, - }, - }), - space: { - userSelect: "none", - width: 24, - display: "block", - flexShrink: 0, - }, - time: (theme) => ({ - userSelect: "none", - whiteSpace: "pre", - display: "inline-block", - color: theme.palette.text.secondary, - }), - number: (theme) => ({ - width: 32, - textAlign: "right", - flexShrink: 0, - color: theme.palette.text.disabled, - }), -} satisfies Record>; diff --git a/site/src/modules/workspaces/WorkspaceBuildLogs/WorkspaceBuildLogs.tsx b/site/src/modules/workspaces/WorkspaceBuildLogs/WorkspaceBuildLogs.tsx index 647500e92059c..1d17363a00a67 100644 --- a/site/src/modules/workspaces/WorkspaceBuildLogs/WorkspaceBuildLogs.tsx +++ b/site/src/modules/workspaces/WorkspaceBuildLogs/WorkspaceBuildLogs.tsx @@ -2,8 +2,8 @@ import { type Interpolation, type Theme, useTheme } from "@emotion/react"; import dayjs from "dayjs"; import { type FC, Fragment, type HTMLAttributes } from "react"; import type { ProvisionerJobLog } from "api/typesGenerated"; +import { DEFAULT_LOG_LINE_SIDE_PADDING, Logs } from "components/Logs/Logs"; import { BODY_FONT_FAMILY, MONOSPACE_FONT_FAMILY } from "theme/constants"; -import { DEFAULT_LOG_LINE_SIDE_PADDING, Logs } from "./Logs"; const Language = { seconds: "seconds", From 6f46085d5b52efa45d1a2eb16a00f40c0945a198 Mon Sep 17 00:00:00 2001 From: BrunoQuaresma Date: Tue, 12 Mar 2024 13:59:41 +0000 Subject: [PATCH 2/8] Add stories for LogLine --- site/src/components/Logs/LogLine.stories.tsx | 49 +++++++++++++++++++ site/src/components/Logs/LogLine.tsx | 2 +- site/src/components/Logs/Logs.stories.tsx | 26 ++++++---- site/src/modules/resources/AgentLogs.tsx | 8 +-- .../modules/resources/AgentRow.stories.tsx | 2 +- site/src/modules/resources/AgentRow.tsx | 2 +- .../WorkspaceBuildLogs/WorkspaceBuildLogs.tsx | 2 +- .../src/pages/TemplatePage/TemplateLayout.tsx | 2 +- .../TemplateSettingsLayout.tsx | 2 +- .../WorkspaceSchedulePage.tsx | 2 +- 10 files changed, 76 insertions(+), 21 deletions(-) create mode 100644 site/src/components/Logs/LogLine.stories.tsx diff --git a/site/src/components/Logs/LogLine.stories.tsx b/site/src/components/Logs/LogLine.stories.tsx new file mode 100644 index 0000000000000..7aadc72e9a4e3 --- /dev/null +++ b/site/src/components/Logs/LogLine.stories.tsx @@ -0,0 +1,49 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { chromatic } from "testHelpers/chromatic"; +import { LogLine, LogLinePrefix, LogLineSpace } from "./LogLine"; + +const meta: Meta = { + title: "components/Logs/LogLine", + parameters: { chromatic }, + component: LogLine, + args: { + level: "info", + children: ( + <> + 13:45:31.072 + + info: Starting build + + ), + }, +}; + +export default meta; + +type Story = StoryObj; + +export const Info: Story = {}; + +export const Debug: Story = { + args: { + level: "debug", + }, +}; + +export const Error: Story = { + args: { + level: "error", + }, +}; + +export const Trace: Story = { + args: { + level: "trace", + }, +}; + +export const Warn: Story = { + args: { + level: "warn", + }, +}; diff --git a/site/src/components/Logs/LogLine.tsx b/site/src/components/Logs/LogLine.tsx index c410d032bb99a..898de45bfbbd2 100644 --- a/site/src/components/Logs/LogLine.tsx +++ b/site/src/components/Logs/LogLine.tsx @@ -10,7 +10,7 @@ export interface Line { time: string; output: string; level: LogLevel; - source_id: string; + sourceId: string; } type LogLineProps = { diff --git a/site/src/components/Logs/Logs.stories.tsx b/site/src/components/Logs/Logs.stories.tsx index b63c01cc5f901..3bb09401c5332 100644 --- a/site/src/components/Logs/Logs.stories.tsx +++ b/site/src/components/Logs/Logs.stories.tsx @@ -1,20 +1,26 @@ import type { Meta, StoryObj } from "@storybook/react"; import { chromatic } from "testHelpers/chromatic"; import { MockWorkspaceBuildLogs } from "testHelpers/entities"; -import { WorkspaceBuildLogs } from "../../modules/workspaces/WorkspaceBuildLogs/WorkspaceBuildLogs"; +import { Logs } from "./Logs"; -const meta: Meta = { - title: "modules/workspaces/WorkspaceBuildLogs", +const meta: Meta = { + title: "components/Logs", parameters: { chromatic }, - component: WorkspaceBuildLogs, + component: Logs, + args: { + lines: MockWorkspaceBuildLogs.map((log) => ({ + level: log.log_level, + time: log.created_at, + output: log.output, + sourceId: log.log_source, + })), + }, }; export default meta; -type Story = StoryObj; +type Story = StoryObj; -export const InProgress: Story = { - args: { - logs: MockWorkspaceBuildLogs.slice(0, 20), - }, -}; +const Default: Story = {}; + +export { Default as Logs }; diff --git a/site/src/modules/resources/AgentLogs.tsx b/site/src/modules/resources/AgentLogs.tsx index 669ecde90d9ac..203b1fd4005fe 100644 --- a/site/src/modules/resources/AgentLogs.tsx +++ b/site/src/modules/resources/AgentLogs.tsx @@ -56,7 +56,7 @@ export const AgentLogs = forwardRef( } ); }; - const logSource = getLogSource(log.source_id); + const logSource = getLogSource(log.sourceId); let assignedIcon = false; let icon: JSX.Element; @@ -96,7 +96,7 @@ export const AgentLogs = forwardRef( let nextChangesSource = false; if (index < logs.length - 1) { nextChangesSource = - getLogSource(logs[index + 1].source_id).id !== log.source_id; + getLogSource(logs[index + 1].sourceId).id !== log.sourceId; } // We don't want every line to repeat the icon, because // that is ugly and repetitive. This removes the icon @@ -105,7 +105,7 @@ export const AgentLogs = forwardRef( // same source. if ( index > 0 && - getLogSource(logs[index - 1].source_id).id === log.source_id + getLogSource(logs[index - 1].sourceId).id === log.sourceId ) { icon = (
= { diff --git a/site/src/modules/resources/AgentRow.tsx b/site/src/modules/resources/AgentRow.tsx index 8677b7f6d7b5e..c63f0511354ff 100644 --- a/site/src/modules/resources/AgentRow.tsx +++ b/site/src/modules/resources/AgentRow.tsx @@ -112,7 +112,7 @@ export const AgentRow: FC = ({ level: "error", output: "Startup logs exceeded the max size of 1MB!", time: new Date().toISOString(), - source_id: "", + sourceId: "", }); } return logs; diff --git a/site/src/modules/workspaces/WorkspaceBuildLogs/WorkspaceBuildLogs.tsx b/site/src/modules/workspaces/WorkspaceBuildLogs/WorkspaceBuildLogs.tsx index 1d17363a00a67..88cfdd5f14cad 100644 --- a/site/src/modules/workspaces/WorkspaceBuildLogs/WorkspaceBuildLogs.tsx +++ b/site/src/modules/workspaces/WorkspaceBuildLogs/WorkspaceBuildLogs.tsx @@ -69,7 +69,7 @@ export const WorkspaceBuildLogs: FC = ({ time: log.created_at, output: log.output, level: log.log_level, - source_id: log.log_source, + sourceId: log.log_source, })); const duration = getStageDurationInSeconds(logs); const shouldDisplayDuration = duration !== undefined; diff --git a/site/src/pages/TemplatePage/TemplateLayout.tsx b/site/src/pages/TemplatePage/TemplateLayout.tsx index 0ba642a5908b0..78cc12cab942d 100644 --- a/site/src/pages/TemplatePage/TemplateLayout.tsx +++ b/site/src/pages/TemplatePage/TemplateLayout.tsx @@ -26,7 +26,7 @@ const templatePermissions = ( canUpdateTemplate: { object: { resource_type: "template", - resource_id: templateId, + resourceId: templateId, }, action: "update", }, diff --git a/site/src/pages/TemplateSettingsPage/TemplateSettingsLayout.tsx b/site/src/pages/TemplateSettingsPage/TemplateSettingsLayout.tsx index 207b828b1ada7..efb27516e6726 100644 --- a/site/src/pages/TemplateSettingsPage/TemplateSettingsLayout.tsx +++ b/site/src/pages/TemplateSettingsPage/TemplateSettingsLayout.tsx @@ -36,7 +36,7 @@ export const TemplateSettingsLayout: FC = () => { canUpdateTemplate: { object: { resource_type: "template", - resource_id: templateQuery.data?.id ?? "", + resourceId: templateQuery.data?.id ?? "", }, action: "update", }, diff --git a/site/src/pages/WorkspaceSettingsPage/WorkspaceSchedulePage/WorkspaceSchedulePage.tsx b/site/src/pages/WorkspaceSettingsPage/WorkspaceSchedulePage/WorkspaceSchedulePage.tsx index 2cb2e4cabcb14..7830a161c879e 100644 --- a/site/src/pages/WorkspaceSettingsPage/WorkspaceSchedulePage/WorkspaceSchedulePage.tsx +++ b/site/src/pages/WorkspaceSettingsPage/WorkspaceSchedulePage/WorkspaceSchedulePage.tsx @@ -35,7 +35,7 @@ const permissionsToCheck = (workspace: TypesGen.Workspace) => updateWorkspace: { object: { resource_type: "workspace", - resource_id: workspace.id, + resourceId: workspace.id, owner_id: workspace.owner_id, }, action: "update", From 23b3910eb22b45bb5e072af418261e7920e30a5a Mon Sep 17 00:00:00 2001 From: BrunoQuaresma Date: Tue, 12 Mar 2024 14:00:17 +0000 Subject: [PATCH 3/8] Fix source_id prop --- site/src/modules/resources/AgentLogs.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/src/modules/resources/AgentLogs.tsx b/site/src/modules/resources/AgentLogs.tsx index 203b1fd4005fe..626d0a825bafa 100644 --- a/site/src/modules/resources/AgentLogs.tsx +++ b/site/src/modules/resources/AgentLogs.tsx @@ -206,7 +206,7 @@ export const useAgentLogs = ( level: log.level || "info", output: log.output, time: log.created_at, - sourceId: log.sourceId, + sourceId: log.source_id, })); if (!previousLogs) { From c3e39a1927606b36b31a7af3b5a008e7918ba116 Mon Sep 17 00:00:00 2001 From: BrunoQuaresma Date: Tue, 12 Mar 2024 16:10:03 +0000 Subject: [PATCH 4/8] Fix resource_id parametters --- site/src/pages/TemplatePage/TemplateLayout.tsx | 2 +- site/src/pages/TemplateSettingsPage/TemplateSettingsLayout.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/site/src/pages/TemplatePage/TemplateLayout.tsx b/site/src/pages/TemplatePage/TemplateLayout.tsx index 78cc12cab942d..0ba642a5908b0 100644 --- a/site/src/pages/TemplatePage/TemplateLayout.tsx +++ b/site/src/pages/TemplatePage/TemplateLayout.tsx @@ -26,7 +26,7 @@ const templatePermissions = ( canUpdateTemplate: { object: { resource_type: "template", - resourceId: templateId, + resource_id: templateId, }, action: "update", }, diff --git a/site/src/pages/TemplateSettingsPage/TemplateSettingsLayout.tsx b/site/src/pages/TemplateSettingsPage/TemplateSettingsLayout.tsx index efb27516e6726..207b828b1ada7 100644 --- a/site/src/pages/TemplateSettingsPage/TemplateSettingsLayout.tsx +++ b/site/src/pages/TemplateSettingsPage/TemplateSettingsLayout.tsx @@ -36,7 +36,7 @@ export const TemplateSettingsLayout: FC = () => { canUpdateTemplate: { object: { resource_type: "template", - resourceId: templateQuery.data?.id ?? "", + resource_id: templateQuery.data?.id ?? "", }, action: "update", }, From cb7cda9d5d39bb95fce0b093149ecb279f312ff5 Mon Sep 17 00:00:00 2001 From: BrunoQuaresma Date: Tue, 12 Mar 2024 16:20:23 +0000 Subject: [PATCH 5/8] Fix line height --- site/src/components/Logs/LogLine.tsx | 3 +-- site/src/modules/resources/AgentLogs.tsx | 5 ++--- site/src/modules/resources/AgentRow.tsx | 7 +++++-- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/site/src/components/Logs/LogLine.tsx b/site/src/components/Logs/LogLine.tsx index 898de45bfbbd2..839ffa358138b 100644 --- a/site/src/components/Logs/LogLine.tsx +++ b/site/src/components/Logs/LogLine.tsx @@ -4,7 +4,6 @@ import type { LogLevel } from "api/typesGenerated"; import { MONOSPACE_FONT_FAMILY } from "theme/constants"; export const DEFAULT_LOG_LINE_SIDE_PADDING = 24; -export const LOG_LINE_HEIGHT = 20; export interface Line { time: string; @@ -43,7 +42,7 @@ const styles = { fontSize: 13, color: theme.palette.text.primary, fontFamily: MONOSPACE_FONT_FAMILY, - height: LOG_LINE_HEIGHT, + height: "auto", // Whitespace is significant in terminal output for alignment whiteSpace: "pre", padding: `0 var(--log-line-side-padding, ${DEFAULT_LOG_LINE_SIDE_PADDING}px)`, diff --git a/site/src/modules/resources/AgentLogs.tsx b/site/src/modules/resources/AgentLogs.tsx index 626d0a825bafa..599c3fea48935 100644 --- a/site/src/modules/resources/AgentLogs.tsx +++ b/site/src/modules/resources/AgentLogs.tsx @@ -10,9 +10,8 @@ import { import { FixedSizeList as List } from "react-window"; import * as API from "api/api"; import type { WorkspaceAgentLogSource } from "api/typesGenerated"; -import { LOG_LINE_HEIGHT } from "components/Logs/LogLine"; import { AgentLogLine } from "./AgentLogLine"; -import type { LineWithID } from "./AgentRow"; +import { AGENT_LOG_LINE_HEIGHT, type LineWithID } from "./AgentRow"; type AgentLogsProps = Omit< ComponentProps, @@ -37,7 +36,7 @@ export const AgentLogs = forwardRef( ref={ref} css={styles.logs} itemCount={logs.length} - itemSize={LOG_LINE_HEIGHT} + itemSize={AGENT_LOG_LINE_HEIGHT} {...listProps} > {({ index, style }) => { diff --git a/site/src/modules/resources/AgentRow.tsx b/site/src/modules/resources/AgentRow.tsx index c63f0511354ff..45f97288753d7 100644 --- a/site/src/modules/resources/AgentRow.tsx +++ b/site/src/modules/resources/AgentRow.tsx @@ -21,7 +21,7 @@ import type { WorkspaceAgentMetadata, } from "api/typesGenerated"; import { DropdownArrow } from "components/DropdownArrow/DropdownArrow"; -import { LOG_LINE_HEIGHT, type Line } from "components/Logs/LogLine"; +import type { Line } from "components/Logs/LogLine"; import { Stack } from "components/Stack/Stack"; import { useProxy } from "contexts/ProxyContext"; import { AgentLatency } from "./AgentLatency"; @@ -36,6 +36,9 @@ import { TerminalLink } from "./TerminalLink/TerminalLink"; import { VSCodeDesktopButton } from "./VSCodeDesktopButton/VSCodeDesktopButton"; import { XRayScanAlert } from "./XRayScanAlert"; +// Approximate height of a log line. Used to control virtualized list height. +export const AGENT_LOG_LINE_HEIGHT = 20; + // Logs are stored as the Line interface to make rendering // much more efficient. Instead of mapping objects each time, we're // able to just pass the array of logs to the component. @@ -151,7 +154,7 @@ export const AgentRow: FC = ({ const distanceFromBottom = logListDivRef.current.scrollHeight - (props.scrollOffset + parent.clientHeight); - setBottomOfLogs(distanceFromBottom < LOG_LINE_HEIGHT); + setBottomOfLogs(distanceFromBottom < AGENT_LOG_LINE_HEIGHT); }, [logListDivRef], ); From 8b5a8319adf215a398a750fa2f8a6136b3523cf0 Mon Sep 17 00:00:00 2001 From: BrunoQuaresma Date: Wed, 13 Mar 2024 18:22:39 +0000 Subject: [PATCH 6/8] Apply PR review suggestions --- site/src/components/Logs/LogLine.stories.tsx | 3 +-- site/src/components/Logs/LogLine.tsx | 23 ++++++-------------- site/src/modules/resources/AgentLogLine.tsx | 14 ++++-------- site/src/modules/resources/AgentLogs.tsx | 2 +- 4 files changed, 13 insertions(+), 29 deletions(-) diff --git a/site/src/components/Logs/LogLine.stories.tsx b/site/src/components/Logs/LogLine.stories.tsx index 7aadc72e9a4e3..1dbfc835d2441 100644 --- a/site/src/components/Logs/LogLine.stories.tsx +++ b/site/src/components/Logs/LogLine.stories.tsx @@ -1,6 +1,6 @@ import type { Meta, StoryObj } from "@storybook/react"; import { chromatic } from "testHelpers/chromatic"; -import { LogLine, LogLinePrefix, LogLineSpace } from "./LogLine"; +import { LogLine, LogLinePrefix } from "./LogLine"; const meta: Meta = { title: "components/Logs/LogLine", @@ -11,7 +11,6 @@ const meta: Meta = { children: ( <> 13:45:31.072 - info: Starting build ), diff --git a/site/src/components/Logs/LogLine.tsx b/site/src/components/Logs/LogLine.tsx index 839ffa358138b..7d33d23998c41 100644 --- a/site/src/components/Logs/LogLine.tsx +++ b/site/src/components/Logs/LogLine.tsx @@ -14,11 +14,11 @@ export interface Line { type LogLineProps = { level: LogLevel; -} & HTMLAttributes; +} & HTMLAttributes; export const LogLine: FC = ({ level, ...divProps }) => { return ( -
= ({ level, ...divProps }) => { }; export const LogLinePrefix: FC> = (props) => { - return ; -}; - -export const LogLineSpace: FC = () => { - return ; + return
;
 };
 
 const styles = {
   line: (theme) => ({
+    margin: 0,
     wordBreak: "break-all",
     display: "flex",
     alignItems: "center",
@@ -43,8 +40,6 @@ const styles = {
     color: theme.palette.text.primary,
     fontFamily: MONOSPACE_FONT_FAMILY,
     height: "auto",
-    // Whitespace is significant in terminal output for alignment
-    whiteSpace: "pre",
     padding: `0 var(--log-line-side-padding, ${DEFAULT_LOG_LINE_SIDE_PADDING}px)`,
 
     "&.error": {
@@ -74,16 +69,12 @@ const styles = {
       },
     },
   }),
-  space: {
-    userSelect: "none",
-    width: 24,
-    display: "block",
-    flexShrink: 0,
-  },
+
   prefix: (theme) => ({
     userSelect: "none",
-    whiteSpace: "pre",
+    margin: 0,
     display: "inline-block",
     color: theme.palette.text.secondary,
+    marginRight: 24,
   }),
 } satisfies Record>;
diff --git a/site/src/modules/resources/AgentLogLine.tsx b/site/src/modules/resources/AgentLogLine.tsx
index fdbed192117d7..42d741cd0e8bf 100644
--- a/site/src/modules/resources/AgentLogLine.tsx
+++ b/site/src/modules/resources/AgentLogLine.tsx
@@ -1,12 +1,7 @@
 import type { Interpolation, Theme } from "@emotion/react";
 import AnsiToHTML from "ansi-to-html";
 import { type FC, type ReactNode, useMemo } from "react";
-import {
-  type Line,
-  LogLine,
-  LogLinePrefix,
-  LogLineSpace,
-} from "components/Logs/LogLine";
+import { type Line, LogLine, LogLinePrefix } from "components/Logs/LogLine";
 
 const convert = new AnsiToHTML();
 
@@ -15,13 +10,13 @@ interface AgentLogLineProps {
   number: number;
   style: React.CSSProperties;
   sourceIcon: ReactNode;
-  maxNumber: number;
+  maxLineNumber: number;
 }
 
 export const AgentLogLine: FC = ({
   line,
   number,
-  maxNumber,
+  maxLineNumber,
   sourceIcon,
   style,
 }) => {
@@ -35,12 +30,11 @@ export const AgentLogLine: FC = ({
       
         {number}
       
-      
       (
             
Date: Wed, 13 Mar 2024 19:12:00 +0000
Subject: [PATCH 7/8] Fix missing log line space

---
 site/src/components/Logs/Logs.tsx | 11 ++++-------
 1 file changed, 4 insertions(+), 7 deletions(-)

diff --git a/site/src/components/Logs/Logs.tsx b/site/src/components/Logs/Logs.tsx
index 1870709356b39..76a16e7f4e3c2 100644
--- a/site/src/components/Logs/Logs.tsx
+++ b/site/src/components/Logs/Logs.tsx
@@ -1,7 +1,7 @@
 import type { Interpolation, Theme } from "@emotion/react";
 import dayjs from "dayjs";
 import type { FC } from "react";
-import { LogLinePrefix, LogLineSpace, LogLine, type Line } from "./LogLine";
+import { LogLinePrefix, LogLine, type Line } from "./LogLine";
 
 export const DEFAULT_LOG_LINE_SIDE_PADDING = 24;
 
@@ -22,12 +22,9 @@ export const Logs: FC = ({
         {lines.map((line, idx) => (
           
             {!hideTimestamps && (
-              <>
-                
-                  {dayjs(line.time).format(`HH:mm:ss.SSS`)}
-                
-                
-              
+              
+                {dayjs(line.time).format(`HH:mm:ss.SSS`)}
+              
             )}
             {line.output}
           

From 5e6222ab0ea2b109270af5d15cb3debafbdc0e1c Mon Sep 17 00:00:00 2001
From: BrunoQuaresma 
Date: Thu, 14 Mar 2024 13:57:11 +0000
Subject: [PATCH 8/8] Add output comment

---
 site/src/modules/resources/AgentLogLine.tsx | 1 +
 1 file changed, 1 insertion(+)

diff --git a/site/src/modules/resources/AgentLogLine.tsx b/site/src/modules/resources/AgentLogLine.tsx
index 42d741cd0e8bf..7866669b4e5d0 100644
--- a/site/src/modules/resources/AgentLogLine.tsx
+++ b/site/src/modules/resources/AgentLogLine.tsx
@@ -36,6 +36,7 @@ export const AgentLogLine: FC = ({
         {number}