diff --git a/graph/client/src/app/app.tsx b/graph/client/src/app/app.tsx index 90dff08ff3b00..60843cb13da2a 100644 --- a/graph/client/src/app/app.tsx +++ b/graph/client/src/app/app.tsx @@ -1,4 +1,4 @@ -import { themeInit } from '@nx/graph/ui-theme'; +import { themeInit } from '@nx/graph-internal/ui-theme'; import { rankDirInit } from './rankdir-resolver'; import { RouterProvider } from 'react-router-dom'; import { getRouter } from './get-router'; diff --git a/graph/client/src/app/feature-projects/machines/composite-graph.state.ts b/graph/client/src/app/feature-projects/machines/composite-graph.state.ts new file mode 100644 index 0000000000000..3f7dcbc4891be --- /dev/null +++ b/graph/client/src/app/feature-projects/machines/composite-graph.state.ts @@ -0,0 +1,155 @@ +import { ProjectGraphStateNodeConfig } from './interfaces'; +import { assign } from '@xstate/immer'; +import { send } from 'xstate'; + +export const compositeGraphStateConfig: ProjectGraphStateNodeConfig = { + entry: [ + assign((ctx, event) => { + if (event.type !== 'enableCompositeGraph') return; + ctx.compositeGraph.enabled = true; + ctx.compositeGraph.context = event.context || undefined; + }), + send( + (ctx) => ({ + type: 'notifyGraphUpdateGraph', + projects: ctx.projects, + dependencies: ctx.dependencies, + fileMap: ctx.fileMap, + affectedProjects: ctx.affectedProjects, + workspaceLayout: ctx.workspaceLayout, + groupByFolder: ctx.groupByFolder, + selectedProjects: ctx.selectedProjects, + composite: ctx.compositeGraph, + }), + { to: (ctx) => ctx.graphActor } + ), + ], + exit: [ + send(() => ({ type: 'notifyGraphDisableCompositeGraph' }), { + to: (ctx) => ctx.graphActor, + }), + assign((ctx) => { + ctx.compositeGraph.enabled = false; + ctx.compositeGraph.context = undefined; + }), + ], + on: { + focusProject: { + actions: [ + assign((ctx, event) => { + if (event.type !== 'focusProject') return; + ctx.focusedProject = event.projectName; + }), + send( + (context, event) => ({ + type: 'notifyGraphFocusProject', + projectName: context.focusedProject, + searchDepth: context.searchDepthEnabled ? context.searchDepth : -1, + }), + { to: (context) => context.graphActor } + ), + ], + }, + unfocusProject: { + actions: [ + assign((ctx, event) => { + if (event.type !== 'unfocusProject') return; + ctx.focusedProject = null; + }), + send((ctx) => ({ + type: 'enableCompositeGraph', + context: ctx.compositeGraph.context, + })), + ], + }, + deselectProject: { + actions: [ + send( + (ctx, event) => ({ + type: 'notifyGraphHideProjects', + projectNames: [event.projectName], + }), + { to: (ctx) => ctx.graphActor } + ), + ], + }, + selectProject: { + actions: [ + send( + (ctx, event) => ({ + type: 'notifyGraphShowProjects', + projectNames: [event.projectName], + }), + { to: (ctx) => ctx.graphActor } + ), + ], + }, + expandCompositeNode: { + actions: [ + send( + (ctx, event) => ({ + type: 'notifyGraphExpandCompositeNode', + id: event.id, + }), + { to: (ctx) => ctx.graphActor } + ), + ], + }, + collapseCompositeNode: { + actions: [ + send( + (ctx, event) => ({ + type: 'notifyGraphCollapseCompositeNode', + id: event.id, + }), + { to: (ctx) => ctx.graphActor } + ), + ], + }, + enableCompositeGraph: { + actions: [ + assign((ctx, event) => { + if (event.type !== 'enableCompositeGraph') return; + ctx.compositeGraph.enabled = true; + ctx.compositeGraph.context = event.context || undefined; + }), + send( + (ctx, event) => ({ + type: 'notifyGraphUpdateGraph', + projects: ctx.projects, + dependencies: ctx.dependencies, + fileMap: ctx.fileMap, + affectedProjects: ctx.affectedProjects, + workspaceLayout: ctx.workspaceLayout, + groupByFolder: ctx.groupByFolder, + selectedProjects: ctx.selectedProjects, + composite: ctx.compositeGraph, + }), + { to: (ctx) => ctx.graphActor } + ), + ], + }, + disableCompositeGraph: { + target: 'unselected', + }, + updateGraph: { + actions: [ + 'setGraph', + send( + (ctx, event) => ({ + type: 'notifyGraphUpdateGraph', + projects: ctx.projects, + dependencies: ctx.dependencies, + fileMap: ctx.fileMap, + affectedProjects: ctx.affectedProjects, + workspaceLayout: ctx.workspaceLayout, + groupByFolder: ctx.groupByFolder, + selectedProjects: ctx.selectedProjects, + composite: ctx.compositeGraph, + }), + { to: (ctx) => ctx.graphActor } + ), + ], + }, + }, +}; diff --git a/graph/client/src/app/feature-projects/machines/custom-selected.state.ts b/graph/client/src/app/feature-projects/machines/custom-selected.state.ts index 2081814eec245..0ebf923e13638 100644 --- a/graph/client/src/app/feature-projects/machines/custom-selected.state.ts +++ b/graph/client/src/app/feature-projects/machines/custom-selected.state.ts @@ -31,6 +31,7 @@ export const customSelectedStateConfig: ProjectGraphStateNodeConfig = { workspaceLayout: ctx.workspaceLayout, groupByFolder: ctx.groupByFolder, selectedProjects: ctx.selectedProjects, + composite: ctx.compositeGraph, }), { to: (context) => context.graphActor, diff --git a/graph/client/src/app/feature-projects/machines/focused.state.ts b/graph/client/src/app/feature-projects/machines/focused.state.ts index d3c6858a0a2d3..0b9e557a23e8b 100644 --- a/graph/client/src/app/feature-projects/machines/focused.state.ts +++ b/graph/client/src/app/feature-projects/machines/focused.state.ts @@ -45,6 +45,7 @@ export const focusedStateConfig: ProjectGraphStateNodeConfig = { workspaceLayout: ctx.workspaceLayout, groupByFolder: ctx.groupByFolder, selectedProjects: ctx.selectedProjects, + composite: ctx.compositeGraph, }), { to: (context) => context.graphActor, diff --git a/graph/client/src/app/feature-projects/machines/graph.actor.ts b/graph/client/src/app/feature-projects/machines/graph.actor.ts index 89261ff2b1ec9..6d0ff5f0dbd2f 100644 --- a/graph/client/src/app/feature-projects/machines/graph.actor.ts +++ b/graph/client/src/app/feature-projects/machines/graph.actor.ts @@ -4,12 +4,13 @@ export const graphActor = (callback, receive) => { const graphService = getGraphService(); receive((e) => { - const { selectedProjectNames, perfReport } = + const { selectedProjectNames, perfReport, compositeNodes } = graphService.handleProjectEvent(e); callback({ type: 'setSelectedProjectsFromGraph', selectedProjectNames, perfReport, + compositeNodes, }); }); }; diff --git a/graph/client/src/app/feature-projects/machines/interfaces.ts b/graph/client/src/app/feature-projects/machines/interfaces.ts index 35a7f091cb7c6..27ed974e1bdc4 100644 --- a/graph/client/src/app/feature-projects/machines/interfaces.ts +++ b/graph/client/src/app/feature-projects/machines/interfaces.ts @@ -1,4 +1,4 @@ -import { GraphPerfReport } from '../../interfaces'; +import { CompositeNode, GraphPerfReport } from '../../interfaces'; /* eslint-disable @nx/enforce-module-boundaries */ // nx-ignore-next-line import { @@ -30,6 +30,7 @@ export type ProjectGraphMachineEvents = type: 'setSelectedProjectsFromGraph'; selectedProjectNames: string[]; perfReport: GraphPerfReport; + compositeNodes: Array; } | { type: 'selectProject'; projectName: string } | { type: 'deselectProject'; projectName: string } @@ -70,7 +71,12 @@ export type ProjectGraphMachineEvents = projects: ProjectGraphProjectNode[]; dependencies: Record; fileMap: ProjectFileMap; - }; + } + | { type: 'enableCompositeGraph'; context: string | null } + | { type: 'setCompositeContext'; context: string | null } + | { type: 'expandCompositeNode'; id: string } + | { type: 'collapseCompositeNode'; id: string } + | { type: 'disableCompositeGraph' }; // The context (extended state) of the machine export interface ProjectGraphContext { @@ -97,6 +103,7 @@ export interface ProjectGraphContext { end: string; algorithm: TracingAlgorithmType; }; + compositeGraph: CompositeGraph; } export type ProjectGraphStateNodeConfig = StateNodeConfig< @@ -115,3 +122,9 @@ export type ProjectGraphState = State< context: ProjectGraphContext; } >; + +export interface CompositeGraph { + enabled: boolean; + context?: string; + nodes: CompositeNode[]; +} diff --git a/graph/client/src/app/feature-projects/machines/project-graph.machine.ts b/graph/client/src/app/feature-projects/machines/project-graph.machine.ts index 8b4de2cfc4b15..c66d9e1458046 100644 --- a/graph/client/src/app/feature-projects/machines/project-graph.machine.ts +++ b/graph/client/src/app/feature-projects/machines/project-graph.machine.ts @@ -7,6 +7,7 @@ import { textFilteredStateConfig } from './text-filtered.state'; import { tracingStateConfig } from './tracing.state'; import { unselectedStateConfig } from './unselected.state'; import { ProjectGraphContext, ProjectGraphMachineEvents } from './interfaces'; +import { compositeGraphStateConfig } from './composite-graph.state'; export const initialContext: ProjectGraphContext = { projects: [], @@ -36,6 +37,10 @@ export const initialContext: ProjectGraphContext = { end: null, algorithm: 'shortest', }, + compositeGraph: { + enabled: false, + nodes: [], + }, }; export const projectGraphMachine = createMachine< @@ -54,6 +59,7 @@ export const projectGraphMachine = createMachine< focused: focusedStateConfig, textFiltered: textFilteredStateConfig, tracing: tracingStateConfig, + composite: compositeGraphStateConfig, }, on: { setProjects: { @@ -70,6 +76,7 @@ export const projectGraphMachine = createMachine< workspaceLayout: ctx.workspaceLayout, groupByFolder: ctx.groupByFolder, collapseEdges: ctx.collapseEdges, + composite: ctx.compositeGraph.enabled, }), { to: (context) => context.graphActor, @@ -82,6 +89,7 @@ export const projectGraphMachine = createMachine< assign((ctx, event) => { ctx.selectedProjects = event.selectedProjectNames; ctx.lastPerfReport = event.perfReport; + ctx.compositeGraph.nodes = event.compositeNodes; }), ], }, @@ -147,6 +155,7 @@ export const projectGraphMachine = createMachine< groupByFolder: ctx.groupByFolder, collapseEdges: ctx.collapseEdges, selectedProjects: ctx.selectedProjects, + composite: ctx.compositeGraph, }), { to: (context) => context.graphActor, @@ -168,6 +177,7 @@ export const projectGraphMachine = createMachine< groupByFolder: ctx.groupByFolder, collapseEdges: ctx.collapseEdges, selectedProjects: ctx.selectedProjects, + composite: ctx.compositeGraph, }), { to: (context) => context.graphActor, @@ -205,6 +215,9 @@ export const projectGraphMachine = createMachine< filterByText: { target: 'textFiltered', }, + enableCompositeGraph: { + target: 'composite', + }, }, }, { @@ -212,6 +225,9 @@ export const projectGraphMachine = createMachine< deselectLastProject: (ctx) => { return ctx.selectedProjects.length <= 1; }, + isCompositeGraphEnabled: (ctx) => { + return ctx.compositeGraph.enabled; + }, }, actions: { setGroupByFolder: assign((ctx, event) => { @@ -356,7 +372,6 @@ export const projectGraphMachine = createMachine< to: (context) => context.graphActor, } ), - notifyGraphFilterProjectsByText: send( (context, event) => ({ type: 'notifyGraphFilterProjectsByText', diff --git a/graph/client/src/app/feature-projects/machines/project-graph.spec.ts b/graph/client/src/app/feature-projects/machines/project-graph.spec.ts index 1a4a47bdd5042..68396dac9a984 100644 --- a/graph/client/src/app/feature-projects/machines/project-graph.spec.ts +++ b/graph/client/src/app/feature-projects/machines/project-graph.spec.ts @@ -106,6 +106,8 @@ const mockAppConfig: AppConfig = { label: 'local', projectGraphUrl: 'assets/project-graphs/e2e.json', taskGraphUrl: 'assets/task-graphs/e2e.json', + taskInputsUrl: '', + sourceMapsUrl: '', }, ], defaultWorkspaceId: 'local', diff --git a/graph/client/src/app/feature-projects/machines/selectors.ts b/graph/client/src/app/feature-projects/machines/selectors.ts index c1a1e0dd5fcfd..435d3928943dd 100644 --- a/graph/client/src/app/feature-projects/machines/selectors.ts +++ b/graph/client/src/app/feature-projects/machines/selectors.ts @@ -3,7 +3,11 @@ import type { ProjectGraphProjectNode } from '@nx/devkit'; /* eslint-enable @nx/enforce-module-boundaries */ import { ProjectGraphSelector } from '../hooks/use-project-graph-selector'; -import { GraphPerfReport, WorkspaceLayout } from '../../interfaces'; +import { + CompositeNode, + GraphPerfReport, + WorkspaceLayout, +} from '../../interfaces'; import { TracingAlgorithmType } from './interfaces'; export const allProjectsSelector: ProjectGraphSelector< @@ -46,6 +50,15 @@ export const groupByFolderSelector: ProjectGraphSelector = (state) => export const collapseEdgesSelector: ProjectGraphSelector = (state) => state.context.collapseEdges; +export const compositeGraphEnabledSelector: ProjectGraphSelector = ( + state +) => state.context.compositeGraph.enabled; +export const compositeContextSelector: ProjectGraphSelector = ( + state +) => state.context.compositeGraph.context; +export const compositeNodesSelector: ProjectGraphSelector = ( + state +) => state.context.compositeGraph.nodes; export const textFilterSelector: ProjectGraphSelector = (state) => state.context.textFilter; diff --git a/graph/client/src/app/feature-projects/machines/text-filtered.state.ts b/graph/client/src/app/feature-projects/machines/text-filtered.state.ts index ba2c9b576a6e7..dba072ca0667f 100644 --- a/graph/client/src/app/feature-projects/machines/text-filtered.state.ts +++ b/graph/client/src/app/feature-projects/machines/text-filtered.state.ts @@ -44,6 +44,7 @@ export const textFilteredStateConfig: ProjectGraphStateNodeConfig = { workspaceLayout: ctx.workspaceLayout, groupByFolder: ctx.groupByFolder, selectedProjects: ctx.selectedProjects, + composite: ctx.compositeGraph, }), { to: (context) => context.graphActor, diff --git a/graph/client/src/app/feature-projects/machines/unselected.state.ts b/graph/client/src/app/feature-projects/machines/unselected.state.ts index cd997be97a784..54098b1724d6f 100644 --- a/graph/client/src/app/feature-projects/machines/unselected.state.ts +++ b/graph/client/src/app/feature-projects/machines/unselected.state.ts @@ -33,6 +33,7 @@ export const unselectedStateConfig: ProjectGraphStateNodeConfig = { workspaceLayout: ctx.workspaceLayout, groupByFolder: ctx.groupByFolder, selectedProjects: ctx.selectedProjects, + composite: ctx.compositeGraph, }), { to: (context) => context.graphActor, diff --git a/graph/client/src/app/feature-projects/panels/composite-graph-panel.tsx b/graph/client/src/app/feature-projects/panels/composite-graph-panel.tsx new file mode 100644 index 0000000000000..0b1a147de81c0 --- /dev/null +++ b/graph/client/src/app/feature-projects/panels/composite-graph-panel.tsx @@ -0,0 +1,42 @@ +import { memo } from 'react'; + +export interface CompositeGraphPanelProps { + compositeEnabled: boolean; + compositeEnabledChanged: (checked: boolean) => void; +} + +export const CompositeGraphPanel = memo( + ({ compositeEnabled, compositeEnabledChanged }: CompositeGraphPanelProps) => { + return ( +
+
+
+ + compositeEnabledChanged(event.target.checked) + } + checked={compositeEnabled} + /> +
+
+ +

+ Enables experimental composite graph with composite nodes and + edges +

