From f5fac293dc184ec676150a9fe7272d8f611bad6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=82=B1=E3=82=A4=E3=83=A9?= Date: Tue, 16 Sep 2025 14:33:57 -0600 Subject: [PATCH] fix(site): show available logs consistently on template creation page (#19832) --- .../WorkspaceBuildLogs/WorkspaceBuildLogs.tsx | 51 ++++++++--------- .../CreateTemplatePage/BuildLogsDrawer.tsx | 55 +++++++------------ .../TemplateVersionEditor.tsx | 14 +---- .../WorkspaceBuildPageView.tsx | 1 + .../WorkspaceBuildLogsSection.tsx | 18 +----- 5 files changed, 45 insertions(+), 94 deletions(-) diff --git a/site/src/modules/workspaces/WorkspaceBuildLogs/WorkspaceBuildLogs.tsx b/site/src/modules/workspaces/WorkspaceBuildLogs/WorkspaceBuildLogs.tsx index 161efe260e..7b4d52bb7b 100644 --- a/site/src/modules/workspaces/WorkspaceBuildLogs/WorkspaceBuildLogs.tsx +++ b/site/src/modules/workspaces/WorkspaceBuildLogs/WorkspaceBuildLogs.tsx @@ -1,10 +1,16 @@ -import { type Interpolation, type Theme, useTheme } from "@emotion/react"; +import type { Interpolation, Theme } from "@emotion/react"; import type { ProvisionerJobLog, WorkspaceBuild } from "api/typesGenerated"; import type { Line } from "components/Logs/LogLine"; import { DEFAULT_LOG_LINE_SIDE_PADDING, Logs } from "components/Logs/Logs"; import dayjs from "dayjs"; -import { type FC, Fragment, type HTMLAttributes, useMemo } from "react"; -import { BODY_FONT_FAMILY, MONOSPACE_FONT_FAMILY } from "theme/constants"; +import { + type FC, + Fragment, + type HTMLAttributes, + useLayoutEffect, + useRef, +} from "react"; +import { BODY_FONT_FAMILY } from "theme/constants"; const Language = { seconds: "seconds", @@ -43,6 +49,7 @@ interface WorkspaceBuildLogsProps extends HTMLAttributes { sticky?: boolean; logs: ProvisionerJobLog[]; build?: WorkspaceBuild; + disableAutoscroll?: boolean; } export const WorkspaceBuildLogs: FC = ({ @@ -50,38 +57,24 @@ export const WorkspaceBuildLogs: FC = ({ sticky, logs, build, + disableAutoscroll, + className, ...attrs }) => { - const theme = useTheme(); - - const _processedLogs = useMemo(() => { - const allLogs = logs || []; - - // Add synthetic overflow message if needed - if (build?.job?.logs_overflowed) { - allLogs.push({ - id: -1, - created_at: new Date().toISOString(), - log_level: "error", - log_source: "provisioner", - output: - "Provisioner logs exceeded the max size of 1MB. Will not continue to write provisioner logs for workspace build.", - stage: "overflow", - }); - } - - return allLogs; - }, [logs, build?.job?.logs_overflowed]); - const groupedLogsByStage = groupLogsByStage(logs); + const ref = useRef(null); + useLayoutEffect(() => { + if (disableAutoscroll || logs.length === 0) { + return; + } + ref.current?.scrollIntoView({ block: "end" }); + }, [logs, disableAutoscroll]); + return (
{Object.entries(groupedLogsByStage).map(([stage, logs]) => { diff --git a/site/src/pages/CreateTemplatePage/BuildLogsDrawer.tsx b/site/src/pages/CreateTemplatePage/BuildLogsDrawer.tsx index b19368bcf1..fbca0b5626 100644 --- a/site/src/pages/CreateTemplatePage/BuildLogsDrawer.tsx +++ b/site/src/pages/CreateTemplatePage/BuildLogsDrawer.tsx @@ -11,7 +11,7 @@ import { AlertVariant } from "modules/provisioners/ProvisionerAlert"; import { ProvisionerStatusAlert } from "modules/provisioners/ProvisionerStatusAlert"; import { useWatchVersionLogs } from "modules/templates/useWatchVersionLogs"; import { WorkspaceBuildLogs } from "modules/workspaces/WorkspaceBuildLogs/WorkspaceBuildLogs"; -import { type FC, useLayoutEffect, useRef } from "react"; +import type { FC } from "react"; import { navHeight } from "theme/constants"; type BuildLogsDrawerProps = { @@ -29,27 +29,6 @@ export const BuildLogsDrawer: FC = ({ ...drawerProps }) => { const logs = useWatchVersionLogs(templateVersion); - const logsContainer = useRef(null); - - const scrollToBottom = () => { - setTimeout(() => { - if (logsContainer.current) { - logsContainer.current.scrollTop = logsContainer.current.scrollHeight; - } - }, 0); - }; - - // biome-ignore lint/correctness/useExhaustiveDependencies: consider refactoring - useLayoutEffect(() => { - scrollToBottom(); - }, [logs]); - - // biome-ignore lint/correctness/useExhaustiveDependencies: consider refactoring - useLayoutEffect(() => { - if (drawerProps.open) { - scrollToBottom(); - } - }, [drawerProps.open]); const isMissingVariables = error instanceof JobError && @@ -58,6 +37,7 @@ export const BuildLogsDrawer: FC = ({ const matchingProvisioners = templateVersion?.matched_provisioners?.count; const availableProvisioners = templateVersion?.matched_provisioners?.available; + const hasLogs = logs && logs.length > 0; return ( @@ -70,8 +50,6 @@ export const BuildLogsDrawer: FC = ({ - {} - {isMissingVariables ? ( { @@ -80,23 +58,28 @@ export const BuildLogsDrawer: FC = ({ }); const firstVariableInput = variablesSectionRef.current?.querySelector("input"); - setTimeout(() => firstVariableInput?.focus(), 0); + firstVariableInput?.focus(); drawerProps.onClose(); }} /> - ) : availableProvisioners && availableProvisioners > 0 && logs ? ( -
- -
) : ( <> - - + {(matchingProvisioners === 0 || !hasLogs) && ( + + )} + + {hasLogs ? ( +
+ +
+ ) : ( + + )} )}
diff --git a/site/src/pages/TemplateVersionEditorPage/TemplateVersionEditor.tsx b/site/src/pages/TemplateVersionEditorPage/TemplateVersionEditor.tsx index 906c8ff074..cba63cdf65 100644 --- a/site/src/pages/TemplateVersionEditorPage/TemplateVersionEditor.tsx +++ b/site/src/pages/TemplateVersionEditorPage/TemplateVersionEditor.tsx @@ -197,15 +197,6 @@ export const TemplateVersionEditor: FC = ({ const isEditorValueBinary = typeof editorValue === "string" ? isBinaryData(editorValue) : false; - // Auto scroll - const logsContentRef = useRef(null); - // biome-ignore lint/correctness/useExhaustiveDependencies: consider refactoring - useEffect(() => { - if (logsContentRef.current) { - logsContentRef.current.scrollTop = logsContentRef.current.scrollHeight; - } - }, [buildLogs, resources]); - useLeaveSiteWarning(dirty); const canBuild = !isBuilding; @@ -596,10 +587,7 @@ export const TemplateVersionEditor: FC = ({ {selectedTab === "logs" && ( -
+
{templateVersion.job.error ? (
); }; diff --git a/site/src/pages/WorkspacePage/WorkspaceBuildLogsSection.tsx b/site/src/pages/WorkspacePage/WorkspaceBuildLogsSection.tsx index 9c3e6d5479..e5d74cf3c4 100644 --- a/site/src/pages/WorkspacePage/WorkspaceBuildLogsSection.tsx +++ b/site/src/pages/WorkspacePage/WorkspaceBuildLogsSection.tsx @@ -2,7 +2,7 @@ import { useTheme } from "@emotion/react"; import type { ProvisionerJobLog } from "api/typesGenerated"; import { Loader } from "components/Loader/Loader"; import { WorkspaceBuildLogs } from "modules/workspaces/WorkspaceBuildLogs/WorkspaceBuildLogs"; -import { type FC, useEffect, useRef } from "react"; +import type { FC } from "react"; interface WorkspaceBuildLogsSectionProps { logs?: ProvisionerJobLog[]; @@ -11,22 +11,8 @@ interface WorkspaceBuildLogsSectionProps { export const WorkspaceBuildLogsSection: FC = ({ logs, }) => { - const scrollRef = useRef(null); const theme = useTheme(); - // biome-ignore lint/correctness/useExhaustiveDependencies: reset scroll when logs change - useEffect(() => { - // Auto scrolling makes hard to snapshot test using Chromatic - if (process.env.STORYBOOK === "true") { - return; - } - - const scrollEl = scrollRef.current; - if (scrollEl) { - scrollEl.scrollTop = scrollEl.scrollHeight; - } - }, [logs]); - return (
= ({ > Build logs -
+
{logs ? (