/* eslint-disable @nx/enforce-module-boundaries */ import type { MigrationDetailsWithId } from 'nx/src/config/misc-interfaces'; import { FileChange } from 'nx/src/devkit-exports'; import type { MigrationsJsonMetadata } from 'nx/src/command-line/migrate/migrate-ui-api'; /* eslint-enable @nx/enforce-module-boundaries */ import { ArrowPathIcon, CodeBracketIcon, ExclamationCircleIcon, ListBulletIcon, PlayIcon, } from '@heroicons/react/24/outline'; import { Pill } from '@nx/graph-internal/ui-project-details'; import { useState, forwardRef, useImperativeHandle, useEffect } from 'react'; import { AnimatePresence, motion } from 'framer-motion'; export interface MigrationCardHandle { expand: () => void; collapse: () => void; toggle: () => void; } export const MigrationCard = forwardRef< MigrationCardHandle, { migration: MigrationDetailsWithId; nxConsoleMetadata: MigrationsJsonMetadata; isSelected?: boolean; onSelect?: (isSelected: boolean) => void; onRunMigration?: () => void; onFileClick: (file: Omit) => void; onViewImplementation: () => void; onViewDocumentation: () => void; forceIsRunning?: boolean; isExpanded?: boolean; } >(function MigrationCard( { migration, nxConsoleMetadata, isSelected, onSelect, onRunMigration, onFileClick, onViewImplementation, onViewDocumentation, forceIsRunning, isExpanded: isExpandedProp, }, ref ) { const [isExpanded, setIsExpanded] = useState(isExpandedProp ?? false); useImperativeHandle( ref, () => ({ expand: () => setIsExpanded(true), collapse: () => setIsExpanded(false), toggle: () => setIsExpanded((prev) => !prev), }), [] ); useEffect(() => { if (isExpandedProp !== undefined) { setIsExpanded(isExpandedProp); } }, [isExpandedProp]); const migrationResult = nxConsoleMetadata.completedMigrations?.[migration.id]; const succeeded = migrationResult?.type === 'successful'; const failed = migrationResult?.type === 'failed'; const skipped = migrationResult?.type === 'skipped'; const inProgress = nxConsoleMetadata.runningMigrations?.includes( migration.id ); const madeChanges = succeeded && !!migrationResult?.changedFiles.length; const renderSelectBox = onSelect && isSelected !== undefined; const isNxMigration = migration.package.startsWith('@nx') || migration.package.startsWith('nx'); return (
{renderSelectBox && (
onSelect((e.target as any).checked)} id={migration.id} name={migration.id} value={migration.id} type="checkbox" className={`h-4 w-4 ${ succeeded ? 'accent-green-600 dark:accent-green-500' : failed ? 'accent-red-600 dark:accent-red-500' : 'accent-blue-500 dark:accent-sky-500' }`} />
)}
{ if (isNxMigration) { onViewDocumentation(); } }} > {/*
{migration.name}
{isNxMigration && ( )} */}
{migration.description}
{migration.package && ( )}
{' '} {succeeded && !madeChanges && ( )} {succeeded && madeChanges && (
{ setIsExpanded(!isExpanded); }} >
)} {failed && (
)} {skipped && (
)} {(onRunMigration || forceIsRunning) && ( {inProgress || forceIsRunning ? ( ) : !succeeded && !failed ? ( ) : ( )} )}
{failed && ( )} {succeeded && madeChanges && ( )}
{failed && isExpanded && (
{migrationResult?.error}
)}
{succeeded && madeChanges && isExpanded && (
File Changes
    {migrationResult?.changedFiles.map((file) => { return (
  • { onFileClick(file); }} > {file.path}
  • ); })}
)}
); });