+
+
+
+ ); + } +); diff --git a/graph/client/src/app/feature-projects/project-list.tsx b/graph/client/src/app/feature-projects/project-list.tsx index 4ee3bf2e006d4..33af5316eb9c8 100644 --- a/graph/client/src/app/feature-projects/project-list.tsx +++ b/graph/client/src/app/feature-projects/project-list.tsx @@ -1,4 +1,6 @@ import { + ArrowsPointingInIcon, + ArrowsPointingOutIcon, DocumentMagnifyingGlassIcon, EyeIcon, FlagIcon, @@ -11,6 +13,9 @@ import type { ProjectGraphProjectNode } from '@nx/devkit'; import { useProjectGraphSelector } from './hooks/use-project-graph-selector'; import { allProjectsSelector, + compositeContextSelector, + compositeGraphEnabledSelector, + compositeNodesSelector, getTracingInfo, selectedProjectNamesSelector, workspaceLayoutSelector, @@ -19,8 +24,9 @@ import { getProjectsByType, parseParentDirectoriesFromFilePath } from '../util'; import { ExperimentalFeature } from '../ui-components/experimental-feature'; import { TracingAlgorithmType } from './machines/interfaces'; import { getProjectGraphService } from '../machines/get-services'; -import { Link, useNavigate } from 'react-router-dom'; +import { Link, useNavigate, useNavigation } from 'react-router-dom'; import { useRouteConstructor } from '@nx/graph/shared'; +import { CompositeNode } from '../interfaces'; interface SidebarProject { projectGraphNode: ProjectGraphProjectNode; @@ -234,6 +240,120 @@ function SubProjectList({ ); } +function CompositeNodeListItem({ + compositeNode, +}: { + compositeNode: CompositeNode; +}) { + const projectGraphService = getProjectGraphService(); + const routeConstructor = useRouteConstructor(); + const navigate = useNavigate(); + + function toggleProject() { + if (compositeNode.state !== 'hidden') { + projectGraphService.send({ + type: 'deselectProject', + projectName: compositeNode.id, + }); + } else { + projectGraphService.send({ + type: 'selectProject', + projectName: compositeNode.id, + }); + } + navigate(routeConstructor('/projects', true)); + } + + function toggleExpansion() { + if (compositeNode.state === 'expanded') { + projectGraphService.send({ + type: 'collapseCompositeNode', + id: compositeNode.id, + }); + } else { + projectGraphService.send({ + type: 'expandCompositeNode', + id: compositeNode.id, + }); + } + } + + return ( +
  • +
    + + + + + + + +
    + + {compositeNode.state !== 'hidden' ? ( + + + + ) : null} +
  • + ); +} + +function CompositeNodeList({ + compositeNodes, +}: { + compositeNodes: CompositeNode[]; +}) { + const projectGraphService = getProjectGraphService(); + + if (compositeNodes.length === 0) { + return

    No composite nodes

    ; + } + + return ( +
      + {compositeNodes.map((node) => { + return ; + })} +
    + ); +} + export function ProjectList() { const tracingInfo = useProjectGraphSelector(getTracingInfo); @@ -242,6 +362,11 @@ export function ProjectList() { const selectedProjects = useProjectGraphSelector( selectedProjectNamesSelector ); + const compositeGraphEnabled = useProjectGraphSelector( + compositeGraphEnabledSelector + ); + const compositeContext = useProjectGraphSelector(compositeContextSelector); + const compositeNodes = useProjectGraphSelector(compositeNodesSelector); const appProjects = getProjectsByType('app', projects); const libProjects = getProjectsByType('lib', projects); @@ -269,6 +394,15 @@ export function ProjectList() { return (
    + {compositeGraphEnabled && !compositeContext ? ( + <> +

    + composite nodes +

    + + + ) : null} +

    app projects

    diff --git a/graph/client/src/app/feature-projects/projects-sidebar.tsx b/graph/client/src/app/feature-projects/projects-sidebar.tsx index 8ffb6607309c2..676f318bdb084 100644 --- a/graph/client/src/app/feature-projects/projects-sidebar.tsx +++ b/graph/client/src/app/feature-projects/projects-sidebar.tsx @@ -68,24 +68,24 @@ export function ProjectsSidebar(): JSX.Element { const [lastHash, setLastHash] = useState(selectedProjectRouteData.hash); const params = useParams(); const navigate = useNavigate(); - const routeContructor = useRouteConstructor(); + const routeConstructor = useRouteConstructor(); function resetFocus() { projectGraphService.send({ type: 'unfocusProject' }); - navigate(routeContructor('/projects', true)); + navigate(routeConstructor('/projects', true)); } function showAllProjects() { - navigate(routeContructor('/projects/all', true)); + navigate(routeConstructor('/projects/all', true)); } function hideAllProjects() { projectGraphService.send({ type: 'deselectAll' }); - navigate(routeContructor('/projects', true)); + navigate(routeConstructor('/projects', true)); } function showAffectedProjects() { - navigate(routeContructor('/projects/affected', true)); + navigate(routeConstructor('/projects/affected', true)); } function searchDepthFilterEnabledChange(checked: boolean) { @@ -166,12 +166,12 @@ export function ProjectsSidebar(): JSX.Element { function resetTraceStart() { projectGraphService.send({ type: 'clearTraceStart' }); - navigate(routeContructor('/projects', true)); + navigate(routeConstructor('/projects', true)); } function resetTraceEnd() { projectGraphService.send({ type: 'clearTraceEnd' }); - navigate(routeContructor('/projects', true)); + navigate(routeConstructor('/projects', true)); } function setAlgorithm(algorithm: TracingAlgorithmType) { @@ -320,7 +320,7 @@ export function ProjectsSidebar(): JSX.Element { const updateTextFilter = useCallback( (textFilter: string) => { projectGraphService.send({ type: 'filterByText', search: textFilter }); - navigate(routeContructor('/projects', true)); + navigate(routeConstructor('/projects', true)); }, [projectGraphService] ); @@ -335,6 +335,7 @@ export function ProjectsSidebar(): JSX.Element { resetFocus={resetFocus} > ) : null} + {isTracing ? ( -
    +

    Experimental Features

    diff --git a/graph/client/src/app/interfaces.ts b/graph/client/src/app/interfaces.ts index 6b4fc69873d5c..3fc4f5b46a004 100644 --- a/graph/client/src/app/interfaces.ts +++ b/graph/client/src/app/interfaces.ts @@ -31,3 +31,9 @@ export interface GraphPerfReport { numNodes: number; numEdges: number; } + +export interface CompositeNode { + id: string; + label: string; + state: 'expanded' | 'collapsed' | 'hidden'; +} diff --git a/graph/client/src/app/machines/graph.service.ts b/graph/client/src/app/machines/graph.service.ts index 94267370f26c2..4353627478ac2 100644 --- a/graph/client/src/app/machines/graph.service.ts +++ b/graph/client/src/app/machines/graph.service.ts @@ -3,7 +3,7 @@ import { getEnvironmentConfig, getProjectGraphDataService, } from '@nx/graph/shared'; -import { selectValueByThemeStatic } from '@nx/graph/ui-theme'; +import { selectValueByThemeStatic } from '@nx/graph-internal/ui-theme'; let graphService: GraphService; diff --git a/graph/client/src/app/machines/interfaces.ts b/graph/client/src/app/machines/interfaces.ts index 9d501eaa4f806..f0cf798973f2b 100644 --- a/graph/client/src/app/machines/interfaces.ts +++ b/graph/client/src/app/machines/interfaces.ts @@ -22,6 +22,7 @@ export type GraphRenderEvents = }; groupByFolder: boolean; collapseEdges: boolean; + composite: { enabled: boolean; context: string | null }; } | { type: 'notifyGraphUpdateGraph'; @@ -36,6 +37,7 @@ export type GraphRenderEvents = groupByFolder: boolean; collapseEdges: boolean; selectedProjects: string[]; + composite: { enabled: boolean; context: string | null }; } | { type: 'notifyGraphFocusProject'; @@ -70,4 +72,5 @@ export type GraphRenderEvents = start: string; end: string; algorithm: TracingAlgorithmType; - }; + } + | { type: 'notifyGraphDisableCompositeGraph' }; diff --git a/graph/client/src/app/routes.tsx b/graph/client/src/app/routes.tsx index a724f8fdba151..3a759244b33ec 100644 --- a/graph/client/src/app/routes.tsx +++ b/graph/client/src/app/routes.tsx @@ -16,7 +16,7 @@ import { getProjectGraphDataService, } from '@nx/graph/shared'; import { TasksSidebarErrorBoundary } from './feature-tasks/tasks-sidebar-error-boundary'; -import { ProjectDetailsPage } from '@nx/graph/project-details'; +import { ProjectDetailsPage } from '@nx/graph-internal/project-details'; import { ErrorBoundary } from './ui-components/error-boundary'; const { appConfig } = getEnvironmentConfig(); diff --git a/graph/client/src/app/shell.tsx b/graph/client/src/app/shell.tsx index aa18b7559b029..6e424ee0f8ee2 100644 --- a/graph/client/src/app/shell.tsx +++ b/graph/client/src/app/shell.tsx @@ -10,6 +10,7 @@ import { ArrowDownTrayIcon, ArrowLeftCircleIcon, InformationCircleIcon, + ViewfinderCircleIcon, } from '@heroicons/react/24/outline'; import { ErrorToast, @@ -19,7 +20,7 @@ import { usePoll, } from '@nx/graph/shared'; import { Dropdown, Spinner } from '@nx/graph/ui-components'; -import { getSystemTheme, Theme, ThemePanel } from '@nx/graph/ui-theme'; +import { getSystemTheme, Theme, ThemePanel } from '@nx/graph-internal/ui-theme'; import { Tooltip } from '@nx/graph/ui-tooltips'; import classNames from 'classnames'; import { useLayoutEffect, useState } from 'react'; @@ -118,6 +119,11 @@ export function Shell(): JSX.Element { ); } + function resetLayout() { + const graph = getGraphService(); + graph.resetLayout(); + } + return (
    + +
    diff --git a/graph/client/src/app/ui-components/composite-context-panel.tsx b/graph/client/src/app/ui-components/composite-context-panel.tsx new file mode 100644 index 0000000000000..56124b29929c3 --- /dev/null +++ b/graph/client/src/app/ui-components/composite-context-panel.tsx @@ -0,0 +1,32 @@ +import { ArrowRightCircleIcon, XCircleIcon } from '@heroicons/react/24/outline'; +import { memo } from 'react'; + +export interface CompositeContextPanelProps { + compositeContext: string; + reset: () => void; +} + +export const CompositeContextPanel = memo( + ({ compositeContext, reset }: CompositeContextPanelProps) => { + return ( +
    +
    reset()} + > +

    + + Focused on {compositeContext} +

    +
    + Reset + + + +
    +
    +
    + ); + } +); diff --git a/graph/client/src/app/ui-components/error-boundary.tsx b/graph/client/src/app/ui-components/error-boundary.tsx index b9e0c38c59fc4..e4993ca9a47e8 100644 --- a/graph/client/src/app/ui-components/error-boundary.tsx +++ b/graph/client/src/app/ui-components/error-boundary.tsx @@ -1,4 +1,4 @@ -import { ProjectDetailsHeader } from '@nx/graph/project-details'; +import { ProjectDetailsHeader } from '@nx/graph-internal/project-details'; import { fetchProjectGraph, getProjectGraphDataService, diff --git a/graph/client/src/app/ui-components/project-details-modal.tsx b/graph/client/src/app/ui-components/project-details-modal.tsx index e70a0b67faf77..78a4b514712b5 100644 --- a/graph/client/src/app/ui-components/project-details-modal.tsx +++ b/graph/client/src/app/ui-components/project-details-modal.tsx @@ -2,7 +2,7 @@ // nx-ignore-next-line import { ProjectGraphClientResponse } from 'nx/src/command-line/graph/graph'; // nx-ignore-next-line -import { ProjectDetailsWrapper } from '@nx/graph/project-details'; +import { ProjectDetailsWrapper } from '@nx/graph-internal/project-details'; /* eslint-enable @nx/enforce-module-boundaries */ import { useFloating } from '@floating-ui/react'; import { XMarkIcon } from '@heroicons/react/24/outline'; diff --git a/graph/client/src/app/ui-tooltips/graph-tooltip-display.tsx b/graph/client/src/app/ui-tooltips/graph-tooltip-display.tsx index 2e7281884a8ad..9bcf1c0f2e5d5 100644 --- a/graph/client/src/app/ui-tooltips/graph-tooltip-display.tsx +++ b/graph/client/src/app/ui-tooltips/graph-tooltip-display.tsx @@ -1,15 +1,22 @@ import { useSyncExternalStore } from 'use-sync-external-store/shim'; -import { getTooltipService } from '../machines/get-services'; import { + getProjectGraphService, + getTooltipService, +} from '../machines/get-services'; +import { + CompositeNodeTooltip, + CompositeNodeTooltipActions, + NodeTooltipAction, ProjectEdgeNodeTooltip, ProjectNodeToolTip, + ProjectNodeTooltipActions, TaskNodeTooltip, Tooltip, } from '@nx/graph/ui-tooltips'; -import { ProjectNodeActions } from './project-node-actions'; import { TaskNodeActions } from './task-node-actions'; import { getExternalApiService, useRouteConstructor } from '@nx/graph/shared'; import { useNavigate } from 'react-router-dom'; +import { useCallback } from 'react'; const tooltipService = getTooltipService(); @@ -17,12 +24,73 @@ export function TooltipDisplay() { const navigate = useNavigate(); const routeConstructor = useRouteConstructor(); const externalApiService = getExternalApiService(); + const projectGraphService = getProjectGraphService(); const currentTooltip = useSyncExternalStore( (callback) => tooltipService.subscribe(callback), () => tooltipService.currentTooltip ); + const onAction = useCallback( + (action: NodeTooltipAction) => { + switch (action.type) { + case 'expand-node': + projectGraphService.send({ + type: 'expandCompositeNode', + id: action.id, + }); + break; + case 'focus-node': { + const to = + action.tooltipNodeType === 'compositeNode' + ? routeConstructor( + { + pathname: `/projects`, + search: `?composite=true&compositeContext=${action.id}`, + }, + false + ) + : routeConstructor(`/projects/${action.id}`, true); + navigate(to); + break; + } + case 'collapse-node': + projectGraphService.send({ + type: 'collapseCompositeNode', + id: action.id, + }); + + break; + case 'exclude-node': + projectGraphService.send({ + type: 'deselectProject', + projectName: + action.tooltipNodeType === 'projectNode' + ? action.rawId + : action.id, + }); + if (action.tooltipNodeType === 'projectNode') { + navigate(routeConstructor('/projects', true)); + } + break; + case 'start-trace': + navigate(routeConstructor(`/projects/trace/${action.id}`, true)); + break; + case 'end-trace': { + const { start } = projectGraphService.getSnapshot().context.tracing; + navigate( + routeConstructor( + `/projects/trace/${encodeURIComponent(start)}/${action.id}`, + true + ) + ); + break; + } + } + }, + [projectGraphService, navigate, routeConstructor] + ); + let tooltipToRender; if (currentTooltip) { if (currentTooltip.type === 'projectNode') { @@ -59,9 +127,21 @@ export function TooltipDisplay() { {...currentTooltip.props} openConfigCallback={onConfigClick} > - + ); + } else if (currentTooltip.type === 'compositeNode') { + tooltipToRender = ( + + + + ); } else if (currentTooltip.type === 'projectEdge') { const onFileClick = currentTooltip.props.renderMode === 'nx-console' diff --git a/graph/client/src/app/ui-tooltips/project-node-actions.tsx b/graph/client/src/app/ui-tooltips/project-node-actions.tsx deleted file mode 100644 index 08ec3e4c4e130..0000000000000 --- a/graph/client/src/app/ui-tooltips/project-node-actions.tsx +++ /dev/null @@ -1,67 +0,0 @@ -import { ProjectNodeToolTipProps } from '@nx/graph/ui-tooltips'; -import { getProjectGraphService } from '../machines/get-services'; -import { useNavigate, useSearchParams } from 'react-router-dom'; -import { TooltipButton, TooltipLinkButton } from '@nx/graph/ui-tooltips'; -import { FlagIcon, MapPinIcon } from '@heroicons/react/24/solid'; -import { useRouteConstructor } from '@nx/graph/shared'; - -export function ProjectNodeActions({ id }: ProjectNodeToolTipProps) { - const projectGraphService = getProjectGraphService(); - const { start, end, algorithm } = - projectGraphService.getSnapshot().context.tracing; - const routeConstructor = useRouteConstructor(); - const navigate = useNavigate(); - const encodedId = encodeURIComponent(id); - const [searchParams, setSearchParams] = useSearchParams(); - - function onProjectDetails() { - setSearchParams({ projectDetails: id }); - } - function onExclude() { - projectGraphService.send({ - type: 'deselectProject', - projectName: id, - }); - navigate(routeConstructor('/projects', true)); - } - - function onStartTrace() { - navigate(routeConstructor(`/projects/trace/${encodedId}`, true)); - } - - function onEndTrace() { - navigate( - routeConstructor( - `/projects/trace/${encodeURIComponent(start)}/${encodedId}`, - true - ) - ); - } - - return ( -
    - {/* Project Details */} - - Focus - - Exclude - {!start ? ( - - - Start - - ) : ( - - - End - - )} -
    - ); -} diff --git a/graph/client/src/globals.d.ts b/graph/client/src/globals.d.ts index 8d7552d1cbb64..844bea3c3d1b3 100644 --- a/graph/client/src/globals.d.ts +++ b/graph/client/src/globals.d.ts @@ -5,7 +5,7 @@ import type { ProjectGraphClientResponse, TaskGraphClientResponse, } from 'nx/src/command-line/graph/graph'; -import { AppConfig, ExternalApi } from '@nx/graph/shared'; +import type { AppConfig, ExternalApi } from '@nx/graph/shared'; export declare global { interface Window { diff --git a/graph/client/tailwind.config.js b/graph/client/tailwind.config.js index 18a8d985ec32a..b29e8f50517b0 100644 --- a/graph/client/tailwind.config.js +++ b/graph/client/tailwind.config.js @@ -1,5 +1,10 @@ -const path = require('path'); +// @ts-check +const path = require('node:path'); + +// Ignore these nx related dependencies since they are the installed versions not the ones in the workspace +// nx-ignore-next-line +const { workspaceRoot } = require('@nx/devkit'); // nx-ignore-next-line const { createGlobPatternsForDependencies } = require('@nx/react/tailwind'); @@ -7,6 +12,12 @@ module.exports = { content: [ path.join(__dirname, 'src/**/*.{js,ts,jsx,tsx,html}'), ...createGlobPatternsForDependencies(__dirname), + // Resolve the classes used in @nx/graph components + // TODO: make a decision on whether this is really the best approach, or if precompiling and deduplicating the classes would be better + path.join( + workspaceRoot, + 'node_modules/@nx/graph/**/*.{js,ts,jsx,tsx,html}' + ), ], darkMode: 'class', // or 'media' or 'class' theme: { diff --git a/graph/project-details/src/lib/project-details-header.tsx b/graph/project-details/src/lib/project-details-header.tsx index 6082a63bf3fff..37a0c5ab1cfd7 100644 --- a/graph/project-details/src/lib/project-details-header.tsx +++ b/graph/project-details/src/lib/project-details-header.tsx @@ -1,6 +1,6 @@ import { Link } from 'react-router-dom'; import { useRouteConstructor } from '@nx/graph/shared'; -import { ThemePanel } from '@nx/graph/ui-theme'; +import { ThemePanel } from '@nx/graph-internal/ui-theme'; export function ProjectDetailsHeader() { const routeConstructor = useRouteConstructor(); diff --git a/graph/project-details/src/lib/project-details-wrapper.tsx b/graph/project-details/src/lib/project-details-wrapper.tsx index 74598094e8c7e..9bc5911461a2b 100644 --- a/graph/project-details/src/lib/project-details-wrapper.tsx +++ b/graph/project-details/src/lib/project-details-wrapper.tsx @@ -14,7 +14,7 @@ import { } from '@nx/graph/shared'; import { Spinner } from '@nx/graph/ui-components'; -import { ProjectDetails } from '@nx/graph/ui-project-details'; +import { ProjectDetails } from '@nx/graph-internal/ui-project-details'; import { useCallback, useContext, useEffect } from 'react'; interface ProjectDetailsProps { diff --git a/graph/shared/.babelrc b/graph/shared/.babelrc deleted file mode 100644 index 1ea870ead410c..0000000000000 --- a/graph/shared/.babelrc +++ /dev/null @@ -1,12 +0,0 @@ -{ - "presets": [ - [ - "@nx/react/babel", - { - "runtime": "automatic", - "useBuiltIns": "usage" - } - ] - ], - "plugins": [] -} diff --git a/graph/shared/.eslintrc.json b/graph/shared/.eslintrc.json deleted file mode 100644 index a39ac5d057803..0000000000000 --- a/graph/shared/.eslintrc.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "extends": ["plugin:@nx/react", "../../.eslintrc.json"], - "ignorePatterns": ["!**/*"], - "overrides": [ - { - "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], - "rules": {} - }, - { - "files": ["*.ts", "*.tsx"], - "rules": {} - }, - { - "files": ["*.js", "*.jsx"], - "rules": {} - } - ] -} diff --git a/graph/shared/README.md b/graph/shared/README.md deleted file mode 100644 index e11e47550c79e..0000000000000 --- a/graph/shared/README.md +++ /dev/null @@ -1,7 +0,0 @@ -# graph-shared - -This library was generated with [Nx](https://nx.dev). - -## Running unit tests - -Run `nx test graph-shared` to execute the unit tests via [Jest](https://jestjs.io). diff --git a/graph/shared/jest.config.ts b/graph/shared/jest.config.ts deleted file mode 100644 index 9ba82f79a6c2f..0000000000000 --- a/graph/shared/jest.config.ts +++ /dev/null @@ -1,9 +0,0 @@ -/* eslint-disable */ -export default { - displayName: 'graph-shared', - preset: '../../jest.preset.js', - transform: { - '^.+\\.[tj]sx?$': 'babel-jest', - }, - moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'], -}; diff --git a/graph/shared/project.json b/graph/shared/project.json deleted file mode 100644 index b5bb434f37ec0..0000000000000 --- a/graph/shared/project.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "name": "graph-shared", - "$schema": "../../node_modules/nx/schemas/project-schema.json", - "sourceRoot": "graph/shared/src", - "projectType": "library", - "tags": [], - "targets": {} -} diff --git a/graph/shared/src/globals.d.ts b/graph/shared/src/globals.d.ts deleted file mode 100644 index 1f1dc6d95488e..0000000000000 --- a/graph/shared/src/globals.d.ts +++ /dev/null @@ -1,25 +0,0 @@ -/* eslint-disable @nx/enforce-module-boundaries */ -// nx-ignore-next-line -import type { - ExpandedTaskInputsReponse, - ProjectGraphClientResponse, - TaskGraphClientResponse, -} from 'nx/src/command-line/graph/graph'; -import { AppConfig } from './lib/app-config'; -import { ExternalApi } from './lib/external-api'; - -export declare global { - interface Window { - exclude: string[]; - watch: boolean; - localMode: 'serve' | 'build'; - projectGraphResponse?: ProjectGraphClientResponse; - taskGraphResponse?: TaskGraphClientResponse; - expandedTaskInputsResponse?: ExpandedTaskInputsReponse; - sourceMapsResponse?: Record>; - environment: 'dev' | 'watch' | 'release' | 'nx-console'; - appConfig: AppConfig; - useXstateInspect: boolean; - externalApi?: ExternalApi; - } -} diff --git a/graph/shared/src/index.ts b/graph/shared/src/index.ts deleted file mode 100644 index f7c0fee4f5cdf..0000000000000 --- a/graph/shared/src/index.ts +++ /dev/null @@ -1,10 +0,0 @@ -export * from './lib/external-api'; -export * from './lib/external-api-service'; -export * from './lib/use-environment-config'; -export * from './lib/app-config'; -export * from './lib/use-route-constructor'; -export * from './lib/use-poll'; -export * from './lib/project-graph-data-service/get-project-graph-data-service'; -export * from './lib/fetch-project-graph'; -export * from './lib/error-toast'; -export * from './lib/expanded-targets-provider'; diff --git a/graph/shared/src/lib/app-config.ts b/graph/shared/src/lib/app-config.ts deleted file mode 100644 index b9cf26140ed19..0000000000000 --- a/graph/shared/src/lib/app-config.ts +++ /dev/null @@ -1,15 +0,0 @@ -export interface AppConfig { - showDebugger: boolean; - showExperimentalFeatures: boolean; - workspaces: WorkspaceData[]; - defaultWorkspaceId: string; -} - -export interface WorkspaceData { - id: string; - label: string; - projectGraphUrl: string; - taskGraphUrl: string; - taskInputsUrl: string; - sourceMapsUrl: string; -} diff --git a/graph/shared/src/lib/error-toast.tsx b/graph/shared/src/lib/error-toast.tsx deleted file mode 100644 index 4ce3564c65943..0000000000000 --- a/graph/shared/src/lib/error-toast.tsx +++ /dev/null @@ -1,132 +0,0 @@ -/* eslint-disable @nx/enforce-module-boundaries */ -// nx-ignore-next-line -import { GraphError } from 'nx/src/command-line/graph/graph'; -/* eslint-enable @nx/enforce-module-boundaries */ - -import { - createRef, - ForwardedRef, - forwardRef, - useCallback, - useImperativeHandle, - useLayoutEffect, -} from 'react'; - -import { Transition } from '@headlessui/react'; -import { ExclamationCircleIcon } from '@heroicons/react/24/outline'; -import { SetURLSearchParams, useSearchParams } from 'react-router-dom'; -import { ErrorRenderer, Modal, ModalHandle } from '@nx/graph/ui-components'; - -export interface ErrorToastImperativeHandle { - closeModal: () => void; - openModal: () => void; -} - -interface ErrorToastProps { - errors?: GraphError[] | undefined; -} - -export const ErrorToast = forwardRef( - ( - { errors }: ErrorToastProps, - ref: ForwardedRef - ) => { - const inputsModalRef = createRef(); - - const [searchParams, setSearchParams] = useSearchParams(); - - useImperativeHandle(ref, () => ({ - openModal: () => { - inputsModalRef?.current?.openModal(); - }, - closeModal: () => { - inputsModalRef?.current?.closeModal(); - }, - })); - - const handleModalOpen = useCallback(() => { - if (searchParams.get('show-error') === 'true') return; - setSearchParams( - (currentSearchParams) => { - currentSearchParams.set('show-error', 'true'); - return currentSearchParams; - }, - { replace: true, preventScrollReset: true } - ); - }, [setSearchParams, searchParams]); - - const handleModalClose = useCallback(() => { - if (!searchParams.get('show-error')) return; - setSearchParams( - (currentSearchParams) => { - currentSearchParams.delete('show-error'); - return currentSearchParams; - }, - { replace: true, preventScrollReset: true } - ); - }, [setSearchParams, searchParams]); - - useLayoutEffect(() => { - if (searchParams.get('show-error') === 'true') { - if (errors && errors.length > 0) { - inputsModalRef.current?.openModal(); - } else { - setSearchParams( - (currentSearchParams) => { - currentSearchParams.delete('show-error'); - return currentSearchParams; - }, - { replace: true, preventScrollReset: true } - ); - } - } - }, [searchParams, inputsModalRef, errors, setSearchParams]); - - return ( - 0} - enter="ease-out duration-300" - enterFrom="opacity-0" - enterTo="opacity-100" - leave="ease-in duration-200" - leaveFrom="opacity-100" - leaveTo="opacity-0" - > -
    -
    inputsModalRef.current?.openModal()} - className="z-50 mx-auto flex w-fit max-w-[75%] cursor-pointer items-center rounded-md bg-red-600 p-4 text-slate-200 shadow-lg" - > - - Some project information might be missing. Click to see errors. -
    - {errors?.length > 0 && ( - - - - )} -
    -
    - ); - } -); - -export const useRouterHandleModalOpen = ( - searchParams: URLSearchParams, - setSearchParams: SetURLSearchParams -) => - useCallback(() => { - if (searchParams.get('show-error') === 'true') return; - setSearchParams( - (currentSearchParams) => { - currentSearchParams.set('show-error', 'true'); - return currentSearchParams; - }, - { replace: true, preventScrollReset: true } - ); - }, [setSearchParams, searchParams]); diff --git a/graph/shared/src/lib/expanded-targets-provider.tsx b/graph/shared/src/lib/expanded-targets-provider.tsx deleted file mode 100644 index 47e3e29d58d37..0000000000000 --- a/graph/shared/src/lib/expanded-targets-provider.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import { createContext, useState } from 'react'; - -export const ExpandedTargetsContext = createContext<{ - expandedTargets?: string[]; - setExpandedTargets?: (expandedTargets: string[]) => void; - toggleTarget?: (targetName: string) => void; - collapseAllTargets?: () => void; -}>({}); - -export const ExpandedTargetsProvider = ({ - children, - initialExpanededTargets = [], -}: { - children: React.ReactNode; - initialExpanededTargets?: string[]; -}) => { - const [expandedTargets, setExpandedTargets] = useState( - initialExpanededTargets - ); - - const toggleTarget = (targetName: string) => { - setExpandedTargets((prevExpandedTargets) => { - if (prevExpandedTargets.includes(targetName)) { - return prevExpandedTargets.filter((name) => name !== targetName); - } - return [...prevExpandedTargets, targetName]; - }); - }; - - const collapseAllTargets = () => { - setExpandedTargets([]); - }; - - return ( - - {children} - - ); -}; diff --git a/graph/shared/src/lib/external-api-service.ts b/graph/shared/src/lib/external-api-service.ts deleted file mode 100644 index 1b9426dc5b03e..0000000000000 --- a/graph/shared/src/lib/external-api-service.ts +++ /dev/null @@ -1,24 +0,0 @@ -let externalApiService: ExternalApiService | null = null; - -export function getExternalApiService() { - if (!externalApiService) { - externalApiService = new ExternalApiService(); - } - - return externalApiService; -} - -export class ExternalApiService { - private subscribers: Set<(event: { type: string; payload?: any }) => void> = - new Set(); - - postEvent(event: { type: string; payload?: any }) { - this.subscribers.forEach((subscriber) => { - subscriber(event); - }); - } - - subscribe(callback: (event: { type: string; payload: any }) => void) { - this.subscribers.add(callback); - } -} diff --git a/graph/shared/src/lib/external-api.ts b/graph/shared/src/lib/external-api.ts deleted file mode 100644 index bf4fc79e1ef2c..0000000000000 --- a/graph/shared/src/lib/external-api.ts +++ /dev/null @@ -1,42 +0,0 @@ -/* eslint-disable @nx/enforce-module-boundaries */ -// nx-ignore-next-line -import type { - ProjectGraphClientResponse, - TaskGraphClientResponse, -} from 'nx/src/command-line/graph/graph'; - -export abstract class ExternalApi { - abstract openProjectDetails(projectName: string, targetName?: string): void; - - abstract focusProject(projectName: string): void; - - abstract toggleSelectProject(projectName: string): void; - - abstract selectAllProjects(): void; - - abstract showAffectedProjects(): void; - - abstract focusTarget(projectName: string, targetName: string): void; - - abstract selectAllTargetsByName(targetName: string): void; - - abstract enableExperimentalFeatures(): void; - - abstract disableExperimentalFeatures(): void; - - loadProjectGraph: - | ((url: string) => Promise) - | null = null; - loadTaskGraph: ((url: string) => Promise) | null = - null; - loadExpandedTaskInputs: - | ((taskId: string) => Promise>>) - | null = null; - loadSourceMaps: - | ((url: string) => Promise>>) - | null = null; - - graphInteractionEventListener: - | ((event: { type: string; payload: any }) => void | undefined) - | null = null; -} diff --git a/graph/shared/src/lib/fetch-project-graph.ts b/graph/shared/src/lib/fetch-project-graph.ts deleted file mode 100644 index b9bf15787c94c..0000000000000 --- a/graph/shared/src/lib/fetch-project-graph.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Params } from 'react-router-dom'; -import { ProjectGraphService } from './project-graph-data-service/get-project-graph-data-service'; -import { AppConfig } from './app-config'; - -export async function fetchProjectGraph( - projectGraphService: ProjectGraphService, - params: Readonly>, - appConfig: AppConfig -) { - const selectedWorkspaceId = - params.selectedWorkspaceId ?? appConfig.defaultWorkspaceId; - - const projectInfo = appConfig.workspaces.find( - (graph) => graph.id === selectedWorkspaceId - ); - - return await projectGraphService.getProjectGraph(projectInfo.projectGraphUrl); -} diff --git a/graph/shared/src/lib/project-graph-data-service/fetch-project-graph-service.ts b/graph/shared/src/lib/project-graph-data-service/fetch-project-graph-service.ts deleted file mode 100644 index 955af67b32201..0000000000000 --- a/graph/shared/src/lib/project-graph-data-service/fetch-project-graph-service.ts +++ /dev/null @@ -1,64 +0,0 @@ -/* eslint-disable @nx/enforce-module-boundaries */ -// nx-ignore-next-line -import type { - ProjectGraphClientResponse, - TaskGraphClientResponse, -} from 'nx/src/command-line/graph/graph'; -import { ProjectGraphService } from './get-project-graph-data-service'; -/* eslint-enable @nx/enforce-module-boundaries */ - -export class FetchProjectGraphService implements ProjectGraphService { - private taskInputsUrl: string; - - async getHash(): Promise { - const request = new Request('currentHash', { mode: 'no-cors' }); - - const response = await fetch(request); - - return response.json(); - } - - async getProjectGraph(url: string): Promise { - const request = new Request(url, { mode: 'no-cors' }); - - const response = await fetch(request); - - return response.json(); - } - - async getTaskGraph(url: string): Promise { - const request = new Request(url, { mode: 'no-cors' }); - - const response = await fetch(request); - - return response.json(); - } - - async getSourceMaps( - url: string - ): Promise>> { - const request = new Request(url, { mode: 'no-cors' }); - - const response = await fetch(request); - - return response.json(); - } - - setTaskInputsUrl(url: string) { - this.taskInputsUrl = url; - } - - async getExpandedTaskInputs( - taskId: string - ): Promise> { - if (!this.taskInputsUrl) { - return {}; - } - const request = new Request(`${this.taskInputsUrl}?taskId=${taskId}`, { - mode: 'no-cors', - }); - - const response = await fetch(request); - return (await response.json())[taskId]; - } -} diff --git a/graph/shared/src/lib/project-graph-data-service/get-project-graph-data-service.ts b/graph/shared/src/lib/project-graph-data-service/get-project-graph-data-service.ts deleted file mode 100644 index 707f6223a8c19..0000000000000 --- a/graph/shared/src/lib/project-graph-data-service/get-project-graph-data-service.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { FetchProjectGraphService } from './fetch-project-graph-service'; -import { LocalProjectGraphService } from './local-project-graph-service'; -import { MockProjectGraphService } from './mock-project-graph-service'; -import { NxConsoleProjectGraphService } from './nx-console-project-graph-service'; - -/* eslint-disable @nx/enforce-module-boundaries */ -// nx-ignore-next-line -import type { - ProjectGraphClientResponse, - TaskGraphClientResponse, -} from 'nx/src/command-line/graph/graph'; - -let projectGraphService: ProjectGraphService; - -export interface ProjectGraphService { - getHash: () => Promise; - getProjectGraph: (url: string) => Promise; - getTaskGraph: (url: string) => Promise; - setTaskInputsUrl?: (url: string) => void; - getExpandedTaskInputs?: (taskId: string) => Promise>; - getSourceMaps?: ( - url: string - ) => Promise>>; -} - -export function getProjectGraphDataService() { - if (projectGraphService === undefined) { - if (window.environment === 'dev') { - projectGraphService = new FetchProjectGraphService(); - } else if (window.environment === 'watch') { - projectGraphService = new MockProjectGraphService(); - } else if (window.environment === 'nx-console') { - projectGraphService = new NxConsoleProjectGraphService(); - } else if (window.environment === 'release') { - if (window.localMode === 'build') { - projectGraphService = new LocalProjectGraphService(); - } else { - projectGraphService = new FetchProjectGraphService(); - } - } - } - - return projectGraphService; -} diff --git a/graph/shared/src/lib/project-graph-data-service/local-project-graph-service.ts b/graph/shared/src/lib/project-graph-data-service/local-project-graph-service.ts deleted file mode 100644 index 716fe09542646..0000000000000 --- a/graph/shared/src/lib/project-graph-data-service/local-project-graph-service.ts +++ /dev/null @@ -1,36 +0,0 @@ -/* eslint-disable @nx/enforce-module-boundaries */ -// nx-ignore-next-line -import type { - ProjectGraphClientResponse, - TaskGraphClientResponse, -} from 'nx/src/command-line/graph/graph'; -import { ProjectGraphService } from './get-project-graph-data-service'; -/* eslint-enable @nx/enforce-module-boundaries */ - -export class LocalProjectGraphService implements ProjectGraphService { - async getHash(): Promise { - return new Promise((resolve) => resolve('some-hash')); - } - - async getProjectGraph(url: string): Promise { - return new Promise((resolve) => resolve(window.projectGraphResponse)); - } - - async getTaskGraph(url: string): Promise { - return new Promise((resolve) => resolve(window.taskGraphResponse)); - } - - async getExpandedTaskInputs( - taskId: string - ): Promise> { - return new Promise((resolve) => - resolve(window.expandedTaskInputsResponse[taskId]) - ); - } - - async getSourceMaps( - url: string - ): Promise>> { - return new Promise((resolve) => resolve(window.sourceMapsResponse)); - } -} diff --git a/graph/shared/src/lib/project-graph-data-service/mock-project-graph-service.ts b/graph/shared/src/lib/project-graph-data-service/mock-project-graph-service.ts deleted file mode 100644 index b992e2cafe59e..0000000000000 --- a/graph/shared/src/lib/project-graph-data-service/mock-project-graph-service.ts +++ /dev/null @@ -1,133 +0,0 @@ -/* eslint-disable @nx/enforce-module-boundaries */ -// nx-ignore-next-line -import type { - ProjectGraphDependency, - ProjectGraphProjectNode, -} from '@nx/devkit'; -// nx-ignore-next-line -import type { - ProjectGraphClientResponse, - TaskGraphClientResponse, -} from 'nx/src/command-line/graph/graph'; -import { ProjectGraphService } from './get-project-graph-data-service'; -/* eslint-enable @nx/enforce-module-boundaries */ - -export class MockProjectGraphService implements ProjectGraphService { - private projectGraphsResponse: ProjectGraphClientResponse = { - hash: '79054025255fb1a26e4bc422aef54eb4', - layout: { - appsDir: 'apps', - libsDir: 'libs', - }, - projects: [ - { - name: 'existing-app-1', - type: 'app', - data: { - root: 'apps/app1', - tags: [], - }, - }, - { - name: 'existing-lib-1', - type: 'lib', - data: { - root: 'libs/lib1', - tags: [], - }, - }, - ], - dependencies: { - 'existing-app-1': [ - { - source: 'existing-app-1', - target: 'existing-lib-1', - type: 'static', - }, - ], - 'existing-lib-1': [], - }, - fileMap: { - 'existing-app-1': [ - { - file: 'some/file.ts', - hash: 'ecccd8481d2e5eae0e59928be1bc4c2d071729d7', - deps: ['existing-lib-1'], - }, - ], - 'exiting-lib-1': [], - }, - affected: [], - focus: null, - exclude: [], - groupByFolder: false, - isPartial: false, - }; - - private taskGraphsResponse: TaskGraphClientResponse = { - taskGraphs: {}, - errors: {}, - }; - - constructor(updateFrequency: number = 5000) { - setInterval(() => this.updateResponse(), updateFrequency); - } - - async getHash(): Promise { - return new Promise((resolve) => resolve(this.projectGraphsResponse.hash)); - } - - getProjectGraph(url: string): Promise { - return new Promise((resolve) => resolve(this.projectGraphsResponse)); - } - - getTaskGraph(url: string): Promise { - return new Promise((resolve) => resolve(this.taskGraphsResponse)); - } - - getSourceMaps( - url: string - ): Promise>> { - return new Promise((resolve) => resolve({})); - } - - private createNewProject(): ProjectGraphProjectNode { - const type = Math.random() > 0.25 ? 'lib' : 'app'; - const name = `${type}-${this.projectGraphsResponse.projects.length + 1}`; - - return { - name, - type, - data: { - root: type === 'app' ? `apps/${name}` : `libs/${name}`, - tags: [], - }, - }; - } - - private updateResponse() { - const newProject = this.createNewProject(); - const libProjects = this.projectGraphsResponse.projects.filter( - (project) => project.type === 'lib' - ); - - const targetDependency = - libProjects[Math.floor(Math.random() * libProjects.length)]; - const newDependency: ProjectGraphDependency[] = [ - { - source: newProject.name, - target: targetDependency.name, - type: 'static', - }, - ]; - - this.projectGraphsResponse = { - ...this.projectGraphsResponse, - projects: [...this.projectGraphsResponse.projects, newProject], - dependencies: { - ...this.projectGraphsResponse.dependencies, - [newProject.name]: newDependency, - }, - }; - } -} diff --git a/graph/shared/src/lib/project-graph-data-service/nx-console-project-graph-service.ts b/graph/shared/src/lib/project-graph-data-service/nx-console-project-graph-service.ts deleted file mode 100644 index 7148bb119eb27..0000000000000 --- a/graph/shared/src/lib/project-graph-data-service/nx-console-project-graph-service.ts +++ /dev/null @@ -1,34 +0,0 @@ -/* eslint-disable @nx/enforce-module-boundaries */ -// nx-ignore-next-line -import type { - ProjectGraphClientResponse, - TaskGraphClientResponse, -} from 'nx/src/command-line/graph/graph'; -import { ProjectGraphService } from './get-project-graph-data-service'; - -export class NxConsoleProjectGraphService implements ProjectGraphService { - async getHash(): Promise { - return new Promise((resolve) => resolve('some-hash')); - } - - async getProjectGraph(url: string): Promise { - return await window.externalApi.loadProjectGraph?.(url); - } - - async getTaskGraph(url: string): Promise { - return await window.externalApi.loadTaskGraph?.(url); - } - - async getExpandedTaskInputs( - taskId: string - ): Promise> { - const res = await window.externalApi.loadExpandedTaskInputs?.(taskId); - return res ? res[taskId] : {}; - } - - async getSourceMaps( - url: string - ): Promise>> { - return await window.externalApi.loadSourceMaps?.(url); - } -} diff --git a/graph/shared/src/lib/use-environment-config.ts b/graph/shared/src/lib/use-environment-config.ts deleted file mode 100644 index 602f2058d719c..0000000000000 --- a/graph/shared/src/lib/use-environment-config.ts +++ /dev/null @@ -1,39 +0,0 @@ -/* eslint-disable @nx/enforce-module-boundaries */ -// nx-ignore-next-line -import type { ProjectGraphClientResponse } from 'nx/src/command-line/graph/graph'; -/* eslint-enable @nx/enforce-module-boundaries */ -import { useRef } from 'react'; -import { AppConfig } from './app-config'; - -export function useEnvironmentConfig(): { - exclude: string[]; - watch: boolean; - localMode: 'serve' | 'build'; - projectGraphResponse?: ProjectGraphClientResponse; - environment: 'dev' | 'watch' | 'release' | 'nx-console' | 'docs'; - appConfig: AppConfig; - useXstateInspect: boolean; -} { - const environmentConfig = useRef(getEnvironmentConfig()); - - return environmentConfig.current; -} - -export function getEnvironmentConfig() { - return { - exclude: window.exclude, - watch: window.watch, - localMode: window.localMode, - projectGraphResponse: window.projectGraphResponse, - // If this was not built into JS or HTML, then it is rendered on docs (nx.dev). - environment: window.environment ?? ('docs' as const), - appConfig: { - ...window.appConfig, - showExperimentalFeatures: - localStorage.getItem('showExperimentalFeatures') === 'true' - ? true - : window.appConfig?.showExperimentalFeatures, - }, - useXstateInspect: window.useXstateInspect, - }; -} diff --git a/graph/shared/src/lib/use-poll.ts b/graph/shared/src/lib/use-poll.ts deleted file mode 100644 index 20d8e8db092b5..0000000000000 --- a/graph/shared/src/lib/use-poll.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { useEffect, useRef } from 'react'; - -export const usePoll = ( - callback: () => Promise, - delay: number, - condition: boolean -) => { - const savedCallback = useRef(() => Promise.resolve()); - - useEffect(() => { - if (condition) { - savedCallback.current = callback; - } - }, [callback, condition]); - - useEffect(() => { - if (!condition) { - return; - } - let timeoutId: NodeJS.Timeout; - - async function callTickAfterDelay() { - await savedCallback.current(); - if (delay !== null) { - timeoutId = setTimeout(callTickAfterDelay, delay); - } - } - - callTickAfterDelay(); - - return () => { - if (timeoutId) { - clearTimeout(timeoutId); - } - }; - }, [delay, condition]); -}; diff --git a/graph/shared/src/lib/use-route-constructor.ts b/graph/shared/src/lib/use-route-constructor.ts deleted file mode 100644 index be148bd3df482..0000000000000 --- a/graph/shared/src/lib/use-route-constructor.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { To, useParams, useSearchParams } from 'react-router-dom'; -import { getEnvironmentConfig } from './use-environment-config'; - -export const useRouteConstructor = (): (( - to: To, - retainSearchParams: boolean, - searchParamsKeysToOmit?: string[] -) => To) => { - const { environment } = getEnvironmentConfig(); - const { selectedWorkspaceId } = useParams(); - const [searchParams] = useSearchParams(); - - return ( - to: To, - retainSearchParams: boolean = true, - searchParamsKeysToOmit: string[] = [] - ) => { - if (searchParamsKeysToOmit?.length) { - searchParamsKeysToOmit.forEach((key) => { - searchParams.delete(key); - }); - } - let pathname = ''; - - if (typeof to === 'object') { - if (environment === 'dev') { - pathname = `/${selectedWorkspaceId}${to.pathname}`; - } else { - pathname = to.pathname; - } - return { - ...to, - pathname, - search: to.search - ? to.search.toString() - : retainSearchParams - ? searchParams.toString() - : '', - }; - } else if (typeof to === 'string') { - if (environment === 'dev') { - pathname = `/${selectedWorkspaceId}${to}`; - } else { - pathname = to; - } - return { - pathname, - search: retainSearchParams ? searchParams.toString() : '', - }; - } - }; -}; diff --git a/graph/shared/tsconfig.json b/graph/shared/tsconfig.json deleted file mode 100644 index 31245daec2d42..0000000000000 --- a/graph/shared/tsconfig.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "compilerOptions": { - "jsx": "react-jsx", - "allowJs": false, - "esModuleInterop": false, - "allowSyntheticDefaultImports": true - }, - "files": [], - "include": [], - "references": [ - { - "path": "./tsconfig.lib.json" - }, - { - "path": "./tsconfig.spec.json" - } - ], - "extends": "../../tsconfig.base.json" -} diff --git a/graph/shared/tsconfig.lib.json b/graph/shared/tsconfig.lib.json deleted file mode 100644 index 3b824cf3a50b7..0000000000000 --- a/graph/shared/tsconfig.lib.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "types": [ - "node", - "@nx/react/typings/cssmodule.d.ts", - "@nx/react/typings/image.d.ts" - ], - "lib": ["dom"] - }, - "exclude": [ - "jest.config.ts", - "src/**/*.spec.ts", - "src/**/*.test.ts", - "src/**/*.spec.tsx", - "src/**/*.test.tsx", - "src/**/*.spec.js", - "src/**/*.test.js", - "src/**/*.spec.jsx", - "src/**/*.test.jsx" - ], - "include": ["src/**/*.js", "src/**/*.jsx", "src/**/*.ts", "src/**/*.tsx"] -} diff --git a/graph/shared/tsconfig.spec.json b/graph/shared/tsconfig.spec.json deleted file mode 100644 index 26ef046ac5e54..0000000000000 --- a/graph/shared/tsconfig.spec.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "module": "commonjs", - "types": ["jest", "node"] - }, - "include": [ - "jest.config.ts", - "src/**/*.test.ts", - "src/**/*.spec.ts", - "src/**/*.test.tsx", - "src/**/*.spec.tsx", - "src/**/*.test.js", - "src/**/*.spec.js", - "src/**/*.test.jsx", - "src/**/*.spec.jsx", - "src/**/*.d.ts" - ] -} diff --git a/graph/ui-components/.babelrc b/graph/ui-components/.babelrc deleted file mode 100644 index 1ea870ead410c..0000000000000 --- a/graph/ui-components/.babelrc +++ /dev/null @@ -1,12 +0,0 @@ -{ - "presets": [ - [ - "@nx/react/babel", - { - "runtime": "automatic", - "useBuiltIns": "usage" - } - ] - ], - "plugins": [] -} diff --git a/graph/ui-components/.eslintrc.json b/graph/ui-components/.eslintrc.json deleted file mode 100644 index a39ac5d057803..0000000000000 --- a/graph/ui-components/.eslintrc.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "extends": ["plugin:@nx/react", "../../.eslintrc.json"], - "ignorePatterns": ["!**/*"], - "overrides": [ - { - "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], - "rules": {} - }, - { - "files": ["*.ts", "*.tsx"], - "rules": {} - }, - { - "files": ["*.js", "*.jsx"], - "rules": {} - } - ] -} diff --git a/graph/ui-components/.storybook/main.js b/graph/ui-components/.storybook/main.js deleted file mode 100644 index e443e1d6da410..0000000000000 --- a/graph/ui-components/.storybook/main.js +++ /dev/null @@ -1,9 +0,0 @@ -module.exports = { - stories: ['../src/lib/**/*.@(mdx|stories.@(js|jsx|ts|tsx))'], - addons: ['@storybook/addon-essentials', '@nx/react/plugins/storybook'], - framework: { - name: '@storybook/react-webpack5', - options: {}, - }, - docs: {}, -}; diff --git a/graph/ui-components/.storybook/preview.js b/graph/ui-components/.storybook/preview.js deleted file mode 100644 index 6458fd2b5328a..0000000000000 --- a/graph/ui-components/.storybook/preview.js +++ /dev/null @@ -1,4 +0,0 @@ -import 'graph/client/.storybook/tailwind-imports.css'; - -export const parameters = {}; -export const tags = ['autodocs']; diff --git a/graph/ui-components/.storybook/tailwind-imports.css b/graph/ui-components/.storybook/tailwind-imports.css deleted file mode 100644 index b5c61c956711f..0000000000000 --- a/graph/ui-components/.storybook/tailwind-imports.css +++ /dev/null @@ -1,3 +0,0 @@ -@tailwind base; -@tailwind components; -@tailwind utilities; diff --git a/graph/ui-components/README.md b/graph/ui-components/README.md deleted file mode 100644 index edebff9c731b0..0000000000000 --- a/graph/ui-components/README.md +++ /dev/null @@ -1,7 +0,0 @@ -# graph-ui-components - -This library was generated with [Nx](https://nx.dev). - -## Running unit tests - -Run `nx test graph-ui-components` to execute the unit tests via [Jest](https://jestjs.io). diff --git a/graph/ui-components/jest.config.ts b/graph/ui-components/jest.config.ts deleted file mode 100644 index 48db49fd473de..0000000000000 --- a/graph/ui-components/jest.config.ts +++ /dev/null @@ -1,10 +0,0 @@ -/* eslint-disable */ -export default { - displayName: 'graph-ui-components', - preset: '../../jest.preset.js', - transform: { - '^.+\\.[tj]sx?$': 'babel-jest', - }, - moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'], - coverageDirectory: '../../coverage/graph/ui-graph', -}; diff --git a/graph/ui-components/postcss.config.js b/graph/ui-components/postcss.config.js deleted file mode 100644 index d743b2e6af150..0000000000000 --- a/graph/ui-components/postcss.config.js +++ /dev/null @@ -1,8 +0,0 @@ -module.exports = { - plugins: { - tailwindcss: { - config: './graph/ui-components/tailwind.config.js', - }, - autoprefixer: {}, - }, -}; diff --git a/graph/ui-components/project.json b/graph/ui-components/project.json deleted file mode 100644 index 5cf93ceb5c158..0000000000000 --- a/graph/ui-components/project.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "name": "graph-ui-components", - "$schema": "../../node_modules/nx/schemas/project-schema.json", - "sourceRoot": "graph/ui-components/src", - "projectType": "library", - "tags": [], - "targets": { - "storybook": { - "executor": "@nx/storybook:storybook", - "options": { - "port": 4400, - "configDir": "graph/ui-components/.storybook" - }, - "configurations": { - "ci": { - "quiet": true - } - } - }, - "build-storybook": { - "executor": "@nx/storybook:build", - "outputs": ["{options.outputDir}"], - "options": { - "configDir": "graph/ui-components/.storybook", - "outputDir": "dist/storybook/graph-ui-components" - }, - "configurations": { - "ci": { - "quiet": true - } - } - } - } -} diff --git a/graph/ui-components/src/index.ts b/graph/ui-components/src/index.ts deleted file mode 100644 index 31f916a742583..0000000000000 --- a/graph/ui-components/src/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -export * from './lib/copy-to-clipboard-button'; -export * from './lib/debounced-text-input'; -export * from './lib/tag'; -export * from './lib/dropdown'; -export * from './lib/spinner'; -export * from './lib/error-renderer'; -export * from './lib/modal'; diff --git a/graph/ui-components/src/lib/copy-to-clipboard-button.stories.tsx b/graph/ui-components/src/lib/copy-to-clipboard-button.stories.tsx deleted file mode 100644 index 5cba0a8f7e23e..0000000000000 --- a/graph/ui-components/src/lib/copy-to-clipboard-button.stories.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import type { Meta, StoryObj } from '@storybook/react'; -import { - CopyToClipboardButton, - CopyToClipboardButtonProps, -} from './copy-to-clipboard-button'; - -const meta: Meta = { - component: CopyToClipboardButton, - title: 'CopyToClipboardButton', -}; -export default meta; - -type Story = StoryObj; - -export const Simple: Story = { - args: { - text: 'Hello, world!', - tooltipAlignment: 'left', - } as CopyToClipboardButtonProps, -}; diff --git a/graph/ui-components/src/lib/copy-to-clipboard-button.tsx b/graph/ui-components/src/lib/copy-to-clipboard-button.tsx deleted file mode 100644 index 0f7b6675084b0..0000000000000 --- a/graph/ui-components/src/lib/copy-to-clipboard-button.tsx +++ /dev/null @@ -1,61 +0,0 @@ -// @ts-ignore -import { CopyToClipboard } from 'react-copy-to-clipboard'; -import { JSX, ReactNode, useEffect, useState } from 'react'; -import { - ClipboardDocumentCheckIcon, - ClipboardDocumentIcon, -} from '@heroicons/react/24/outline'; - -export interface CopyToClipboardButtonProps { - text: string; - tooltipText?: string; - tooltipAlignment?: 'left' | 'right'; - className?: string; - children?: ReactNode; -} - -export function CopyToClipboardButton({ - text, - tooltipAlignment, - tooltipText, - className, - children, -}: CopyToClipboardButtonProps) { - const [copied, setCopied] = useState(false); - - useEffect(() => { - if (!copied) return; - const t = setTimeout(() => { - setCopied(false); - }, 3000); - return () => clearTimeout(t); - }, [copied]); - - return ( - { - setCopied(true); - }} - > - - - ); -} diff --git a/graph/ui-components/src/lib/debounced-text-input.stories.tsx b/graph/ui-components/src/lib/debounced-text-input.stories.tsx deleted file mode 100644 index 785ac52ff4557..0000000000000 --- a/graph/ui-components/src/lib/debounced-text-input.stories.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import type { Meta, StoryObj } from '@storybook/react'; -import { DebouncedTextInput } from './debounced-text-input'; - -const meta: Meta = { - component: DebouncedTextInput, - title: 'Shared/DebouncedTextInput', - argTypes: { - resetTextFilter: { - action: 'resetTextFilter', - }, - updateTextFilter: { - action: 'updateTextFilter', - }, - }, -}; - -export default meta; -type Story = StoryObj; - -export const Primary: Story = { - args: { - initialText: '', - placeholderText: '', - }, -}; diff --git a/graph/ui-components/src/lib/debounced-text-input.tsx b/graph/ui-components/src/lib/debounced-text-input.tsx deleted file mode 100644 index 5a625f399eb6b..0000000000000 --- a/graph/ui-components/src/lib/debounced-text-input.tsx +++ /dev/null @@ -1,85 +0,0 @@ -import { KeyboardEvent, useEffect, useState } from 'react'; -import { useDebounce } from './use-debounce'; -import { BackspaceIcon, FunnelIcon } from '@heroicons/react/24/outline'; - -export interface DebouncedTextInputProps { - initialText: string; - placeholderText: string; - resetTextFilter: () => void; - updateTextFilter: (textFilter: string) => void; -} - -export function DebouncedTextInput({ - initialText, - placeholderText, - resetTextFilter, - updateTextFilter, -}: DebouncedTextInputProps) { - const [currentTextFilter, setCurrentTextFilter] = useState(initialText ?? ''); - - const [debouncedValue, setDebouncedValue] = useDebounce( - currentTextFilter, - 500 - ); - - function onTextFilterKeyUp(event: KeyboardEvent) { - if (event.key === 'Enter') { - onTextInputChange(event.currentTarget.value); - } - } - - function onTextInputChange(change: string) { - if (change === '') { - setCurrentTextFilter(''); - setDebouncedValue(''); - - resetTextFilter(); - } else { - setCurrentTextFilter(change); - } - } - - function resetClicked() { - setCurrentTextFilter(''); - setDebouncedValue(''); - - resetTextFilter(); - } - - useEffect(() => { - if (debouncedValue !== '') { - updateTextFilter(debouncedValue); - } - }, [debouncedValue, updateTextFilter]); - - return ( -
    event.preventDefault()} - > - - - - onTextInputChange(event.currentTarget.value)} - > - {currentTextFilter.length > 0 ? ( - - ) : null} -
    - ); -} diff --git a/graph/ui-components/src/lib/dropdown.stories.tsx b/graph/ui-components/src/lib/dropdown.stories.tsx deleted file mode 100644 index b7d9d64d17c8c..0000000000000 --- a/graph/ui-components/src/lib/dropdown.stories.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import type { Meta, StoryObj } from '@storybook/react'; -import { Dropdown } from './dropdown'; - -const meta: Meta = { - component: Dropdown, - title: 'Shared/Dropdown', - argTypes: { - onChange: { action: 'onChange' }, - }, -}; - -export default meta; -type Story = StoryObj; - -export const Primary: Story = { - render: () => ( - - - - - ), -}; diff --git a/graph/ui-components/src/lib/dropdown.tsx b/graph/ui-components/src/lib/dropdown.tsx deleted file mode 100644 index 2954f258f4926..0000000000000 --- a/graph/ui-components/src/lib/dropdown.tsx +++ /dev/null @@ -1,18 +0,0 @@ -/* eslint-disable-next-line */ -import React, { ReactNode } from 'react'; - -export type DropdownProps = { - children: ReactNode[]; -} & React.HTMLAttributes; - -export function Dropdown(props: DropdownProps) { - const { className, children, ...rest } = props; - return ( - - ); -} diff --git a/graph/ui-components/src/lib/error-renderer.tsx b/graph/ui-components/src/lib/error-renderer.tsx deleted file mode 100644 index b5b7586144026..0000000000000 --- a/graph/ui-components/src/lib/error-renderer.tsx +++ /dev/null @@ -1,65 +0,0 @@ -/* eslint-disable @nx/enforce-module-boundaries */ -// nx-ignore-next-line -import { GraphError } from 'nx/src/command-line/graph/graph'; -/* eslint-enable @nx/enforce-module-boundaries */ -export function ErrorRenderer({ errors }: { errors: GraphError[] }) { - return ( -
    - {errors.map((error, index) => { - const errorHeading = - error.pluginName && error.name - ? `${error.name} - ${error.pluginName}` - : error.name ?? error.message; - const fileSpecifier = - isCauseWithLocation(error.cause) && error.cause.errors.length === 1 - ? `${error.fileName}:${error.cause.errors[0].location.line}:${error.cause.errors[0].location.column}` - : error.fileName; - return ( -
    - - {errorHeading} - {fileSpecifier && ( - - - )} - {fileSpecifier} - -
    -              {isCauseWithErrors(error.cause) &&
    -              error.cause.errors.length === 1 ? (
    -                
    - {error.message}
    - {error.cause.errors[0].text}{' '} -
    - ) : ( -
    {error.stack}
    - )} -
    -
    - ); - })} -
    - ); -} - -function isCauseWithLocation(cause: unknown): cause is { - errors: { - location: { - column: number; - line: number; - }; - text: string; - }[]; -} { - return ( - isCauseWithErrors(cause) && - (cause as any).errors[0].location && - (cause as any).errors[0].location.column && - (cause as any).errors[0].location.line - ); -} - -function isCauseWithErrors( - cause: unknown -): cause is { errors: { text: string }[] } { - return cause && (cause as any).errors && (cause as any).errors[0].text; -} diff --git a/graph/ui-components/src/lib/modal.tsx b/graph/ui-components/src/lib/modal.tsx deleted file mode 100644 index 5a2dfe65140e0..0000000000000 --- a/graph/ui-components/src/lib/modal.tsx +++ /dev/null @@ -1,108 +0,0 @@ -// component from https://tailwindui.com/components/application-ui/overlays/dialogs -import { Dialog, Transition } from '@headlessui/react'; -import { XMarkIcon } from '@heroicons/react/24/outline'; -import { - ForwardedRef, - Fragment, - ReactNode, - forwardRef, - useEffect, - useImperativeHandle, - useState, -} from 'react'; - -export interface ModalProps { - children: ReactNode; - title: string; - onOpen?: () => void; - onClose?: () => void; -} - -export interface ModalHandle { - openModal: () => void; - closeModal: () => void; -} - -export const Modal = forwardRef( - ( - { children, title, onOpen, onClose }: ModalProps, - ref: ForwardedRef - ) => { - const [open, setOpen] = useState(false); - - useEffect(() => { - if (open) { - onOpen?.(); - } else { - onClose?.(); - } - }, [open, onOpen, onClose]); - - useImperativeHandle(ref, () => ({ - closeModal: () => { - setOpen(false); - }, - openModal: () => { - setOpen(true); - }, - })); - - return ( - - - -
    - - -
    -
    - - -
    - - {title} - - -
    -
    - {children} -
    -
    -
    -
    -
    -
    -
    - ); - } -); diff --git a/graph/ui-components/src/lib/spinner.stories.tsx b/graph/ui-components/src/lib/spinner.stories.tsx deleted file mode 100644 index c7d7036e05a88..0000000000000 --- a/graph/ui-components/src/lib/spinner.stories.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import type { Meta, StoryObj } from '@storybook/react'; -import { Spinner } from './spinner'; - -const meta: Meta = { - component: Spinner, - title: 'Shared/Spinner', -}; - -export default meta; -type Story = StoryObj; - -export const Primary: Story = { - args: { - className: '', - }, -}; diff --git a/graph/ui-components/src/lib/spinner.tsx b/graph/ui-components/src/lib/spinner.tsx deleted file mode 100644 index fa84dd2af8500..0000000000000 --- a/graph/ui-components/src/lib/spinner.tsx +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Spinner component from https://tailwindcss.com/docs/animation#spin - */ - -import React from 'react'; - -export type SpinnerProps = React.SVGProps; - -export function Spinner({ className, ...rest }: SpinnerProps) { - return ( - - - - - ); -} diff --git a/graph/ui-components/src/lib/tag.stories.tsx b/graph/ui-components/src/lib/tag.stories.tsx deleted file mode 100644 index d20fcd34032f7..0000000000000 --- a/graph/ui-components/src/lib/tag.stories.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import type { Meta, StoryObj } from '@storybook/react'; -import { Tag } from './tag'; - -const meta: Meta = { - component: Tag, - title: 'Shared/Tag', -}; - -export default meta; -type Story = StoryObj; - -export const Primary: Story = { - args: { - content: 'tag', - }, -}; diff --git a/graph/ui-components/src/lib/tag.tsx b/graph/ui-components/src/lib/tag.tsx deleted file mode 100644 index a780d7095c6c8..0000000000000 --- a/graph/ui-components/src/lib/tag.tsx +++ /dev/null @@ -1,19 +0,0 @@ -/* eslint-disable-next-line */ -import React, { ReactNode } from 'react'; - -export type TagProps = Partial<{ - className: string; - children: ReactNode | ReactNode[]; -}> & - React.HTMLAttributes; - -export function Tag({ className, children, ...rest }: TagProps) { - return ( - - {children} - - ); -} diff --git a/graph/ui-components/src/lib/use-debounce.ts b/graph/ui-components/src/lib/use-debounce.ts deleted file mode 100644 index 13d94540b3f2c..0000000000000 --- a/graph/ui-components/src/lib/use-debounce.ts +++ /dev/null @@ -1,26 +0,0 @@ -import type { Dispatch, SetStateAction } from 'react'; -import { useEffect, useState } from 'react'; - -export function useDebounce( - value: string, - delay: number -): [string, Dispatch>] { - // State and setters for debounced value - const [debouncedValue, setDebouncedValue] = useState(value); - useEffect( - () => { - // Update debounced value after delay - const handler = setTimeout(() => { - setDebouncedValue(value); - }, delay); - // Cancel the timeout if value changes (also on delay change or unmount) - // This is how we prevent debounced value from updating if value is changed ... - // .. within the delay period. Timeout gets cleared and restarted. - return () => { - clearTimeout(handler); - }; - }, - [value, delay] // Only re-call effect if value or delay changes - ); - return [debouncedValue, setDebouncedValue]; -} diff --git a/graph/ui-components/tailwind.config.js b/graph/ui-components/tailwind.config.js deleted file mode 100644 index a130bfceccd48..0000000000000 --- a/graph/ui-components/tailwind.config.js +++ /dev/null @@ -1,40 +0,0 @@ -const path = require('path'); - -// nx-ignore-next-line -const { createGlobPatternsForDependencies } = require('@nx/react/tailwind'); - -module.exports = { - content: [ - path.join(__dirname, 'src/**/*.{js,ts,jsx,tsx,html}'), - ...createGlobPatternsForDependencies(__dirname), - ], - darkMode: 'class', // or 'media' or 'class' - theme: { - extend: { - typography: { - DEFAULT: { - css: { - 'code::before': { - content: '', - }, - 'code::after': { - content: '', - }, - 'blockquote p:first-of-type::before': { - content: '', - }, - 'blockquote p:last-of-type::after': { - content: '', - }, - }, - }, - }, - }, - }, - variants: { - extend: { - translate: ['group-hover'], - }, - }, - plugins: [require('@tailwindcss/typography')], -}; diff --git a/graph/ui-components/tsconfig.json b/graph/ui-components/tsconfig.json deleted file mode 100644 index 79d9ca983d86d..0000000000000 --- a/graph/ui-components/tsconfig.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "compilerOptions": { - "jsx": "react-jsx", - "allowJs": false, - "esModuleInterop": false, - "allowSyntheticDefaultImports": true, - "strict": true - }, - "files": [], - "include": [], - "references": [ - { - "path": "./tsconfig.lib.json" - }, - { - "path": "./tsconfig.spec.json" - }, - { - "path": "./tsconfig.storybook.json" - } - ], - "extends": "../../tsconfig.base.json" -} diff --git a/graph/ui-components/tsconfig.lib.json b/graph/ui-components/tsconfig.lib.json deleted file mode 100644 index b1b39d36d9cdc..0000000000000 --- a/graph/ui-components/tsconfig.lib.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "types": ["node"], - "lib": ["dom"] - }, - "files": [ - "../../node_modules/@nx/react/typings/cssmodule.d.ts", - "../../node_modules/@nx/react/typings/image.d.ts" - ], - "exclude": [ - "jest.config.ts", - "src/**/*.spec.ts", - "src/**/*.test.ts", - "src/**/*.spec.tsx", - "src/**/*.test.tsx", - "src/**/*.spec.js", - "src/**/*.test.js", - "src/**/*.spec.jsx", - "src/**/*.test.jsx", - "**/*.stories.ts", - "**/*.stories.js", - "**/*.stories.jsx", - "**/*.stories.tsx" - ], - "include": ["src/**/*.js", "src/**/*.jsx", "src/**/*.ts", "src/**/*.tsx"] -} diff --git a/graph/ui-components/tsconfig.spec.json b/graph/ui-components/tsconfig.spec.json deleted file mode 100644 index 26ef046ac5e54..0000000000000 --- a/graph/ui-components/tsconfig.spec.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "module": "commonjs", - "types": ["jest", "node"] - }, - "include": [ - "jest.config.ts", - "src/**/*.test.ts", - "src/**/*.spec.ts", - "src/**/*.test.tsx", - "src/**/*.spec.tsx", - "src/**/*.test.js", - "src/**/*.spec.js", - "src/**/*.test.jsx", - "src/**/*.spec.jsx", - "src/**/*.d.ts" - ] -} diff --git a/graph/ui-components/tsconfig.storybook.json b/graph/ui-components/tsconfig.storybook.json deleted file mode 100644 index 98ee6645c6232..0000000000000 --- a/graph/ui-components/tsconfig.storybook.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "emitDecoratorMetadata": true, - "outDir": "" - }, - "files": [ - "../../node_modules/@nx/react/typings/styled-jsx.d.ts", - "../../node_modules/@nx/react/typings/cssmodule.d.ts", - "../../node_modules/@nx/react/typings/image.d.ts" - ], - "exclude": [ - "src/**/*.spec.ts", - "src/**/*.spec.js", - "src/**/*.spec.tsx", - "src/**/*.spec.jsx" - ], - "include": [ - "src/**/*.stories.ts", - "src/**/*.stories.js", - "src/**/*.stories.jsx", - "src/**/*.stories.tsx", - "src/**/*.stories.mdx", - ".storybook/*.js" - ] -} diff --git a/graph/ui-graph/.babelrc b/graph/ui-graph/.babelrc deleted file mode 100644 index 1ea870ead410c..0000000000000 --- a/graph/ui-graph/.babelrc +++ /dev/null @@ -1,12 +0,0 @@ -{ - "presets": [ - [ - "@nx/react/babel", - { - "runtime": "automatic", - "useBuiltIns": "usage" - } - ] - ], - "plugins": [] -} diff --git a/graph/ui-graph/.eslintrc.json b/graph/ui-graph/.eslintrc.json deleted file mode 100644 index a39ac5d057803..0000000000000 --- a/graph/ui-graph/.eslintrc.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "extends": ["plugin:@nx/react", "../../.eslintrc.json"], - "ignorePatterns": ["!**/*"], - "overrides": [ - { - "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], - "rules": {} - }, - { - "files": ["*.ts", "*.tsx"], - "rules": {} - }, - { - "files": ["*.js", "*.jsx"], - "rules": {} - } - ] -} diff --git a/graph/ui-graph/.storybook/main.js b/graph/ui-graph/.storybook/main.js deleted file mode 100644 index 98b74a9cb2588..0000000000000 --- a/graph/ui-graph/.storybook/main.js +++ /dev/null @@ -1,9 +0,0 @@ -module.exports = { - stories: ['../src/lib/**/*.stories.@(mdx|js|jsx|ts|tsx)'], - addons: ['@storybook/addon-essentials', '@nx/react/plugins/storybook'], - framework: { - name: '@storybook/react-webpack5', - options: {}, - }, - docs: {}, -}; diff --git a/graph/ui-graph/.storybook/preview-head.html b/graph/ui-graph/.storybook/preview-head.html deleted file mode 100644 index 928d6bd7814e3..0000000000000 --- a/graph/ui-graph/.storybook/preview-head.html +++ /dev/null @@ -1,26 +0,0 @@ - diff --git a/graph/ui-graph/.storybook/preview.js b/graph/ui-graph/.storybook/preview.js deleted file mode 100644 index 245891b1b254c..0000000000000 --- a/graph/ui-graph/.storybook/preview.js +++ /dev/null @@ -1,4 +0,0 @@ -import './tailwind-imports.css'; - -export const parameters = {}; -export const tags = ['autodocs']; diff --git a/graph/ui-graph/.storybook/tailwind-imports.css b/graph/ui-graph/.storybook/tailwind-imports.css deleted file mode 100644 index b5c61c956711f..0000000000000 --- a/graph/ui-graph/.storybook/tailwind-imports.css +++ /dev/null @@ -1,3 +0,0 @@ -@tailwind base; -@tailwind components; -@tailwind utilities; diff --git a/graph/ui-graph/README.md b/graph/ui-graph/README.md deleted file mode 100644 index 19422969d913a..0000000000000 --- a/graph/ui-graph/README.md +++ /dev/null @@ -1,7 +0,0 @@ -# graph-ui-graph - -This library was generated with [Nx](https://nx.dev). - -## Running unit tests - -Run `nx test graph-ui-graph` to execute the unit tests via [Jest](https://jestjs.io). diff --git a/graph/ui-graph/jest.config.ts b/graph/ui-graph/jest.config.ts deleted file mode 100644 index c603de0306376..0000000000000 --- a/graph/ui-graph/jest.config.ts +++ /dev/null @@ -1,10 +0,0 @@ -/* eslint-disable */ -export default { - displayName: 'graph-ui-graph', - preset: '../../jest.preset.js', - transform: { - '^.+\\.[tj]sx?$': 'babel-jest', - }, - moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'], - coverageDirectory: '../../coverage/graph/ui-graph', -}; diff --git a/graph/ui-graph/postcss.config.js b/graph/ui-graph/postcss.config.js deleted file mode 100644 index 8b2e63b9e6bea..0000000000000 --- a/graph/ui-graph/postcss.config.js +++ /dev/null @@ -1,10 +0,0 @@ -const path = require('path'); - -module.exports = { - plugins: { - tailwindcss: { - config: path.join(__dirname, 'tailwind.config.js'), - }, - autoprefixer: {}, - }, -}; diff --git a/graph/ui-graph/project.json b/graph/ui-graph/project.json deleted file mode 100644 index dc2627fbbbe17..0000000000000 --- a/graph/ui-graph/project.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "name": "graph-ui-graph", - "$schema": "../../node_modules/nx/schemas/project-schema.json", - "sourceRoot": "graph/ui-graph/src", - "projectType": "library", - "tags": [], - "targets": { - "storybook": { - "executor": "@nx/storybook:storybook", - "options": { - "port": 4400, - "configDir": "graph/ui-graph/.storybook" - }, - "configurations": { - "ci": { - "quiet": true - } - } - }, - "build-storybook": { - "executor": "@nx/storybook:build", - "outputs": ["{options.outputDir}"], - "options": { - "configDir": "graph/ui-graph/.storybook", - "outputDir": "dist/storybook/graph-ui-graph" - }, - "configurations": { - "ci": { - "quiet": true - } - } - } - } -} diff --git a/graph/ui-graph/src/index.ts b/graph/ui-graph/src/index.ts deleted file mode 100644 index 8e29488822804..0000000000000 --- a/graph/ui-graph/src/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -export * from './lib/nx-project-graph-viz'; -export * from './lib/nx-task-graph-viz'; -export * from './lib/graph'; -export * from './lib/tooltip-service'; -export * from './lib/graph-interaction-events'; diff --git a/graph/ui-graph/src/lib/graph-interaction-events.ts b/graph/ui-graph/src/lib/graph-interaction-events.ts deleted file mode 100644 index 77a0b92d3854c..0000000000000 --- a/graph/ui-graph/src/lib/graph-interaction-events.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { VirtualElement } from '@floating-ui/react'; -import { ProjectNodeDataDefinition } from './util-cytoscape/project-node'; -import { TaskNodeDataDefinition } from './util-cytoscape/task-node'; -import { ProjectEdgeDataDefinition } from './util-cytoscape'; - -interface ProjectNodeClickEvent { - type: 'ProjectNodeClick'; - ref: VirtualElement; - id: string; - data: ProjectNodeDataDefinition; -} - -interface TaskNodeClickEvent { - type: 'TaskNodeClick'; - ref: VirtualElement; - id: string; - data: TaskNodeDataDefinition; -} - -interface EdgeClickEvent { - type: 'EdgeClick'; - ref: VirtualElement; - id: string; - data: ProjectEdgeDataDefinition; -} - -interface GraphRegeneratedEvent { - type: 'GraphRegenerated'; -} - -interface BackgroundClickEvent { - type: 'BackgroundClick'; -} - -export type GraphInteractionEvents = - | ProjectNodeClickEvent - | EdgeClickEvent - | GraphRegeneratedEvent - | TaskNodeClickEvent - | BackgroundClickEvent; diff --git a/graph/ui-graph/src/lib/graph.ts b/graph/ui-graph/src/lib/graph.ts deleted file mode 100644 index e28886c4094ee..0000000000000 --- a/graph/ui-graph/src/lib/graph.ts +++ /dev/null @@ -1,294 +0,0 @@ -// nx-ignore-next-line -import { CollectionReturnValue, use } from 'cytoscape'; -import cytoscapeDagre from 'cytoscape-dagre'; -import popper from 'cytoscape-popper'; -import { - GraphPerfReport, - ProjectGraphRenderEvents, - TaskGraphRenderEvents, -} from './interfaces'; -import { GraphInteractionEvents } from './graph-interaction-events'; -import { RenderGraph } from './util-cytoscape/render-graph'; -import { ProjectTraversalGraph } from './util-cytoscape/project-traversal-graph'; -import { TaskTraversalGraph } from './util-cytoscape/task-traversal.graph'; - -export class GraphService { - private projectTraversalGraph: ProjectTraversalGraph; - private taskTraversalGraph: TaskTraversalGraph; - private renderGraph: RenderGraph; - - lastPerformanceReport: GraphPerfReport = { - numEdges: 0, - numNodes: 0, - renderTime: 0, - }; - - private listeners = new Map< - number, - (event: GraphInteractionEvents) => void - >(); - - constructor( - container: string | HTMLElement, - theme: 'light' | 'dark', - public renderMode?: 'nx-console' | 'nx-docs', - rankDir: 'TB' | 'LR' = 'TB', - public getTaskInputs: ( - taskId: string - ) => Promise> = undefined - ) { - use(cytoscapeDagre); - use(popper); - - this.renderGraph = new RenderGraph(container, theme, renderMode, rankDir); - - this.renderGraph.listen((event) => this.broadcast(event)); - this.projectTraversalGraph = new ProjectTraversalGraph(); - this.taskTraversalGraph = new TaskTraversalGraph(); - } - - set theme(theme: 'light' | 'dark') { - this.renderGraph.theme = theme; - } - - set rankDir(rankDir: 'TB' | 'LR') { - this.renderGraph.rankDir = rankDir; - } - - listen(callback: (event: GraphInteractionEvents) => void) { - const listenerId = this.listeners.size + 1; - this.listeners.set(listenerId, callback); - - return () => { - this.listeners.delete(listenerId); - }; - } - - broadcast(event: GraphInteractionEvents) { - this.listeners.forEach((callback) => callback(event)); - } - - handleProjectEvent(event: ProjectGraphRenderEvents): { - selectedProjectNames: string[]; - perfReport: GraphPerfReport; - } { - const time = Date.now(); - - if (event.type !== 'notifyGraphUpdateGraph') { - this.renderGraph.clearFocussedElement(); - } - - let elementsToSendToRender: CollectionReturnValue; - - switch (event.type) { - case 'notifyGraphInitGraph': - this.renderGraph.collapseEdges = event.collapseEdges; - this.broadcast({ type: 'GraphRegenerated' }); - this.projectTraversalGraph.initGraph( - event.fileMap, - event.projects, - event.groupByFolder, - event.workspaceLayout, - event.dependencies, - event.affectedProjects, - event.collapseEdges - ); - break; - - case 'notifyGraphUpdateGraph': - this.renderGraph.collapseEdges = event.collapseEdges; - this.broadcast({ type: 'GraphRegenerated' }); - this.projectTraversalGraph.initGraph( - event.fileMap, - event.projects, - event.groupByFolder, - event.workspaceLayout, - event.dependencies, - event.affectedProjects, - event.collapseEdges - ); - elementsToSendToRender = this.projectTraversalGraph.setShownProjects( - event.selectedProjects.length > 0 - ? event.selectedProjects - : this.renderGraph.getCurrentlyShownProjectIds() - ); - break; - - case 'notifyGraphFocusProject': - elementsToSendToRender = this.projectTraversalGraph.focusProject( - event.projectName, - event.searchDepth - ); - - break; - - case 'notifyGraphFilterProjectsByText': - elementsToSendToRender = - this.projectTraversalGraph.filterProjectsByText( - event.search, - event.includeProjectsByPath, - event.searchDepth - ); - break; - - case 'notifyGraphShowProjects': - elementsToSendToRender = this.projectTraversalGraph.showProjects( - event.projectNames, - this.renderGraph.getCurrentlyShownProjectIds() - ); - break; - - case 'notifyGraphHideProjects': - elementsToSendToRender = this.projectTraversalGraph.hideProjects( - event.projectNames, - this.renderGraph.getCurrentlyShownProjectIds() - ); - break; - - case 'notifyGraphShowAllProjects': - elementsToSendToRender = this.projectTraversalGraph.showAllProjects(); - break; - - case 'notifyGraphHideAllProjects': - elementsToSendToRender = this.projectTraversalGraph.hideAllProjects(); - break; - - case 'notifyGraphShowAffectedProjects': - elementsToSendToRender = - this.projectTraversalGraph.showAffectedProjects(); - break; - - case 'notifyGraphTracing': - if (event.start && event.end) { - if (event.algorithm === 'shortest') { - elementsToSendToRender = this.projectTraversalGraph.traceProjects( - event.start, - event.end - ); - } else { - elementsToSendToRender = - this.projectTraversalGraph.traceAllProjects( - event.start, - event.end - ); - } - } - break; - } - - let selectedProjectNames: string[] = []; - let perfReport: GraphPerfReport = { - numEdges: 0, - numNodes: 0, - renderTime: 0, - }; - - if (this.renderGraph) { - if (elementsToSendToRender) { - this.renderGraph.setElements(elementsToSendToRender); - - if (event.type === 'notifyGraphFocusProject') { - this.renderGraph.setFocussedElement(event.projectName); - } - - const { numEdges, numNodes } = this.renderGraph.render(); - - selectedProjectNames = ( - elementsToSendToRender.nodes('[type!="dir"]') ?? [] - ).map((node) => node.id()); - - const renderTime = Date.now() - time; - - perfReport = { - renderTime, - numNodes, - numEdges, - }; - } else { - const { numEdges, numNodes } = this.renderGraph.render(); - - this.renderGraph.getCurrentlyShownProjectIds(); - - const renderTime = Date.now() - time; - - perfReport = { - renderTime, - numNodes, - numEdges, - }; - } - } - - this.lastPerformanceReport = perfReport; - this.broadcast({ type: 'GraphRegenerated' }); - - return { selectedProjectNames, perfReport }; - } - - handleTaskEvent(event: TaskGraphRenderEvents) { - const time = Date.now(); - - this.broadcast({ type: 'GraphRegenerated' }); - - let elementsToSendToRender: CollectionReturnValue; - switch (event.type) { - case 'notifyTaskGraphSetProjects': - this.taskTraversalGraph.setProjects(event.projects, event.taskGraphs); - break; - case 'notifyTaskGraphSetTasks': - elementsToSendToRender = this.taskTraversalGraph.setTasks( - event.taskIds - ); - break; - case 'notifyTaskGraphTasksSelected': - elementsToSendToRender = this.taskTraversalGraph.selectTask( - event.taskIds - ); - break; - case 'notifyTaskGraphTasksDeselected': - elementsToSendToRender = this.taskTraversalGraph.deselectTask( - event.taskIds - ); - break; - case 'setGroupByProject': - elementsToSendToRender = this.taskTraversalGraph.setGroupByProject( - event.groupByProject - ); - break; - } - - let selectedProjectNames: string[] = []; - let perfReport: GraphPerfReport = { - numEdges: 0, - numNodes: 0, - renderTime: 0, - }; - - if (this.renderGraph && elementsToSendToRender) { - this.renderGraph.setElements(elementsToSendToRender); - - const { numEdges, numNodes } = this.renderGraph.render(); - - selectedProjectNames = ( - elementsToSendToRender.nodes('[type!="dir"]') ?? [] - ).map((node) => node.id()); - - const renderTime = Date.now() - time; - - perfReport = { - renderTime, - numNodes, - numEdges, - }; - } - - this.lastPerformanceReport = perfReport; - this.broadcast({ type: 'GraphRegenerated' }); - - return { selectedProjectNames, perfReport }; - } - - getImage() { - return this.renderGraph.getImage(); - } -} diff --git a/graph/ui-graph/src/lib/interfaces.ts b/graph/ui-graph/src/lib/interfaces.ts deleted file mode 100644 index 839d06f550215..0000000000000 --- a/graph/ui-graph/src/lib/interfaces.ts +++ /dev/null @@ -1,122 +0,0 @@ -/* eslint-disable @nx/enforce-module-boundaries */ -// nx-ignore-next-line -import type { - ProjectFileMap, - ProjectGraphDependency, - ProjectGraphProjectNode, - TaskGraph, -} from '@nx/devkit'; -/* eslint-enable @nx/enforce-module-boundaries */ -import { VirtualElement } from '@floating-ui/react'; -import { - ProjectEdgeNodeTooltipProps, - ProjectNodeToolTipProps, - TaskNodeTooltipProps, -} from '@nx/graph/ui-tooltips'; - -export interface GraphPerfReport { - renderTime: number; - numNodes: number; - numEdges: number; -} - -export type TracingAlgorithmType = 'shortest' | 'all'; - -// The events that the graph actor handles - -export type ProjectGraphRenderEvents = - | { - type: 'notifyGraphInitGraph'; - projects: ProjectGraphProjectNode[]; - fileMap: ProjectFileMap; - dependencies: Record; - affectedProjects: string[]; - workspaceLayout: { - libsDir: string; - appsDir: string; - }; - groupByFolder: boolean; - collapseEdges: boolean; - } - | { - type: 'notifyGraphUpdateGraph'; - projects: ProjectGraphProjectNode[]; - fileMap: ProjectFileMap; - dependencies: Record; - affectedProjects: string[]; - workspaceLayout: { - libsDir: string; - appsDir: string; - }; - groupByFolder: boolean; - collapseEdges: boolean; - selectedProjects: string[]; - } - | { - type: 'notifyGraphFocusProject'; - projectName: string; - searchDepth: number; - } - | { - type: 'notifyGraphShowProjects'; - projectNames: string[]; - } - | { - type: 'notifyGraphHideProjects'; - projectNames: string[]; - } - | { - type: 'notifyGraphShowAllProjects'; - } - | { - type: 'notifyGraphHideAllProjects'; - } - | { - type: 'notifyGraphShowAffectedProjects'; - } - | { - type: 'notifyGraphFilterProjectsByText'; - search: string; - includeProjectsByPath: boolean; - searchDepth: number; - } - | { - type: 'notifyGraphTracing'; - start: string; - end: string; - algorithm: TracingAlgorithmType; - }; - -export type TaskGraphRecord = Record; -export type TaskGraphRenderEvents = - | { - type: 'notifyTaskGraphSetProjects'; - projects: ProjectGraphProjectNode[]; - taskGraphs: TaskGraphRecord; - } - | { - type: 'notifyTaskGraphTasksSelected'; - taskIds: string[]; - } - | { - type: 'notifyTaskGraphTasksDeselected'; - taskIds: string[]; - } - | { - type: 'setGroupByProject'; - groupByProject: boolean; - } - | { type: 'notifyTaskGraphSetTasks'; taskIds: string[] }; - -export type TooltipEvent = - | { - ref: VirtualElement; - type: 'projectNode'; - props: ProjectNodeToolTipProps; - } - | { ref: VirtualElement; type: 'taskNode'; props: TaskNodeTooltipProps } - | { - ref: VirtualElement; - type: 'projectEdge'; - props: ProjectEdgeNodeTooltipProps; - }; diff --git a/graph/ui-graph/src/lib/nx-project-graph-viz.stories.tsx b/graph/ui-graph/src/lib/nx-project-graph-viz.stories.tsx deleted file mode 100644 index fdf4e9a23dc4c..0000000000000 --- a/graph/ui-graph/src/lib/nx-project-graph-viz.stories.tsx +++ /dev/null @@ -1,70 +0,0 @@ -import type { Meta, StoryObj } from '@storybook/react'; -import { NxProjectGraphViz } from './nx-project-graph-viz'; - -const meta: Meta = { - component: NxProjectGraphViz, - title: 'NxProjectGraphViz', -}; - -export default meta; -type Story = StoryObj; - -export const Primary: Story = { - args: { - projects: [ - { - type: 'app', - name: 'app', - data: { - tags: ['scope:cart'], - description: 'This is your top-level app', - files: [ - { - file: 'whatever.ts', - deps: ['lib'], - }, - ], - }, - } as any, - { - type: 'lib', - name: 'lib', - data: { - tags: ['scope:cart'], - description: 'This lib implements some type of feature for your app.', - }, - }, - { - type: 'lib', - name: 'lib2', - data: { - root: 'libs/nested-scope/lib2', - tags: ['scope:cart'], - }, - }, - { - type: 'lib', - name: 'lib3', - data: { - root: 'libs/nested-scope/lib3', - tags: ['scope:cart'], - }, - }, - ], - groupByFolder: true, - workspaceLayout: { appsDir: 'apps', libsDir: 'libs' }, - dependencies: { - app: [{ target: 'lib', source: 'app', type: 'direct' }], - lib: [ - { target: 'lib2', source: 'lib', type: 'implicit' }, - { target: 'lib3', source: 'lib', type: 'direct' }, - ], - lib2: [], - lib3: [], - }, - affectedProjectIds: [], - theme: 'light', - height: '450px', - enableTooltips: true, - }, -}; diff --git a/graph/ui-graph/src/lib/nx-project-graph-viz.tsx b/graph/ui-graph/src/lib/nx-project-graph-viz.tsx deleted file mode 100644 index e415a2c99cd04..0000000000000 --- a/graph/ui-graph/src/lib/nx-project-graph-viz.tsx +++ /dev/null @@ -1,137 +0,0 @@ -'use client'; -/* eslint-disable @nx/enforce-module-boundaries */ -/* nx-ignore-next-line */ -import type { - ProjectGraphProjectNode, - ProjectGraphDependency, - ProjectFileMap, -} from 'nx/src/config/project-graph'; -/* eslint-enable @nx/enforce-module-boundaries */ -import { useEffect, useRef, useState } from 'react'; -import { GraphService } from './graph'; -import { - ProjectEdgeNodeTooltip, - ProjectNodeToolTip, - TaskNodeTooltip, - Tooltip, -} from '@nx/graph/ui-tooltips'; -import { GraphTooltipService } from './tooltip-service'; -import { TooltipEvent } from './interfaces'; - -type Theme = 'light' | 'dark' | 'system'; - -export interface GraphUiGraphProps { - projects: ProjectGraphProjectNode[]; - fileMap: ProjectFileMap; - groupByFolder: boolean; - workspaceLayout: { appsDir: string; libsDir: string }; - dependencies: Record; - affectedProjectIds: string[]; - theme: Theme; - height: string; - enableTooltips: boolean; -} - -function resolveTheme(theme: Theme): 'dark' | 'light' { - if (theme !== 'system') { - return theme; - } else { - const darkMedia = window.matchMedia('(prefers-color-scheme: dark)'); - return darkMedia.matches ? 'dark' : 'light'; - } -} - -export function NxProjectGraphViz({ - projects, - fileMap, - groupByFolder, - workspaceLayout, - dependencies, - affectedProjectIds, - theme, - height, - enableTooltips, -}: GraphUiGraphProps) { - const containerRef = useRef(null); - const [graph, setGraph] = useState(null); - const [currentTooltip, setCurrenTooltip] = useState(null); - - const [resolvedTheme, setResolvedTheme] = useState<'light' | 'dark'>(); - - const newlyResolvedTheme = resolveTheme(theme); - - if (newlyResolvedTheme !== resolvedTheme) { - setResolvedTheme(newlyResolvedTheme); - - if (graph) { - graph.theme = newlyResolvedTheme; - } - } - - useEffect(() => { - if (containerRef.current !== null) { - import('./graph') - .then((module) => module.GraphService) - .then((GraphService) => { - const graph = new GraphService( - containerRef.current, - resolvedTheme, - 'nx-docs', - 'TB' - ); - graph.handleProjectEvent({ - type: 'notifyGraphInitGraph', - fileMap, - projects, - groupByFolder, - workspaceLayout, - dependencies, - affectedProjects: affectedProjectIds, - collapseEdges: false, - }); - graph.handleProjectEvent({ type: 'notifyGraphShowAllProjects' }); - - if (enableTooltips) { - const tooltipService = new GraphTooltipService(graph); - tooltipService.subscribe((tooltip) => { - setCurrenTooltip(tooltip); - }); - } - }); - } - }, []); - - let tooltipToRender; - if (currentTooltip) { - switch (currentTooltip.type) { - case 'projectNode': - tooltipToRender = ; - break; - case 'projectEdge': - tooltipToRender = ; - break; - case 'taskNode': - tooltipToRender = ; - break; - } - } - - return ( -
    -
    - {tooltipToRender ? ( - - ) : null} -
    - ); -} diff --git a/graph/ui-graph/src/lib/nx-task-graph-viz.stories.tsx b/graph/ui-graph/src/lib/nx-task-graph-viz.stories.tsx deleted file mode 100644 index e1dca41caa84b..0000000000000 --- a/graph/ui-graph/src/lib/nx-task-graph-viz.stories.tsx +++ /dev/null @@ -1,112 +0,0 @@ -import type { Meta, StoryObj } from '@storybook/react'; -import { NxTaskGraphViz } from './nx-task-graph-viz'; - -const meta: Meta = { - component: NxTaskGraphViz, - title: 'NxTaskGraphViz', -}; - -export default meta; -type Story = StoryObj; - -export const Primary: Story = { - args: { - projects: [ - { - type: 'app', - name: 'app', - data: { - tags: ['scope:cart'], - targets: { - build: { - executor: '@nrwl/js:tsc', - }, - }, - description: 'The app uses this task to build itself.', - }, - } as any, - { - type: 'lib', - name: 'lib1', - data: { - tags: ['scope:cart'], - targets: { - build: { - executor: '@nrwl/js:tsc', - }, - }, - description: 'The lib uses this task to build itself.', - }, - }, - { - type: 'lib', - name: 'lib2', - data: { - root: 'libs/nested-scope/lib2', - tags: ['scope:cart'], - targets: { - build: { - executor: '@nrwl/js:tsc', - }, - }, - }, - }, - { - type: 'lib', - name: 'lib3', - data: { - root: 'libs/nested-scope/lib3', - tags: ['scope:cart'], - targets: { - build: { - executor: '@nrwl/js:tsc', - }, - }, - }, - }, - ], - taskGraphs: { - 'app:build': { - tasks: { - 'app:build': { - id: 'app:build', - target: { - project: 'app', - target: 'build', - }, - } as any, - 'lib1:build': { - id: 'lib1:build', - target: { - project: 'lib1', - target: 'build', - }, - } as any, - 'lib2:build': { - id: 'lib2:build', - target: { - project: 'lib2', - target: 'build', - }, - } as any, - 'lib3:build': { - id: 'lib3:build', - target: { - project: 'lib3', - target: 'build', - }, - } as any, - }, - dependencies: { - 'app:build': ['lib1:build', 'lib2:build', 'lib3:build'], - 'lib1:build': [], - 'lib2:build': [], - 'lib3:build': [], - }, - } as any, - }, - taskId: 'app:build', - height: '450px', - enableTooltips: true, - }, -}; diff --git a/graph/ui-graph/src/lib/nx-task-graph-viz.tsx b/graph/ui-graph/src/lib/nx-task-graph-viz.tsx deleted file mode 100644 index 42b140c721f6e..0000000000000 --- a/graph/ui-graph/src/lib/nx-task-graph-viz.tsx +++ /dev/null @@ -1,114 +0,0 @@ -'use client'; -/* eslint-disable @nx/enforce-module-boundaries */ -/* nx-ignore-next-line */ -import type { ProjectGraphProjectNode } from 'nx/src/config/project-graph'; -/* eslint-enable @nx/enforce-module-boundaries */ -import { useEffect, useRef, useState } from 'react'; -import { GraphService } from './graph'; -import { TaskGraphRecord, TooltipEvent } from './interfaces'; -import { TaskNodeTooltip, Tooltip } from '@nx/graph/ui-tooltips'; -import { GraphTooltipService } from './tooltip-service'; - -type Theme = 'light' | 'dark' | 'system'; - -export interface TaskGraphUiGraphProps { - projects: ProjectGraphProjectNode[]; - taskGraphs: TaskGraphRecord; - taskId: string; - theme: Theme; - height: string; - enableTooltips: boolean; -} - -function resolveTheme(theme: Theme): 'dark' | 'light' { - if (theme !== 'system') { - return theme; - } else { - const darkMedia = window.matchMedia('(prefers-color-scheme: dark)'); - return darkMedia.matches ? 'dark' : 'light'; - } -} - -export function NxTaskGraphViz({ - projects, - taskId, - taskGraphs, - theme, - height, - enableTooltips, -}: TaskGraphUiGraphProps) { - const containerRef = useRef(null); - const [graph, setGraph] = useState(null); - const [currentTooltip, setCurrenTooltip] = useState(null); - - const [resolvedTheme, setResolvedTheme] = useState<'light' | 'dark'>(); - - const newlyResolvedTheme = resolveTheme(theme); - - if (newlyResolvedTheme !== resolvedTheme) { - setResolvedTheme(newlyResolvedTheme); - - if (graph) { - graph.theme = newlyResolvedTheme; - } - } - useEffect(() => { - if (containerRef.current !== null) { - import('./graph') - .then((module) => module.GraphService) - .then((GraphService) => { - const graph = new GraphService( - containerRef.current, - resolvedTheme, - 'nx-docs', - 'TB' - ); - graph.handleTaskEvent({ - type: 'notifyTaskGraphSetProjects', - projects, - taskGraphs, - }); - graph.handleTaskEvent({ - type: 'notifyTaskGraphSetTasks', - taskIds: [taskId], - }); - setGraph(graph); - - if (enableTooltips) { - const tooltipService = new GraphTooltipService(graph); - tooltipService.subscribe((tooltip) => { - setCurrenTooltip(tooltip); - }); - } - }); - } - }, []); - - let tooltipToRender; - if (currentTooltip) { - switch (currentTooltip.type) { - case 'taskNode': - tooltipToRender = ; - break; - } - } - - return ( -
    -
    - {tooltipToRender ? ( - - ) : null} -
    - ); -} diff --git a/graph/ui-graph/src/lib/styles-graph/dark-mode.ts b/graph/ui-graph/src/lib/styles-graph/dark-mode.ts deleted file mode 100644 index 899e36019eff4..0000000000000 --- a/graph/ui-graph/src/lib/styles-graph/dark-mode.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { SingularData, Core } from 'cytoscape'; - -export const darkModeScratchKey = 'NX_GRAPH_DARK_MODE'; - -export function scratchHasDarkMode(element: SingularData | Core) { - return element.scratch(darkModeScratchKey) === true; -} - -export function switchValueByDarkMode( - element: SingularData | Core, - dark: T, - light: T -) { - return scratchHasDarkMode(element) ? dark : light; -} diff --git a/graph/ui-graph/src/lib/styles-graph/edges.ts b/graph/ui-graph/src/lib/styles-graph/edges.ts deleted file mode 100644 index ec4d5aa35332e..0000000000000 --- a/graph/ui-graph/src/lib/styles-graph/edges.ts +++ /dev/null @@ -1,73 +0,0 @@ -import { EdgeSingular, Stylesheet } from 'cytoscape'; -import { NrwlPalette } from './palette'; -import { switchValueByDarkMode } from './dark-mode'; - -const allEdges: Stylesheet = { - selector: 'edge', - style: { - width: '1px', - 'line-color': (node) => - switchValueByDarkMode(node, NrwlPalette.slate_400, NrwlPalette.slate_500), - 'text-outline-color': (node: EdgeSingular) => - switchValueByDarkMode(node, NrwlPalette.slate_400, NrwlPalette.slate_500), - 'text-outline-width': '0px', - color: (node: EdgeSingular) => - switchValueByDarkMode(node, NrwlPalette.slate_400, NrwlPalette.slate_500), - 'curve-style': 'unbundled-bezier', - 'target-arrow-shape': 'triangle', - 'target-arrow-fill': 'filled', - 'target-arrow-color': (node) => - switchValueByDarkMode(node, NrwlPalette.slate_400, NrwlPalette.slate_500), - }, -}; - -const affectedEdges: Stylesheet = { - selector: 'edge.affected', - style: { - 'line-color': (node) => - switchValueByDarkMode( - node, - NrwlPalette.fuchsia_500, - NrwlPalette.pink_500 - ), - 'target-arrow-color': (node) => - switchValueByDarkMode( - node, - NrwlPalette.fuchsia_500, - NrwlPalette.pink_500 - ), - 'curve-style': 'unbundled-bezier', - }, -}; - -const implicitEdges: Stylesheet = { - selector: 'edge.implicit', - style: { - label: 'implicit', - 'font-size': '16px', - 'curve-style': 'unbundled-bezier', - 'text-rotation': 'autorotate', - }, -}; - -const transparentEdges: Stylesheet = { - selector: 'edge.transparent', - style: { opacity: 0.2 }, -}; - -const dynamicEdges: Stylesheet = { - selector: 'edge.dynamic', - style: { - 'line-dash-pattern': [5, 5], - 'line-style': 'dashed', - 'curve-style': 'unbundled-bezier', - }, -}; - -export const edgeStyles: Stylesheet[] = [ - allEdges, - affectedEdges, - implicitEdges, - dynamicEdges, - transparentEdges, -]; diff --git a/graph/ui-graph/src/lib/styles-graph/fonts.ts b/graph/ui-graph/src/lib/styles-graph/fonts.ts deleted file mode 100644 index eaf490825a9ad..0000000000000 --- a/graph/ui-graph/src/lib/styles-graph/fonts.ts +++ /dev/null @@ -1 +0,0 @@ -export const FONTS = 'system-ui, "Helvetica Neue", sans-serif'; diff --git a/graph/ui-graph/src/lib/styles-graph/index.ts b/graph/ui-graph/src/lib/styles-graph/index.ts deleted file mode 100644 index c557f1698c230..0000000000000 --- a/graph/ui-graph/src/lib/styles-graph/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './edges'; -export * from './nodes'; diff --git a/graph/ui-graph/src/lib/styles-graph/label-width.ts b/graph/ui-graph/src/lib/styles-graph/label-width.ts deleted file mode 100644 index fe6a904990af8..0000000000000 --- a/graph/ui-graph/src/lib/styles-graph/label-width.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { NodeSingular } from 'cytoscape'; - -export class LabelWidthCalculator { - private cache = new Map(); - private ctx: CanvasRenderingContext2D; - - constructor() {} - - calculateWidth(node: NodeSingular): number { - if (!this.ctx) { - this.ctx = document - .createElement('canvas') - .getContext('2d') as CanvasRenderingContext2D; - } - const label = node.data('id'); - const fStyle = node.style('font-style'); - const size = node.style('font-size'); - const family = node.style('font-family'); - const weight = node.style('font-weight'); - - this.ctx.font = fStyle + ' ' + weight + ' ' + size + ' ' + family; - - const cachedValue = this.cache.get(label); - - if (cachedValue) { - return cachedValue; - } else { - const width = this.ctx.measureText(node.data('id')).width; - - this.cache.set(label, width); - return width; - } - } -} diff --git a/graph/ui-graph/src/lib/styles-graph/nodes.ts b/graph/ui-graph/src/lib/styles-graph/nodes.ts deleted file mode 100644 index 1a8b0ffe00035..0000000000000 --- a/graph/ui-graph/src/lib/styles-graph/nodes.ts +++ /dev/null @@ -1,125 +0,0 @@ -import { NodeSingular, Stylesheet } from 'cytoscape'; -import { FONTS } from './fonts'; -import { NrwlPalette } from './palette'; -import { LabelWidthCalculator } from './label-width'; -import { switchValueByDarkMode } from './dark-mode'; - -const labelWidthCalculator = new LabelWidthCalculator(); - -const allNodes: Stylesheet = { - selector: 'node', - style: { - 'font-size': '32px', - 'font-family': FONTS, - backgroundColor: (node) => - switchValueByDarkMode(node, NrwlPalette.slate_600, NrwlPalette.slate_200), - 'border-style': 'solid', - 'border-color': (node) => - switchValueByDarkMode(node, NrwlPalette.slate_700, NrwlPalette.slate_300), - 'border-width': '1px', - 'text-halign': 'center', - 'text-valign': 'center', - 'padding-left': '16px', - color: (node: NodeSingular) => - switchValueByDarkMode(node, NrwlPalette.slate_200, NrwlPalette.slate_600), - label: 'data(id)', - width: (node: NodeSingular) => labelWidthCalculator.calculateWidth(node), - 'transition-property': - 'background-color, border-color, line-color, target-arrow-color', - 'transition-duration': 250, - 'transition-timing-function': 'ease-out', - shape: 'round-rectangle', - }, -}; - -const focusedNodes: Stylesheet = { - selector: 'node.focused', - style: { - color: NrwlPalette.white, - 'border-color': (node) => - switchValueByDarkMode(node, NrwlPalette.slate_700, NrwlPalette.slate_200), - backgroundColor: (node) => - switchValueByDarkMode(node, NrwlPalette.sky_500, NrwlPalette.blue_500), - width: (node: NodeSingular) => labelWidthCalculator.calculateWidth(node), - }, -}; - -const affectedNodes: Stylesheet = { - selector: 'node.affected', - style: { - color: NrwlPalette.white, - 'border-color': (node) => - switchValueByDarkMode( - node, - NrwlPalette.fuchsia_800, - NrwlPalette.pink_500 - ), - backgroundColor: (node) => - switchValueByDarkMode( - node, - NrwlPalette.fuchsia_700, - NrwlPalette.pink_400 - ), - }, -}; - -const parentNodes: Stylesheet = { - selector: 'node.parentNode', - style: { - 'background-opacity': (node) => switchValueByDarkMode(node, 0.5, 0.8), - backgroundColor: (node) => - switchValueByDarkMode(node, NrwlPalette.slate_700, NrwlPalette.slate_50), - 'border-color': (node) => - switchValueByDarkMode(node, NrwlPalette.slate_500, NrwlPalette.slate_400), - 'border-style': 'dashed', - 'border-width': 2, - label: 'data(label)', - 'text-halign': 'center', - 'text-valign': 'top', - 'font-weight': 'bold', - 'font-size': '48px', - }, -}; - -const highlightedNodes: Stylesheet = { - selector: 'node.highlight', - style: { - color: NrwlPalette.white, - 'border-color': (node) => - switchValueByDarkMode(node, NrwlPalette.sky_600, NrwlPalette.blue_600), - backgroundColor: (node) => - switchValueByDarkMode(node, NrwlPalette.sky_500, NrwlPalette.blue_500), - }, -}; - -const taskNodes: Stylesheet = { - selector: 'node.taskNode', - style: { - label: 'data(label)', - }, -}; - -const transparentProjectNodes: Stylesheet = { - selector: 'node.transparent:childless', - style: { opacity: 0.5 }, -}; - -const transparentParentNodes: Stylesheet = { - selector: 'node.transparent:parent', - style: { - 'text-opacity': 0.5, - 'background-opacity': 0.25, - 'border-opacity': 0.5, - }, -}; - -export const nodeStyles = [ - allNodes, - focusedNodes, - affectedNodes, - parentNodes, - highlightedNodes, - transparentProjectNodes, - transparentParentNodes, - taskNodes, -]; diff --git a/graph/ui-graph/src/lib/styles-graph/palette.ts b/graph/ui-graph/src/lib/styles-graph/palette.ts deleted file mode 100644 index eef4182b29696..0000000000000 --- a/graph/ui-graph/src/lib/styles-graph/palette.ts +++ /dev/null @@ -1,22 +0,0 @@ -export enum NrwlPalette { - blue_500 = 'hsla(217, 91%, 60%, 1)', - blue_600 = 'hsla(221, 83%, 53%, 1)', - sky_500 = 'hsla(199, 89%, 48%, 1)', - sky_600 = 'hsla(200, 98%, 39%, 1)', - pink_400 = 'hsla(329, 86%, 70%, 1)', - pink_500 = 'hsla(330, 81%, 60%, 1)', - fuchsia_500 = 'hsla(292, 84%, 61%, 1)', - fuchsia_600 = 'hsla(293, 69%, 49%, 1)', - fuchsia_700 = 'hsla(295, 72%, 40%, 1)', - fuchsia_800 = 'hsla(295, 70%, 33%, 1)', - slate_50 = 'hsla(210, 40%, 98%, 1)', - slate_100 = 'hsla(210, 40%, 96%, 1)', - slate_200 = 'hsla(214, 32%, 91%, 1)', - slate_300 = 'hsla(213, 27%, 84%, 1)', - slate_400 = 'hsla(213, 27%, 84%, 1)', - slate_500 = 'hsla(215, 16%, 47%, 1)', - slate_600 = 'hsla(215, 19%, 35%, 1)', - slate_700 = 'hsla(215, 25%, 27%, 1)', - slate_800 = 'hsla(217, 33%, 17%, 1)', - white = '#fff', -} diff --git a/graph/ui-graph/src/lib/tooltip-service.ts b/graph/ui-graph/src/lib/tooltip-service.ts deleted file mode 100644 index eb32f49f6bb16..0000000000000 --- a/graph/ui-graph/src/lib/tooltip-service.ts +++ /dev/null @@ -1,103 +0,0 @@ -import { VirtualElement } from '@floating-ui/react'; -import { GraphService } from './graph'; -import { - TaskNodeTooltipProps, - ProjectNodeToolTipProps, - ProjectEdgeNodeTooltipProps, -} from '@nx/graph/ui-tooltips'; -import { TooltipEvent } from './interfaces'; -import { GraphInteractionEvents } from './graph-interaction-events'; - -export class GraphTooltipService { - private subscribers: Set = new Set(); - - constructor(graph: GraphService) { - graph.listen((event: GraphInteractionEvents) => { - switch (event.type) { - case 'GraphRegenerated': - this.hideAll(); - break; - case 'BackgroundClick': - this.hideAll(); - break; - case 'ProjectNodeClick': - this.openProjectNodeToolTip(event.ref, { - id: event.data.id, - tags: event.data.tags, - type: event.data.type, - description: event.data.description, - renderMode: graph.renderMode, - }); - break; - case 'TaskNodeClick': - this.openTaskNodeTooltip(event.ref, { - ...event.data, - renderMode: graph.renderMode, - }); - if (graph.getTaskInputs) { - graph.getTaskInputs(event.data.id).then((inputs) => { - if ( - this.currentTooltip?.type === 'taskNode' && - this.currentTooltip?.props.id === event.data.id - ) { - this.openTaskNodeTooltip(event.ref, { - ...event.data, - renderMode: graph.renderMode, - inputs, - }); - } - }); - } - break; - case 'EdgeClick': - this.openEdgeToolTip(event.ref, { - type: event.data.type, - target: event.data.target, - source: event.data.source, - fileDependencies: event.data.fileDependencies, - renderMode: graph.renderMode, - sourceRoot: event.data.sourceRoot, - }); - break; - } - }); - } - - currentTooltip: TooltipEvent; - - openProjectNodeToolTip(ref: VirtualElement, props: ProjectNodeToolTipProps) { - this.currentTooltip = { type: 'projectNode', ref, props }; - this.broadcastChange(); - } - - openTaskNodeTooltip(ref: VirtualElement, props: TaskNodeTooltipProps) { - this.currentTooltip = { type: 'taskNode', ref, props }; - this.broadcastChange(); - } - - openEdgeToolTip(ref: VirtualElement, props: ProjectEdgeNodeTooltipProps) { - this.currentTooltip = { - type: 'projectEdge', - ref, - props, - }; - this.broadcastChange(); - } - - broadcastChange() { - this.subscribers.forEach((subscriber) => subscriber(this.currentTooltip)); - } - - subscribe(callback: Function) { - this.subscribers.add(callback); - - return () => { - this.subscribers.delete(callback); - }; - } - - hideAll() { - this.currentTooltip = null; - this.broadcastChange(); - } -} diff --git a/graph/ui-graph/src/lib/util-cytoscape/cytoscape.models.ts b/graph/ui-graph/src/lib/util-cytoscape/cytoscape.models.ts deleted file mode 100644 index 64c79c899d73b..0000000000000 --- a/graph/ui-graph/src/lib/util-cytoscape/cytoscape.models.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { EdgeSingular, Position, BaseLayoutOptions } from 'cytoscape'; - -export interface CytoscapeDagreConfig extends BaseLayoutOptions { - // dagre algo options, uses default value on undefined - nodeSep: number; // the separation between adjacent nodes in the same rank - edgeSep: number; // the separation between adjacent edges in the same rank - rankSep: number; // the separation between each rank in the layout - rankDir: 'TB' | 'LR'; // 'TB' for top to bottom flow, 'LR' for left to right, - ranker: 'network-simplex' | 'tight-tree' | 'longest-path'; // Type of algorithm to assign a rank to each node in the input graph. Possible values: 'network-simplex', 'tight-tree' or 'longest-path' - minLen: (edge: EdgeSingular) => number; // number of ranks to keep between the source and target of the edge - edgeWeight: (edge: EdgeSingular) => number; // higher weight edges are generally made shorter and straighter than lower weight edges - - // general layout options - fit: boolean; // whether to fit to viewport - padding: number; // fit padding - spacingFactor: number; // Applies a multiplicative factor (>0) to expand or compress the overall area that the nodes take up - nodeDimensionsIncludeLabels: boolean; // whether labels should be included in determining the space used by a node - animate: boolean; // whether to transition the node positions - animateFilter: (node, i) => boolean; // whether to animate specific nodes when animation is on; non-animated nodes immediately go to their final positions - animationDuration: number; // duration of animation in ms if enabled - animationEasing: string; // easing of animation if enabled - boundingBox: - | { x1: number; y1: number; x2: number; y2: number } - | { x1: number; y1: number; w: number; h: number }; // constrain layout bounds; { x1, y1, x2, y2 } or { x1, y1, w, h } - transform: (node, pos) => Position; // a function that applies a transform to the final node position - ready: () => void; // on layoutready - stop: () => void; // on layoutstop -} diff --git a/graph/ui-graph/src/lib/util-cytoscape/index.ts b/graph/ui-graph/src/lib/util-cytoscape/index.ts deleted file mode 100644 index 06dade8987cfb..0000000000000 --- a/graph/ui-graph/src/lib/util-cytoscape/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from './cytoscape.models'; -export * from './project-edge'; -export * from './parent-node'; -export * from './project-node'; diff --git a/graph/ui-graph/src/lib/util-cytoscape/parent-node.ts b/graph/ui-graph/src/lib/util-cytoscape/parent-node.ts deleted file mode 100644 index f40152c73a554..0000000000000 --- a/graph/ui-graph/src/lib/util-cytoscape/parent-node.ts +++ /dev/null @@ -1,23 +0,0 @@ -import * as cy from 'cytoscape'; - -export class ParentNode { - constructor( - private config: { id: string; parentId: string; label: string } - ) {} - - getCytoscapeNodeDef(): cy.NodeDefinition & { pannable?: boolean } { - return { - group: 'nodes', - classes: 'parentNode', - data: { - id: this.config.id, - parent: this.config.parentId, - label: this.config.label, - type: 'dir', - }, - selectable: false, - grabbable: false, - pannable: true, - }; - } -} diff --git a/graph/ui-graph/src/lib/util-cytoscape/project-edge.ts b/graph/ui-graph/src/lib/util-cytoscape/project-edge.ts deleted file mode 100644 index a3e8e0a2e8e5d..0000000000000 --- a/graph/ui-graph/src/lib/util-cytoscape/project-edge.ts +++ /dev/null @@ -1,40 +0,0 @@ -/* eslint-disable @nx/enforce-module-boundaries */ -// nx-ignore-next-line -import type { ProjectGraphDependency } from '@nx/devkit'; -/* eslint-enable @nx/enforce-module-boundaries */ -import * as cy from 'cytoscape'; - -export interface ProjectEdgeDataDefinition extends cy.NodeDataDefinition { - id: string; - source: string; - target: string; - type: 'static' | 'dynamic' | 'implicit'; - sourceRoot?: string; - fileDependencies?: { fileName: string }[]; -} - -export class ProjectEdge { - affected = false; - - constructor(private dep: ProjectGraphDependency) {} - - getCytoscapeNodeDef(): cy.EdgeDefinition { - let edge: cy.EdgeDefinition; - edge = { - group: 'edges', - classes: 'projectEdge', - data: { - id: `${this.dep.source}|${this.dep.target}`, - source: this.dep.source, - target: this.dep.target, - type: this.dep.type, - }, - }; - edge.classes += ` ${this.dep.type}` ?? ''; - if (this.affected) { - edge.classes += ' affected'; - } - - return edge; - } -} diff --git a/graph/ui-graph/src/lib/util-cytoscape/project-node.spec.ts b/graph/ui-graph/src/lib/util-cytoscape/project-node.spec.ts deleted file mode 100644 index ef3fc8b304753..0000000000000 --- a/graph/ui-graph/src/lib/util-cytoscape/project-node.spec.ts +++ /dev/null @@ -1,130 +0,0 @@ -import { ProjectNode } from './project-node'; - -describe('ProjectNode', () => { - describe('app nodes', () => { - it('should not set parentId if groupByFolder is false', () => { - const projectNode = new ProjectNode( - {}, - { - name: 'sub-app', - type: 'app', - data: { - projectType: 'application', - root: 'apps/sub/app', - sourceRoot: 'apps/sub/app/src', - tags: [], - }, - }, - 'apps' - ); - - const result = projectNode.getCytoscapeNodeDef(false); - - expect(result.data.parent).toBeNull(); - }); - - it('should not set parentId if app is not nested', () => { - const projectNode = new ProjectNode( - {}, - { - name: 'app', - type: 'app', - data: { - projectType: 'application', - root: 'apps/app', - sourceRoot: 'apps/app/src', - tags: [], - }, - }, - 'apps' - ); - - const result = projectNode.getCytoscapeNodeDef(false); - - expect(result.data.parent).toBeNull(); - }); - - it('should set parentId if the app is nested and groupByFolder is true', () => { - const projectNode = new ProjectNode( - {}, - { - name: 'sub-app', - type: 'app', - data: { - projectType: 'application', - root: 'apps/sub/app', - sourceRoot: 'apps/sub/app/src', - tags: [], - }, - }, - 'apps' - ); - - const result = projectNode.getCytoscapeNodeDef(true); - - expect(result.data.parent).toEqual('dir-sub'); - }); - }); - - describe('lib nodes', () => { - it('should not set parentId if groupByFolder is false', () => { - const projectNode = new ProjectNode( - {}, - { - name: 'sub-lib', - type: 'lib', - data: { - root: 'libs/sub/lib', - sourceRoot: 'libs/sub/lib/src', - projectType: 'library', - }, - }, - 'libs' - ); - - const result = projectNode.getCytoscapeNodeDef(false); - - expect(result.data.parent).toBeNull(); - }); - - it('should not set parentId if lib is not nested', () => { - const projectNode = new ProjectNode( - {}, - { - name: 'lib', - type: 'lib', - data: { - root: 'libs/lib', - sourceRoot: 'libs/lib/src', - projectType: 'library', - }, - }, - 'libs' - ); - - const result = projectNode.getCytoscapeNodeDef(false); - - expect(result.data.parent).toBeNull(); - }); - - it('should set parentId if the lib is nested and groupByFolder is true', () => { - const projectNode = new ProjectNode( - {}, - { - name: 'sub-lib', - type: 'lib', - data: { - root: 'libs/sub/lib', - sourceRoot: 'libs/sub/lib/src', - projectType: 'library', - }, - }, - 'libs' - ); - - const result = projectNode.getCytoscapeNodeDef(true); - - expect(result.data.parent).toEqual('dir-sub'); - }); - }); -}); diff --git a/graph/ui-graph/src/lib/util-cytoscape/project-node.ts b/graph/ui-graph/src/lib/util-cytoscape/project-node.ts deleted file mode 100644 index fa2dee9b58b40..0000000000000 --- a/graph/ui-graph/src/lib/util-cytoscape/project-node.ts +++ /dev/null @@ -1,105 +0,0 @@ -/* eslint-disable @nx/enforce-module-boundaries */ -// nx-ignore-next-line -import type { ProjectFileMap, ProjectGraphProjectNode } from '@nx/devkit'; -/* eslint-enable @nx/enforce-module-boundaries */ -import * as cy from 'cytoscape'; -import { parseParentDirectoriesFromFilePath } from '../util'; - -export interface ProjectNodeDataDefinition extends cy.NodeDataDefinition { - id: string; - type: 'app' | 'lib' | 'e2e'; - tags: string[]; - - description?: string; -} - -export interface Ancestor { - id: string; - parentId: string; - label: string; -} - -export class ProjectNode { - affected = false; - focused = false; - - constructor( - private fileMap: ProjectFileMap, - private project: ProjectGraphProjectNode, - private workspaceRoot: string - ) {} - - getCytoscapeNodeDef( - groupByFolder: boolean - ): cy.NodeDefinition & { pannable: boolean } { - return { - group: 'nodes', - data: this.getData(groupByFolder), - classes: this.getClasses(), - selectable: false, - grabbable: false, - pannable: true, - }; - } - - private getData(groupByFolder: boolean): ProjectNodeDataDefinition { - return { - id: this.project.name, - type: this.project.type, - tags: this.project.data.tags, - parent: - groupByFolder && this.project.data.hasOwnProperty('root') - ? this.getParentId() - : null, - files: (this.fileMap || {})[this.project.data.name] || [], - root: this.project.data.root, - description: this.project.data.description, - }; - } - - private getClasses(): string { - let classes = `projectNode ${this.project.type}`; - - if (this.affected) { - classes += ' affected'; - } - - return classes; - } - - private getParentId(): string | null { - const ancestors = this.getAncestors(); - - if (ancestors.length > 0) { - return ancestors[ancestors.length - 1].id; - } else { - return null; - } - } - - public getAncestors(): Ancestor[] { - // if there's no root, we can't figure out the parent - if (!this.project.data.root) { - return []; - } - - const directories = parseParentDirectoriesFromFilePath( - this.project.data.root, - this.workspaceRoot - ); - - return directories.map((directory, index, allDirectories) => { - const label = [...allDirectories].slice(0, index + 1).join('/'); - const id = `dir-${label}`; - const parentId = - index > 0 - ? `dir-${[...allDirectories].slice(0, index).join('/')}` - : null; - return { - label, - id, - parentId, - }; - }); - } -} diff --git a/graph/ui-graph/src/lib/util-cytoscape/project-traversal-graph.ts b/graph/ui-graph/src/lib/util-cytoscape/project-traversal-graph.ts deleted file mode 100644 index acacf2b31fa40..0000000000000 --- a/graph/ui-graph/src/lib/util-cytoscape/project-traversal-graph.ts +++ /dev/null @@ -1,346 +0,0 @@ -import cytoscape, { - CollectionReturnValue, - Core, - ElementDefinition, - NodeCollection, - NodeSingular, -} from 'cytoscape'; - -/* eslint-disable @nx/enforce-module-boundaries */ -// nx-ignore-next-line -import { - ProjectFileMap, - ProjectGraphDependency, - ProjectGraphProjectNode, -} from 'nx/src/config/project-graph'; -/* eslint-enable @nx/enforce-module-boundaries */ -import { ProjectNode } from './project-node'; -import { ProjectEdge } from './project-edge'; -import { ParentNode } from './parent-node'; - -export class ProjectTraversalGraph { - private cy?: Core; - - setShownProjects(selectedProjectNames: string[]) { - let nodesToAdd = this.cy.collection(); - - selectedProjectNames.forEach((name) => { - nodesToAdd = nodesToAdd.union(this.cy.$id(name)); - }); - - const ancestorsToAdd = nodesToAdd.ancestors(); - - const nodesToRender = nodesToAdd.union(ancestorsToAdd); - const edgesToRender = nodesToRender.edgesTo(nodesToRender); - - return nodesToRender.union(edgesToRender); - } - - showProjects(selectedProjectNames: string[], alreadyShownProjects: string[]) { - let nodesToAdd = this.cy.collection(); - - selectedProjectNames.forEach((name) => { - nodesToAdd = nodesToAdd.union(this.cy.$id(name)); - }); - - alreadyShownProjects.forEach((name) => { - nodesToAdd = nodesToAdd.union(this.cy.$id(name)); - }); - - const ancestorsToAdd = nodesToAdd.ancestors(); - - const nodesToRender = nodesToAdd.union(ancestorsToAdd); - const edgesToRender = nodesToRender.edgesTo(nodesToRender); - - return nodesToRender.union(edgesToRender); - } - - hideProjects(projectNames: string[], alreadyShownProjects: string[]) { - let currentNodes = this.cy.collection(); - alreadyShownProjects.forEach((name) => { - currentNodes = currentNodes.union(this.cy.$id(name)); - }); - let nodesToHide = this.cy.collection(); - - projectNames.forEach((projectName) => { - nodesToHide = nodesToHide.union(this.cy.$id(projectName)); - }); - - const nodesToAdd = currentNodes - .difference(nodesToHide) - .difference(nodesToHide.ancestors()); - const ancestorsToAdd = nodesToAdd.ancestors(); - - let nodesToRender = nodesToAdd.union(ancestorsToAdd); - - const edgesToRender = nodesToRender.edgesTo(nodesToRender); - - return nodesToRender.union(edgesToRender); - } - - showAffectedProjects() { - const affectedProjects = this.cy.nodes('.affected'); - const affectedAncestors = affectedProjects.ancestors(); - - const affectedNodes = affectedProjects.union(affectedAncestors); - const affectedEdges = affectedNodes.edgesTo(affectedNodes); - - return affectedNodes.union(affectedEdges); - } - - focusProject(focusedProjectName: string, searchDepth: number = 1) { - const focusedProject = this.cy.$id(focusedProjectName); - - const includedProjects = this.includeProjectsByDepth( - focusedProject, - searchDepth - ); - - const includedNodes = focusedProject.union(includedProjects); - - const includedAncestors = includedNodes.ancestors(); - - const nodesToRender = includedNodes.union(includedAncestors); - const edgesToRender = nodesToRender.edgesTo(nodesToRender); - - return nodesToRender.union(edgesToRender); - } - - showAllProjects() { - return this.cy.elements(); - } - - hideAllProjects() { - return this.cy.collection(); - } - - filterProjectsByText( - search: string, - includePath: boolean, - searchDepth: number = -1 - ) { - if (search === '') { - return this.cy.collection(); - } else { - const split = search.split(','); - - let filteredProjects = this.cy.nodes().filter((node) => { - return ( - split.findIndex((splitItem) => node.id().includes(splitItem)) > -1 - ); - }); - - if (includePath) { - filteredProjects = filteredProjects.union( - this.includeProjectsByDepth(filteredProjects, searchDepth) - ); - } - - filteredProjects = filteredProjects.union(filteredProjects.ancestors()); - const edgesToRender = filteredProjects.edgesTo(filteredProjects); - - return filteredProjects.union(edgesToRender); - } - } - - traceProjects(start: string, end: string) { - const dijkstra = this.cy - .elements() - .dijkstra({ root: `[id = "${start}"]`, directed: true }); - - const path = dijkstra.pathTo(this.cy.$(`[id = "${end}"]`)); - - return path.union(path.ancestors()); - } - - traceAllProjects(start: string, end: string) { - const startNode = this.cy.$id(start).nodes().first(); - - const queue: NodeSingular[][] = [[startNode]]; - - const paths: NodeSingular[][] = []; - let iterations = 0; - - while (queue.length > 0 && iterations <= 1000) { - const currentPath = queue.pop(); - - const nodeToTest = currentPath[currentPath.length - 1]; - - const outgoers = nodeToTest.outgoers('node'); - - if (outgoers.length > 0) { - outgoers.forEach((outgoer) => { - const newPath = [...currentPath, outgoer]; - if (outgoer.id() === end) { - paths.push(newPath); - } else { - queue.push(newPath); - } - }); - } - - iterations++; - } - - if (iterations >= 1000) { - console.log('failsafe triggered!'); - } - - let finalCollection = this.cy.collection(); - - paths.forEach((path) => { - for (let i = 0; i < path.length; i++) { - finalCollection = finalCollection.union(path[i]); - - const nextIndex = i + 1; - if (nextIndex < path.length) { - finalCollection = finalCollection.union( - path[i].edgesTo(path[nextIndex]) - ); - } - } - }); - - return finalCollection.union(finalCollection.ancestors()); - } - - private includeProjectsByDepth( - projects: NodeCollection | NodeSingular, - depth: number = -1 - ) { - let predecessors: CollectionReturnValue; - - if (depth === -1) { - predecessors = projects.predecessors(); - } else { - predecessors = projects.incomers(); - - for (let i = 1; i < depth; i++) { - predecessors = predecessors.union(predecessors.incomers()); - } - } - - let successors: CollectionReturnValue; - - if (depth === -1) { - successors = projects.successors(); - } else { - successors = projects.outgoers(); - - for (let i = 1; i < depth; i++) { - successors = successors.union(successors.outgoers()); - } - } - - return projects.union(predecessors).union(successors); - } - - initGraph( - fileMap: ProjectFileMap, - allProjects: ProjectGraphProjectNode[], - groupByFolder: boolean, - workspaceLayout, - dependencies: Record, - affectedProjectIds: string[], - collapseEdges: boolean - ) { - this.generateCytoscapeLayout( - fileMap, - allProjects, - groupByFolder, - workspaceLayout, - dependencies, - affectedProjectIds - ); - } - - private generateCytoscapeLayout( - fileMap: ProjectFileMap, - allProjects: ProjectGraphProjectNode[], - groupByFolder: boolean, - workspaceLayout, - dependencies: Record, - affectedProjectIds: string[] - ) { - const elements = this.createElements( - fileMap, - allProjects, - groupByFolder, - workspaceLayout, - dependencies, - affectedProjectIds - ); - - this.cy = cytoscape({ - headless: true, - elements: [...elements], - boxSelectionEnabled: false, - }); - } - - private createElements( - fileMap: ProjectFileMap, - projects: ProjectGraphProjectNode[], - groupByFolder: boolean, - workspaceLayout: { - appsDir: string; - libsDir: string; - }, - dependencies: Record, - affectedProjectIds: string[] - ) { - let elements: ElementDefinition[] = []; - const filteredProjectNames = projects.map((project) => project.name); - - const projectNodes: ProjectNode[] = []; - const edgeNodes: ProjectEdge[] = []; - const parents: Record< - string, - { id: string; parentId: string; label: string } - > = {}; - - projects.forEach((project) => { - const workspaceRoot = - project.type === 'app' || project.type === 'e2e' - ? workspaceLayout.appsDir - : workspaceLayout.libsDir; - - const projectNode = new ProjectNode(fileMap, project, workspaceRoot); - - projectNode.affected = affectedProjectIds.includes(project.name); - - projectNodes.push(projectNode); - dependencies[project.name].forEach((dep) => { - if (filteredProjectNames.includes(dep.target)) { - const edge = new ProjectEdge(dep); - edgeNodes.push(edge); - } - }); - - if (groupByFolder) { - const ancestors = projectNode.getAncestors(); - ancestors.forEach((ancestor) => (parents[ancestor.id] = ancestor)); - } - }); - - const projectElements: (ElementDefinition & { pannable?: boolean })[] = - projectNodes.map((projectNode) => - projectNode.getCytoscapeNodeDef(groupByFolder) - ); - - const edgeElements = edgeNodes.map((edgeNode) => - edgeNode.getCytoscapeNodeDef() - ); - - elements = projectElements.concat(edgeElements); - - if (groupByFolder) { - const parentElements = Object.keys(parents).map((id) => - new ParentNode(parents[id]).getCytoscapeNodeDef() - ); - elements = parentElements.concat(elements); - } - - return elements; - } -} diff --git a/graph/ui-graph/src/lib/util-cytoscape/render-graph.ts b/graph/ui-graph/src/lib/util-cytoscape/render-graph.ts deleted file mode 100644 index 118f4a7af8e41..0000000000000 --- a/graph/ui-graph/src/lib/util-cytoscape/render-graph.ts +++ /dev/null @@ -1,356 +0,0 @@ -import cytoscape, { - Collection, - Core, - EdgeDefinition, - EdgeSingular, -} from 'cytoscape'; -import { edgeStyles, nodeStyles } from '../styles-graph'; -import { GraphInteractionEvents } from '../graph-interaction-events'; -import { VirtualElement } from '@floating-ui/react'; -import { - darkModeScratchKey, - switchValueByDarkMode, -} from '../styles-graph/dark-mode'; -import { CytoscapeDagreConfig } from './cytoscape.models'; - -const cytoscapeDagreConfig = { - name: 'dagre', - nodeDimensionsIncludeLabels: true, - rankSep: 75, - rankDir: 'TB', - edgeSep: 50, - ranker: 'network-simplex', -} as CytoscapeDagreConfig; - -export class RenderGraph { - private cy?: Core; - collapseEdges = false; - - private _theme: 'light' | 'dark'; - private _rankDir: 'TB' | 'LR' = 'TB'; - - private listeners = new Map< - number, - (event: GraphInteractionEvents) => void - >(); - - constructor( - private container: string | HTMLElement, - theme: 'light' | 'dark', - private renderMode?: 'nx-console' | 'nx-docs', - rankDir: 'TB' | 'LR' = 'TB' - ) { - this._theme = theme; - this._rankDir = rankDir; - } - - set theme(theme: 'light' | 'dark') { - this._theme = theme; - this.render(); - } - - set rankDir(rankDir: 'LR' | 'TB') { - this._rankDir = rankDir; - this.render(); - } - - get activeContainer() { - return typeof this.container === 'string' - ? document.getElementById(this.container) - : this.container; - } - - private broadcast(event: GraphInteractionEvents) { - this.listeners.forEach((callback) => callback(event)); - } - - listen(callback: (event: GraphInteractionEvents) => void) { - const listenerId = this.listeners.size + 1; - this.listeners.set(listenerId, callback); - - return () => { - this.listeners.delete(listenerId); - }; - } - - setElements(elements: Collection) { - let currentFocusedProjectName; - if (this.cy) { - currentFocusedProjectName = this.cy.nodes('.focused').first().id(); - this.cy.destroy(); - delete this.cy; - } - - this.cy = cytoscape({ - headless: this.activeContainer === null, - container: this.activeContainer, - boxSelectionEnabled: false, - style: [...nodeStyles, ...edgeStyles], - panningEnabled: true, - userZoomingEnabled: this.renderMode !== 'nx-docs', - }); - - this.cy.add(elements); - - if (!!currentFocusedProjectName) { - this.cy.$id(currentFocusedProjectName).addClass('focused'); - } - - this.cy.on('zoom pan', () => { - this.broadcast({ type: 'GraphRegenerated' }); - }); - - this.listenForProjectNodeClicks(); - this.listenForEdgeNodeClicks(); - this.listenForProjectNodeHovers(); - this.listenForTaskNodeClicks(); - this.listenForEmptyClicks(); - } - - render(): { numEdges: number; numNodes: number } { - if (this.cy) { - const elements = this.cy.elements().sort((a, b) => { - return a.id().localeCompare(b.id()); - }); - - elements - .layout({ - ...cytoscapeDagreConfig, - ...{ rankDir: this._rankDir }, - }) - .run(); - - if (this.collapseEdges) { - this.cy.remove(this.cy.edges()); - - elements.edges().forEach((edge) => { - const sourceNode = edge.source(); - const targetNode = edge.target(); - - if ( - sourceNode.parent().first().id() === - targetNode.parent().first().id() - ) { - this.cy.add(edge); - } else { - let sourceAncestors, targetAncestors; - const commonAncestors = edge.connectedNodes().commonAncestors(); - - if (commonAncestors.length > 0) { - sourceAncestors = sourceNode - .ancestors() - .filter((anc) => !commonAncestors.contains(anc)); - targetAncestors = targetNode - .ancestors() - .filter((anc) => !commonAncestors.contains(anc)); - } else { - sourceAncestors = sourceNode.ancestors(); - targetAncestors = targetNode.ancestors(); - } - - let sourceId, targetId; - - if (sourceAncestors.length > 0 && targetAncestors.length === 0) { - sourceId = sourceAncestors.last().id(); - targetId = targetNode.id(); - } else if ( - targetAncestors.length > 0 && - sourceAncestors.length === 0 - ) { - sourceId = sourceNode.id(); - targetId = targetAncestors.last().id(); - } else { - sourceId = sourceAncestors.last().id(); - targetId = targetAncestors.last().id(); - } - - if (sourceId !== undefined && targetId !== undefined) { - const edgeId = `${sourceId}|${targetId}`; - - if (this.cy.$id(edgeId).length === 0) { - const ancestorEdge: EdgeDefinition = { - group: 'edges', - data: { - id: edgeId, - source: sourceId, - target: targetId, - }, - }; - - this.cy.add(ancestorEdge); - } - } else { - console.log(`Couldn't figure out how to draw edge ${edge.id()}`); - console.log( - 'source ancestors', - sourceAncestors.map((anc) => anc.id()) - ); - console.log( - 'target ancestors', - targetAncestors.map((anc) => anc.id()) - ); - } - } - }); - } - - if (this.renderMode === 'nx-console') { - // when in the nx-console environment, adjust graph width and position to be to right of floating panel - // 175 is a magic number that represents the width of the floating panels divided in half plus some padding - this.cy - .fit(this.cy.elements(), 175) - .center() - .resize() - .panBy({ x: 150, y: 0 }); - } else { - this.cy.fit(this.cy.elements(), 25).center().resize(); - } - - this.cy.scratch(darkModeScratchKey, this._theme === 'dark'); - this.cy.elements().scratch(darkModeScratchKey, this._theme === 'dark'); - - this.cy.mount(this.activeContainer); - } - - return { - numNodes: this.cy?.nodes().length ?? 0, - numEdges: this.cy?.edges().length ?? 0, - }; - } - - private listenForProjectNodeClicks() { - this.cy.$('node.projectNode').on('click', (event) => { - const node = event.target; - - let ref: VirtualElement = node.popperRef(); // used only for positioning - this.broadcast({ - type: 'ProjectNodeClick', - ref, - id: node.id(), - data: { - id: node.id(), - type: node.data('type'), - tags: node.data('tags'), - description: node.data('description'), - }, - }); - }); - } - - private listenForTaskNodeClicks() { - this.cy.$('node.taskNode').on('click', (event) => { - const node = event.target; - - let ref: VirtualElement = node.popperRef(); // used only for positioning - - this.broadcast({ - type: 'TaskNodeClick', - ref, - id: node.id(), - data: { - id: node.id(), - label: node.data('label'), - executor: node.data('executor'), - description: node.data('description'), - }, - }); - }); - } - - private listenForEdgeNodeClicks() { - this.cy.$('edge.projectEdge').on('click', (event) => { - const edge: EdgeSingular & { popperRef: () => VirtualElement } = - event.target; - let ref: VirtualElement = edge.popperRef(); // used only for positioning - - this.broadcast({ - type: 'EdgeClick', - ref, - id: edge.id(), - data: { - id: edge.id(), - type: edge.data('type'), - source: edge.source().id(), - target: edge.target().id(), - sourceRoot: edge.source().data('root'), - fileDependencies: - edge - .source() - .data('files') - ?.filter( - (file) => - file.deps && - file.deps.find( - (d) => - (typeof d === 'string' ? d : d[0]) === edge.target().id() - ) - ) - .map((file) => { - return { - fileName: file.file.replace( - `${edge.source().data('root')}/`, - '' - ), - target: edge.target().id(), - }; - }) || [], - }, - }); - }); - } - - private listenForProjectNodeHovers(): void { - this.cy.on('mouseover', (event) => { - const node = event.target; - if (!node.isNode || !node.isNode() || node.isParent()) return; - - this.cy - .elements() - .difference(node.outgoers().union(node.incomers())) - .not(node) - .addClass('transparent'); - node - .addClass('highlight') - .outgoers() - .union(node.incomers()) - .addClass('highlight'); - }); - - this.cy.on('mouseout', (event) => { - const node = event.target; - if (!node.isNode || !node.isNode() || node.isParent()) return; - - this.cy.elements().removeClass('transparent'); - node - .removeClass('highlight') - .outgoers() - .union(node.incomers()) - .removeClass('highlight'); - }); - } - - private listenForEmptyClicks(): void { - this.cy.on('click', (event) => { - if (event.target === this.cy) { - this.broadcast({ type: 'BackgroundClick' }); - } - }); - } - - getImage() { - const bg = switchValueByDarkMode(this.cy, '#0F172A', '#FFFFFF'); - return this.cy.png({ bg, full: true }); - } - - setFocussedElement(id: string) { - this.cy.$id(id).addClass('focused'); - } - - clearFocussedElement() { - this.cy?.nodes('.focused').removeClass('focused'); - } - - getCurrentlyShownProjectIds(): string[] { - return this.cy?.nodes().map((node) => node.data('id')) ?? []; - } -} diff --git a/graph/ui-graph/src/lib/util-cytoscape/task-edge.ts b/graph/ui-graph/src/lib/util-cytoscape/task-edge.ts deleted file mode 100644 index 4c3792bc3f528..0000000000000 --- a/graph/ui-graph/src/lib/util-cytoscape/task-edge.ts +++ /dev/null @@ -1,25 +0,0 @@ -import * as cy from 'cytoscape'; - -export interface TaskEdgeDataDefinition extends cy.NodeDataDefinition { - id: string; - source: string; - target: string; -} - -export class TaskEdge { - constructor(private source: string, private target: string) {} - - getCytoscapeNodeDef(): cy.NodeDefinition { - let edge: cy.EdgeDefinition; - edge = { - group: 'edges', - data: { - id: `${this.source}|${this.target}`, - source: this.source, - target: this.target, - }, - }; - - return edge; - } -} diff --git a/graph/ui-graph/src/lib/util-cytoscape/task-node.ts b/graph/ui-graph/src/lib/util-cytoscape/task-node.ts deleted file mode 100644 index 4e3543527ef42..0000000000000 --- a/graph/ui-graph/src/lib/util-cytoscape/task-node.ts +++ /dev/null @@ -1,42 +0,0 @@ -/* eslint-disable @nx/enforce-module-boundaries */ -// nx-ignore-next-line -import type { ProjectGraphProjectNode, Task } from '@nx/devkit'; -/* eslint-enable @nx/enforce-module-boundaries */ -import * as cy from 'cytoscape'; - -export interface TaskNodeDataDefinition extends cy.NodeDataDefinition { - id: string; - label: string; - executor: string; - description?: string; -} - -export class TaskNode { - constructor(private task: Task, private project: ProjectGraphProjectNode) {} - - getCytoscapeNodeDef( - groupByProject: boolean - ): cy.NodeDefinition & { pannable: boolean } { - return { - group: 'nodes', - classes: 'taskNode', - data: this.getData(groupByProject), - selectable: false, - grabbable: false, - pannable: true, - }; - } - - private getData(groupByProject: boolean): TaskNodeDataDefinition { - const label = groupByProject - ? this.task.id.split(':').slice(1).join(':') - : this.task.id; - return { - id: this.task.id, - label, - executor: this.project.data.targets[this.task.target.target].executor, - parent: groupByProject ? this.task.target.project : null, - description: this.project.data.description, - }; - } -} diff --git a/graph/ui-graph/src/lib/util-cytoscape/task-traversal.graph.ts b/graph/ui-graph/src/lib/util-cytoscape/task-traversal.graph.ts deleted file mode 100644 index a89f602f8fd66..0000000000000 --- a/graph/ui-graph/src/lib/util-cytoscape/task-traversal.graph.ts +++ /dev/null @@ -1,135 +0,0 @@ -/* eslint-disable @nx/enforce-module-boundaries */ -// nx-ignore-next-line -import type { ProjectGraphProjectNode } from '@nx/devkit'; -/* eslint-enable @nx/enforce-module-boundaries */ -import { TaskGraphRecord } from '../interfaces'; -import { TaskNode } from './task-node'; -import { TaskEdge } from './task-edge'; -import cytoscape, { Core } from 'cytoscape'; -import { ParentNode } from './parent-node'; - -export class TaskTraversalGraph { - private projects: ProjectGraphProjectNode[] = []; - private taskGraphs: TaskGraphRecord = {}; - private cy: Core; - private groupByProject: boolean = false; - private selectedTasks = new Set(); - - setProjects( - projects: ProjectGraphProjectNode[], - taskGraphs: TaskGraphRecord - ) { - this.selectedTasks.clear(); - this.projects = projects; - this.taskGraphs = taskGraphs; - } - - setGroupByProject(groupByProject: boolean) { - this.groupByProject = groupByProject; - - if (this.selectedTasks.size > 0) { - this.createElements(Array.from(this.selectedTasks), groupByProject); - } else { - this.cy = cytoscape({ - headless: true, - elements: [], - }); - } - - return this.cy.elements(); - } - - setTasks(taskIds: string[]) { - let changed = false; - this.selectedTasks.forEach((selectedTask) => { - if (!taskIds.includes(selectedTask)) { - this.selectedTasks.delete(selectedTask); - changed = true; - } - }); - for (const taskId of taskIds) { - if (!this.selectedTasks.has(taskId)) { - this.selectedTasks.add(taskId); - changed = true; - } - } - if (changed) { - this.createElements(Array.from(this.selectedTasks), this.groupByProject); - } - return this.cy.elements(); - } - - selectTask(taskIds: string[]) { - taskIds.forEach((taskId) => { - this.selectedTasks.add(taskId); - }); - this.createElements(Array.from(this.selectedTasks), this.groupByProject); - - return this.cy.elements(); - } - - deselectTask(taskIds: string[]) { - taskIds.forEach((taskId) => { - this.selectedTasks.delete(taskId); - }); - this.createElements(Array.from(this.selectedTasks), this.groupByProject); - - return this.cy.elements(); - } - - private createElements(taskIds: string[], groupByFolder: boolean) { - const taskElements = []; - - taskIds.forEach((taskId) => { - const taskGraph = this.taskGraphs[taskId]; - - if (taskGraph === undefined) { - throw new Error(`Could not find task graph for ${taskId}`); - } - - const parents: Record< - string, - { id: string; parentId: string; label: string } - > = {}; - - for (let taskName in taskGraph.tasks) { - const task = taskGraph.tasks[taskName]; - const project = this.projects.find( - (project) => project.name === task.target.project - ); - - if (project === undefined) { - throw new Error(`Could not find project ${project.name}`); - } - - taskElements.push(new TaskNode(taskGraph.tasks[taskName], project)); - - if (groupByFolder) { - parents[project.name] = { - id: project.name, - parentId: null, - label: project.name, - }; - } - } - - for (let parent in parents) { - taskElements.push(new ParentNode(parents[parent])); - } - - for (let topDep in taskGraph.dependencies) { - taskGraph.dependencies[topDep].forEach((childDep) => - taskElements.push(new TaskEdge(topDep, childDep)) - ); - } - }); - - this.cy = cytoscape({ - headless: true, - elements: taskElements.map((element) => - element.getCytoscapeNodeDef(groupByFolder) - ), - boxSelectionEnabled: false, - }); - } -} diff --git a/graph/ui-graph/src/lib/util.ts b/graph/ui-graph/src/lib/util.ts deleted file mode 100644 index c1aea409c0595..0000000000000 --- a/graph/ui-graph/src/lib/util.ts +++ /dev/null @@ -1,52 +0,0 @@ -/* eslint-disable @nx/enforce-module-boundaries */ -// nx-ignore-next-line -import { ProjectGraphDependency } from '@nx/devkit'; -/* eslint-enable @nx/enforce-module-boundaries */ - -export function trimBackSlash(value: string): string { - return value.replace(/\/$/, ''); -} - -export function parseParentDirectoriesFromFilePath( - path: string, - workspaceRoot: string -) { - const directories = path - .replace(workspaceRoot, '') - .split('/') - .filter((directory) => directory !== ''); - // last directory is the project - directories.pop(); - return directories; -} - -export function hasPath( - dependencies: Record, - target: string, - node: string, - visited: string[], - currentSearchDepth: number, - maxSearchDepth: number = -1 // -1 indicates unlimited search depth -) { - if (target === node) return true; - - if (maxSearchDepth === -1 || currentSearchDepth <= maxSearchDepth) { - for (let d of dependencies[node] || []) { - if (visited.indexOf(d.target) > -1) continue; - visited.push(d.target); - if ( - hasPath( - dependencies, - target, - d.target, - visited, - currentSearchDepth + 1, - maxSearchDepth - ) - ) - return true; - } - } - - return false; -} diff --git a/graph/ui-graph/tailwind.config.js b/graph/ui-graph/tailwind.config.js deleted file mode 100644 index a130bfceccd48..0000000000000 --- a/graph/ui-graph/tailwind.config.js +++ /dev/null @@ -1,40 +0,0 @@ -const path = require('path'); - -// nx-ignore-next-line -const { createGlobPatternsForDependencies } = require('@nx/react/tailwind'); - -module.exports = { - content: [ - path.join(__dirname, 'src/**/*.{js,ts,jsx,tsx,html}'), - ...createGlobPatternsForDependencies(__dirname), - ], - darkMode: 'class', // or 'media' or 'class' - theme: { - extend: { - typography: { - DEFAULT: { - css: { - 'code::before': { - content: '', - }, - 'code::after': { - content: '', - }, - 'blockquote p:first-of-type::before': { - content: '', - }, - 'blockquote p:last-of-type::after': { - content: '', - }, - }, - }, - }, - }, - }, - variants: { - extend: { - translate: ['group-hover'], - }, - }, - plugins: [require('@tailwindcss/typography')], -}; diff --git a/graph/ui-graph/tsconfig.json b/graph/ui-graph/tsconfig.json deleted file mode 100644 index 37317ac3a7b0d..0000000000000 --- a/graph/ui-graph/tsconfig.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "compilerOptions": { - "jsx": "react-jsx", - "allowSyntheticDefaultImports": true - }, - "files": [], - "include": [], - "references": [ - { - "path": "./tsconfig.lib.json" - }, - { - "path": "./tsconfig.spec.json" - }, - { - "path": "./tsconfig.storybook.json" - } - ] -} diff --git a/graph/ui-graph/tsconfig.lib.json b/graph/ui-graph/tsconfig.lib.json deleted file mode 100644 index 6739bf0096eae..0000000000000 --- a/graph/ui-graph/tsconfig.lib.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "types": ["node"], - "lib": ["DOM", "es2019"] - }, - "files": [ - "../../node_modules/@nx/react/typings/cssmodule.d.ts", - "../../node_modules/@nx/react/typings/image.d.ts" - ], - "exclude": [ - "jest.config.ts", - "**/*.spec.ts", - "**/*.test.ts", - "**/*.spec.tsx", - "**/*.test.tsx", - "**/*.spec.js", - "**/*.test.js", - "**/*.spec.jsx", - "**/*.test.jsx", - "**/*.stories.ts", - "**/*.stories.js", - "**/*.stories.jsx", - "**/*.stories.tsx" - ], - "include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"] -} diff --git a/graph/ui-graph/tsconfig.spec.json b/graph/ui-graph/tsconfig.spec.json deleted file mode 100644 index ff08addd60ff5..0000000000000 --- a/graph/ui-graph/tsconfig.spec.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "module": "commonjs", - "types": ["jest", "node"] - }, - "include": [ - "jest.config.ts", - "**/*.test.ts", - "**/*.spec.ts", - "**/*.test.tsx", - "**/*.spec.tsx", - "**/*.test.js", - "**/*.spec.js", - "**/*.test.jsx", - "**/*.spec.jsx", - "**/*.d.ts" - ] -} diff --git a/graph/ui-graph/tsconfig.storybook.json b/graph/ui-graph/tsconfig.storybook.json deleted file mode 100644 index 98ee6645c6232..0000000000000 --- a/graph/ui-graph/tsconfig.storybook.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "emitDecoratorMetadata": true, - "outDir": "" - }, - "files": [ - "../../node_modules/@nx/react/typings/styled-jsx.d.ts", - "../../node_modules/@nx/react/typings/cssmodule.d.ts", - "../../node_modules/@nx/react/typings/image.d.ts" - ], - "exclude": [ - "src/**/*.spec.ts", - "src/**/*.spec.js", - "src/**/*.spec.tsx", - "src/**/*.spec.jsx" - ], - "include": [ - "src/**/*.stories.ts", - "src/**/*.stories.js", - "src/**/*.stories.jsx", - "src/**/*.stories.tsx", - "src/**/*.stories.mdx", - ".storybook/*.js" - ] -} diff --git a/graph/ui-icons/.babelrc b/graph/ui-icons/.babelrc deleted file mode 100644 index 1ea870ead410c..0000000000000 --- a/graph/ui-icons/.babelrc +++ /dev/null @@ -1,12 +0,0 @@ -{ - "presets": [ - [ - "@nx/react/babel", - { - "runtime": "automatic", - "useBuiltIns": "usage" - } - ] - ], - "plugins": [] -} diff --git a/graph/ui-icons/.eslintrc.json b/graph/ui-icons/.eslintrc.json deleted file mode 100644 index b96a5b888e9c0..0000000000000 --- a/graph/ui-icons/.eslintrc.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "extends": ["plugin:@nx/react", "../../.eslintrc.json"], - "ignorePatterns": ["!**/*", "storybook-static"], - "overrides": [ - { - "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], - "rules": {} - }, - { - "files": ["*.ts", "*.tsx"], - "rules": {} - }, - { - "files": ["*.js", "*.jsx"], - "rules": {} - } - ] -} diff --git a/graph/ui-icons/.storybook/main.ts b/graph/ui-icons/.storybook/main.ts deleted file mode 100644 index dfca18212214d..0000000000000 --- a/graph/ui-icons/.storybook/main.ts +++ /dev/null @@ -1,21 +0,0 @@ -/* eslint-disable @nx/enforce-module-boundaries */ -import type { StorybookConfig } from '@storybook/react-vite'; -import { mergeConfig } from 'vite'; -// nx-ignore-next-line -import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin'; - -const config: StorybookConfig = { - stories: ['../src/lib/**/*.stories.@(js|jsx|ts|tsx|mdx)'], - addons: ['@storybook/addon-essentials', '@storybook/addon-interactions'], - framework: { - name: '@storybook/react-vite', - options: {}, - }, - - viteFinal: async (config) => - mergeConfig(config, { - plugins: [nxViteTsPaths()], - }), -}; - -export default config; diff --git a/graph/ui-icons/.storybook/preview.ts b/graph/ui-icons/.storybook/preview.ts deleted file mode 100644 index 195b052493edc..0000000000000 --- a/graph/ui-icons/.storybook/preview.ts +++ /dev/null @@ -1 +0,0 @@ -import './tailwind.css'; diff --git a/graph/ui-icons/.storybook/tailwind.css b/graph/ui-icons/.storybook/tailwind.css deleted file mode 100644 index 23d597fe51b0b..0000000000000 --- a/graph/ui-icons/.storybook/tailwind.css +++ /dev/null @@ -1,3 +0,0 @@ -@tailwind components; -@tailwind base; -@tailwind utilities; diff --git a/graph/ui-icons/README.md b/graph/ui-icons/README.md deleted file mode 100644 index fda4b05bf551d..0000000000000 --- a/graph/ui-icons/README.md +++ /dev/null @@ -1,7 +0,0 @@ -# ui-icons - -This library was generated with [Nx](https://nx.dev). - -## Running unit tests - -Run `nx test ui-icons` to execute the unit tests via [Jest](https://jestjs.io). diff --git a/graph/ui-icons/postcss.config.js b/graph/ui-icons/postcss.config.js deleted file mode 100644 index 8b2e63b9e6bea..0000000000000 --- a/graph/ui-icons/postcss.config.js +++ /dev/null @@ -1,10 +0,0 @@ -const path = require('path'); - -module.exports = { - plugins: { - tailwindcss: { - config: path.join(__dirname, 'tailwind.config.js'), - }, - autoprefixer: {}, - }, -}; diff --git a/graph/ui-icons/project.json b/graph/ui-icons/project.json deleted file mode 100644 index a12607785331a..0000000000000 --- a/graph/ui-icons/project.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "name": "graph-ui-icons", - "$schema": "../../node_modules/nx/schemas/project-schema.json", - "sourceRoot": "graph/ui-icons/src", - "projectType": "library", - "tags": [], - "// targets": "to see all targets run: nx show project ui-icons --web", - "targets": { - "lint": {}, - "storybook": { - "executor": "@nx/storybook:storybook", - "options": { - "port": 4400, - "configDir": "graph/ui-icons/.storybook" - }, - "configurations": { - "ci": { - "quiet": true - } - } - }, - "build-storybook": { - "executor": "@nx/storybook:build", - "outputs": ["{options.outputDir}"], - "options": { - "outputDir": "dist/storybook/graph-ui-icons", - "configDir": "graph/ui-icons/.storybook" - }, - "configurations": { - "ci": { - "quiet": true - } - } - }, - "test-storybook": { - "executor": "nx:run-commands", - "options": { - "command": "test-storybook -c graph/ui-icons/.storybook --url=http://localhost:4400" - } - }, - "static-storybook": { - "executor": "@nx/web:file-server", - "options": { - "buildTarget": "graph-ui-icons:build-storybook", - "staticFilePath": "dist/storybook/graph-ui-icons" - }, - "configurations": { - "ci": { - "buildTarget": "graph-ui-icons:build-storybook:ci" - } - } - } - } -} diff --git a/graph/ui-icons/src/index.ts b/graph/ui-icons/src/index.ts deleted file mode 100644 index cc3c66aa312c9..0000000000000 --- a/graph/ui-icons/src/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './lib/technology-icon'; -export * from './lib/framework-icons'; -export * from './lib/ nx-cloud-icon'; diff --git a/graph/ui-icons/src/lib/ nx-cloud-icon.tsx b/graph/ui-icons/src/lib/ nx-cloud-icon.tsx deleted file mode 100644 index 805e0fb0cff41..0000000000000 --- a/graph/ui-icons/src/lib/ nx-cloud-icon.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import { FC, SVGProps } from 'react'; - -export const NxCloudIcon: FC> = (props) => ( - - - -); diff --git a/graph/ui-icons/src/lib/framework-icons.stories.tsx b/graph/ui-icons/src/lib/framework-icons.stories.tsx deleted file mode 100644 index e57eaf595c9b2..0000000000000 --- a/graph/ui-icons/src/lib/framework-icons.stories.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import type { Meta, StoryObj } from '@storybook/react'; -import { Framework, frameworkIcons } from './framework-icons'; - -const meta: Meta = { - component: () => ( - <> - {Object.keys(frameworkIcons).map((key) => ( - <> -
    {key}
    -
    - {frameworkIcons[key as Framework].image} -
    - - ))} - - ), - title: 'frameworkIcons', -}; -export default meta; -type Story = StoryObj; - -export const Primary: Story = { - args: {}, -}; diff --git a/graph/ui-icons/src/lib/framework-icons.tsx b/graph/ui-icons/src/lib/framework-icons.tsx deleted file mode 100644 index ec1e15ee20a82..0000000000000 --- a/graph/ui-icons/src/lib/framework-icons.tsx +++ /dev/null @@ -1,1886 +0,0 @@ -export type Framework = - | 'reactMono' - | 'tsMono' - | 'jsMono' - | 'nodeMono' - | 'angularMono' - | 'typescript' - | 'javascript' - | 'node' - | 'angular' - | 'youtube' - | 'nxagents' - | 'nxcloud' - | 'nx' - | 'nextjs' - | 'nestjs' - | 'rspack' - | 'express' - | 'jest' - | 'fastify' - | 'storybook' - | 'solid' - | 'lit' - | 'vite' - | 'trpc' - | 'remix' - | 'dotnet' - | 'qwik' - | 'gradle' - | 'go' - | 'vue' - | 'rust' - | 'nuxt' - | 'svelte' - | 'gatsby' - | 'astro' - | 'playwright' - | 'pnpm' - | 'monorepo' - | 'cra' - | 'cypress' - | 'expo' - | 'react' - | 'azure' - | 'bitbucket' - | 'circleci' - | 'github' - | 'gitlab' - | 'jenkins' - | 'apollo' - | 'prisma' - | 'redis' - | 'postgres' - | 'planetscale' - | 'mongodb' - | 'mfe' - | 'eslint' - | 'office' - | 'tool'; - -export const frameworkIcons: Record< - Framework, - { - image: JSX.Element; - // this key determines whether the icon should be adaptive or not - // if true means icon is mostly monotone (black/white), its parent needs to specify the fill color - isAdaptiveIcon?: boolean; - } -> = { - reactMono: { - image: ( - - - - ), - }, - tsMono: { - image: ( - - - - - - - - - ), - }, - jsMono: { - image: ( - - - - - - - - - ), - }, - nodeMono: { - image: ( - - - - ), - }, - angularMono: { - image: ( - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ), - }, - typescript: { - image: ( - - - - - ), - }, - youtube: { - image: ( - - - - - ), - }, - nxagents: { - image: ( - - - - ), - }, - nxcloud: { - image: ( - - - - ), - }, - nx: { - image: ( - - - - ), - }, - node: { - image: ( - - Node.js - - - ), - }, - nextjs: { - image: ( - - Next.js - - - ), - isAdaptiveIcon: true, - }, - nestjs: { - image: ( - - NestJS - - - ), - }, - rspack: { - image: ( - - - - - - - - ), - }, - jest: { - image: ( - - - - - - - - - - - - - ), - }, - fastify: { - image: ( - - Fastify - - - ), - isAdaptiveIcon: true, - }, - express: { - image: ( - - Express - - - ), - isAdaptiveIcon: true, - }, - storybook: { - image: ( - - Storybook - - - ), - }, - solid: { - image: ( - - Solid - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - // Solid - // - // - ), - }, - lit: { - image: ( - - Lit - - - ), - }, - vite: { - image: ( - - Vite - - - - - - - - - - - - - - - ), - }, - trpc: { - image: ( - - tRPC - - - ), - }, - remix: { - image: ( - - - - - - - - - - - - - - - - - - - - - - - - - - ), - }, - dotnet: { - image: ( - - - - - - - - ), - }, - qwik: { - image: ( - - - - - - ), - }, - gradle: { - image: ( - - - - - - - - gradle-elephant-icon-gradient-primary - - - ), - }, - go: { - image: ( - - - - - - - ), - }, - vue: { - image: ( - - - - - - ), - }, - rust: { - image: ( - - - - ), - isAdaptiveIcon: true, - }, - nuxt: { - image: ( - - - - ), - }, - svelte: { - image: ( - - - - - ), - }, - gatsby: { - image: ( - - file_type_gatsby - - - - ), - }, - astro: { - image: ( - - Astro - - - ), - }, - playwright: { - image: ( - - Playwright - - - ), - }, - pnpm: { - image: ( - - pnpm - - - ), - }, - monorepo: { - image: ( - - - - - - ), - }, - javascript: { - image: ( - - JavaScript Unofficial Logo - - - - ), - }, - cra: { - image: ( - - - - ), - }, - angular: { - image: ( - - Angular - Angular - - - - - - - - - - - - - - - - - - ), - }, - cypress: { - image: ( - - Cypress - - - ), - isAdaptiveIcon: true, - }, - expo: { - image: ( - - Expo - - - ), - isAdaptiveIcon: true, - }, - react: { - image: ( - - React - - - ), - }, - azure: { - image: ( - - Azure Pipelines - - - - - - - - - ), - }, - bitbucket: { - image: ( - - - - - - - - Bitbucket - - - - - - - - ), - }, - circleci: { - image: ( - - Circle CI - - - - ), - }, - github: { - image: ( - - GitHub - - - ), - }, - gitlab: { - image: ( - - GitLab - - - - - - - - ), - }, - jenkins: { - image: ( - - jenkins-logo - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ), - }, - apollo: { - image: ( - - - - ), - }, - prisma: { - image: ( - - - - ), - }, - redis: { - image: ( - - - - - - - - - - - - - - - ), - }, - postgres: { - image: ( - - - - - - - - - ), - }, - planetscale: { - image: ( - - - - - - - ), - }, - mongodb: { - image: ( - - - - ), - }, - mfe: { - image: ( - - - - ), - }, - eslint: { - image: ( - - - - - - - ), - }, - office: { - image: ( - - - - ), - }, - tool: { - image: ( - - - - - ), - }, -}; diff --git a/graph/ui-icons/src/lib/technologies/angular.tsx b/graph/ui-icons/src/lib/technologies/angular.tsx deleted file mode 100644 index f581bb1d3c5a4..0000000000000 --- a/graph/ui-icons/src/lib/technologies/angular.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import { FC, SVGProps } from 'react'; - -export const AngularIcon: FC> = (props) => ( - - Angular - - -); diff --git a/graph/ui-icons/src/lib/technologies/cypress.tsx b/graph/ui-icons/src/lib/technologies/cypress.tsx deleted file mode 100644 index 1edcea194dae6..0000000000000 --- a/graph/ui-icons/src/lib/technologies/cypress.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import { FC, SVGProps } from 'react'; - -export const CypressIcon: FC> = (props) => ( - - Cypress - - -); diff --git a/graph/ui-icons/src/lib/technologies/esbuild.tsx b/graph/ui-icons/src/lib/technologies/esbuild.tsx deleted file mode 100644 index 12f8006410326..0000000000000 --- a/graph/ui-icons/src/lib/technologies/esbuild.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import { FC, SVGProps } from 'react'; - -export const EsbuildIcon: FC> = (props) => ( - - esbuild - - -); diff --git a/graph/ui-icons/src/lib/technologies/eslint.tsx b/graph/ui-icons/src/lib/technologies/eslint.tsx deleted file mode 100644 index 40138eed4d505..0000000000000 --- a/graph/ui-icons/src/lib/technologies/eslint.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import { FC, SVGProps } from 'react'; - -export const EslintIcon: FC> = (props) => ( - - ESLint - - -); diff --git a/graph/ui-icons/src/lib/technologies/expo.tsx b/graph/ui-icons/src/lib/technologies/expo.tsx deleted file mode 100644 index 31d1acf1678d5..0000000000000 --- a/graph/ui-icons/src/lib/technologies/expo.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import { FC, SVGProps } from 'react'; - -export const ExpoIcon: FC> = (props) => ( - - Expo - - -); diff --git a/graph/ui-icons/src/lib/technologies/express.tsx b/graph/ui-icons/src/lib/technologies/express.tsx deleted file mode 100644 index 5968a72072e5b..0000000000000 --- a/graph/ui-icons/src/lib/technologies/express.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import { FC, SVGProps } from 'react'; - -export const ExpressIcon: FC> = (props) => ( - - Express - - -); diff --git a/graph/ui-icons/src/lib/technologies/gradle.tsx b/graph/ui-icons/src/lib/technologies/gradle.tsx deleted file mode 100644 index e491d3b81ddd2..0000000000000 --- a/graph/ui-icons/src/lib/technologies/gradle.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import { FC, SVGProps } from 'react'; - -export const GradleIcon: FC> = (props) => ( - - Gradle - - -); diff --git a/graph/ui-icons/src/lib/technologies/html5.tsx b/graph/ui-icons/src/lib/technologies/html5.tsx deleted file mode 100644 index b0651c113c9a1..0000000000000 --- a/graph/ui-icons/src/lib/technologies/html5.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import { FC, SVGProps } from 'react'; - -export const HTML5Icon: FC> = (props) => ( - - HTML5 - - -); diff --git a/graph/ui-icons/src/lib/technologies/javascript.tsx b/graph/ui-icons/src/lib/technologies/javascript.tsx deleted file mode 100644 index fdcf1dcb7414f..0000000000000 --- a/graph/ui-icons/src/lib/technologies/javascript.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import { FC, SVGProps } from 'react'; - -export const JavaScriptIcon: FC> = (props) => ( - - JavaScript - - -); diff --git a/graph/ui-icons/src/lib/technologies/jest.tsx b/graph/ui-icons/src/lib/technologies/jest.tsx deleted file mode 100644 index 3374a50e6a612..0000000000000 --- a/graph/ui-icons/src/lib/technologies/jest.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import { FC, SVGProps } from 'react'; - -export const JestIcon: FC> = (props) => ( - - Jest - - -); diff --git a/graph/ui-icons/src/lib/technologies/nestjs.tsx b/graph/ui-icons/src/lib/technologies/nestjs.tsx deleted file mode 100644 index a64875fe2fa10..0000000000000 --- a/graph/ui-icons/src/lib/technologies/nestjs.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import { FC, SVGProps } from 'react'; - -export const NestJSIcon: FC> = (props) => ( - - NestJS - - -); diff --git a/graph/ui-icons/src/lib/technologies/nextjs.tsx b/graph/ui-icons/src/lib/technologies/nextjs.tsx deleted file mode 100644 index 99e86baa23464..0000000000000 --- a/graph/ui-icons/src/lib/technologies/nextjs.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import { FC, SVGProps } from 'react'; - -export const NextJSIcon: FC> = (props) => ( - - Next.js - - -); diff --git a/graph/ui-icons/src/lib/technologies/nodejs.tsx b/graph/ui-icons/src/lib/technologies/nodejs.tsx deleted file mode 100644 index 850ae53a7e4d3..0000000000000 --- a/graph/ui-icons/src/lib/technologies/nodejs.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import { FC, SVGProps } from 'react'; - -export const NodeIcon: FC> = (props) => ( - - Node.js - - -); diff --git a/graph/ui-icons/src/lib/technologies/nuxtjs.tsx b/graph/ui-icons/src/lib/technologies/nuxtjs.tsx deleted file mode 100644 index 45525aa42eb4f..0000000000000 --- a/graph/ui-icons/src/lib/technologies/nuxtjs.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import { FC, SVGProps } from 'react'; - -export const NuxtIcon: FC> = (props) => ( - - Nuxt - - -); diff --git a/graph/ui-icons/src/lib/technologies/playwright.tsx b/graph/ui-icons/src/lib/technologies/playwright.tsx deleted file mode 100644 index 7355ae4b65eca..0000000000000 --- a/graph/ui-icons/src/lib/technologies/playwright.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import { FC, SVGProps } from 'react'; - -export const PlaywrightIcon: FC> = (props) => ( - - Playwright - - -); diff --git a/graph/ui-icons/src/lib/technologies/prettier.tsx b/graph/ui-icons/src/lib/technologies/prettier.tsx deleted file mode 100644 index 0c9595d6d9382..0000000000000 --- a/graph/ui-icons/src/lib/technologies/prettier.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import { FC, SVGProps } from 'react'; - -export const PrettierIcon: FC> = (props) => ( - - Prettier - - -); diff --git a/graph/ui-icons/src/lib/technologies/react.tsx b/graph/ui-icons/src/lib/technologies/react.tsx deleted file mode 100644 index 53608823f180f..0000000000000 --- a/graph/ui-icons/src/lib/technologies/react.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import { FC, SVGProps } from 'react'; - -export const ReactIcon: FC> = (props) => ( - - React - - -); diff --git a/graph/ui-icons/src/lib/technologies/remix.tsx b/graph/ui-icons/src/lib/technologies/remix.tsx deleted file mode 100644 index 89f93d08f6837..0000000000000 --- a/graph/ui-icons/src/lib/technologies/remix.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import { FC, SVGProps } from 'react'; - -export const RemixIcon: FC> = (props) => ( - - Remix - - -); diff --git a/graph/ui-icons/src/lib/technologies/rollup.tsx b/graph/ui-icons/src/lib/technologies/rollup.tsx deleted file mode 100644 index f5dd0e16cc52d..0000000000000 --- a/graph/ui-icons/src/lib/technologies/rollup.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import { FC, SVGProps } from 'react'; - -export const RollupIcon: FC> = (props) => ( - - Rollup - - -); diff --git a/graph/ui-icons/src/lib/technologies/rspack.tsx b/graph/ui-icons/src/lib/technologies/rspack.tsx deleted file mode 100644 index da927bed2fc8a..0000000000000 --- a/graph/ui-icons/src/lib/technologies/rspack.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import { FC, SVGProps } from 'react'; - -export const RspackIcon: FC> = (props) => ( - - Rspack - - -); diff --git a/graph/ui-icons/src/lib/technologies/storybook.tsx b/graph/ui-icons/src/lib/technologies/storybook.tsx deleted file mode 100644 index bd4d072815b19..0000000000000 --- a/graph/ui-icons/src/lib/technologies/storybook.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import { FC, SVGProps } from 'react'; - -export const StorybookIcon: FC> = (props) => ( - - Storybook - - -); diff --git a/graph/ui-icons/src/lib/technologies/typescript.tsx b/graph/ui-icons/src/lib/technologies/typescript.tsx deleted file mode 100644 index 4493f989bfab1..0000000000000 --- a/graph/ui-icons/src/lib/technologies/typescript.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import { FC, SVGProps } from 'react'; - -export const TypeScriptIcon: FC> = (props) => ( - - TypeScript - - -); diff --git a/graph/ui-icons/src/lib/technologies/vite.tsx b/graph/ui-icons/src/lib/technologies/vite.tsx deleted file mode 100644 index 3c6d809c0490c..0000000000000 --- a/graph/ui-icons/src/lib/technologies/vite.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import { FC, SVGProps } from 'react'; - -export const ViteIcon: FC> = (props) => ( - - Vite - - -); diff --git a/graph/ui-icons/src/lib/technologies/vitest.tsx b/graph/ui-icons/src/lib/technologies/vitest.tsx deleted file mode 100644 index ec4d059b2f444..0000000000000 --- a/graph/ui-icons/src/lib/technologies/vitest.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import { FC, SVGProps } from 'react'; - -export const VitestIcon: FC> = (props) => ( - - Vitest - - -); diff --git a/graph/ui-icons/src/lib/technologies/vue.tsx b/graph/ui-icons/src/lib/technologies/vue.tsx deleted file mode 100644 index 6086580476f3c..0000000000000 --- a/graph/ui-icons/src/lib/technologies/vue.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import { FC, SVGProps } from 'react'; - -export const VueIcon: FC> = (props) => ( - - Vue.js - - -); diff --git a/graph/ui-icons/src/lib/technologies/webpack.tsx b/graph/ui-icons/src/lib/technologies/webpack.tsx deleted file mode 100644 index 0b0b927aac737..0000000000000 --- a/graph/ui-icons/src/lib/technologies/webpack.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import { FC, SVGProps } from 'react'; - -export const WebpackIcon: FC> = (props) => ( - - Webpack - - -); diff --git a/graph/ui-icons/src/lib/technology-icon.stories.tsx b/graph/ui-icons/src/lib/technology-icon.stories.tsx deleted file mode 100644 index 0bdc92e22f316..0000000000000 --- a/graph/ui-icons/src/lib/technology-icon.stories.tsx +++ /dev/null @@ -1,58 +0,0 @@ -import type { Meta, StoryObj } from '@storybook/react'; -import { TechnologyIcon } from './technology-icon'; - -const meta: Meta = { - component: TechnologyIcon, - title: 'TechnologyIcon', -}; -export default meta; - -type Story = StoryObj; - -export const Simple: Story = { - args: { - technology: 'react', - }, -}; - -export const SimpleLarge: Story = { - args: { - technology: 'react', - className: 'h-8 w-8', - }, -}; - -export const Monochromatic: Story = { - args: { - technology: 'react', - monochromatic: true, - }, -}; - -export const MonochromaticLarge: Story = { - args: { - technology: 'react', - monochromatic: true, - className: 'h-8 w-8', - }, -}; - -export const UnknownTechnology: Story = { - args: { - technology: 'unknown', - }, -}; - -export const UnknownTechnologyLarge: Story = { - args: { - technology: 'unknown', - className: 'h-8 w-8', - }, -}; - -export const MonochromaticUnknownTechnology: Story = { - args: { - technology: 'unknown', - monochromatic: true, - }, -}; diff --git a/graph/ui-icons/src/lib/technology-icon.tsx b/graph/ui-icons/src/lib/technology-icon.tsx deleted file mode 100644 index ad6c9d1458422..0000000000000 --- a/graph/ui-icons/src/lib/technology-icon.tsx +++ /dev/null @@ -1,128 +0,0 @@ -import { HTMLProps } from 'react'; -import { twMerge } from 'tailwind-merge'; -import { Framework, frameworkIcons } from './framework-icons'; -import { MonochromaticTechnologyIconsMap } from './technology-icons-map-monochromatic'; - -export interface TechnologyIconProps extends HTMLProps { - technology?: string; - showTooltip?: boolean; - monochromatic?: boolean; -} - -export function TechnologyIcon({ - technology, - showTooltip, - monochromatic, - ...props -}: TechnologyIconProps) { - if (!technology) { - return null; - } - if (monochromatic) { - return ( - - ); - } - return ( - - ); -} - -function UnknownTechnologyIcon({ - technology, - showTooltip, - ...props -}: TechnologyIconProps) { - if (!technology) { - return null; - } - return ( -
    - {technology[0]} -
    - ); -} - -export function TechnologyIconMonochromatic({ - technology, - showTooltip, - ...props -}: TechnologyIconProps) { - if (!technology) { - return null; - } - const Icon = MonochromaticTechnologyIconsMap[technology as any]?.icon; - - if (!Icon) { - return ( - - ); - } - - return ( -
    - -
    - ); -} - -export function TechnologyIconColor({ - technology, - showTooltip, - ...props -}: TechnologyIconProps) { - if (!technology) { - return null; - } - const image = frameworkIcons[technology as Framework]?.image; - - if (!image) { - return ( - - ); - } - - return ( -
    - {image} -
    - ); -} diff --git a/graph/ui-icons/src/lib/technology-icons-map-monochromatic.stories.tsx b/graph/ui-icons/src/lib/technology-icons-map-monochromatic.stories.tsx deleted file mode 100644 index c17c1ef5cf2fd..0000000000000 --- a/graph/ui-icons/src/lib/technology-icons-map-monochromatic.stories.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import type { Meta, StoryObj } from '@storybook/react'; -import { MonochromaticTechnologyIconsMap } from './technology-icons-map-monochromatic'; - -const meta: Meta = { - component: () => ( - <> - {Object.keys(MonochromaticTechnologyIconsMap).map((key) => { - const Icon = MonochromaticTechnologyIconsMap[key].icon; - return ( - <> -
    {key}
    -
    - -
    - - ); - })} - - ), - title: 'MonochromaticTechnologyIconsMap', -}; -export default meta; -type Story = StoryObj; - -export const Primary: Story = { - args: {}, -}; diff --git a/graph/ui-icons/src/lib/technology-icons-map-monochromatic.tsx b/graph/ui-icons/src/lib/technology-icons-map-monochromatic.tsx deleted file mode 100644 index d56b8c21293d9..0000000000000 --- a/graph/ui-icons/src/lib/technology-icons-map-monochromatic.tsx +++ /dev/null @@ -1,61 +0,0 @@ -import { FunctionComponent, SVGProps } from 'react'; -import { AngularIcon } from './technologies/angular'; -import { CypressIcon } from './technologies/cypress'; -import { EsbuildIcon } from './technologies/esbuild'; -import { EslintIcon } from './technologies/eslint'; -import { ExpoIcon } from './technologies/expo'; -import { ExpressIcon } from './technologies/express'; -import { GradleIcon } from './technologies/gradle'; -import { HTML5Icon } from './technologies/html5'; -import { JavaScriptIcon } from './technologies/javascript'; -import { JestIcon } from './technologies/jest'; -import { NestJSIcon } from './technologies/nestjs'; -import { NextJSIcon } from './technologies/nextjs'; -import { NodeIcon } from './technologies/nodejs'; -import { NuxtIcon } from './technologies/nuxtjs'; -import { PlaywrightIcon } from './technologies/playwright'; -import { PrettierIcon } from './technologies/prettier'; -import { ReactIcon } from './technologies/react'; -import { RemixIcon } from './technologies/remix'; -import { RollupIcon } from './technologies/rollup'; -import { RspackIcon } from './technologies/rspack'; -import { StorybookIcon } from './technologies/storybook'; -import { TypeScriptIcon } from './technologies/typescript'; -import { ViteIcon } from './technologies/vite'; -import { VitestIcon } from './technologies/vitest'; -import { VueIcon } from './technologies/vue'; -import { WebpackIcon } from './technologies/webpack'; - -export const MonochromaticTechnologyIconsMap: Record< - string, - { icon: FunctionComponent> } -> = { - angular: { icon: AngularIcon }, - cypress: { icon: CypressIcon }, - detox: { icon: ReactIcon }, - esbuild: { icon: EsbuildIcon }, - eslint: { icon: EslintIcon }, - expo: { icon: ExpoIcon }, - express: { icon: ExpressIcon }, - gradle: { icon: GradleIcon }, - javascript: { icon: JavaScriptIcon }, - jest: { icon: JestIcon }, - nest: { icon: NestJSIcon }, - next: { icon: NextJSIcon }, - node: { icon: NodeIcon }, - nuxt: { icon: NuxtIcon }, - playwright: { icon: PlaywrightIcon }, - prettier: { icon: PrettierIcon }, - react: { icon: ReactIcon }, - reactnative: { icon: ReactIcon }, - remix: { icon: RemixIcon }, - rollup: { icon: RollupIcon }, - rspack: { icon: RspackIcon }, - storybook: { icon: StorybookIcon }, - typescript: { icon: TypeScriptIcon }, - vite: { icon: ViteIcon }, - vitest: { icon: VitestIcon }, - vue: { icon: VueIcon }, - webcomponents: { icon: HTML5Icon }, - webpack: { icon: WebpackIcon }, -}; diff --git a/graph/ui-icons/tailwind.config.js b/graph/ui-icons/tailwind.config.js deleted file mode 100644 index a130bfceccd48..0000000000000 --- a/graph/ui-icons/tailwind.config.js +++ /dev/null @@ -1,40 +0,0 @@ -const path = require('path'); - -// nx-ignore-next-line -const { createGlobPatternsForDependencies } = require('@nx/react/tailwind'); - -module.exports = { - content: [ - path.join(__dirname, 'src/**/*.{js,ts,jsx,tsx,html}'), - ...createGlobPatternsForDependencies(__dirname), - ], - darkMode: 'class', // or 'media' or 'class' - theme: { - extend: { - typography: { - DEFAULT: { - css: { - 'code::before': { - content: '', - }, - 'code::after': { - content: '', - }, - 'blockquote p:first-of-type::before': { - content: '', - }, - 'blockquote p:last-of-type::after': { - content: '', - }, - }, - }, - }, - }, - }, - variants: { - extend: { - translate: ['group-hover'], - }, - }, - plugins: [require('@tailwindcss/typography')], -}; diff --git a/graph/ui-icons/tsconfig.json b/graph/ui-icons/tsconfig.json deleted file mode 100644 index 53e12dc04e104..0000000000000 --- a/graph/ui-icons/tsconfig.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "compilerOptions": { - "jsx": "react-jsx", - "allowJs": false, - "esModuleInterop": false, - "allowSyntheticDefaultImports": true, - "strict": true - }, - "files": [], - "include": [], - "references": [ - { - "path": "./tsconfig.lib.json" - }, - { - "path": "./tsconfig.storybook.json" - } - ], - "extends": "../../tsconfig.base.json" -} diff --git a/graph/ui-icons/tsconfig.lib.json b/graph/ui-icons/tsconfig.lib.json deleted file mode 100644 index 8c1bec17db74e..0000000000000 --- a/graph/ui-icons/tsconfig.lib.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "types": [ - "node", - "@nx/react/typings/cssmodule.d.ts", - "@nx/react/typings/image.d.ts" - ] - }, - "exclude": [ - "jest.config.ts", - "src/**/*.spec.ts", - "src/**/*.test.ts", - "src/**/*.spec.tsx", - "src/**/*.test.tsx", - "src/**/*.spec.js", - "src/**/*.test.js", - "src/**/*.spec.jsx", - "src/**/*.test.jsx", - "**/*.stories.ts", - "**/*.stories.js", - "**/*.stories.jsx", - "**/*.stories.tsx" - ], - "include": ["src/**/*.js", "src/**/*.jsx", "src/**/*.ts", "src/**/*.tsx"] -} diff --git a/graph/ui-icons/tsconfig.storybook.json b/graph/ui-icons/tsconfig.storybook.json deleted file mode 100644 index 2da3caee121ed..0000000000000 --- a/graph/ui-icons/tsconfig.storybook.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "emitDecoratorMetadata": true, - "outDir": "" - }, - "files": [ - "../../node_modules/@nx/react/typings/styled-jsx.d.ts", - "../../node_modules/@nx/react/typings/cssmodule.d.ts", - "../../node_modules/@nx/react/typings/image.d.ts" - ], - "exclude": [ - "src/**/*.spec.ts", - "src/**/*.test.ts", - "src/**/*.spec.js", - "src/**/*.test.js", - "src/**/*.spec.tsx", - "src/**/*.test.tsx", - "src/**/*.spec.jsx", - "src/**/*.test.js" - ], - "include": [ - "src/**/*.stories.ts", - "src/**/*.stories.js", - "src/**/*.stories.jsx", - "src/**/*.stories.tsx", - "src/**/*.stories.mdx", - ".storybook/*.js", - ".storybook/*.ts" - ] -} diff --git a/graph/ui-project-details/src/lib/target-configuration-details/target-configuration-details.tsx b/graph/ui-project-details/src/lib/target-configuration-details/target-configuration-details.tsx index bb99534f984d7..0020c20c323b8 100644 --- a/graph/ui-project-details/src/lib/target-configuration-details/target-configuration-details.tsx +++ b/graph/ui-project-details/src/lib/target-configuration-details/target-configuration-details.tsx @@ -1,22 +1,22 @@ /* eslint-disable @nx/enforce-module-boundaries */ // nx-ignore-next-line import type { TargetConfiguration } from '@nx/devkit'; -import { JsonCodeBlock } from '@nx/graph/ui-code-block'; +import { JsonCodeBlock } from '@nx/graph-internal/ui-code-block'; +import { ExpandedTargetsContext } from '@nx/graph/shared'; import { CopyToClipboardButton } from '@nx/graph/ui-components'; -import { useCallback, useContext, useEffect, useState } from 'react'; -import { FadingCollapsible } from './fading-collapsible'; -import { TargetConfigurationProperty } from './target-configuration-property'; import { PropertyInfoTooltip, Tooltip } from '@nx/graph/ui-tooltips'; -import { TooltipTriggerText } from './tooltip-trigger-text'; +import { useCallback, useContext, useEffect, useState } from 'react'; import { Pill } from '../pill'; +import { ShowOptionsHelp } from '../show-all-options/show-options-help'; import { TargetConfigurationDetailsHeader } from '../target-configuration-details-header/target-configuration-details-header'; -import { ExpandedTargetsContext } from '@nx/graph/shared'; -import { getDisplayHeaderFromTargetConfiguration } from '../utils/get-display-header-from-target-configuration'; import { TargetExecutor } from '../target-executor/target-executor'; import { TargetExecutorTitle } from '../target-executor/target-executor-title'; -import { TargetSourceInfo } from '../target-source-info/target-source-info'; import { getTargetExecutorSourceMapKey } from '../target-source-info/get-target-executor-source-map-key'; -import { ShowOptionsHelp } from '../show-all-options/show-options-help'; +import { TargetSourceInfo } from '../target-source-info/target-source-info'; +import { getDisplayHeaderFromTargetConfiguration } from '../utils/get-display-header-from-target-configuration'; +import { FadingCollapsible } from './fading-collapsible'; +import { TargetConfigurationProperty } from './target-configuration-property'; +import { TooltipTriggerText } from './tooltip-trigger-text'; interface TargetConfigurationDetailsProps { projectName: string; diff --git a/graph/ui-project-details/tailwind.config.js b/graph/ui-project-details/tailwind.config.js index 18a8d985ec32a..b29e8f50517b0 100644 --- a/graph/ui-project-details/tailwind.config.js +++ b/graph/ui-project-details/tailwind.config.js @@ -1,5 +1,10 @@ -const path = require('path'); +// @ts-check +const path = require('node:path'); + +// Ignore these nx related dependencies since they are the installed versions not the ones in the workspace +// nx-ignore-next-line +const { workspaceRoot } = require('@nx/devkit'); // nx-ignore-next-line const { createGlobPatternsForDependencies } = require('@nx/react/tailwind'); @@ -7,6 +12,12 @@ module.exports = { content: [ path.join(__dirname, 'src/**/*.{js,ts,jsx,tsx,html}'), ...createGlobPatternsForDependencies(__dirname), + // Resolve the classes used in @nx/graph components + // TODO: make a decision on whether this is really the best approach, or if precompiling and deduplicating the classes would be better + path.join( + workspaceRoot, + 'node_modules/@nx/graph/**/*.{js,ts,jsx,tsx,html}' + ), ], darkMode: 'class', // or 'media' or 'class' theme: { diff --git a/graph/ui-tooltips/.babelrc b/graph/ui-tooltips/.babelrc deleted file mode 100644 index 1ea870ead410c..0000000000000 --- a/graph/ui-tooltips/.babelrc +++ /dev/null @@ -1,12 +0,0 @@ -{ - "presets": [ - [ - "@nx/react/babel", - { - "runtime": "automatic", - "useBuiltIns": "usage" - } - ] - ], - "plugins": [] -} diff --git a/graph/ui-tooltips/.eslintrc.json b/graph/ui-tooltips/.eslintrc.json deleted file mode 100644 index a39ac5d057803..0000000000000 --- a/graph/ui-tooltips/.eslintrc.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "extends": ["plugin:@nx/react", "../../.eslintrc.json"], - "ignorePatterns": ["!**/*"], - "overrides": [ - { - "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], - "rules": {} - }, - { - "files": ["*.ts", "*.tsx"], - "rules": {} - }, - { - "files": ["*.js", "*.jsx"], - "rules": {} - } - ] -} diff --git a/graph/ui-tooltips/.storybook/main.js b/graph/ui-tooltips/.storybook/main.js deleted file mode 100644 index 98b74a9cb2588..0000000000000 --- a/graph/ui-tooltips/.storybook/main.js +++ /dev/null @@ -1,9 +0,0 @@ -module.exports = { - stories: ['../src/lib/**/*.stories.@(mdx|js|jsx|ts|tsx)'], - addons: ['@storybook/addon-essentials', '@nx/react/plugins/storybook'], - framework: { - name: '@storybook/react-webpack5', - options: {}, - }, - docs: {}, -}; diff --git a/graph/ui-tooltips/.storybook/preview.js b/graph/ui-tooltips/.storybook/preview.js deleted file mode 100644 index a7e6fafa19908..0000000000000 --- a/graph/ui-tooltips/.storybook/preview.js +++ /dev/null @@ -1,2 +0,0 @@ -import './tailwind-imports.css'; -export const tags = ['autodocs']; diff --git a/graph/ui-tooltips/.storybook/tailwind-imports.css b/graph/ui-tooltips/.storybook/tailwind-imports.css deleted file mode 100644 index b5c61c956711f..0000000000000 --- a/graph/ui-tooltips/.storybook/tailwind-imports.css +++ /dev/null @@ -1,3 +0,0 @@ -@tailwind base; -@tailwind components; -@tailwind utilities; diff --git a/graph/ui-tooltips/README.md b/graph/ui-tooltips/README.md deleted file mode 100644 index 0facb27ac5f5f..0000000000000 --- a/graph/ui-tooltips/README.md +++ /dev/null @@ -1,7 +0,0 @@ -# graph-ui-tooltips - -This library was generated with [Nx](https://nx.dev). - -## Running unit tests - -Run `nx test graph-ui-tooltips` to execute the unit tests via [Jest](https://jestjs.io). diff --git a/graph/ui-tooltips/jest.config.ts b/graph/ui-tooltips/jest.config.ts deleted file mode 100644 index cf6c1056e6e54..0000000000000 --- a/graph/ui-tooltips/jest.config.ts +++ /dev/null @@ -1,10 +0,0 @@ -/* eslint-disable */ -export default { - displayName: 'graph-ui-tooltips', - preset: '../../jest.preset.js', - transform: { - '^.+\\.[tj]sx?$': 'babel-jest', - }, - moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'], - coverageDirectory: '../../coverage/graph/graph-ui-tooltips', -}; diff --git a/graph/ui-tooltips/postcss.config.js b/graph/ui-tooltips/postcss.config.js deleted file mode 100644 index 8b2e63b9e6bea..0000000000000 --- a/graph/ui-tooltips/postcss.config.js +++ /dev/null @@ -1,10 +0,0 @@ -const path = require('path'); - -module.exports = { - plugins: { - tailwindcss: { - config: path.join(__dirname, 'tailwind.config.js'), - }, - autoprefixer: {}, - }, -}; diff --git a/graph/ui-tooltips/project.json b/graph/ui-tooltips/project.json deleted file mode 100644 index a284cb108a359..0000000000000 --- a/graph/ui-tooltips/project.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "name": "graph-ui-tooltips", - "$schema": "../../node_modules/nx/schemas/project-schema.json", - "sourceRoot": "graph/ui-tooltips/src", - "projectType": "library", - "tags": [], - "targets": { - "storybook": { - "executor": "@nx/storybook:storybook", - "options": { - "port": 4400, - "configDir": "graph/ui-tooltips/.storybook" - }, - "configurations": { - "ci": { - "quiet": true - } - } - }, - "build-storybook": { - "executor": "@nx/storybook:build", - "outputs": ["{options.outputDir}"], - "options": { - "configDir": "graph/ui-tooltips/.storybook", - "outputDir": "dist/storybook/graph-ui-tooltips" - }, - "configurations": { - "ci": { - "quiet": true - } - } - } - } -} diff --git a/graph/ui-tooltips/src/index.ts b/graph/ui-tooltips/src/index.ts deleted file mode 100644 index 643d1d963ed44..0000000000000 --- a/graph/ui-tooltips/src/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -export * from './lib/tooltip'; -export * from './lib/project-edge-tooltip'; -export * from './lib/project-node-tooltip'; -export * from './lib/task-node-tooltip'; -export * from './lib/tooltip-button'; -export * from './lib/property-info-tooltip'; -export * from './lib/sourcemap-info-tooltip'; -export * from './lib/external-link'; -export * from './lib/atomizer-tooltip'; diff --git a/graph/ui-tooltips/src/lib/atomizer-tooltip.stories.tsx b/graph/ui-tooltips/src/lib/atomizer-tooltip.stories.tsx deleted file mode 100644 index 532ed8967ee30..0000000000000 --- a/graph/ui-tooltips/src/lib/atomizer-tooltip.stories.tsx +++ /dev/null @@ -1,72 +0,0 @@ -import type { Meta, StoryObj } from '@storybook/react'; -import { AtomizerTooltip, AtomizerTooltipProps } from './atomizer-tooltip'; -import { Tooltip } from './tooltip'; - -const meta: Meta = { - component: AtomizerTooltip, - title: 'Tooltips/AtomizerTooltip', -}; - -export default meta; -type Story = StoryObj; - -export const Cloud: Story = { - args: { - connectedToCloud: true, - nonAtomizedTarget: 'e2e', - } as AtomizerTooltipProps, - render: (args) => { - return ( -
    - ) as any} - > -

    Internal Reference

    -
    -
    - ); - }, -}; - -export const NoCloud: Story = { - args: { - connectedToCloud: false, - nonAtomizedTarget: 'e2e', - } as AtomizerTooltipProps, - render: (args) => { - return ( -
    - ) as any} - > -

    Internal Reference

    -
    -
    - ); - }, -}; - -export const NoCloudConsole: Story = { - args: { - connectedToCloud: false, - nonAtomizedTarget: 'e2e', - nxConnectCallback: () => console.log('nxConnectCallback'), - } as AtomizerTooltipProps, - render: (args) => { - return ( -
    - ) as any} - > -

    Internal Reference

    -
    -
    - ); - }, -}; diff --git a/graph/ui-tooltips/src/lib/atomizer-tooltip.tsx b/graph/ui-tooltips/src/lib/atomizer-tooltip.tsx deleted file mode 100644 index 8576e728ca27f..0000000000000 --- a/graph/ui-tooltips/src/lib/atomizer-tooltip.tsx +++ /dev/null @@ -1,107 +0,0 @@ -import { NxCloudIcon } from '@nx/graph/ui-icons'; -import { twMerge } from 'tailwind-merge'; - -export interface AtomizerTooltipProps { - connectedToCloud: boolean; - nonAtomizedTarget: string; - onNxConnect?: () => void; -} -export function AtomizerTooltip(props: AtomizerTooltipProps) { - return ( -
    -

    - Atomizer -

    -
    -

    - {'Nx '} - - {' the potentially slow'} - - {props.nonAtomizedTarget} - - {'task into separate tasks for each file. Enable '} - {!props.connectedToCloud ? ( - - ) : ( - - )} - {' to benefit from '} - - {!props.connectedToCloud && ( - <> - {', '} - - - )} - {' and '} - - . Use - - {props.nonAtomizedTarget} - - when running without{' '} - {!props.connectedToCloud ? 'Nx Cloud' : 'Nx Agents'}. -

    -
    - {!props.connectedToCloud && ( -
    -

    - {props.onNxConnect ? ( - - ) : ( - - {'Run'} - - nx connect - - {'to connect to Nx Cloud'} - - )} -

    -
    - )} -
    - ); -} - -function Link({ href, text }: { href: string; text: string }) { - return ( - - {text} - - ); -} diff --git a/graph/ui-tooltips/src/lib/external-link.tsx b/graph/ui-tooltips/src/lib/external-link.tsx deleted file mode 100644 index 80a4e32f63c59..0000000000000 --- a/graph/ui-tooltips/src/lib/external-link.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import { ArrowTopRightOnSquareIcon } from '@heroicons/react/24/outline'; -import { twMerge } from 'tailwind-merge'; - -export function ExternalLink({ - children, - href, - title, - className, -}: { - children?: React.ReactNode; - href: string; - className?: string; - title?: string; -}) { - return ( - - {children} - - ); -} diff --git a/graph/ui-tooltips/src/lib/project-edge-tooltip.stories.tsx b/graph/ui-tooltips/src/lib/project-edge-tooltip.stories.tsx deleted file mode 100644 index 5e2ee45bcf612..0000000000000 --- a/graph/ui-tooltips/src/lib/project-edge-tooltip.stories.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import type { Meta, StoryObj } from '@storybook/react'; -import { - ProjectEdgeNodeTooltip, - ProjectEdgeNodeTooltipProps, -} from './project-edge-tooltip'; -import { Tooltip } from './tooltip'; - -const meta: Meta = { - component: ProjectEdgeNodeTooltip, - title: 'Tooltips/ProjectEdgeNodeTooltip', -}; - -export default meta; -type Story = StoryObj; - -export const Primary: Story = { - args: { - type: 'static', - target: 'lib1', - source: 'lib2', - fileDependencies: [{ fileName: 'some/file.ts' }], - } as ProjectEdgeNodeTooltipProps, - render: (args) => { - return ( -
    - ) as any} - > -

    Internal Reference

    -
    -
    - ); - }, -}; diff --git a/graph/ui-tooltips/src/lib/project-edge-tooltip.tsx b/graph/ui-tooltips/src/lib/project-edge-tooltip.tsx deleted file mode 100644 index 6f16f67d69e3f..0000000000000 --- a/graph/ui-tooltips/src/lib/project-edge-tooltip.tsx +++ /dev/null @@ -1,61 +0,0 @@ -import { Tag } from '@nx/graph/ui-components'; - -export interface ProjectEdgeNodeTooltipProps { - type: string; - source: string; - target: string; - fileDependencies: Array<{ fileName: string }>; - description?: string; - renderMode?: 'nx-console' | 'nx-docs'; - sourceRoot?: string; - fileClickCallback?: (fileName: string) => void; -} - -export function ProjectEdgeNodeTooltip({ - type, - source, - target, - fileDependencies, - description, - fileClickCallback, -}: ProjectEdgeNodeTooltipProps) { - return ( -
    -

    - {type ?? 'unknown'} - - {source} → {target} - -

    - {description ?

    {description}

    : null} - {type !== 'implicit' && fileDependencies?.length > 0 ? ( -
    -
    - Files -
    -
      - {fileDependencies.map((fileDep) => ( -
    • fileClickCallback(fileDep.fileName) - : () => {} - } - > - - {fileDep.fileName} - -
    • - ))} -
    -
    - ) : null} -
    - ); -} diff --git a/graph/ui-tooltips/src/lib/project-node-tooltip.stories.tsx b/graph/ui-tooltips/src/lib/project-node-tooltip.stories.tsx deleted file mode 100644 index 1d3859f753c02..0000000000000 --- a/graph/ui-tooltips/src/lib/project-node-tooltip.stories.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import type { Meta, StoryObj } from '@storybook/react'; -import { - ProjectNodeToolTip, - ProjectNodeToolTipProps, -} from './project-node-tooltip'; -import { Tooltip } from './tooltip'; - -const meta: Meta = { - component: ProjectNodeToolTip, - title: 'Tooltips/ProjectNodeToolTip', -}; - -export default meta; -type Story = StoryObj; - -export const Primary: Story = { - render: (args) => ( -
    - ) as any}> -

    Internal Reference

    -
    -
    - ), - args: { - type: 'app', - tags: ['type:app', 'scope:store'], - id: 'store', - } as ProjectNodeToolTipProps, -}; diff --git a/graph/ui-tooltips/src/lib/project-node-tooltip.tsx b/graph/ui-tooltips/src/lib/project-node-tooltip.tsx deleted file mode 100644 index 79191a10b1449..0000000000000 --- a/graph/ui-tooltips/src/lib/project-node-tooltip.tsx +++ /dev/null @@ -1,63 +0,0 @@ -import { - PencilSquareIcon, - DocumentMagnifyingGlassIcon, -} from '@heroicons/react/24/outline'; -import { Tag } from '@nx/graph/ui-components'; -import { ReactNode } from 'react'; - -export interface ProjectNodeToolTipProps { - type: 'app' | 'lib' | 'e2e'; - id: string; - tags: string[]; - description?: string; - openConfigCallback?: () => void; - renderMode?: 'nx-console' | 'nx-docs'; - children?: ReactNode | ReactNode[]; -} - -export function ProjectNodeToolTip({ - type, - id, - tags, - children, - description, - openConfigCallback, - renderMode, -}: ProjectNodeToolTipProps) { - return ( -
    -

    -
    - {type} - {id} -
    - {openConfigCallback && ( - - )} -

    - {tags.length > 0 ? ( -

    - tags -

    - {tags.join(', ')} -

    - ) : null} - {description ?

    {description}

    : null} - {children} -
    - ); -} diff --git a/graph/ui-tooltips/src/lib/property-info-tooltip.stories.tsx b/graph/ui-tooltips/src/lib/property-info-tooltip.stories.tsx deleted file mode 100644 index 48fe2be3248a9..0000000000000 --- a/graph/ui-tooltips/src/lib/property-info-tooltip.stories.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import type { Meta, StoryObj } from '@storybook/react'; -import { - PropertyInfoTooltipProps, - PropertyInfoTooltip, -} from './property-info-tooltip'; -import { Tooltip } from './tooltip'; - -const meta: Meta = { - component: PropertyInfoTooltip, - title: 'Tooltips/PropertyInfoToolTip', -}; - -export default meta; -type Story = StoryObj; - -export const Primary: Story = { - render: (args) => ( -
    - ) as any}> -

    Internal Reference

    -
    -
    - ), - args: { - type: 'inputs', - } as PropertyInfoTooltipProps, -}; diff --git a/graph/ui-tooltips/src/lib/property-info-tooltip.tsx b/graph/ui-tooltips/src/lib/property-info-tooltip.tsx deleted file mode 100644 index 2d12ae6a81db1..0000000000000 --- a/graph/ui-tooltips/src/lib/property-info-tooltip.tsx +++ /dev/null @@ -1,125 +0,0 @@ -import { ExternalLink } from './external-link'; -import { twMerge } from 'tailwind-merge'; - -type PropertyInfoTooltipType = - | 'targets' - | 'executors' - | 'cacheable' - | 'inputs' - | 'outputs' - | 'dependsOn' - | 'options' - | 'configurations' - | 'release' - | 'parallelism'; - -type PropertyInfoTooltipTypeOptions = { - docsUrl?: string; - docsLinkText?: string; - heading: string; - description: string; -}; -export interface PropertyInfoTooltipProps { - type: PropertyInfoTooltipType; -} - -const PROPERTY_INFO_TOOLTIP_TYPE_OPTIONS: Record< - PropertyInfoTooltipType, - PropertyInfoTooltipTypeOptions -> = { - targets: { - docsUrl: 'https://nx.dev/features/run-tasks', - docsLinkText: 'Learn more about running tasks', - heading: 'Target', - description: - 'A Target is the definition of a task for a project. These can be run in many different ways.', - }, - executors: { - docsUrl: 'https://nx.dev/concepts/executors-and-configurations', - heading: 'Executors', - description: - 'Executors define what happens when a task is run.\nCheck the documentation of the executor below to learn more about what it does.', - }, - cacheable: { - docsUrl: 'https://nx.dev/concepts/how-caching-works', - docsLinkText: 'Learn more about Caching', - heading: 'Caching', - description: - 'This task will be cached by Nx. When the Inputs have not changed the Outputs will be restored from the cache.', - }, - inputs: { - docsUrl: 'https://nx.dev/recipes/running-tasks/configure-inputs', - heading: 'Inputs', - description: `Inputs are used by the task to produce Outputs. Inputs are used to determine when the Outputs of a task can be restored from the cache.`, - }, - outputs: { - docsUrl: 'https://nx.dev/recipes/running-tasks/configure-outputs', - heading: 'Outputs', - description: - 'Outputs are the results of a task. Outputs are restored from the cache when the Inputs are the same as a previous run.', - }, - dependsOn: { - docsUrl: 'https://nx.dev/concepts/task-pipeline-configuration', - docsLinkText: 'Learn more about creating dependencies between tasks', - heading: 'Depends On', - description: - 'This is a list of other tasks which must be completed before running this task.', - }, - options: { - docsUrl: 'https://nx.dev/concepts/executors-and-configurations', - heading: 'Options', - description: 'Options modify the behaviour of the task.', - }, - configurations: { - docsUrl: 'https://nx.dev/concepts/executors-and-configurations', - heading: 'Configurations', - description: - 'Configurations are sets of Options to allow a Target to be used in different scenarios.', - }, - release: { - heading: 'nx release', - description: - "The nx-release-publish target is used to publish your project with nxrelease. Don't invoke this directly - use nx release publish instead.", - docsUrl: 'https://nx.dev/nx-api/nx/documents/release', - }, - parallelism: { - heading: 'Parallelism', - description: - 'By default, tasks are run in parallel with other tasks. Setting `"parallelism": false` ensures that the target will not run in parallel with other tasks on the same machine.', - docsUrl: 'https://nx.dev/reference/project-configuration#parallelism', - }, -}; - -export function PropertyInfoTooltip({ type }: PropertyInfoTooltipProps) { - const propertyInfo = PROPERTY_INFO_TOOLTIP_TYPE_OPTIONS[type]; - - return ( -
    -

    - {propertyInfo.heading} -

    -
    -

    - {propertyInfo.description} -

    -
    - {propertyInfo.docsUrl ? ( -
    -

    - - {propertyInfo.docsLinkText ?? - `Learn more about ${propertyInfo.heading}`} - -

    -
    - ) : null} -
    - ); -} diff --git a/graph/ui-tooltips/src/lib/sourcemap-info-tooltip.stories.tsx b/graph/ui-tooltips/src/lib/sourcemap-info-tooltip.stories.tsx deleted file mode 100644 index 19de6116c5c70..0000000000000 --- a/graph/ui-tooltips/src/lib/sourcemap-info-tooltip.stories.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import type { Meta, StoryObj } from '@storybook/react'; -import { - SourcemapInfoToolTipProps, - SourcemapInfoToolTip, -} from './sourcemap-info-tooltip'; -import { Tooltip } from './tooltip'; - -const meta: Meta = { - component: SourcemapInfoToolTip, - title: 'Tooltips/SourcemapInfoToolTip', -}; - -export default meta; -type Story = StoryObj; - -export const Primary: Story = { - render: (args) => ( -
    - ) as any} - > -

    Internal Reference

    -
    -
    - ), - args: { - propertyKey: 'targets.build.command', - plugin: 'nx-core-build-project-json-nodes', - file: 'tools/eslint-rules/project.json', - } as SourcemapInfoToolTipProps, -}; diff --git a/graph/ui-tooltips/src/lib/sourcemap-info-tooltip.tsx b/graph/ui-tooltips/src/lib/sourcemap-info-tooltip.tsx deleted file mode 100644 index b7534c68cdd07..0000000000000 --- a/graph/ui-tooltips/src/lib/sourcemap-info-tooltip.tsx +++ /dev/null @@ -1,68 +0,0 @@ -import { type ReactNode } from 'react'; -import { ExternalLink } from './external-link'; -import { twMerge } from 'tailwind-merge'; - -export interface SourcemapInfoToolTipProps { - propertyKey: string; - plugin: string; - file: string; - children?: ReactNode | ReactNode[]; - showLink?: boolean; -} - -export function SourcemapInfoToolTip({ - propertyKey, - plugin, - file, - showLink, -}: SourcemapInfoToolTipProps) { - // Target property key is in the form `target.${targetName}` - // Every other property within in the target has the form `target.${targetName}.${propertyName} - const isTarget = propertyKey.split('.').length === 2; - - const docsUrlSlug: string | undefined = plugin?.startsWith('@nx/') - ? plugin.replace('@nx/', '').split('/')[0] - : undefined; - - const tooltipContent = ( - <> -

    - {isTarget ? 'Created' : 'Set'} by: - - {docsUrlSlug ? ( - - {plugin} - - ) : ( - `${plugin}` - )} - -

    -

    - From: {file} -

    - - ); - - return ( -
    -
    - {tooltipContent} -
    - {showLink && ( -
    -

    - - Learn more about how projects are configured - -

    -
    - )} -
    - ); -} diff --git a/graph/ui-tooltips/src/lib/task-node-tooltip.stories.tsx b/graph/ui-tooltips/src/lib/task-node-tooltip.stories.tsx deleted file mode 100644 index e36f3fc550e5c..0000000000000 --- a/graph/ui-tooltips/src/lib/task-node-tooltip.stories.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import type { Meta, StoryObj } from '@storybook/react'; -import { TaskNodeTooltip } from './task-node-tooltip'; -import { Tooltip } from './tooltip'; - -const meta: Meta = { - component: TaskNodeTooltip, - title: 'Tooltips/TaskNodeTooltip', -}; - -export default meta; -type Story = StoryObj; - -export const Primary: Story = { - args: { - id: 'my-lib:build', - executor: '@nrwl/webpack:webpack', - }, - render: (args) => ( -
    - ) as any}> -

    Internal Reference

    -
    -
    - ), -}; diff --git a/graph/ui-tooltips/src/lib/task-node-tooltip.tsx b/graph/ui-tooltips/src/lib/task-node-tooltip.tsx deleted file mode 100644 index 2f5d4e87cad1e..0000000000000 --- a/graph/ui-tooltips/src/lib/task-node-tooltip.tsx +++ /dev/null @@ -1,69 +0,0 @@ -import { - DocumentMagnifyingGlassIcon, - PencilSquareIcon, - PlayIcon, -} from '@heroicons/react/24/outline'; -import { Tag } from '@nx/graph/ui-components'; -import { ReactNode } from 'react'; - -export interface TaskNodeTooltipProps { - id: string; - executor: string; - runTaskCallback?: () => void; - description?: string; - inputs?: Record; - openConfigCallback?: () => void; - renderMode?: 'nx-console' | 'nx-docs'; - children?: ReactNode | ReactNode[]; -} - -export function TaskNodeTooltip({ - id, - executor, - description, - renderMode, - runTaskCallback, - openConfigCallback, - children, -}: TaskNodeTooltipProps) { - return ( -
    -

    -
    -
    - {executor} - {id} -
    - {openConfigCallback && ( - - )} -
    - {runTaskCallback && ( - - )} -

    - {description ?

    {description}

    : null} - {children} -
    - ); -} diff --git a/graph/ui-tooltips/src/lib/tooltip-button.tsx b/graph/ui-tooltips/src/lib/tooltip-button.tsx deleted file mode 100644 index 49859c90cfdc1..0000000000000 --- a/graph/ui-tooltips/src/lib/tooltip-button.tsx +++ /dev/null @@ -1,31 +0,0 @@ -/* eslint-disable-next-line */ -import { Link, LinkProps } from 'react-router-dom'; -import { HTMLAttributes } from 'react'; - -const sharedClasses = - 'inline-flex justify-center rounded-md border border-slate-300 bg-slate-50 py-2 px-4 mt-2 text-slate-500 hover:bg-slate-100 dark:border-slate-600 dark:bg-slate-800 dark:text-slate-300 hover:dark:bg-slate-700'; - -export function TooltipButton({ - className, - children, - ...rest -}: HTMLAttributes) { - return ( - - ); -} - -export function TooltipLinkButton({ - to, - className, - children, - ...rest -}: LinkProps) { - return ( - - {children} - - ); -} diff --git a/graph/ui-tooltips/src/lib/tooltip.tsx b/graph/ui-tooltips/src/lib/tooltip.tsx deleted file mode 100644 index 6520a43edf54e..0000000000000 --- a/graph/ui-tooltips/src/lib/tooltip.tsx +++ /dev/null @@ -1,175 +0,0 @@ -import { - Attributes, - cloneElement, - HTMLAttributes, - ReactElement, - ReactNode, - useLayoutEffect, - useRef, - useState, -} from 'react'; - -import { - useClick, - arrow, - autoUpdate, - flip, - offset, - Placement, - ReferenceType, - shift, - useFloating, - useInteractions, - useDismiss, - useHover, - useRole, - safePolygon, - useTransitionStyles, - FloatingPortal, -} from '@floating-ui/react'; - -export type TooltipProps = HTMLAttributes & { - open?: boolean; - content: ReactNode; - children?: ReactElement; - placement?: Placement; - reference?: ReferenceType; - openAction?: 'click' | 'hover' | 'manual'; - buffer?: number; - showTooltipArrow?: boolean; - strategy?: 'absolute' | 'fixed'; - usePortal?: boolean; -}; - -export function Tooltip({ - children, - open = false, - content, - placement = 'top', - reference: externalReference, - openAction = 'click', - strategy = 'absolute', - buffer = 0, - showTooltipArrow = true, - usePortal = false, -}: TooltipProps) { - const [isOpen, setIsOpen] = useState(open); - const arrowRef = useRef(null); - - const { - x, - y, - refs, - strategy: appliedStrategy, - placement: finalPlacement, - middlewareData: { arrow: { x: arrowX, y: arrowY } = {} }, - context, - } = useFloating({ - placement, - whileElementsMounted: strategy === 'fixed' ? autoUpdate : undefined, - open: isOpen, - onOpenChange: setIsOpen, - strategy, - middleware: [ - offset(6), - flip(), - shift({ padding: 6 }), - arrow({ element: arrowRef }), - ], - }); - - const { isMounted, styles: animationStyles } = useTransitionStyles(context, { - duration: 200, - initial: { - opacity: openAction === 'hover' ? 0 : 1, - }, - }); - - const staticSide: string = - { - top: 'bottom', - right: 'left', - bottom: 'top', - left: 'right', - }[finalPlacement.split('-')[0]] || 'bottom'; - - useLayoutEffect(() => { - if (!!externalReference) { - refs.setReference(externalReference); - } - }, [refs, externalReference]); - - const click = useClick(context, { enabled: openAction === 'click' }); - const dismiss = useDismiss(context, { - enabled: openAction === 'click', - referencePress: false, - outsidePress: true, - outsidePressEvent: 'mousedown', - }); - const hover = useHover(context, { - restMs: 300, - enabled: openAction === 'hover', - delay: { open: 0, close: 150 }, - handleClose: safePolygon({ buffer }), - }); - const role = useRole(context, { role: 'tooltip' }); - - const { getReferenceProps, getFloatingProps } = useInteractions([ - click, - hover, - dismiss, - role, - ]); - - const cloneProps: Partial & Attributes = { - ref: refs.setReference, - ...getReferenceProps(), - }; - - const renderTooltip = () => ( -
    - {showTooltipArrow && ( -
    - )} -
    - {content} -
    -
    - ); - - return ( - <> - {!externalReference && !!children - ? cloneElement(children, cloneProps) - : children} - {isOpen && isMounted ? ( - usePortal ? ( - {renderTooltip()} - ) : ( - renderTooltip() - ) - ) : null} - - ); -} diff --git a/graph/ui-tooltips/tailwind.config.js b/graph/ui-tooltips/tailwind.config.js deleted file mode 100644 index a130bfceccd48..0000000000000 --- a/graph/ui-tooltips/tailwind.config.js +++ /dev/null @@ -1,40 +0,0 @@ -const path = require('path'); - -// nx-ignore-next-line -const { createGlobPatternsForDependencies } = require('@nx/react/tailwind'); - -module.exports = { - content: [ - path.join(__dirname, 'src/**/*.{js,ts,jsx,tsx,html}'), - ...createGlobPatternsForDependencies(__dirname), - ], - darkMode: 'class', // or 'media' or 'class' - theme: { - extend: { - typography: { - DEFAULT: { - css: { - 'code::before': { - content: '', - }, - 'code::after': { - content: '', - }, - 'blockquote p:first-of-type::before': { - content: '', - }, - 'blockquote p:last-of-type::after': { - content: '', - }, - }, - }, - }, - }, - }, - variants: { - extend: { - translate: ['group-hover'], - }, - }, - plugins: [require('@tailwindcss/typography')], -}; diff --git a/graph/ui-tooltips/tsconfig.json b/graph/ui-tooltips/tsconfig.json deleted file mode 100644 index 0672cc05841f6..0000000000000 --- a/graph/ui-tooltips/tsconfig.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "compilerOptions": { - "jsx": "react-jsx", - "allowJs": false, - "esModuleInterop": false, - "allowSyntheticDefaultImports": true, - "strict": true, - "lib": ["DOM", "es2022"] - }, - "files": [], - "include": [], - "references": [ - { - "path": "./tsconfig.lib.json" - }, - { - "path": "./tsconfig.spec.json" - }, - { - "path": "./tsconfig.storybook.json" - } - ], - "extends": "../../tsconfig.base.json" -} diff --git a/graph/ui-tooltips/tsconfig.lib.json b/graph/ui-tooltips/tsconfig.lib.json deleted file mode 100644 index e802584e02ae9..0000000000000 --- a/graph/ui-tooltips/tsconfig.lib.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "types": ["node"] - }, - "files": [ - "../../node_modules/@nx/react/typings/cssmodule.d.ts", - "../../node_modules/@nx/react/typings/image.d.ts" - ], - "exclude": [ - "jest.config.ts", - "src/**/*.spec.ts", - "src/**/*.test.ts", - "src/**/*.spec.tsx", - "src/**/*.test.tsx", - "src/**/*.spec.js", - "src/**/*.test.js", - "src/**/*.spec.jsx", - "src/**/*.test.jsx", - "**/*.stories.ts", - "**/*.stories.js", - "**/*.stories.jsx", - "**/*.stories.tsx" - ], - "include": ["src/**/*.js", "src/**/*.jsx", "src/**/*.ts", "src/**/*.tsx"] -} diff --git a/graph/ui-tooltips/tsconfig.spec.json b/graph/ui-tooltips/tsconfig.spec.json deleted file mode 100644 index 26ef046ac5e54..0000000000000 --- a/graph/ui-tooltips/tsconfig.spec.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "module": "commonjs", - "types": ["jest", "node"] - }, - "include": [ - "jest.config.ts", - "src/**/*.test.ts", - "src/**/*.spec.ts", - "src/**/*.test.tsx", - "src/**/*.spec.tsx", - "src/**/*.test.js", - "src/**/*.spec.js", - "src/**/*.test.jsx", - "src/**/*.spec.jsx", - "src/**/*.d.ts" - ] -} diff --git a/graph/ui-tooltips/tsconfig.storybook.json b/graph/ui-tooltips/tsconfig.storybook.json deleted file mode 100644 index 98ee6645c6232..0000000000000 --- a/graph/ui-tooltips/tsconfig.storybook.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "emitDecoratorMetadata": true, - "outDir": "" - }, - "files": [ - "../../node_modules/@nx/react/typings/styled-jsx.d.ts", - "../../node_modules/@nx/react/typings/cssmodule.d.ts", - "../../node_modules/@nx/react/typings/image.d.ts" - ], - "exclude": [ - "src/**/*.spec.ts", - "src/**/*.spec.js", - "src/**/*.spec.tsx", - "src/**/*.spec.jsx" - ], - "include": [ - "src/**/*.stories.ts", - "src/**/*.stories.js", - "src/**/*.stories.jsx", - "src/**/*.stories.tsx", - "src/**/*.stories.mdx", - ".storybook/*.js" - ] -} diff --git a/nx-dev/feature-ai/src/lib/feed/feed-answer.spec.tsx b/nx-dev/feature-ai/src/lib/feed/feed-answer.spec.tsx index 02f983f7c9192..9db41fa96def4 100644 --- a/nx-dev/feature-ai/src/lib/feed/feed-answer.spec.tsx +++ b/nx-dev/feature-ai/src/lib/feed/feed-answer.spec.tsx @@ -1,5 +1,32 @@ import { normalizeContent } from './feed-answer'; +jest.mock('@nx/graph/ui-icons', () => { + return { + Icon: jest.fn(() => null), + }; +}); +jest.mock('@nx/graph/ui-tooltips', () => { + return { + Tooltip: jest.fn(() => null), + PropertyInfoTooltip: jest.fn(() => null), + }; +}); +jest.mock('@nx/graph/ui-components', () => { + return { + CopyToClipboardButton: jest.fn(() => null), + }; +}); +jest.mock('@nx/graph/shared', () => { + return { + ExpandedTargetsContext: jest.fn(() => null), + }; +}); +jest.mock('@nx/nx-dev/ui-primitives', () => { + return { + cx: jest.fn(() => null), + }; +}); + describe('FeedAnswer', () => { describe('normalizeContent', () => { it('should normalize links to format expected by renderMarkdown', () => { diff --git a/nx-dev/nx-dev/tailwind.config.js b/nx-dev/nx-dev/tailwind.config.js index 876ca005986b9..5ac8e9c37446d 100644 --- a/nx-dev/nx-dev/tailwind.config.js +++ b/nx-dev/nx-dev/tailwind.config.js @@ -1,12 +1,17 @@ -const path = require('path'); -// Ignore @nx/next dependency since it is the installed version not the one in the workspace -// nx-ignore-next-line -const { createGlobPatternsForDependencies } = require('@nx/next/tailwind'); +// @ts-check + +const path = require('node:path'); const plugin = require('tailwindcss/plugin'); const { default: flattenColorPalette, } = require('tailwindcss/lib/util/flattenColorPalette'); +// Ignore these nx related dependencies since they are the installed versions not the ones in the workspace +// nx-ignore-next-line +const { workspaceRoot } = require('@nx/devkit'); +// nx-ignore-next-line +const { createGlobPatternsForDependencies } = require('@nx/next/tailwind'); + if (!createGlobPatternsForDependencies(__dirname).length) throw Error('GRAPH ISSUE: No dependency found when many are expected.'); @@ -48,6 +53,12 @@ module.exports = { content: [ path.join(__dirname, '{pages,app}/**/*.{js,ts,jsx,tsx}'), ...createGlobPatternsForDependencies(__dirname), + // Resolve the classes used in @nx/graph components + // TODO: make a decision on whether this is really the best approach, or if precompiling and deduplicating the classes would be better + path.join( + workspaceRoot, + 'node_modules/@nx/graph/**/*.{js,ts,jsx,tsx,html}' + ), ], theme: { extend: { diff --git a/nx-dev/ui-markdoc/src/lib/tags/project-details.component.tsx b/nx-dev/ui-markdoc/src/lib/tags/project-details.component.tsx index 13a8aeef4609c..796b606b88b8b 100644 --- a/nx-dev/ui-markdoc/src/lib/tags/project-details.component.tsx +++ b/nx-dev/ui-markdoc/src/lib/tags/project-details.component.tsx @@ -7,7 +7,7 @@ import { useLayoutEffect, useState, } from 'react'; -import { ProjectDetails as ProjectDetailsUi } from '@nx/graph/ui-project-details'; +import { ProjectDetails as ProjectDetailsUi } from '@nx/graph-internal/ui-project-details'; import { ExpandedTargetsProvider } from '@nx/graph/shared'; export function Loading() { diff --git a/package.json b/package.json index 5808ea098412d..26394755ca7aa 100644 --- a/package.json +++ b/package.json @@ -220,7 +220,7 @@ "less": "4.1.3", "less-loader": "11.1.0", "license-webpack-plugin": "^4.0.2", - "lines-and-columns": "~2.0.3", + "lines-and-columns": "2.0.3", "loader-utils": "2.0.3", "magic-string": "~0.30.2", "markdown-factory": "^0.0.6", @@ -319,6 +319,7 @@ "@markdoc/markdoc": "0.2.2", "@monaco-editor/react": "^4.4.6", "@napi-rs/canvas": "^0.1.52", + "@nx/graph": "0.0.1-alpha.13", "@react-spring/three": "^9.7.3", "@react-three/drei": "^9.108.3", "@react-three/fiber": "^8.16.8", diff --git a/packages/nx/package.json b/packages/nx/package.json index 92d1f174e56f6..d389ce2022040 100644 --- a/packages/nx/package.json +++ b/packages/nx/package.json @@ -56,7 +56,7 @@ "ignore": "^5.0.4", "jest-diff": "^29.4.1", "jsonc-parser": "3.2.0", - "lines-and-columns": "~2.0.3", + "lines-and-columns": "2.0.3", "minimatch": "9.0.3", "npm-run-path": "^4.0.1", "open": "^8.4.0", diff --git a/packages/workspace/src/utilities/typescript/get-source-nodes.ts b/packages/workspace/src/utilities/typescript/get-source-nodes.ts index 6c3ce9c83b2df..ae24733aa9dd5 100644 --- a/packages/workspace/src/utilities/typescript/get-source-nodes.ts +++ b/packages/workspace/src/utilities/typescript/get-source-nodes.ts @@ -13,7 +13,7 @@ export function getSourceNodes(sourceFile: ts.SourceFile): ts.Node[] { if (node) { result.push(node); if (node.getChildCount(sourceFile) >= 0) { - nodes.unshift(...node.getChildren()); + nodes.unshift(...node.getChildren(sourceFile)); } } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4a1e680474c4e..ea383fd7134ee 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -30,6 +30,9 @@ importers: '@napi-rs/canvas': specifier: ^0.1.52 version: 0.1.52 + '@nx/graph': + specifier: 0.0.1-alpha.13 + version: 0.0.1-alpha.13(@nx/devkit@19.7.0-beta.1(nx@19.7.0-beta.1(@swc-node/register@1.9.1(@swc/core@1.5.7(@swc/helpers@0.5.11))(@swc/types@0.1.7)(typescript@5.5.3))(@swc/core@1.5.7(@swc/helpers@0.5.11))))(nx@19.7.0-beta.1(@swc-node/register@1.9.1(@swc/core@1.5.7(@swc/helpers@0.5.11))(@swc/types@0.1.7)(typescript@5.5.3))(@swc/core@1.5.7(@swc/helpers@0.5.11)))(react-dom@18.3.1(react@18.3.1))(react-router-dom@6.23.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1) '@react-spring/three': specifier: ^9.7.3 version: 9.7.3(@react-three/fiber@8.16.8(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(three@0.166.1))(react@18.3.1)(three@0.166.1) @@ -752,7 +755,7 @@ importers: specifier: ^4.0.2 version: 4.0.2(webpack@5.88.0(@swc/core@1.5.7(@swc/helpers@0.5.11))(esbuild@0.19.5)(webpack-cli@5.1.4)) lines-and-columns: - specifier: ~2.0.3 + specifier: 2.0.3 version: 2.0.3 loader-utils: specifier: 2.0.3 @@ -5771,6 +5774,15 @@ packages: '@zkochan/js-yaml': optional: true + '@nx/graph@0.0.1-alpha.13': + resolution: {integrity: sha512-sNWhHix9CykuzVUBBsUBOSvTx+OrAen/r9qNZhxNhmGsvmAySIgL5yElShwBGjy09n4AiaCWek+ovkhYb2h9KQ==} + peerDependencies: + '@nx/devkit': '>= 19 < 20' + nx: '>= 19 < 20' + react: '>= 18 < 19' + react-dom: '>= 18 < 19' + react-router-dom: '>= 6 < 7' + '@nx/jest@19.7.0-beta.1': resolution: {integrity: sha512-5xygZTCCtYheCaL5fnK9B6uBSNhf/SZIx1YqxzB6MvgAWv+Ghnoj04DZ6hmyEWuIpHuVOPgR4ys6x/Q5ZIJiYw==} @@ -20824,7 +20836,7 @@ snapshots: '@babel/plugin-transform-class-properties@7.24.7(@babel/core@7.24.7)': dependencies: '@babel/core': 7.24.7 - '@babel/helper-create-class-features-plugin': 7.24.7(@babel/core@7.24.7) + '@babel/helper-create-class-features-plugin': 7.24.7(@babel/core@7.23.2) '@babel/helper-plugin-utils': 7.24.7 transitivePeerDependencies: - supports-color @@ -21309,7 +21321,7 @@ snapshots: '@babel/plugin-transform-modules-commonjs@7.24.7(@babel/core@7.24.7)': dependencies: '@babel/core': 7.24.7 - '@babel/helper-module-transforms': 7.24.7(@babel/core@7.24.7) + '@babel/helper-module-transforms': 7.24.7(@babel/core@7.23.2) '@babel/helper-plugin-utils': 7.24.7 '@babel/helper-simple-access': 7.24.7 transitivePeerDependencies: @@ -21448,7 +21460,7 @@ snapshots: dependencies: '@babel/core': 7.24.7 '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.24.7) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.23.2) '@babel/plugin-transform-nullish-coalescing-operator@7.24.7(@babel/core@7.25.2)': dependencies: @@ -21572,7 +21584,7 @@ snapshots: '@babel/core': 7.24.7 '@babel/helper-plugin-utils': 7.24.7 '@babel/helper-skip-transparent-expression-wrappers': 7.24.7 - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.24.7) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.23.2) transitivePeerDependencies: - supports-color @@ -21631,7 +21643,7 @@ snapshots: '@babel/plugin-transform-private-methods@7.24.7(@babel/core@7.24.7)': dependencies: '@babel/core': 7.24.7 - '@babel/helper-create-class-features-plugin': 7.24.7(@babel/core@7.24.7) + '@babel/helper-create-class-features-plugin': 7.24.7(@babel/core@7.23.2) '@babel/helper-plugin-utils': 7.24.8 transitivePeerDependencies: - supports-color @@ -25558,6 +25570,23 @@ snapshots: - supports-color - verdaccio + '@nx/graph@0.0.1-alpha.13(@nx/devkit@19.7.0-beta.1(nx@19.7.0-beta.1(@swc-node/register@1.9.1(@swc/core@1.5.7(@swc/helpers@0.5.11))(@swc/types@0.1.7)(typescript@5.5.3))(@swc/core@1.5.7(@swc/helpers@0.5.11))))(nx@19.7.0-beta.1(@swc-node/register@1.9.1(@swc/core@1.5.7(@swc/helpers@0.5.11))(@swc/types@0.1.7)(typescript@5.5.3))(@swc/core@1.5.7(@swc/helpers@0.5.11)))(react-dom@18.3.1(react@18.3.1))(react-router-dom@6.23.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)': + dependencies: + '@floating-ui/react': 0.26.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@headlessui/react': 1.7.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@heroicons/react': 2.1.5(react@18.3.1) + '@nx/devkit': 19.7.0-beta.1(nx@19.7.0-beta.1(@swc-node/register@1.9.1(@swc/core@1.5.7(@swc/helpers@0.5.11))(@swc/types@0.1.7)(typescript@5.5.3))(@swc/core@1.5.7(@swc/helpers@0.5.11))) + classnames: 2.5.1 + cytoscape: 3.23.0 + cytoscape-dagre: 2.4.0(cytoscape@3.23.0) + cytoscape-popper: 2.0.0(cytoscape@3.23.0) + nx: 19.7.0-beta.1(@swc-node/register@1.9.1(@swc/core@1.5.7(@swc/helpers@0.5.11))(@swc/types@0.1.7)(typescript@5.5.3))(@swc/core@1.5.7(@swc/helpers@0.5.11)) + react: 18.3.1 + react-copy-to-clipboard: 5.1.0(react@18.3.1) + react-dom: 18.3.1(react@18.3.1) + react-router-dom: 6.23.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + tailwind-merge: 2.4.0 + '@nx/jest@19.7.0-beta.1(@babel/traverse@7.25.4)(@swc-node/register@1.9.1(@swc/core@1.5.7(@swc/helpers@0.5.11))(@swc/types@0.1.7)(typescript@5.5.3))(@swc/core@1.5.7(@swc/helpers@0.5.11))(@types/node@18.19.8)(nx@19.7.0-beta.1(@swc-node/register@1.9.1(@swc/core@1.5.7(@swc/helpers@0.5.11))(@swc/types@0.1.7)(typescript@5.5.3))(@swc/core@1.5.7(@swc/helpers@0.5.11)))(ts-node@10.9.1(@swc/core@1.5.7(@swc/helpers@0.5.11))(@types/node@18.19.8)(typescript@5.5.3))(typescript@5.5.3)(verdaccio@5.31.0(encoding@0.1.13)(typanion@3.14.0))': dependencies: '@jest/reporters': 29.5.0 @@ -30456,7 +30485,7 @@ snapshots: code-red@1.0.4: dependencies: - '@jridgewell/sourcemap-codec': 1.4.15 + '@jridgewell/sourcemap-codec': 1.5.0 '@types/estree': 1.0.5 acorn: 8.11.3 estree-walker: 3.0.3 @@ -39936,7 +39965,7 @@ snapshots: svelte@4.2.8: dependencies: '@ampproject/remapping': 2.3.0 - '@jridgewell/sourcemap-codec': 1.4.15 + '@jridgewell/sourcemap-codec': 1.5.0 '@jridgewell/trace-mapping': 0.3.25 acorn: 8.11.3 aria-query: 5.3.0 @@ -39946,7 +39975,7 @@ snapshots: estree-walker: 3.0.3 is-reference: 3.0.2 locate-character: 3.0.0 - magic-string: 0.30.10 + magic-string: 0.30.11 periscopic: 3.1.0 svg-parser@2.0.4: {} diff --git a/tsconfig.base.json b/tsconfig.base.json index 1edc5103a0bdf..099654fb78efe 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -37,15 +37,14 @@ "@nx/express": ["packages/express"], "@nx/gradle": ["packages/gradle/src/index.ts"], "@nx/gradle/*": ["packages/gradle/*"], - "@nx/graph/project-details": ["graph/project-details/src/index.ts"], - "@nx/graph/shared": ["graph/shared/src/index.ts"], - "@nx/graph/ui-code-block": ["graph/ui-code-block/src/index.ts"], - "@nx/graph/ui-components": ["graph/ui-components/src/index.ts"], - "@nx/graph/ui-graph": ["graph/ui-graph/src/index.ts"], - "@nx/graph/ui-icons": ["graph/ui-icons/src/index.ts"], - "@nx/graph/ui-project-details": ["graph/ui-project-details/src/index.ts"], - "@nx/graph/ui-theme": ["graph/ui-theme/src/index.ts"], - "@nx/graph/ui-tooltips": ["graph/ui-tooltips/src/index.ts"], + "@nx/graph-internal/project-details": [ + "graph/project-details/src/index.ts" + ], + "@nx/graph-internal/ui-code-block": ["graph/ui-code-block/src/index.ts"], + "@nx/graph-internal/ui-project-details": [ + "graph/ui-project-details/src/index.ts" + ], + "@nx/graph-internal/ui-theme": ["graph/ui-theme/src/index.ts"], "@nx/jest": ["packages/jest"], "@nx/jest/*": ["packages/jest/*"], "@nx/js": ["packages/js/src/index.ts"],