import { useMemo } from 'react'; import { useSelector } from 'react-redux'; import { IconCheck, IconRefresh } from '@tabler/icons'; import Button from 'ui/Button'; import StatusBadge from 'ui/StatusBadge'; import ConfirmSyncModal from '../ConfirmSyncModal'; import SyncReviewPage from '../SyncReviewPage'; import useSyncFlow from '../hooks/useSyncFlow'; const SpecStatusSection = ({ collection, sourceUrl, isLoading, error, setError, fileNotFound, specDrift, storedSpec, collectionDrift, remoteDrift, onCheck, onOpenSettings }) => { const openApiSyncConfig = collection?.brunoConfig?.openapi?.[0]; const lastCheckedAt = useSelector((state) => state.openapiSync?.collectionUpdates?.[collection.uid]?.lastChecked); const { isSyncing, showConfirmModal, confirmGroups, handleSyncNow, handleApplySync, cancelConfirmModal, handleConfirmModalSync } = useSyncFlow({ collection, specDrift, remoteDrift, collectionDrift, sourceUrl, setError, checkForUpdates: onCheck }); const lastSyncedAt = openApiSyncConfig?.lastSyncDate; const bannerState = useMemo(() => { if (fileNotFound) { return { variant: 'danger', message: `Source file not found at ${sourceUrl}`, actions: ['open-settings'] }; } if (error || specDrift?.isValid === false) { return { variant: 'danger', message: error || specDrift?.error || 'Invalid OpenAPI specification', actions: [] }; } if (!specDrift) { return null; // TODO: re-enable success banner // if (!lastSyncedAt) return null; // return { // variant: 'success', message: 'Spec is up to date', actions: [], // version: storedSpec?.info?.version, // lastChecked: moment(lastCheckedAt || lastSyncedAt).fromNow() // }; } if (specDrift.storedSpecMissing) { if (!lastSyncedAt) { return { variant: 'warning', message: 'Initial sync required — your collection differs from the spec', actions: [] }; } if (specDrift.hasRemoteChanges) { return { variant: 'warning', message: 'Last synced spec not found — Restore the latest spec from the source to track future changes.', actions: [] }; } return { variant: 'warning', message: 'Last synced spec not found — Restore the latest spec from the source to track future changes.', actions: [] }; } if (specDrift.hasRemoteChanges) { const versionInfo = (specDrift.storedVersion && specDrift.newVersion && specDrift.storedVersion !== specDrift.newVersion) ? ` (v${specDrift.storedVersion} → v${specDrift.newVersion})` : ''; return { variant: 'warning', message: `OpenAPI spec has been updated${versionInfo}`, actions: [], changes: { added: specDrift.added?.length || 0, modified: specDrift.modified?.length || 0, removed: specDrift.removed?.length || 0 } }; } // return { // variant: 'success', message: 'Spec is up to date', actions: [], // version: specDrift.newVersion || storedSpec?.info?.version || specDrift.storedVersion, // lastChecked: lastCheckedAt ? moment(lastCheckedAt).fromNow() : 'just now' // }; return null; }, [isLoading, fileNotFound, error, sourceUrl, specDrift, lastSyncedAt, storedSpec, lastCheckedAt]); return ( <> {bannerState && (
v{bannerState.version}>
)}
{bannerState.lastChecked && (
· Checked {bannerState.lastChecked}
)}
{bannerState.changes && (
{bannerState.changes.added > 0 && The last synced spec is missing in the storage. Restore the latest spec from the source to track future changes.