mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
refactor(site): update build log to be displayed only on active statuses (#8459)
This commit is contained in:
@@ -5,7 +5,6 @@ import { HelmetProvider } from "react-helmet-async"
|
||||
import { dark } from "../src/theme"
|
||||
import "../src/theme/globalFonts"
|
||||
import "../src/i18n"
|
||||
import { LocalPreferencesProvider } from "../src/contexts/LocalPreferencesContext"
|
||||
|
||||
export const decorators = [
|
||||
(Story) => (
|
||||
@@ -24,13 +23,6 @@ export const decorators = [
|
||||
</HelmetProvider>
|
||||
)
|
||||
},
|
||||
(Story) => {
|
||||
return (
|
||||
<LocalPreferencesProvider>
|
||||
<Story />
|
||||
</LocalPreferencesProvider>
|
||||
)
|
||||
},
|
||||
]
|
||||
|
||||
export const parameters = {
|
||||
|
||||
+11
-14
@@ -9,7 +9,6 @@ import { GlobalSnackbar } from "./components/GlobalSnackbar/GlobalSnackbar"
|
||||
import { dark } from "./theme"
|
||||
import "./theme/globalFonts"
|
||||
import { StyledEngineProvider, ThemeProvider } from "@mui/material/styles"
|
||||
import { LocalPreferencesProvider } from "contexts/LocalPreferencesContext"
|
||||
|
||||
const queryClient = new QueryClient({
|
||||
defaultOptions: {
|
||||
@@ -26,19 +25,17 @@ export const AppProviders: FC<PropsWithChildren> = ({ children }) => {
|
||||
return (
|
||||
<HelmetProvider>
|
||||
<StyledEngineProvider injectFirst>
|
||||
<LocalPreferencesProvider>
|
||||
<ThemeProvider theme={dark}>
|
||||
<CssBaseline enableColorScheme />
|
||||
<ErrorBoundary>
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<AuthProvider>
|
||||
{children}
|
||||
<GlobalSnackbar />
|
||||
</AuthProvider>
|
||||
</QueryClientProvider>
|
||||
</ErrorBoundary>
|
||||
</ThemeProvider>
|
||||
</LocalPreferencesProvider>
|
||||
<ThemeProvider theme={dark}>
|
||||
<CssBaseline enableColorScheme />
|
||||
<ErrorBoundary>
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<AuthProvider>
|
||||
{children}
|
||||
<GlobalSnackbar />
|
||||
</AuthProvider>
|
||||
</QueryClientProvider>
|
||||
</ErrorBoundary>
|
||||
</ThemeProvider>
|
||||
</StyledEngineProvider>
|
||||
</HelmetProvider>
|
||||
)
|
||||
|
||||
@@ -71,8 +71,6 @@ export interface WorkspaceProps {
|
||||
quota_budget?: number
|
||||
handleBuildRetry: () => void
|
||||
buildLogs?: React.ReactNode
|
||||
canChangeBuildLogsVisibility: boolean
|
||||
isWorkspaceBuildLogsUIActive: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -106,8 +104,6 @@ export const Workspace: FC<React.PropsWithChildren<WorkspaceProps>> = ({
|
||||
handleBuildRetry,
|
||||
templateWarnings,
|
||||
buildLogs,
|
||||
canChangeBuildLogsVisibility,
|
||||
isWorkspaceBuildLogsUIActive,
|
||||
}) => {
|
||||
const styles = useStyles()
|
||||
const navigate = useNavigate()
|
||||
@@ -211,8 +207,6 @@ export const Workspace: FC<React.PropsWithChildren<WorkspaceProps>> = ({
|
||||
canChangeVersions={canChangeVersions}
|
||||
isUpdating={isUpdating}
|
||||
isRestarting={isRestarting}
|
||||
canChangeBuildLogsVisibility={canChangeBuildLogsVisibility}
|
||||
isWorkspaceBuildLogsUIActive={isWorkspaceBuildLogsUIActive}
|
||||
/>
|
||||
</PageHeaderActions>
|
||||
</FullWidthPageHeader>
|
||||
|
||||
@@ -22,10 +22,6 @@ import SettingsOutlined from "@mui/icons-material/SettingsOutlined"
|
||||
import HistoryOutlined from "@mui/icons-material/HistoryOutlined"
|
||||
import DeleteOutlined from "@mui/icons-material/DeleteOutlined"
|
||||
import IconButton from "@mui/material/IconButton"
|
||||
import Divider from "@mui/material/Divider"
|
||||
import VisibilityOffOutlined from "@mui/icons-material/VisibilityOffOutlined"
|
||||
import VisibilityOutlined from "@mui/icons-material/VisibilityOutlined"
|
||||
import { useLocalPreferences } from "contexts/LocalPreferencesContext"
|
||||
|
||||
export interface WorkspaceActionsProps {
|
||||
workspaceStatus: WorkspaceStatus
|
||||
@@ -42,8 +38,6 @@ export interface WorkspaceActionsProps {
|
||||
isRestarting: boolean
|
||||
children?: ReactNode
|
||||
canChangeVersions: boolean
|
||||
canChangeBuildLogsVisibility: boolean
|
||||
isWorkspaceBuildLogsUIActive: boolean
|
||||
}
|
||||
|
||||
export const WorkspaceActions: FC<WorkspaceActionsProps> = ({
|
||||
@@ -60,8 +54,6 @@ export const WorkspaceActions: FC<WorkspaceActionsProps> = ({
|
||||
isUpdating,
|
||||
isRestarting,
|
||||
canChangeVersions,
|
||||
canChangeBuildLogsVisibility,
|
||||
isWorkspaceBuildLogsUIActive,
|
||||
}) => {
|
||||
const styles = useStyles()
|
||||
const {
|
||||
@@ -72,9 +64,6 @@ export const WorkspaceActions: FC<WorkspaceActionsProps> = ({
|
||||
const canBeUpdated = isOutdated && canAcceptJobs
|
||||
const menuTriggerRef = useRef<HTMLButtonElement>(null)
|
||||
const [isMenuOpen, setIsMenuOpen] = useState(false)
|
||||
const localPreferences = useLocalPreferences()
|
||||
const isBuildLogsVisible =
|
||||
localPreferences.getPreference("buildLogsVisibility") === "visible"
|
||||
|
||||
// A mapping of button type to the corresponding React component
|
||||
const buttonMapping: ButtonMapping = {
|
||||
@@ -151,39 +140,6 @@ export const WorkspaceActions: FC<WorkspaceActionsProps> = ({
|
||||
<DeleteOutlined />
|
||||
Delete
|
||||
</MenuItem>
|
||||
|
||||
{isWorkspaceBuildLogsUIActive && (
|
||||
<>
|
||||
<Divider sx={{ borderColor: (theme) => theme.palette.divider }} />
|
||||
{isBuildLogsVisible ? (
|
||||
<MenuItem
|
||||
disabled={!canChangeBuildLogsVisibility}
|
||||
onClick={onMenuItemClick(() => {
|
||||
localPreferences.setPreference(
|
||||
"buildLogsVisibility",
|
||||
"hide",
|
||||
)
|
||||
})}
|
||||
>
|
||||
<VisibilityOffOutlined />
|
||||
Hide build logs
|
||||
</MenuItem>
|
||||
) : (
|
||||
<MenuItem
|
||||
disabled={!canChangeBuildLogsVisibility}
|
||||
onClick={onMenuItemClick(() => {
|
||||
localPreferences.setPreference(
|
||||
"buildLogsVisibility",
|
||||
"visible",
|
||||
)
|
||||
})}
|
||||
>
|
||||
<VisibilityOutlined />
|
||||
Show build logs
|
||||
</MenuItem>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</Menu>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,111 +0,0 @@
|
||||
import {
|
||||
ReactNode,
|
||||
createContext,
|
||||
useCallback,
|
||||
useContext,
|
||||
useEffect,
|
||||
useState,
|
||||
} from "react"
|
||||
|
||||
const LOCAL_PREFERENCES_KEY = "local-preferences"
|
||||
|
||||
const defaultValues = {
|
||||
buildLogsVisibility: "visible" as "visible" | "hide",
|
||||
}
|
||||
|
||||
type LocalPreferencesValues = typeof defaultValues
|
||||
type LocalPreference = keyof LocalPreferencesValues
|
||||
type LocalPreferenceContextValues = {
|
||||
values: LocalPreferencesValues
|
||||
getPreference: (
|
||||
name: LocalPreference,
|
||||
) => LocalPreferencesValues[LocalPreference]
|
||||
setPreference: (
|
||||
name: LocalPreference,
|
||||
value: LocalPreferencesValues[LocalPreference],
|
||||
) => void
|
||||
}
|
||||
|
||||
const LocalPreferencesContext = createContext<
|
||||
LocalPreferenceContextValues | undefined
|
||||
>(undefined)
|
||||
|
||||
export const LocalPreferencesProvider = ({
|
||||
children,
|
||||
}: {
|
||||
children: ReactNode
|
||||
}) => {
|
||||
const [state, setState] = useState<{
|
||||
ready: boolean
|
||||
values: LocalPreferencesValues
|
||||
}>({ ready: false, values: defaultValues })
|
||||
|
||||
useEffect(() => {
|
||||
const preferencesStr = window.localStorage.getItem(LOCAL_PREFERENCES_KEY)
|
||||
if (preferencesStr) {
|
||||
try {
|
||||
const values = JSON.parse(preferencesStr)
|
||||
setState({ ...values, ready: true })
|
||||
return
|
||||
} catch (error) {
|
||||
console.warn(
|
||||
"Error on parsing local preferences. Default values are used.",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
setState((state) => ({ ...state, ready: true }))
|
||||
}, [])
|
||||
|
||||
const getPreference: LocalPreferenceContextValues["getPreference"] =
|
||||
useCallback(
|
||||
(name) => {
|
||||
return state.values[name]
|
||||
},
|
||||
[state.values],
|
||||
)
|
||||
|
||||
const setPreference: LocalPreferenceContextValues["setPreference"] =
|
||||
useCallback((name, value) => {
|
||||
setState((state) => {
|
||||
const newState = {
|
||||
...state,
|
||||
values: {
|
||||
...state.values,
|
||||
[name]: value,
|
||||
},
|
||||
}
|
||||
window.localStorage.setItem(
|
||||
LOCAL_PREFERENCES_KEY,
|
||||
JSON.stringify(newState),
|
||||
)
|
||||
return newState
|
||||
})
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<LocalPreferencesContext.Provider
|
||||
value={
|
||||
state.ready
|
||||
? {
|
||||
values: state.values,
|
||||
getPreference,
|
||||
setPreference,
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
>
|
||||
{children}
|
||||
</LocalPreferencesContext.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
export const useLocalPreferences = () => {
|
||||
const context = useContext(LocalPreferencesContext)
|
||||
if (context === undefined) {
|
||||
throw new Error(
|
||||
"useLocalPreference must be used within a LocalPreferenceProvider",
|
||||
)
|
||||
}
|
||||
return context
|
||||
}
|
||||
@@ -1,7 +1,4 @@
|
||||
import CloseOutlined from "@mui/icons-material/CloseOutlined"
|
||||
import Box from "@mui/material/Box"
|
||||
import IconButton from "@mui/material/IconButton"
|
||||
import Tooltip from "@mui/material/Tooltip"
|
||||
import { ProvisionerJobLog } from "api/typesGenerated"
|
||||
import { Loader } from "components/Loader/Loader"
|
||||
import { WorkspaceBuildLogs } from "components/WorkspaceBuildLogs/WorkspaceBuildLogs"
|
||||
@@ -9,10 +6,8 @@ import { useRef, useEffect } from "react"
|
||||
|
||||
export const WorkspaceBuildLogsSection = ({
|
||||
logs,
|
||||
onHide,
|
||||
}: {
|
||||
logs: ProvisionerJobLog[] | undefined
|
||||
onHide?: () => void
|
||||
}) => {
|
||||
const scrollRef = useRef<HTMLDivElement>(null)
|
||||
|
||||
@@ -43,24 +38,6 @@ export const WorkspaceBuildLogsSection = ({
|
||||
})}
|
||||
>
|
||||
Build logs
|
||||
{onHide && (
|
||||
<Box sx={{ marginLeft: "auto" }}>
|
||||
<Tooltip title="Hide build logs" placement="top">
|
||||
<IconButton
|
||||
onClick={onHide}
|
||||
size="small"
|
||||
sx={(theme) => ({
|
||||
color: theme.palette.text.secondary,
|
||||
"&:hover": {
|
||||
color: theme.palette.text.primary,
|
||||
},
|
||||
})}
|
||||
>
|
||||
<CloseOutlined sx={{ height: 16, width: 16 }} />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
<Box
|
||||
ref={scrollRef}
|
||||
|
||||
@@ -39,7 +39,6 @@ import Checkbox from "@mui/material/Checkbox"
|
||||
import FormControlLabel from "@mui/material/FormControlLabel"
|
||||
import { workspaceBuildMachine } from "xServices/workspaceBuild/workspaceBuildXService"
|
||||
import * as TypesGen from "api/typesGenerated"
|
||||
import { useLocalPreferences } from "contexts/LocalPreferencesContext"
|
||||
import { WorkspaceBuildLogsSection } from "./WorkspaceBuildLogsSection"
|
||||
|
||||
interface WorkspaceReadyPageProps {
|
||||
@@ -94,16 +93,13 @@ export const WorkspaceReadyPage = ({
|
||||
const user = useMe()
|
||||
const { isWarningIgnored, ignoreWarning } = useIgnoreWarnings(user.id)
|
||||
const buildLogs = useBuildLogs(workspace)
|
||||
const localPreferences = useLocalPreferences()
|
||||
const dashboard = useDashboard()
|
||||
const canChangeBuildLogsVisibility = !hasJobError(workspace)
|
||||
const isWorkspaceBuildLogsUIActive = dashboard.experiments.includes(
|
||||
"workspace_build_logs_ui",
|
||||
)
|
||||
const shouldDisplayBuildLogs =
|
||||
hasJobError(workspace) ||
|
||||
(localPreferences.getPreference("buildLogsVisibility") === "visible" &&
|
||||
isWorkspaceBuildLogsUIActive)
|
||||
(dashboard.experiments.includes("workspace_build_logs_ui") &&
|
||||
["canceling", "deleting", "pending", "starting", "stopping"].includes(
|
||||
workspace.latest_build.status,
|
||||
))
|
||||
|
||||
const {
|
||||
mutate: restartWorkspace,
|
||||
@@ -195,18 +191,9 @@ export const WorkspaceReadyPage = ({
|
||||
template={template}
|
||||
quota_budget={quotaState.context.quota?.budget}
|
||||
templateWarnings={templateVersion?.warnings}
|
||||
canChangeBuildLogsVisibility={canChangeBuildLogsVisibility}
|
||||
isWorkspaceBuildLogsUIActive={isWorkspaceBuildLogsUIActive}
|
||||
buildLogs={
|
||||
shouldDisplayBuildLogs && (
|
||||
<WorkspaceBuildLogsSection
|
||||
logs={buildLogs}
|
||||
onHide={() => {
|
||||
if (canChangeBuildLogsVisibility) {
|
||||
localPreferences.setPreference("buildLogsVisibility", "hide")
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<WorkspaceBuildLogsSection logs={buildLogs} />
|
||||
)
|
||||
}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user