refactor(site): update build log to be displayed only on active statuses (#8459)

This commit is contained in:
Bruno Quaresma
2023-07-12 13:34:07 -03:00
committed by GitHub
parent 29e4205abf
commit f8f4ae8e2c
7 changed files with 16 additions and 224 deletions
-8
View File
@@ -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
View File
@@ -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} />
)
}
/>