docs(nxdev): graph widget loads json from file (#13717)
This commit is contained in:
parent
fd7ca43324
commit
c9e39e31d7
@ -40,40 +40,7 @@ graph and then executes the tasks in that graph.
|
||||
|
||||
For instance `nx test lib` creates a task graph with a single node:
|
||||
|
||||
{% graph height="100px" type="task" %}
|
||||
|
||||
```json
|
||||
{
|
||||
"projects": [
|
||||
{
|
||||
"name": "lib",
|
||||
"type": "lib",
|
||||
"data": {
|
||||
"tags": [],
|
||||
"targets": {
|
||||
"test": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"taskId": "lib:test",
|
||||
"taskGraphs": {
|
||||
"lib:test": {
|
||||
"roots": ["lib:test"],
|
||||
"tasks": {
|
||||
"lib:test": {
|
||||
"id": "lib:test",
|
||||
"target": { "project": "lib", "target": "test" },
|
||||
"projectRoot": "libs/lib",
|
||||
"overrides": {}
|
||||
}
|
||||
},
|
||||
"dependencies": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
{% graph height="100px" type="task" jsonFile="shared/mental-model/single-task.json" %}
|
||||
{% /graph %}
|
||||
|
||||
A task is an invocation of a target. If you invoke the same target twice, you create two tasks.
|
||||
@ -90,126 +57,10 @@ running `nx run-many --target=test --projects=app1,app2,lib`, the created task g
|
||||
{% /side-by-side %}
|
||||
|
||||
{% side-by-side %}
|
||||
{% graph height="200px" type="project" %}
|
||||
|
||||
```json
|
||||
{
|
||||
"projects": [
|
||||
{
|
||||
"name": "app1",
|
||||
"type": "app",
|
||||
"data": {
|
||||
"tags": [],
|
||||
"targets": {
|
||||
"test": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "app2",
|
||||
"type": "app",
|
||||
"data": {
|
||||
"tags": [],
|
||||
"targets": {
|
||||
"test": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "lib",
|
||||
"type": "lib",
|
||||
"data": {
|
||||
"tags": [],
|
||||
"targets": {
|
||||
"test": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"app1": [{ "source": "app1", "target": "lib", "type": "static" }],
|
||||
"app2": [{ "source": "app2", "target": "lib", "type": "static" }],
|
||||
"lib": []
|
||||
},
|
||||
"workspaceLayout": {
|
||||
"appsDir": "apps",
|
||||
"libsDir": "libs"
|
||||
},
|
||||
"affectedProjectIds": [],
|
||||
"focus": null,
|
||||
"groupByFolder": false,
|
||||
"exclude": []
|
||||
}
|
||||
```
|
||||
|
||||
{% graph height="200px" type="project" jsonFile="shared/mental-model/three-projects.json" %}
|
||||
{% /graph %}
|
||||
|
||||
{% graph height="200px" type="task" %}
|
||||
|
||||
```json
|
||||
{
|
||||
"projects": [
|
||||
{
|
||||
"name": "app1",
|
||||
"type": "app",
|
||||
"data": {
|
||||
"tags": [],
|
||||
"targets": {
|
||||
"test": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "app2",
|
||||
"type": "app",
|
||||
"data": {
|
||||
"tags": [],
|
||||
"targets": {
|
||||
"test": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "lib",
|
||||
"type": "lib",
|
||||
"data": {
|
||||
"tags": [],
|
||||
"targets": {
|
||||
"test": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"taskId": "lib:test",
|
||||
"taskGraphs": {
|
||||
"lib:test": {
|
||||
"roots": ["app1:test", "app2:test", "lib:test"],
|
||||
"tasks": {
|
||||
"app1:test": {
|
||||
"id": "app1:test",
|
||||
"target": { "project": "app1", "target": "test" },
|
||||
"projectRoot": "apps/app1",
|
||||
"overrides": {}
|
||||
},
|
||||
"app2:test": {
|
||||
"id": "app2:test",
|
||||
"target": { "project": "app2", "target": "test" },
|
||||
"projectRoot": "apps/app2",
|
||||
"overrides": {}
|
||||
},
|
||||
"lib:test": {
|
||||
"id": "lib:test",
|
||||
"target": { "project": "lib", "target": "test" },
|
||||
"projectRoot": "libs/lib",
|
||||
"overrides": {}
|
||||
}
|
||||
},
|
||||
"dependencies": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
{% graph height="200px" type="task" jsonFile="shared/mental-model/disconnected-tasks.json"%}
|
||||
{% /graph %}
|
||||
{% /side-by-side %}
|
||||
|
||||
@ -244,129 +95,10 @@ With this, running the same test command creates the following task graph:
|
||||
{% /side-by-side %}
|
||||
|
||||
{% side-by-side %}
|
||||
{% graph height="200px" type="project" %}
|
||||
|
||||
```json
|
||||
{
|
||||
"projects": [
|
||||
{
|
||||
"name": "app1",
|
||||
"type": "app",
|
||||
"data": {
|
||||
"tags": [],
|
||||
"targets": {
|
||||
"test": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "app2",
|
||||
"type": "app",
|
||||
"data": {
|
||||
"tags": [],
|
||||
"targets": {
|
||||
"test": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "lib",
|
||||
"type": "lib",
|
||||
"data": {
|
||||
"tags": [],
|
||||
"targets": {
|
||||
"test": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"app1": [{ "source": "app1", "target": "lib", "type": "static" }],
|
||||
"app2": [{ "source": "app2", "target": "lib", "type": "static" }],
|
||||
"lib": []
|
||||
},
|
||||
"workspaceLayout": {
|
||||
"appsDir": "apps",
|
||||
"libsDir": "libs"
|
||||
},
|
||||
"affectedProjectIds": [],
|
||||
"focus": null,
|
||||
"groupByFolder": false,
|
||||
"exclude": []
|
||||
}
|
||||
```
|
||||
|
||||
{% graph height="200px" type="project" jsonFile="shared/mental-model/three-projects.json" %}
|
||||
{% /graph %}
|
||||
|
||||
{% graph height="200px" type="task" %}
|
||||
|
||||
```json
|
||||
{
|
||||
"projects": [
|
||||
{
|
||||
"name": "app1",
|
||||
"type": "app",
|
||||
"data": {
|
||||
"tags": [],
|
||||
"targets": {
|
||||
"test": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "app2",
|
||||
"type": "app",
|
||||
"data": {
|
||||
"tags": [],
|
||||
"targets": {
|
||||
"test": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "lib",
|
||||
"type": "lib",
|
||||
"data": {
|
||||
"tags": [],
|
||||
"targets": {
|
||||
"test": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"taskId": "lib:test",
|
||||
"taskGraphs": {
|
||||
"lib:test": {
|
||||
"roots": ["app1:test", "app2:test", "lib:test"],
|
||||
"tasks": {
|
||||
"app1:test": {
|
||||
"id": "app1:test",
|
||||
"target": { "project": "app1", "target": "test" },
|
||||
"projectRoot": "apps/app1",
|
||||
"overrides": {}
|
||||
},
|
||||
"app2:test": {
|
||||
"id": "app2:test",
|
||||
"target": { "project": "app2", "target": "test" },
|
||||
"projectRoot": "apps/app2",
|
||||
"overrides": {}
|
||||
},
|
||||
"lib:test": {
|
||||
"id": "lib:test",
|
||||
"target": { "project": "lib", "target": "test" },
|
||||
"projectRoot": "libs/lib",
|
||||
"overrides": {}
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"app1:test": ["lib:test"],
|
||||
"app2:test": ["lib:test"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
{% graph height="200px" type="task" jsonFile="shared/mental-model/connected-tasks.json" %}
|
||||
{% /graph %}
|
||||
{% /side-by-side %}
|
||||
|
||||
|
||||
64
docs/shared/mental-model/connected-tasks.json
Normal file
64
docs/shared/mental-model/connected-tasks.json
Normal file
@ -0,0 +1,64 @@
|
||||
{
|
||||
"projects": [
|
||||
{
|
||||
"name": "app1",
|
||||
"type": "app",
|
||||
"data": {
|
||||
"tags": [],
|
||||
"targets": {
|
||||
"test": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "app2",
|
||||
"type": "app",
|
||||
"data": {
|
||||
"tags": [],
|
||||
"targets": {
|
||||
"test": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "lib",
|
||||
"type": "lib",
|
||||
"data": {
|
||||
"tags": [],
|
||||
"targets": {
|
||||
"test": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"taskId": "lib:test",
|
||||
"taskGraphs": {
|
||||
"lib:test": {
|
||||
"roots": ["app1:test", "app2:test", "lib:test"],
|
||||
"tasks": {
|
||||
"app1:test": {
|
||||
"id": "app1:test",
|
||||
"target": { "project": "app1", "target": "test" },
|
||||
"projectRoot": "apps/app1",
|
||||
"overrides": {}
|
||||
},
|
||||
"app2:test": {
|
||||
"id": "app2:test",
|
||||
"target": { "project": "app2", "target": "test" },
|
||||
"projectRoot": "apps/app2",
|
||||
"overrides": {}
|
||||
},
|
||||
"lib:test": {
|
||||
"id": "lib:test",
|
||||
"target": { "project": "lib", "target": "test" },
|
||||
"projectRoot": "libs/lib",
|
||||
"overrides": {}
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"app1:test": ["lib:test"],
|
||||
"app2:test": ["lib:test"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
61
docs/shared/mental-model/disconnected-tasks.json
Normal file
61
docs/shared/mental-model/disconnected-tasks.json
Normal file
@ -0,0 +1,61 @@
|
||||
{
|
||||
"projects": [
|
||||
{
|
||||
"name": "app1",
|
||||
"type": "app",
|
||||
"data": {
|
||||
"tags": [],
|
||||
"targets": {
|
||||
"test": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "app2",
|
||||
"type": "app",
|
||||
"data": {
|
||||
"tags": [],
|
||||
"targets": {
|
||||
"test": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "lib",
|
||||
"type": "lib",
|
||||
"data": {
|
||||
"tags": [],
|
||||
"targets": {
|
||||
"test": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"taskId": "lib:test",
|
||||
"taskGraphs": {
|
||||
"lib:test": {
|
||||
"roots": ["app1:test", "app2:test", "lib:test"],
|
||||
"tasks": {
|
||||
"app1:test": {
|
||||
"id": "app1:test",
|
||||
"target": { "project": "app1", "target": "test" },
|
||||
"projectRoot": "apps/app1",
|
||||
"overrides": {}
|
||||
},
|
||||
"app2:test": {
|
||||
"id": "app2:test",
|
||||
"target": { "project": "app2", "target": "test" },
|
||||
"projectRoot": "apps/app2",
|
||||
"overrides": {}
|
||||
},
|
||||
"lib:test": {
|
||||
"id": "lib:test",
|
||||
"target": { "project": "lib", "target": "test" },
|
||||
"projectRoot": "libs/lib",
|
||||
"overrides": {}
|
||||
}
|
||||
},
|
||||
"dependencies": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
29
docs/shared/mental-model/single-task.json
Normal file
29
docs/shared/mental-model/single-task.json
Normal file
@ -0,0 +1,29 @@
|
||||
{
|
||||
"projects": [
|
||||
{
|
||||
"name": "lib",
|
||||
"type": "lib",
|
||||
"data": {
|
||||
"tags": [],
|
||||
"targets": {
|
||||
"test": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"taskId": "lib:test",
|
||||
"taskGraphs": {
|
||||
"lib:test": {
|
||||
"roots": ["lib:test"],
|
||||
"tasks": {
|
||||
"lib:test": {
|
||||
"id": "lib:test",
|
||||
"target": { "project": "lib", "target": "test" },
|
||||
"projectRoot": "libs/lib",
|
||||
"overrides": {}
|
||||
}
|
||||
},
|
||||
"dependencies": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 94 KiB |
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 55 KiB |
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 6.4 KiB |
47
docs/shared/mental-model/three-projects.json
Normal file
47
docs/shared/mental-model/three-projects.json
Normal file
@ -0,0 +1,47 @@
|
||||
{
|
||||
"projects": [
|
||||
{
|
||||
"name": "app1",
|
||||
"type": "app",
|
||||
"data": {
|
||||
"tags": [],
|
||||
"targets": {
|
||||
"test": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "app2",
|
||||
"type": "app",
|
||||
"data": {
|
||||
"tags": [],
|
||||
"targets": {
|
||||
"test": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "lib",
|
||||
"type": "lib",
|
||||
"data": {
|
||||
"tags": [],
|
||||
"targets": {
|
||||
"test": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"app1": [{ "source": "app1", "target": "lib", "type": "static" }],
|
||||
"app2": [{ "source": "app2", "target": "lib", "type": "static" }],
|
||||
"lib": []
|
||||
},
|
||||
"workspaceLayout": {
|
||||
"appsDir": "apps",
|
||||
"libsDir": "libs"
|
||||
},
|
||||
"affectedProjectIds": [],
|
||||
"focus": null,
|
||||
"groupByFolder": false,
|
||||
"exclude": []
|
||||
}
|
||||
@ -1,6 +1,19 @@
|
||||
import { useTheme } from '@nrwl/nx-dev/ui-theme';
|
||||
import dynamic from 'next/dynamic';
|
||||
import { ReactElement } from 'react';
|
||||
import { ReactElement, useEffect, useState } from 'react';
|
||||
|
||||
export function Loading() {
|
||||
return (
|
||||
<div className="flex h-[450px] w-full items-center justify-center">
|
||||
<div
|
||||
className="spinner-border inline-block h-8 w-8 animate-spin rounded-full border-4 border-slate-100 border-r-slate-400 dark:border-slate-700 dark:border-r-slate-500"
|
||||
role="status"
|
||||
>
|
||||
<span className="sr-only">Loading...</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* dynamic() can't be used inside of React rendering as it needs to be marked
|
||||
@ -11,66 +24,69 @@ const NxProjectGraphViz = dynamic(
|
||||
import('@nrwl/graph/ui-graph').then((module) => module.NxProjectGraphViz),
|
||||
{
|
||||
ssr: false,
|
||||
loading: () => (
|
||||
<div className="flex h-[450px] w-full items-center justify-center">
|
||||
<div
|
||||
className="spinner-border inline-block h-8 w-8 animate-spin rounded-full border-4 border-slate-100 border-r-slate-400 dark:border-slate-700 dark:border-r-slate-500"
|
||||
role="status"
|
||||
>
|
||||
<span className="sr-only">Loading...</span>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
loading: () => <Loading />,
|
||||
}
|
||||
);
|
||||
const NxTaskGraphViz = dynamic(
|
||||
() => import('@nrwl/graph/ui-graph').then((module) => module.NxTaskGraphViz),
|
||||
{
|
||||
ssr: false,
|
||||
loading: () => (
|
||||
<div className="flex h-[450px] w-full items-center justify-center">
|
||||
<div
|
||||
className="spinner-border inline-block h-8 w-8 animate-spin rounded-full border-4 border-slate-100 border-r-slate-400 dark:border-slate-700 dark:border-r-slate-500"
|
||||
role="status"
|
||||
>
|
||||
<span className="sr-only">Loading...</span>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
loading: () => <Loading />,
|
||||
}
|
||||
);
|
||||
|
||||
export function Graph({
|
||||
height,
|
||||
type,
|
||||
jsonFile,
|
||||
children,
|
||||
}: {
|
||||
height: string;
|
||||
type: 'project' | 'task';
|
||||
jsonFile?: string;
|
||||
children: ReactElement;
|
||||
}): JSX.Element {
|
||||
const [theme] = useTheme();
|
||||
const [parsedProps, setParsedProps] = useState<any>();
|
||||
const getData = async (path: string) => {
|
||||
const response = await fetch('/documentation/' + path, {
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Accept: 'application/json',
|
||||
},
|
||||
});
|
||||
setParsedProps(await response.json());
|
||||
};
|
||||
useEffect(() => {
|
||||
if (jsonFile) {
|
||||
getData(jsonFile);
|
||||
}
|
||||
}, [jsonFile, setParsedProps]);
|
||||
if (!jsonFile && !parsedProps) {
|
||||
if (!children || !children.hasOwnProperty('props')) {
|
||||
return (
|
||||
<div className="no-prose my-6 block rounded-md bg-red-50 p-4 text-red-700 ring-1 ring-red-100 dark:bg-red-900/30 dark:text-red-600 dark:ring-red-900">
|
||||
<p className="mb-4">
|
||||
No JSON provided for graph, use JSON code fence to embed data for
|
||||
the graph.
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (!children || !children.hasOwnProperty('props'))
|
||||
return (
|
||||
<div className="no-prose my-6 block rounded-md bg-red-50 p-4 text-red-700 ring-1 ring-red-100 dark:bg-red-900/30 dark:text-red-600 dark:ring-red-900">
|
||||
<p className="mb-4">
|
||||
No JSON provided for graph, use JSON code fence to embed data for the
|
||||
graph.
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
|
||||
let parsedProps;
|
||||
try {
|
||||
parsedProps = JSON.parse(children?.props.children as any);
|
||||
} catch {
|
||||
return (
|
||||
<div className="not-prose my-6 block rounded-md bg-red-50 p-4 text-red-700 ring-1 ring-red-100 dark:bg-red-900/30 dark:text-red-600 dark:ring-red-900">
|
||||
<p className="mb-4">Could not parse JSON for graph:</p>
|
||||
<pre className="p-4 text-sm">{children?.props.children as any}</pre>
|
||||
</div>
|
||||
);
|
||||
try {
|
||||
setParsedProps(JSON.parse(children?.props.children as any));
|
||||
} catch {
|
||||
return (
|
||||
<div className="not-prose my-6 block rounded-md bg-red-50 p-4 text-red-700 ring-1 ring-red-100 dark:bg-red-900/30 dark:text-red-600 dark:ring-red-900">
|
||||
<p className="mb-4">Could not parse JSON for graph:</p>
|
||||
<pre className="p-4 text-sm">{children?.props.children as any}</pre>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
if (!parsedProps) {
|
||||
return <Loading />;
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@ -5,6 +5,9 @@ export const graph: Schema = {
|
||||
children: [],
|
||||
|
||||
attributes: {
|
||||
jsonFile: {
|
||||
type: 'String',
|
||||
},
|
||||
type: {
|
||||
type: 'String',
|
||||
matches: ['project', 'task'],
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user