feat(graph): add expandedTargets to project details on nx dev (#26911)
<!-- Please make sure you have read the submission guidelines before posting an PR --> <!-- https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr --> <!-- Please make sure that your commit message follows our format --> <!-- Example: `fix(nx): must begin with lowercase` --> <!-- If this is a particularly complex change or feature addition, you can request a dedicated Nx release for this pull request branch. Mention someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they will confirm if the PR warrants its own release for testing purposes, and generate it for you if appropriate. --> ## Current Behavior <!-- This is the behavior we have today --> https://nx.dev/getting-started/tutorials/gradle-tutorial#running-tasks ## Expected Behavior <!-- This is the behavior we should expect with the changes in this PR --> https://nx-dev-git-feat-graph-add-expand-targets-nrwl.vercel.app/getting-started/tutorials/gradle-tutorial#running-tasks ## Related Issue(s) <!-- Please link the issue being fixed so it gets closed when this is merged. --> Fixes # --------- Co-authored-by: Max Kless <maxk@nrwl.io>
This commit is contained in:
parent
31c5745126
commit
66ff751f0d
@ -55,7 +55,7 @@ You can view the available tasks for your project in the project detail view:
|
|||||||
nx show project myproject-e2e --web
|
nx show project myproject-e2e --web
|
||||||
```
|
```
|
||||||
|
|
||||||
{% project-details title="Project Details View" height="100px" %}
|
{% project-details title="Project Details View" %}
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
|
|||||||
@ -111,7 +111,7 @@ details in a browser window.
|
|||||||
nx show project my-workspace --web
|
nx show project my-workspace --web
|
||||||
```
|
```
|
||||||
|
|
||||||
{% project-details title="Project Details View" height="100px" %}
|
{% project-details title="Project Details View" %}
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
|
|||||||
@ -110,7 +110,7 @@ details in a browser window.
|
|||||||
nx show project my-workspace --web
|
nx show project my-workspace --web
|
||||||
```
|
```
|
||||||
|
|
||||||
{% project-details title="Project Details View" height="100px" %}
|
{% project-details title="Project Details View" %}
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
|
|||||||
@ -21,7 +21,7 @@ For this recipe we'll use a project with the following `project.json` file:
|
|||||||
|
|
||||||
And the following [final configuration](/reference/project-configuration):
|
And the following [final configuration](/reference/project-configuration):
|
||||||
|
|
||||||
{% project-details title="Project Details View" height="100px" %}
|
{% project-details title="Project Details View" %}
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
|
|||||||
@ -12,7 +12,7 @@ Each source will [overwrite the previous source](/recipes/running-tasks/pass-arg
|
|||||||
nx show project myproject --web
|
nx show project myproject --web
|
||||||
```
|
```
|
||||||
|
|
||||||
{% project-details title="Project Details View" height="100px" %}
|
{% project-details title="Project Details View" %}
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
|
|||||||
@ -619,7 +619,7 @@ Nx identifies available tasks for your project from [tooling configuration files
|
|||||||
npx nx show project angular-store-e2e --web
|
npx nx show project angular-store-e2e --web
|
||||||
```
|
```
|
||||||
|
|
||||||
{% project-details title="Project Details View" height="100px" %}
|
{% project-details title="Project Details View" %}
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
|
|||||||
@ -211,7 +211,7 @@ Nx identifies available tasks for your project from [tooling configuration files
|
|||||||
nx show project e2e --web
|
nx show project e2e --web
|
||||||
```
|
```
|
||||||
|
|
||||||
{% project-details title="Project Details View" height="100px" %}
|
{% project-details title="Project Details View" %}
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
|
|||||||
@ -126,7 +126,7 @@ that we've installed reflects Gradle's tasks to Nx, which allows it to run any o
|
|||||||
./nx show project application --web
|
./nx show project application --web
|
||||||
```
|
```
|
||||||
|
|
||||||
{% project-details title="Project Details View" jsonFile="shared/tutorials/gradle-pdv.json" %}
|
{% project-details title="Project Details View" jsonFile="shared/tutorials/gradle-pdv.json" expandedTargets=["build"] height="520px" %}
|
||||||
{% /project-details %}
|
{% /project-details %}
|
||||||
|
|
||||||
The Nx command to run the `build` task for the `application` project is:
|
The Nx command to run the `build` task for the `application` project is:
|
||||||
|
|||||||
@ -134,7 +134,7 @@ Nx identifies available tasks for your project from [tooling configuration files
|
|||||||
npx nx show project react-store
|
npx nx show project react-store
|
||||||
```
|
```
|
||||||
|
|
||||||
{% project-details title="Project Details View (Simplified)" height="100px" %}
|
{% project-details title="Project Details View (Simplified)" %}
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
|
|||||||
@ -7,8 +7,16 @@ export const ExpandedTargetsContext = createContext<{
|
|||||||
collapseAllTargets?: () => void;
|
collapseAllTargets?: () => void;
|
||||||
}>({});
|
}>({});
|
||||||
|
|
||||||
export const ExpandedTargetsProvider = ({ children }) => {
|
export const ExpandedTargetsProvider = ({
|
||||||
const [expandedTargets, setExpandedTargets] = useState<string[]>([]);
|
children,
|
||||||
|
initialExpanededTargets = [],
|
||||||
|
}: {
|
||||||
|
children: React.ReactNode;
|
||||||
|
initialExpanededTargets?: string[];
|
||||||
|
}) => {
|
||||||
|
const [expandedTargets, setExpandedTargets] = useState<string[]>(
|
||||||
|
initialExpanededTargets
|
||||||
|
);
|
||||||
|
|
||||||
const toggleTarget = (targetName: string) => {
|
const toggleTarget = (targetName: string) => {
|
||||||
setExpandedTargets((prevExpandedTargets) => {
|
setExpandedTargets((prevExpandedTargets) => {
|
||||||
|
|||||||
@ -15,7 +15,10 @@ export function TargetConfigurationGroupContainer({
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<div className="mb-4 w-full">
|
<div
|
||||||
|
id={`target-group-container-${targetGroupName}`}
|
||||||
|
className="mb-4 w-full"
|
||||||
|
>
|
||||||
<TargetConfigurationGroupHeader
|
<TargetConfigurationGroupHeader
|
||||||
targetGroupName={targetGroupName}
|
targetGroupName={targetGroupName}
|
||||||
targetsNumber={targetsNumber}
|
targetsNumber={targetsNumber}
|
||||||
|
|||||||
@ -16,6 +16,7 @@ export const TargetConfigurationGroupHeader = ({
|
|||||||
}: TargetConfigurationGroupHeaderProps) => {
|
}: TargetConfigurationGroupHeaderProps) => {
|
||||||
return (
|
return (
|
||||||
<header
|
<header
|
||||||
|
id={`target-group-header-${targetGroupName}`}
|
||||||
className={`flex items-center gap-2 px-4 py-2 text-lg capitalize ${className}`}
|
className={`flex items-center gap-2 px-4 py-2 text-lg capitalize ${className}`}
|
||||||
>
|
>
|
||||||
{targetGroupName}{' '}
|
{targetGroupName}{' '}
|
||||||
|
|||||||
@ -71,6 +71,7 @@ export const TargetConfigurationDetailsHeader = ({
|
|||||||
? 'border-b bg-slate-50 dark:border-slate-700/60 dark:bg-slate-800'
|
? 'border-b bg-slate-50 dark:border-slate-700/60 dark:bg-slate-800'
|
||||||
: ''
|
: ''
|
||||||
)}
|
)}
|
||||||
|
id={`target-${targetName}`}
|
||||||
onClick={collapsable ? toggleCollapse : undefined}
|
onClick={collapsable ? toggleCollapse : undefined}
|
||||||
>
|
>
|
||||||
<div className="flex items-center justify-between gap-4">
|
<div className="flex items-center justify-between gap-4">
|
||||||
|
|||||||
@ -1,5 +1,12 @@
|
|||||||
'use client';
|
'use client';
|
||||||
import { JSX, ReactElement, useEffect, useState } from 'react';
|
import {
|
||||||
|
createRef,
|
||||||
|
JSX,
|
||||||
|
ReactElement,
|
||||||
|
useEffect,
|
||||||
|
useLayoutEffect,
|
||||||
|
useState,
|
||||||
|
} from 'react';
|
||||||
import { ProjectDetails as ProjectDetailsUi } from '@nx/graph/ui-project-details';
|
import { ProjectDetails as ProjectDetailsUi } from '@nx/graph/ui-project-details';
|
||||||
import { ExpandedTargetsProvider } from '@nx/graph/shared';
|
import { ExpandedTargetsProvider } from '@nx/graph/shared';
|
||||||
|
|
||||||
@ -20,14 +27,17 @@ export function ProjectDetails({
|
|||||||
height,
|
height,
|
||||||
title,
|
title,
|
||||||
jsonFile,
|
jsonFile,
|
||||||
|
expandedTargets = [],
|
||||||
children,
|
children,
|
||||||
}: {
|
}: {
|
||||||
height: string;
|
height: string;
|
||||||
title: string;
|
title: string;
|
||||||
jsonFile?: string;
|
jsonFile?: string;
|
||||||
|
expandedTargets?: string[];
|
||||||
children: ReactElement;
|
children: ReactElement;
|
||||||
}): JSX.Element {
|
}): JSX.Element {
|
||||||
const [parsedProps, setParsedProps] = useState<any>();
|
const [parsedProps, setParsedProps] = useState<any>();
|
||||||
|
const elementRef = createRef<HTMLDivElement>();
|
||||||
const getData = async (path: string) => {
|
const getData = async (path: string) => {
|
||||||
const response = await fetch('/documentation/' + path, {
|
const response = await fetch('/documentation/' + path, {
|
||||||
headers: {
|
headers: {
|
||||||
@ -43,6 +53,27 @@ export function ProjectDetails({
|
|||||||
}
|
}
|
||||||
}, [jsonFile, setParsedProps]);
|
}, [jsonFile, setParsedProps]);
|
||||||
|
|
||||||
|
useLayoutEffect(() => {
|
||||||
|
if (elementRef && expandedTargets?.length > 0) {
|
||||||
|
const header = document.getElementById('target-' + expandedTargets[0]);
|
||||||
|
const container = document.getElementById('project-details-container');
|
||||||
|
if (header && container) {
|
||||||
|
const groupHeaderOffset =
|
||||||
|
header
|
||||||
|
.closest('[id^="target-group-container-"]')
|
||||||
|
?.querySelector('[id^="target-group-header-"]')
|
||||||
|
?.getBoundingClientRect().height ?? 0;
|
||||||
|
elementRef.current?.scrollTo({
|
||||||
|
top:
|
||||||
|
header?.getBoundingClientRect().top -
|
||||||
|
container.getBoundingClientRect()?.top -
|
||||||
|
groupHeaderOffset,
|
||||||
|
behavior: 'instant',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [elementRef, expandedTargets]);
|
||||||
|
|
||||||
if (!jsonFile && !parsedProps) {
|
if (!jsonFile && !parsedProps) {
|
||||||
if (!children || !children.hasOwnProperty('props')) {
|
if (!children || !children.hasOwnProperty('props')) {
|
||||||
return (
|
return (
|
||||||
@ -78,17 +109,20 @@ export function ProjectDetails({
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div
|
<div
|
||||||
className={`not-prose ${
|
id="project-details-container"
|
||||||
height ? `p-4 h-[${height}] overflow-y-auto` : 'p-4'
|
className="not-prose overflow-y-auto"
|
||||||
}`}
|
style={{ height }}
|
||||||
|
ref={elementRef}
|
||||||
>
|
>
|
||||||
<ExpandedTargetsProvider>
|
<div className="m-4">
|
||||||
<ProjectDetailsUi
|
<ExpandedTargetsProvider initialExpanededTargets={expandedTargets}>
|
||||||
project={parsedProps.project}
|
<ProjectDetailsUi
|
||||||
sourceMap={parsedProps.sourceMap}
|
project={parsedProps.project}
|
||||||
variant="compact"
|
sourceMap={parsedProps.sourceMap}
|
||||||
/>
|
variant="compact"
|
||||||
</ExpandedTargetsProvider>
|
/>
|
||||||
|
</ExpandedTargetsProvider>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -14,5 +14,8 @@ export const projectDetails: Schema = {
|
|||||||
height: {
|
height: {
|
||||||
type: 'String',
|
type: 'String',
|
||||||
},
|
},
|
||||||
|
expandedTargets: {
|
||||||
|
type: 'Array',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user