From dcef5c7cf26eafce3c9de2e7afa19e4a152a9692 Mon Sep 17 00:00:00 2001 From: Jack Hsu Date: Wed, 30 Apr 2025 08:16:30 -0400 Subject: [PATCH] feat(graph): show next steps for successful migrations (#30934) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR updates Migration UI to display "next steps" when they are provided by a migration. This works by writing `nextSteps` into the Nx Console meta in `migrations.json`. If the `nextSteps` is missing or it's empty, then nothing will be shown. Screenshot 2025-04-29 at 5 16 49 PM See: https://www.loom.com/share/c0a4a7dce9df46b5b023fce5e0a3bd2f --- .../src/lib/components/migration-card.tsx | 51 ++++++++++++++++++- graph/migrate/src/lib/migrate.stories.tsx | 9 +++- .../command-line/migrate/migrate-ui-api.ts | 10 ++-- 3 files changed, 63 insertions(+), 7 deletions(-) diff --git a/graph/migrate/src/lib/components/migration-card.tsx b/graph/migrate/src/lib/components/migration-card.tsx index 8b0b95b469..8b315a6efd 100644 --- a/graph/migrate/src/lib/components/migration-card.tsx +++ b/graph/migrate/src/lib/components/migration-card.tsx @@ -12,7 +12,13 @@ import { PlayIcon, } from '@heroicons/react/24/outline'; import { Pill } from '@nx/graph-internal/ui-project-details'; -import { useState, forwardRef, useImperativeHandle, useEffect } from 'react'; +import { + useState, + forwardRef, + useImperativeHandle, + useEffect, + type ReactNode, +} from 'react'; import { AnimatePresence, motion } from 'framer-motion'; export interface MigrationCardHandle { @@ -21,6 +27,30 @@ export interface MigrationCardHandle { toggle: () => void; } +function convertUrlsToLinks(text: string): ReactNode[] { + const urlRegex = /(https?:\/\/[^\s]+)/g; + const parts = text.split(urlRegex); + const urls = text.match(urlRegex) || []; + const result: ReactNode[] = []; + for (let i = 0; i < parts.length; i++) { + if (urls[i - 1]) { + result.push( + + {urls[i - 1]} + + ); + } else if (parts[i]) { + result.push(parts[i]); + } + } + return result; +} + export const MigrationCard = forwardRef< MigrationCardHandle, { @@ -200,6 +230,23 @@ export const MigrationCard = forwardRef< )} + {succeeded && migrationResult?.nextSteps?.length ? ( +
+
+ + More Information & Next Steps + +
    + {migrationResult?.nextSteps.map((step, idx) => ( +
  • + {convertUrlsToLinks(step)} +
  • + ))} +
+

+
+ ) : null} +