UNPKG

@kinvolk/headlamp-plugin

Version:

The needed infrastructure for building Headlamp plugins.

90 lines (89 loc) 4.98 kB
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; /* * Copyright 2025 The Kubernetes Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import Box from '@mui/material/Box'; import Chip from '@mui/material/Chip'; import Table from '@mui/material/Table'; import TableBody from '@mui/material/TableBody'; import TableCell from '@mui/material/TableCell'; import TableContainer from '@mui/material/TableContainer'; import TableHead from '@mui/material/TableHead'; import TableRow from '@mui/material/TableRow'; import Typography from '@mui/material/Typography'; import { useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { DateLabel } from '../Label'; import SectionBox from '../SectionBox'; /** * Helper to extract revision history from a resource that supports it. */ function getRevisionHistoryFn(resource) { if ('getRevisionHistory' in resource && typeof resource.getRevisionHistory === 'function') { return () => resource.getRevisionHistory(); } return undefined; } /** * RevisionHistorySection shows a table of revision history for rollbackable resources. * Displays revision number, creation date, container images, and current status. * * This is added as an extraSection on Deployment, DaemonSet, and StatefulSet details pages. */ export default function RevisionHistorySection(props) { const { resource } = props; const { t } = useTranslation(['translation']); const [revisions, setRevisions] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const getHistory = getRevisionHistoryFn(resource); useEffect(() => { const historyGetter = getRevisionHistoryFn(resource); let isActive = true; if (!historyGetter) { setRevisions([]); setError(null); setLoading(false); return () => { isActive = false; }; } setLoading(true); setError(null); historyGetter() .then(history => { if (!isActive) { return; } setRevisions(history); setLoading(false); }) .catch(err => { if (!isActive) { return; } setError(err instanceof Error ? err.message : String(err)); setLoading(false); }); return () => { isActive = false; }; // eslint-disable-next-line react-hooks/exhaustive-deps }, [resource?.metadata?.uid, resource?.metadata?.resourceVersion]); if (!getHistory) { return null; } return (_jsxs(SectionBox, { title: t('translation|Revision History'), children: [loading && (_jsx(Typography, { variant: "body2", color: "text.secondary", sx: { py: 2 }, children: t('translation|Loading revision history…') })), error && (_jsx(Typography, { variant: "body2", color: "error", sx: { py: 2 }, children: t('translation|Failed to load revision history: {{ error }}', { error }) })), !loading && !error && revisions.length === 0 && (_jsx(Typography, { variant: "body2", color: "text.secondary", sx: { py: 2 }, children: t('translation|No revision history available.') })), !loading && !error && revisions.length > 0 && (_jsx(TableContainer, { children: _jsxs(Table, { size: "small", children: [_jsx(TableHead, { children: _jsxs(TableRow, { children: [_jsx(TableCell, { children: t('translation|Revision') }), _jsx(TableCell, { children: t('translation|Created') }), _jsx(TableCell, { children: t('translation|Images') }), _jsx(TableCell, { children: t('translation|Status') })] }) }), _jsx(TableBody, { children: revisions.map(rev => (_jsxs(TableRow, { children: [_jsx(TableCell, { children: _jsx(Typography, { variant: "body2", children: rev.revision }) }), _jsx(TableCell, { children: _jsx(DateLabel, { date: rev.createdAt }) }), _jsx(TableCell, { children: _jsx(Box, { sx: { display: 'flex', flexDirection: 'column', gap: 0.5 }, children: rev.images.map((img, i) => (_jsx(Typography, { variant: "body2", sx: { fontFamily: 'monospace' }, children: img }, i))) }) }), _jsx(TableCell, { children: rev.isCurrent ? (_jsx(Chip, { label: t('translation|Current'), size: "small", color: "primary", variant: "outlined" })) : (_jsx(Typography, { variant: "body2", color: "text.secondary", children: t('translation|Previous') })) })] }, rev.revision))) })] }) }))] })); }