feat(graph): rework pdv target section & remove unused code (#21159)
This commit is contained in:
parent
253c0ff2ab
commit
e38b0bb6f4
@ -81,6 +81,14 @@ export class ExternalApiImpl extends ExternalApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
openProjectDetails(projectName: string, targetName?: string) {
|
||||||
|
this.router.navigate(
|
||||||
|
`/project-details/${encodeURIComponent(projectName)}${
|
||||||
|
targetName ? `?expanded=${encodeURIComponent(targetName)}` : ''
|
||||||
|
}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
focusProject(projectName: string) {
|
focusProject(projectName: string) {
|
||||||
this.router.navigate(`/projects/${encodeURIComponent(projectName)}`);
|
this.router.navigate(`/projects/${encodeURIComponent(projectName)}`);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,288 +0,0 @@
|
|||||||
import {
|
|
||||||
ChevronDownIcon,
|
|
||||||
ChevronRightIcon,
|
|
||||||
EyeIcon,
|
|
||||||
PlayIcon,
|
|
||||||
} from '@heroicons/react/24/outline';
|
|
||||||
import { getSourceInformation } from './get-source-information';
|
|
||||||
import useMapState from './use-map-state';
|
|
||||||
import {
|
|
||||||
getExternalApiService,
|
|
||||||
useEnvironmentConfig,
|
|
||||||
useRouteConstructor,
|
|
||||||
} from '@nx/graph/shared';
|
|
||||||
import { useNavigate } from 'react-router-dom';
|
|
||||||
import { get } from 'http';
|
|
||||||
import { useEffect } from 'react';
|
|
||||||
|
|
||||||
interface JsonLineRendererProps {
|
|
||||||
jsonData: any;
|
|
||||||
sourceMap: Record<string, string[]>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function JsonLineRenderer(props: JsonLineRendererProps) {
|
|
||||||
let collapsibleSections = new Map<number, number>();
|
|
||||||
let lines: [string, number][] = [];
|
|
||||||
let currentLine = 0;
|
|
||||||
let lineToPropertyPathMap = new Map<number, string>();
|
|
||||||
let lineToInteractionMap = new Map<
|
|
||||||
number,
|
|
||||||
{ target: string; configuration?: string }
|
|
||||||
>();
|
|
||||||
|
|
||||||
const [getCollapsed, setCollapsed] = useMapState<number, boolean>();
|
|
||||||
const { environment } = useEnvironmentConfig();
|
|
||||||
const externalApiService = getExternalApiService();
|
|
||||||
const navigate = useNavigate();
|
|
||||||
const routeContructor = useRouteConstructor();
|
|
||||||
|
|
||||||
function add(value: string, depth: number) {
|
|
||||||
if (lines.length === currentLine) {
|
|
||||||
lines.push(['', depth]);
|
|
||||||
}
|
|
||||||
lines[currentLine] = [lines[currentLine][0] + value, depth];
|
|
||||||
}
|
|
||||||
|
|
||||||
function processJson(
|
|
||||||
jsonData: any,
|
|
||||||
depth = 0,
|
|
||||||
propertyPath = '',
|
|
||||||
isLast = false
|
|
||||||
) {
|
|
||||||
if (Array.isArray(jsonData)) {
|
|
||||||
const sectionStart = currentLine;
|
|
||||||
add('[', depth);
|
|
||||||
currentLine++;
|
|
||||||
|
|
||||||
jsonData.forEach((value, index) => {
|
|
||||||
const newPropertyPath = `${
|
|
||||||
propertyPath ? propertyPath + '.' : ''
|
|
||||||
}${value}`;
|
|
||||||
lineToPropertyPathMap.set(currentLine, newPropertyPath);
|
|
||||||
|
|
||||||
processJson(
|
|
||||||
value,
|
|
||||||
depth + 1,
|
|
||||||
newPropertyPath,
|
|
||||||
index === jsonData.length - 1
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
add(']', depth);
|
|
||||||
if (!isLast) {
|
|
||||||
add(',', depth);
|
|
||||||
}
|
|
||||||
const sectionEnd = currentLine;
|
|
||||||
collapsibleSections.set(sectionStart, sectionEnd);
|
|
||||||
currentLine++;
|
|
||||||
} else if (jsonData && typeof jsonData === 'object') {
|
|
||||||
const sectionStart = currentLine;
|
|
||||||
add('{', depth);
|
|
||||||
currentLine++;
|
|
||||||
|
|
||||||
Object.entries(jsonData).forEach(([key, value], index, array) => {
|
|
||||||
// skip empty objects
|
|
||||||
if (
|
|
||||||
Object.keys(value as any).length === 0 &&
|
|
||||||
typeof value === 'object'
|
|
||||||
) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// skip certain root properties
|
|
||||||
if (
|
|
||||||
depth === 0 &&
|
|
||||||
(key === 'sourceRoot' ||
|
|
||||||
key === 'name' ||
|
|
||||||
key === '$schema' ||
|
|
||||||
key === 'tags')
|
|
||||||
) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
add(`"${key}": `, depth);
|
|
||||||
|
|
||||||
if (propertyPath === 'targets') {
|
|
||||||
lineToInteractionMap.set(currentLine, { target: key });
|
|
||||||
}
|
|
||||||
if (propertyPath.match(/^targets\..*configurations$/)) {
|
|
||||||
lineToInteractionMap.set(currentLine, {
|
|
||||||
target: propertyPath.split('.')[1],
|
|
||||||
configuration: key,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const newPropertyPath = `${
|
|
||||||
propertyPath ? propertyPath + '.' : ''
|
|
||||||
}${key}`;
|
|
||||||
lineToPropertyPathMap.set(currentLine, newPropertyPath);
|
|
||||||
|
|
||||||
processJson(
|
|
||||||
value,
|
|
||||||
depth + 1,
|
|
||||||
newPropertyPath,
|
|
||||||
index === array.length - 1
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
add('}', depth);
|
|
||||||
if (!isLast) {
|
|
||||||
add(',', depth);
|
|
||||||
}
|
|
||||||
const sectionEnd = currentLine;
|
|
||||||
collapsibleSections.set(sectionStart, sectionEnd);
|
|
||||||
currentLine++;
|
|
||||||
} else {
|
|
||||||
add(`"${jsonData}"`, depth);
|
|
||||||
if (!isLast) {
|
|
||||||
add(',', depth);
|
|
||||||
}
|
|
||||||
currentLine++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
processJson(props.jsonData);
|
|
||||||
|
|
||||||
console.log(lineToInteractionMap);
|
|
||||||
// start off with all targets & configurations collapsed~
|
|
||||||
useEffect(() => {
|
|
||||||
for (const line of lineToInteractionMap.keys()) {
|
|
||||||
if (!getCollapsed(line)) {
|
|
||||||
setCollapsed(line, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
function toggleCollapsed(index: number) {
|
|
||||||
setCollapsed(index, !getCollapsed(index));
|
|
||||||
}
|
|
||||||
|
|
||||||
function lineIsCollapsed(index: number) {
|
|
||||||
for (const [start, end] of collapsibleSections) {
|
|
||||||
if (index > start && index < end) {
|
|
||||||
if (getCollapsed(start)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function runTarget({
|
|
||||||
target,
|
|
||||||
configuration,
|
|
||||||
}: {
|
|
||||||
target: string;
|
|
||||||
configuration?: string;
|
|
||||||
}) {
|
|
||||||
const projectName = props.jsonData.name;
|
|
||||||
|
|
||||||
externalApiService.postEvent({
|
|
||||||
type: 'run-task',
|
|
||||||
payload: { taskId: `${projectName}:${target}` },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function viewInTaskGraph({
|
|
||||||
target,
|
|
||||||
configuration,
|
|
||||||
}: {
|
|
||||||
target: string;
|
|
||||||
configuration?: string;
|
|
||||||
}) {
|
|
||||||
const projectName = props.jsonData.name;
|
|
||||||
if (environment === 'nx-console') {
|
|
||||||
externalApiService.postEvent({
|
|
||||||
type: 'open-task-graph',
|
|
||||||
payload: {
|
|
||||||
projectName: projectName,
|
|
||||||
targetName: target,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
navigate(
|
|
||||||
routeContructor(
|
|
||||||
{
|
|
||||||
pathname: `/tasks/${encodeURIComponent(target)}`,
|
|
||||||
search: `?projects=${encodeURIComponent(projectName)}`,
|
|
||||||
},
|
|
||||||
true
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="overflow-auto w-full h-full flex">
|
|
||||||
<div className="h-fit min-h-full w-12 shrink-0 pr-2 border-solid border-r-2 border-slate-700">
|
|
||||||
{lines.map(([text, indentation], index) => {
|
|
||||||
if (
|
|
||||||
lineIsCollapsed(index) ||
|
|
||||||
index === 0 ||
|
|
||||||
index === lines.length - 1
|
|
||||||
) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
const canCollapse =
|
|
||||||
collapsibleSections.has(index) &&
|
|
||||||
collapsibleSections.get(index)! - index > 1;
|
|
||||||
const interaction = lineToInteractionMap.get(index);
|
|
||||||
return (
|
|
||||||
<div className="flex justify-end items-center h-6">
|
|
||||||
{interaction?.target && !interaction?.configuration && (
|
|
||||||
<EyeIcon
|
|
||||||
className="h-4 w-4"
|
|
||||||
onClick={() => viewInTaskGraph(interaction!)}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{environment === 'nx-console' && interaction?.target && (
|
|
||||||
<PlayIcon
|
|
||||||
className="h-4 w-4"
|
|
||||||
onClick={() => runTarget(interaction!)}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{canCollapse && (
|
|
||||||
<div onClick={() => toggleCollapsed(index)} className="h-4 w-4">
|
|
||||||
{getCollapsed(index) ? (
|
|
||||||
<ChevronRightIcon />
|
|
||||||
) : (
|
|
||||||
<ChevronDownIcon />
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
<div className="pl-2">
|
|
||||||
{lines.map(([text, indentation], index) => {
|
|
||||||
if (
|
|
||||||
lineIsCollapsed(index) ||
|
|
||||||
index === 0 ||
|
|
||||||
index === lines.length - 1
|
|
||||||
) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
const propertyPathAtLine = lineToPropertyPathMap.get(index);
|
|
||||||
const sourceInformation = propertyPathAtLine
|
|
||||||
? getSourceInformation(props.sourceMap, propertyPathAtLine)
|
|
||||||
: '';
|
|
||||||
return (
|
|
||||||
<pre
|
|
||||||
style={{ paddingLeft: `${indentation}rem` }}
|
|
||||||
className="group truncate hover:bg-slate-800 h-6"
|
|
||||||
>
|
|
||||||
{text}
|
|
||||||
{getCollapsed(index) ? '...' : ''}
|
|
||||||
|
|
||||||
<span className="ml-16 hidden group-hover:inline-block text-sm text-slate-500">
|
|
||||||
{sourceInformation}
|
|
||||||
</span>
|
|
||||||
</pre>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@ -1,18 +1,17 @@
|
|||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
|
||||||
import { useNavigate, useRouteLoaderData } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
|
||||||
/* eslint-disable @nx/enforce-module-boundaries */
|
/* eslint-disable @nx/enforce-module-boundaries */
|
||||||
// nx-ignore-next-line
|
// nx-ignore-next-line
|
||||||
import { ProjectGraphProjectNode } from '@nx/devkit';
|
import { ProjectGraphProjectNode } from '@nx/devkit';
|
||||||
|
|
||||||
|
import { EyeIcon } from '@heroicons/react/24/outline';
|
||||||
import {
|
import {
|
||||||
getExternalApiService,
|
getExternalApiService,
|
||||||
useEnvironmentConfig,
|
useEnvironmentConfig,
|
||||||
useRouteConstructor,
|
useRouteConstructor,
|
||||||
} from '@nx/graph/shared';
|
} from '@nx/graph/shared';
|
||||||
import { JsonLineRenderer } from './json-line-renderer';
|
|
||||||
import { EyeIcon } from '@heroicons/react/24/outline';
|
|
||||||
import PropertyRenderer from './property-renderer';
|
import PropertyRenderer from './property-renderer';
|
||||||
import Target from './target';
|
import Target from './target';
|
||||||
|
|
||||||
@ -28,7 +27,7 @@ export function ProjectDetails({
|
|||||||
},
|
},
|
||||||
sourceMap,
|
sourceMap,
|
||||||
}: ProjectDetailsProps) {
|
}: ProjectDetailsProps) {
|
||||||
const { environment } = useEnvironmentConfig();
|
const environment = useEnvironmentConfig()?.environment;
|
||||||
const externalApiService = getExternalApiService();
|
const externalApiService = getExternalApiService();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const routeContructor = useRouteConstructor();
|
const routeContructor = useRouteConstructor();
|
||||||
@ -46,35 +45,6 @@ export function ProjectDetails({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// const projectDataSorted = sortObjectWithTargetsFirst(projectData);
|
|
||||||
// return (
|
|
||||||
// <div className="flex flex-col w-full h-full">
|
|
||||||
// <div className="flex">
|
|
||||||
// <div className="w-12 pr-2 border-r-2 border-solid border-slate-700">
|
|
||||||
// <EyeIcon
|
|
||||||
// className="h-6 w-6 ml-3 mt-3"
|
|
||||||
// onClick={viewInProjectGraph}
|
|
||||||
// ></EyeIcon>
|
|
||||||
// </div>
|
|
||||||
// <div className="pl-6 pb-6">
|
|
||||||
// <h1 className="text-4xl flex items-center">
|
|
||||||
// <span>{name}</span>
|
|
||||||
// </h1>
|
|
||||||
// <div className="flex gap-2">
|
|
||||||
// <span className="text-slate-500 text-xl"> {root}</span>
|
|
||||||
|
|
||||||
// {projectData.tags?.map((tag) => (
|
|
||||||
// <div className="dark:bg-sky-500 text-white rounded px-1">
|
|
||||||
// {tag}
|
|
||||||
// </div>
|
|
||||||
// ))}
|
|
||||||
// </div>
|
|
||||||
// </div>
|
|
||||||
// </div>
|
|
||||||
// {JsonLineRenderer({ jsonData: projectDataSorted, sourceMap })}
|
|
||||||
// </div>
|
|
||||||
// );
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="m-4 overflow-auto w-full">
|
<div className="m-4 overflow-auto w-full">
|
||||||
<h1 className="text-2xl flex items-center gap-2">
|
<h1 className="text-2xl flex items-center gap-2">
|
||||||
@ -89,15 +59,17 @@ export function ProjectDetails({
|
|||||||
</h2>
|
</h2>
|
||||||
<div>
|
<div>
|
||||||
<div className="mb-2">
|
<div className="mb-2">
|
||||||
<h2 className="text-xl">Targets</h2>
|
<h2 className="text-xl mb-2">Targets</h2>
|
||||||
{Object.entries(projectData.targets ?? {}).map(
|
{Object.entries(projectData.targets ?? {}).map(
|
||||||
([targetName, target]) =>
|
([targetName, target]) => {
|
||||||
Target({
|
const props = {
|
||||||
projectName: name,
|
projectName: name,
|
||||||
targetName: targetName,
|
targetName: targetName,
|
||||||
targetConfiguration: target,
|
targetConfiguration: target,
|
||||||
sourceMap,
|
sourceMap,
|
||||||
})
|
};
|
||||||
|
return <Target {...props} />;
|
||||||
|
}
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
{Object.entries(projectData).map(([key, value]) => {
|
{Object.entries(projectData).map(([key, value]) => {
|
||||||
@ -123,22 +95,4 @@ export function ProjectDetails({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// function sortObjectWithTargetsFirst(obj: any) {
|
|
||||||
// let sortedObj: any = {};
|
|
||||||
|
|
||||||
// // If 'targets' exists, set it as the first property
|
|
||||||
// if (obj.hasOwnProperty('targets')) {
|
|
||||||
// sortedObj.targets = obj.targets;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Copy the rest of the properties
|
|
||||||
// for (let key in obj) {
|
|
||||||
// if (key !== 'targets') {
|
|
||||||
// sortedObj[key] = obj[key];
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return sortedObj;
|
|
||||||
// }
|
|
||||||
|
|
||||||
export default ProjectDetails;
|
export default ProjectDetails;
|
||||||
|
|||||||
@ -54,7 +54,7 @@ type PropertValueRendererProps = PropertyRendererProps & {
|
|||||||
function PropertyValueRenderer(props: PropertValueRendererProps) {
|
function PropertyValueRenderer(props: PropertValueRendererProps) {
|
||||||
const { propertyKey, propertyValue, sourceMap, keyPrefix, nested } = props;
|
const { propertyKey, propertyValue, sourceMap, keyPrefix, nested } = props;
|
||||||
|
|
||||||
if (Array.isArray(propertyValue) && propertyValue.length) {
|
if (propertyValue && Array.isArray(propertyValue) && propertyValue.length) {
|
||||||
return (
|
return (
|
||||||
<div className="ml-3">
|
<div className="ml-3">
|
||||||
{nested && renderOpening(propertyValue)}
|
{nested && renderOpening(propertyValue)}
|
||||||
@ -107,7 +107,7 @@ function PropertyValueRenderer(props: PropertValueRendererProps) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function renderOpening(value: any): string {
|
function renderOpening(value: any): string {
|
||||||
return Array.isArray(value) && value.length
|
return value && Array.isArray(value) && value.length
|
||||||
? '['
|
? '['
|
||||||
: value && typeof value === 'object'
|
: value && typeof value === 'object'
|
||||||
? '{'
|
? '{'
|
||||||
@ -115,7 +115,7 @@ function renderOpening(value: any): string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function renderClosing(value: any): string {
|
function renderClosing(value: any): string {
|
||||||
return Array.isArray(value) && value.length
|
return value && Array.isArray(value) && value.length
|
||||||
? '],'
|
? '],'
|
||||||
: value && typeof value === 'object'
|
: value && typeof value === 'object'
|
||||||
? '},'
|
? '},'
|
||||||
|
|||||||
@ -1,8 +1,9 @@
|
|||||||
/* eslint-disable @nx/enforce-module-boundaries */
|
/* eslint-disable @nx/enforce-module-boundaries */
|
||||||
// nx-ignore-next-line
|
// nx-ignore-next-line
|
||||||
import {
|
import {
|
||||||
|
ChevronDownIcon,
|
||||||
|
ChevronUpIcon,
|
||||||
EyeIcon,
|
EyeIcon,
|
||||||
PencilSquareIcon,
|
|
||||||
PlayIcon,
|
PlayIcon,
|
||||||
} from '@heroicons/react/24/outline';
|
} from '@heroicons/react/24/outline';
|
||||||
|
|
||||||
@ -13,8 +14,10 @@ import {
|
|||||||
useEnvironmentConfig,
|
useEnvironmentConfig,
|
||||||
useRouteConstructor,
|
useRouteConstructor,
|
||||||
} from '@nx/graph/shared';
|
} from '@nx/graph/shared';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { Fence } from '@nx/shared-ui-fence';
|
||||||
import PropertyRenderer from './property-renderer';
|
import { useEffect, useState } from 'react';
|
||||||
|
import { useNavigate, useSearchParams } from 'react-router-dom';
|
||||||
|
import { FadingCollapsible } from './ui/fading-collapsible.component';
|
||||||
|
|
||||||
/* eslint-disable-next-line */
|
/* eslint-disable-next-line */
|
||||||
export interface TargetProps {
|
export interface TargetProps {
|
||||||
@ -24,16 +27,61 @@ export interface TargetProps {
|
|||||||
sourceMap: Record<string, string[]>;
|
sourceMap: Record<string, string[]>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Target(props: TargetProps) {
|
export function Target({
|
||||||
const { environment } = useEnvironmentConfig();
|
projectName,
|
||||||
|
targetName,
|
||||||
|
targetConfiguration,
|
||||||
|
sourceMap,
|
||||||
|
}: TargetProps) {
|
||||||
|
const environment = useEnvironmentConfig()?.environment;
|
||||||
const externalApiService = getExternalApiService();
|
const externalApiService = getExternalApiService();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const routeContructor = useRouteConstructor();
|
const routeContructor = useRouteConstructor();
|
||||||
|
|
||||||
|
const [searchParams, setSearchParams] = useSearchParams();
|
||||||
|
const [collapsed, setCollapsed] = useState(true);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const expandedSections = searchParams.get('expanded')?.split(',') || [];
|
||||||
|
setCollapsed(!expandedSections.includes(targetName));
|
||||||
|
}, [searchParams, targetName]);
|
||||||
|
|
||||||
|
function toggleCollapsed() {
|
||||||
|
setCollapsed((prevState) => {
|
||||||
|
const newState = !prevState;
|
||||||
|
setSearchParams((currentSearchParams) => {
|
||||||
|
const expandedSections =
|
||||||
|
currentSearchParams.get('expanded')?.split(',') || [];
|
||||||
|
if (newState) {
|
||||||
|
const newExpandedSections = expandedSections.filter(
|
||||||
|
(section) => section !== targetName
|
||||||
|
);
|
||||||
|
updateSearchParams(currentSearchParams, newExpandedSections);
|
||||||
|
} else {
|
||||||
|
if (!expandedSections.includes(targetName)) {
|
||||||
|
expandedSections.push(targetName);
|
||||||
|
updateSearchParams(currentSearchParams, expandedSections);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return currentSearchParams;
|
||||||
|
});
|
||||||
|
|
||||||
|
return newState;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateSearchParams(params: URLSearchParams, sections: string[]) {
|
||||||
|
if (sections.length === 0) {
|
||||||
|
params.delete('expanded');
|
||||||
|
} else {
|
||||||
|
params.set('expanded', sections.join(','));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const runTarget = () => {
|
const runTarget = () => {
|
||||||
externalApiService.postEvent({
|
externalApiService.postEvent({
|
||||||
type: 'run-task',
|
type: 'run-task',
|
||||||
payload: { taskId: `${props.projectName}:${props.targetName}` },
|
payload: { taskId: `${projectName}:${targetName}` },
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -42,16 +90,16 @@ export function Target(props: TargetProps) {
|
|||||||
externalApiService.postEvent({
|
externalApiService.postEvent({
|
||||||
type: 'open-task-graph',
|
type: 'open-task-graph',
|
||||||
payload: {
|
payload: {
|
||||||
projectName: props.projectName,
|
projectName: projectName,
|
||||||
targetName: props.targetName,
|
targetName: targetName,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
navigate(
|
navigate(
|
||||||
routeContructor(
|
routeContructor(
|
||||||
{
|
{
|
||||||
pathname: `/tasks/${encodeURIComponent(props.targetName)}`,
|
pathname: `/tasks/${encodeURIComponent(targetName)}`,
|
||||||
search: `?projects=${encodeURIComponent(props.projectName)}`,
|
search: `?projects=${encodeURIComponent(projectName)}`,
|
||||||
},
|
},
|
||||||
true
|
true
|
||||||
)
|
)
|
||||||
@ -59,74 +107,164 @@ export function Target(props: TargetProps) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const overrideTarget = () => {
|
const shouldRenderOptions =
|
||||||
externalApiService.postEvent({
|
targetConfiguration.options &&
|
||||||
type: 'override-target',
|
(typeof targetConfiguration.options === 'object'
|
||||||
payload: {
|
? Object.keys(targetConfiguration.options).length
|
||||||
projectName: props.projectName,
|
: true);
|
||||||
targetName: props.targetName,
|
|
||||||
targetConfigString: JSON.stringify(props.targetConfiguration),
|
const shouldRenderConfigurations =
|
||||||
},
|
targetConfiguration.configurations &&
|
||||||
});
|
(typeof targetConfiguration.configurations === 'object'
|
||||||
};
|
? Object.keys(targetConfiguration.configurations).length
|
||||||
|
: true);
|
||||||
|
|
||||||
const shouldDisplayOverrideTarget = () => {
|
|
||||||
return (
|
return (
|
||||||
environment === 'nx-console' &&
|
<div className="ml-3 mb-3 rounded-md border border-slate-500 relative overflow-hidden">
|
||||||
Object.entries(props.sourceMap ?? {})
|
{/* header */}
|
||||||
.filter(([key]) => key.startsWith(`targets.${props.targetName}`))
|
<div className="group hover:bg-slate-800 px-2 cursor-pointer ">
|
||||||
.every(([, value]) => value[1] !== 'nx-core-build-project-json-nodes')
|
<h3
|
||||||
);
|
className="text-lg font-bold flex items-center gap-2"
|
||||||
};
|
onClick={toggleCollapsed}
|
||||||
|
>
|
||||||
const targetConfigurationSortedAndFiltered = Object.entries(
|
{targetName}{' '}
|
||||||
props.targetConfiguration
|
<h4 className="text-sm text-slate-600">
|
||||||
)
|
{targetConfiguration?.command ??
|
||||||
.filter(([, value]) => {
|
targetConfiguration.options?.command ??
|
||||||
return (
|
targetConfiguration.executor}
|
||||||
value &&
|
</h4>
|
||||||
(Array.isArray(value) ? value.length : true) &&
|
<span
|
||||||
(typeof value === 'object' ? Object.keys(value).length : true)
|
className={
|
||||||
);
|
collapsed ? 'hidden group-hover:inline-flex' : 'inline-flex'
|
||||||
})
|
|
||||||
.sort(([a], [b]) => {
|
|
||||||
const order = ['executor', 'inputs', 'outputs'];
|
|
||||||
const indexA = order.indexOf(a);
|
|
||||||
const indexB = order.indexOf(b);
|
|
||||||
|
|
||||||
if (indexA !== -1 && indexB !== -1) {
|
|
||||||
return indexA - indexB;
|
|
||||||
} else if (indexA !== -1) {
|
|
||||||
return -1;
|
|
||||||
} else if (indexB !== -1) {
|
|
||||||
return 1;
|
|
||||||
} else {
|
|
||||||
return a.localeCompare(b);
|
|
||||||
}
|
}
|
||||||
});
|
>
|
||||||
return (
|
<span
|
||||||
<div className="ml-3 mb-3">
|
className={`inline-flex justify-center rounded-md p-1 hover:bg-slate-100 hover:dark:bg-slate-700
|
||||||
<h3 className="text-lg font-bold flex items-center gap-2">
|
}`}
|
||||||
{props.targetName}{' '}
|
>
|
||||||
|
<EyeIcon
|
||||||
|
className="h-4 w-4"
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
viewInTaskGraph();
|
||||||
|
}}
|
||||||
|
></EyeIcon>
|
||||||
|
</span>
|
||||||
{environment === 'nx-console' && (
|
{environment === 'nx-console' && (
|
||||||
<PlayIcon className="h-5 w-5" onClick={runTarget} />
|
<span
|
||||||
|
className={`inline-flex justify-center rounded-md p-1 hover:bg-slate-100 hover:dark:bg-slate-700
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
<PlayIcon
|
||||||
|
className="h-4 w-4"
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
runTarget();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
)}
|
)}
|
||||||
<EyeIcon className="h-5 w-5" onClick={viewInTaskGraph}></EyeIcon>
|
</span>
|
||||||
{shouldDisplayOverrideTarget() && (
|
{targetConfiguration.cache && (
|
||||||
<PencilSquareIcon className="h-5 w-5" onClick={overrideTarget} />
|
<span className="rounded-full inline-block text-xs bg-sky-500 px-2 text-slate-50 ml-auto mr-6">
|
||||||
|
Cacheable
|
||||||
|
</span>
|
||||||
)}
|
)}
|
||||||
</h3>
|
</h3>
|
||||||
<div className="ml-3">
|
<div className="absolute top-2 right-3" onClick={toggleCollapsed}>
|
||||||
{targetConfigurationSortedAndFiltered.map(([key, value]) =>
|
{collapsed ? (
|
||||||
PropertyRenderer({
|
<ChevronUpIcon className="h-3 w-3" />
|
||||||
propertyKey: key,
|
) : (
|
||||||
propertyValue: value,
|
<ChevronDownIcon className="h-3 w-3" />
|
||||||
keyPrefix: `targets.${props.targetName}`,
|
|
||||||
sourceMap: props.sourceMap,
|
|
||||||
})
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{/* body */}
|
||||||
|
{!collapsed && (
|
||||||
|
<div className="pl-5 text-base pb-6 pt-2 ">
|
||||||
|
{targetConfiguration.inputs && (
|
||||||
|
<>
|
||||||
|
<h4 className="font-bold">Inputs</h4>
|
||||||
|
<ul className="list-disc pl-5">
|
||||||
|
{targetConfiguration.inputs.map((input) => (
|
||||||
|
<li> {input.toString()} </li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{targetConfiguration.outputs && (
|
||||||
|
<>
|
||||||
|
<h4 className="font-bold pt-2">Outputs</h4>
|
||||||
|
<ul className="list-disc pl-5">
|
||||||
|
{targetConfiguration.outputs?.map((output) => (
|
||||||
|
<li> {output.toString()} </li>
|
||||||
|
)) ?? <span>no outputs</span>}
|
||||||
|
</ul>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{targetConfiguration.dependsOn && (
|
||||||
|
<>
|
||||||
|
<h4 className="font-bold py-2">Depends On</h4>
|
||||||
|
<ul className="list-disc pl-5">
|
||||||
|
{targetConfiguration.dependsOn.map((dep) => (
|
||||||
|
<li> {dep.toString()} </li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{shouldRenderOptions ? (
|
||||||
|
<>
|
||||||
|
<h4 className="font-bold py-2">Options</h4>
|
||||||
|
<FadingCollapsible>
|
||||||
|
<Fence
|
||||||
|
language="json"
|
||||||
|
command=""
|
||||||
|
path=""
|
||||||
|
fileName=""
|
||||||
|
highlightLines={[]}
|
||||||
|
lineGroups={{}}
|
||||||
|
enableCopy={true}
|
||||||
|
>
|
||||||
|
{JSON.stringify(targetConfiguration.options, null, 2)}
|
||||||
|
</Fence>
|
||||||
|
</FadingCollapsible>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
''
|
||||||
|
)}
|
||||||
|
{shouldRenderConfigurations ? (
|
||||||
|
<>
|
||||||
|
<h4 className="font-bold py-2">
|
||||||
|
Configurations{' '}
|
||||||
|
{targetConfiguration.defaultConfiguration && (
|
||||||
|
<span
|
||||||
|
className="ml-3 rounded-full inline-block text-xs bg-sky-500 px-2 text-slate-50 mr-6"
|
||||||
|
title="Default Configuration"
|
||||||
|
>
|
||||||
|
{targetConfiguration.defaultConfiguration}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</h4>
|
||||||
|
<FadingCollapsible>
|
||||||
|
<Fence
|
||||||
|
language="json"
|
||||||
|
command=""
|
||||||
|
path=""
|
||||||
|
fileName=""
|
||||||
|
highlightLines={[]}
|
||||||
|
lineGroups={{}}
|
||||||
|
enableCopy={true}
|
||||||
|
>
|
||||||
|
{JSON.stringify(targetConfiguration.configurations, null, 2)}
|
||||||
|
</Fence>
|
||||||
|
</FadingCollapsible>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
''
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,55 @@
|
|||||||
|
import { ArrowDownIcon, ArrowUpIcon } from '@heroicons/react/24/outline';
|
||||||
|
import { ReactNode, useEffect, useRef, useState } from 'react';
|
||||||
|
|
||||||
|
export function FadingCollapsible({ children }: { children: ReactNode }) {
|
||||||
|
const [collapsed, setCollapsed] = useState(true);
|
||||||
|
const [isCollapsible, setIsCollapsible] = useState(true);
|
||||||
|
const contentRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (contentRef.current) {
|
||||||
|
setIsCollapsible(contentRef.current.offsetHeight > 300);
|
||||||
|
}
|
||||||
|
}, [contentRef, children]);
|
||||||
|
|
||||||
|
function toggleCollapsed() {
|
||||||
|
setCollapsed(!collapsed);
|
||||||
|
}
|
||||||
|
|
||||||
|
const fadeStyles =
|
||||||
|
collapsed && isCollapsible
|
||||||
|
? {
|
||||||
|
maxHeight: '150px',
|
||||||
|
maskImage: 'linear-gradient(to bottom, black 40%, transparent)',
|
||||||
|
WebkitMaskImage: 'linear-gradient(to bottom, black 40%, transparent)',
|
||||||
|
}
|
||||||
|
: {};
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={`relative overflow-hidden ${
|
||||||
|
collapsed && isCollapsible ? 'cursor-pointer' : 'max-h-full'
|
||||||
|
}`}
|
||||||
|
onClick={() => collapsed && isCollapsible && toggleCollapsed()}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className={`${
|
||||||
|
collapsed && isCollapsible ? 'hover:bg-slate-700' : ''
|
||||||
|
} rounded-md`}
|
||||||
|
style={fadeStyles}
|
||||||
|
>
|
||||||
|
<div ref={contentRef}>{children}</div>
|
||||||
|
</div>
|
||||||
|
{isCollapsible && (
|
||||||
|
<div
|
||||||
|
className="h-4 w-4 absolute bottom-2 right-1/2 cursor-pointer"
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
toggleCollapsed();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{collapsed ? <ArrowDownIcon /> : <ArrowUpIcon />}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -1,21 +0,0 @@
|
|||||||
import { useState, useCallback } from 'react';
|
|
||||||
|
|
||||||
function useMapState<K, V>(initialMap: Map<K, V> = new Map()) {
|
|
||||||
const [map, setMap] = useState(new Map(initialMap));
|
|
||||||
|
|
||||||
// Function to set a key-value pair in the map
|
|
||||||
const setKey = useCallback((key: K, value: V) => {
|
|
||||||
setMap((prevMap) => {
|
|
||||||
const newMap = new Map(prevMap);
|
|
||||||
newMap.set(key, value);
|
|
||||||
return newMap;
|
|
||||||
});
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
// Function to get a value by key from the map
|
|
||||||
const getKey = useCallback((key: K) => map.get(key), [map]);
|
|
||||||
|
|
||||||
return [getKey, setKey] as const;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default useMapState;
|
|
||||||
@ -6,7 +6,8 @@
|
|||||||
"node",
|
"node",
|
||||||
"@nx/react/typings/cssmodule.d.ts",
|
"@nx/react/typings/cssmodule.d.ts",
|
||||||
"@nx/react/typings/image.d.ts"
|
"@nx/react/typings/image.d.ts"
|
||||||
]
|
],
|
||||||
|
"lib": ["DOM"]
|
||||||
},
|
},
|
||||||
"exclude": [
|
"exclude": [
|
||||||
"jest.config.ts",
|
"jest.config.ts",
|
||||||
|
|||||||
12
nx-dev/shared-ui-fence/.babelrc
Normal file
12
nx-dev/shared-ui-fence/.babelrc
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"presets": [
|
||||||
|
[
|
||||||
|
"@nx/react/babel",
|
||||||
|
{
|
||||||
|
"runtime": "automatic",
|
||||||
|
"useBuiltIns": "usage"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"plugins": []
|
||||||
|
}
|
||||||
18
nx-dev/shared-ui-fence/.eslintrc.json
Normal file
18
nx-dev/shared-ui-fence/.eslintrc.json
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"extends": ["plugin:@nx/react", "../../.eslintrc.json"],
|
||||||
|
"ignorePatterns": ["!**/*"],
|
||||||
|
"overrides": [
|
||||||
|
{
|
||||||
|
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
|
||||||
|
"rules": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"files": ["*.ts", "*.tsx"],
|
||||||
|
"rules": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"files": ["*.js", "*.jsx"],
|
||||||
|
"rules": {}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
7
nx-dev/shared-ui-fence/README.md
Normal file
7
nx-dev/shared-ui-fence/README.md
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
# shared-ui-fence
|
||||||
|
|
||||||
|
This library was generated with [Nx](https://nx.dev).
|
||||||
|
|
||||||
|
## Running unit tests
|
||||||
|
|
||||||
|
Run `nx test shared-ui-fence` to execute the unit tests via [Jest](https://jestjs.io).
|
||||||
10
nx-dev/shared-ui-fence/jest.config.ts
Normal file
10
nx-dev/shared-ui-fence/jest.config.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
/* eslint-disable */
|
||||||
|
export default {
|
||||||
|
displayName: 'shared-ui-fence',
|
||||||
|
preset: '../../jest.preset.js',
|
||||||
|
transform: {
|
||||||
|
'^.+\\.[tj]sx?$': ['babel-jest', { presets: ['@nx/react/babel'] }],
|
||||||
|
},
|
||||||
|
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'],
|
||||||
|
coverageDirectory: '../../coverage/nx-dev/shared-ui-fence',
|
||||||
|
};
|
||||||
20
nx-dev/shared-ui-fence/project.json
Normal file
20
nx-dev/shared-ui-fence/project.json
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"name": "shared-ui-fence",
|
||||||
|
"$schema": "../../node_modules/nx/schemas/project-schema.json",
|
||||||
|
"sourceRoot": "nx-dev/shared-ui-fence/src",
|
||||||
|
"projectType": "library",
|
||||||
|
"tags": [],
|
||||||
|
"targets": {
|
||||||
|
"lint": {
|
||||||
|
"executor": "@nx/eslint:lint"
|
||||||
|
},
|
||||||
|
"test": {
|
||||||
|
"executor": "@nx/jest:jest",
|
||||||
|
"outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
|
||||||
|
"options": {
|
||||||
|
"jestConfig": "nx-dev/shared-ui-fence/jest.config.ts",
|
||||||
|
"passWithNoTests": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
3
nx-dev/shared-ui-fence/src/index.ts
Normal file
3
nx-dev/shared-ui-fence/src/index.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export * from './lib/fence.component';
|
||||||
|
export { TerminalOutput } from './lib/fences/terminal-output.component';
|
||||||
|
export { TerminalShellWrapper } from './lib/fences/terminal-shell.component';
|
||||||
@ -11,8 +11,7 @@ import { CopyToClipboard } from 'react-copy-to-clipboard';
|
|||||||
import SyntaxHighlighter from 'react-syntax-highlighter';
|
import SyntaxHighlighter from 'react-syntax-highlighter';
|
||||||
import { CodeOutput } from './fences/code-output.component';
|
import { CodeOutput } from './fences/code-output.component';
|
||||||
import { TerminalOutput } from './fences/terminal-output.component';
|
import { TerminalOutput } from './fences/terminal-output.component';
|
||||||
import { useRouter } from 'next/router';
|
import { Selector } from '@nx/shared-ui-selector';
|
||||||
import { Selector } from '@nx/nx-dev/ui-common';
|
|
||||||
|
|
||||||
function resolveLanguage(lang: string) {
|
function resolveLanguage(lang: string) {
|
||||||
switch (lang) {
|
switch (lang) {
|
||||||
@ -57,32 +56,6 @@ function CodeWrapper(options: {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const useUrlHash = (initialValue: string) => {
|
|
||||||
const router = useRouter();
|
|
||||||
const [hash, setHash] = useState(initialValue);
|
|
||||||
|
|
||||||
const updateHash = (str: string) => {
|
|
||||||
if (!str) return;
|
|
||||||
setHash(str.split('#')[1]);
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const onWindowHashChange = () => updateHash(window.location.hash);
|
|
||||||
const onNextJSHashChange = (url: string) => updateHash(url);
|
|
||||||
|
|
||||||
router.events.on('hashChangeStart', onNextJSHashChange);
|
|
||||||
window.addEventListener('hashchange', onWindowHashChange);
|
|
||||||
window.addEventListener('load', onWindowHashChange);
|
|
||||||
return () => {
|
|
||||||
router.events.off('hashChangeStart', onNextJSHashChange);
|
|
||||||
window.removeEventListener('load', onWindowHashChange);
|
|
||||||
window.removeEventListener('hashchange', onWindowHashChange);
|
|
||||||
};
|
|
||||||
}, [router.asPath, router.events]);
|
|
||||||
|
|
||||||
return hash;
|
|
||||||
};
|
|
||||||
|
|
||||||
// pre-process the highlightLines to expand ranges like
|
// pre-process the highlightLines to expand ranges like
|
||||||
// ["8-10", 19, 22] => [8,9,10,19,22]
|
// ["8-10", 19, 22] => [8,9,10,19,22]
|
||||||
function processHighlightLines(highlightLines: any): number[] {
|
function processHighlightLines(highlightLines: any): number[] {
|
||||||
@ -109,6 +82,19 @@ function processHighlightLines(highlightLines: any): number[] {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface FenceProps {
|
||||||
|
children: string;
|
||||||
|
command: string;
|
||||||
|
path: string;
|
||||||
|
fileName: string;
|
||||||
|
highlightLines: number[];
|
||||||
|
lineGroups: Record<string, number[]>;
|
||||||
|
language: string;
|
||||||
|
enableCopy: boolean;
|
||||||
|
selectedLineGroup?: string;
|
||||||
|
onLineGroupSelectionChange?: (selection: string) => void;
|
||||||
|
}
|
||||||
|
|
||||||
export function Fence({
|
export function Fence({
|
||||||
children,
|
children,
|
||||||
command,
|
command,
|
||||||
@ -118,19 +104,9 @@ export function Fence({
|
|||||||
highlightLines,
|
highlightLines,
|
||||||
language,
|
language,
|
||||||
enableCopy,
|
enableCopy,
|
||||||
}: {
|
selectedLineGroup,
|
||||||
children: string;
|
onLineGroupSelectionChange,
|
||||||
command: string;
|
}: FenceProps) {
|
||||||
path: string;
|
|
||||||
fileName: string;
|
|
||||||
highlightLines: number[];
|
|
||||||
lineGroups: Record<string, number[]>;
|
|
||||||
language: string;
|
|
||||||
enableCopy: boolean;
|
|
||||||
}) {
|
|
||||||
const { push, asPath } = useRouter();
|
|
||||||
const hash = decodeURIComponent(useUrlHash(''));
|
|
||||||
|
|
||||||
if (highlightLines) {
|
if (highlightLines) {
|
||||||
highlightLines = processHighlightLines(highlightLines);
|
highlightLines = processHighlightLines(highlightLines);
|
||||||
}
|
}
|
||||||
@ -138,7 +114,9 @@ export function Fence({
|
|||||||
function lineNumberStyle(lineNumber: number) {
|
function lineNumberStyle(lineNumber: number) {
|
||||||
if (
|
if (
|
||||||
(highlightLines && highlightLines.includes(lineNumber)) ||
|
(highlightLines && highlightLines.includes(lineNumber)) ||
|
||||||
(lineGroups[hash] && lineGroups[hash].includes(lineNumber))
|
(selectedLineGroup &&
|
||||||
|
lineGroups[selectedLineGroup] &&
|
||||||
|
lineGroups[selectedLineGroup].includes(lineNumber))
|
||||||
) {
|
) {
|
||||||
return {
|
return {
|
||||||
fontSize: 0,
|
fontSize: 0,
|
||||||
@ -168,7 +146,7 @@ export function Fence({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
let selectedOption =
|
let selectedOption =
|
||||||
highlightOptions.find((option) => option.value === hash) ||
|
highlightOptions.find((option) => option.value === selectedLineGroup) ||
|
||||||
highlightOptions[0];
|
highlightOptions[0];
|
||||||
const [copied, setCopied] = useState(false);
|
const [copied, setCopied] = useState(false);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -185,10 +163,9 @@ export function Fence({
|
|||||||
const showRescopeMessage =
|
const showRescopeMessage =
|
||||||
children.includes('@nx/') || command.includes('@nx/');
|
children.includes('@nx/') || command.includes('@nx/');
|
||||||
function highlightChange(item: { label: string; value: string }) {
|
function highlightChange(item: { label: string; value: string }) {
|
||||||
push(asPath.split('#')[0] + '#' + item.value);
|
onLineGroupSelectionChange?.(item.value);
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<div className="my-8 w-full">
|
|
||||||
<div className="code-block group relative w-full">
|
<div className="code-block group relative w-full">
|
||||||
<div>
|
<div>
|
||||||
<div className="absolute top-0 right-0 z-10 flex">
|
<div className="absolute top-0 right-0 z-10 flex">
|
||||||
@ -257,6 +234,5 @@ export function Fence({
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
20
nx-dev/shared-ui-fence/tsconfig.json
Normal file
20
nx-dev/shared-ui-fence/tsconfig.json
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"jsx": "react-jsx",
|
||||||
|
"allowJs": false,
|
||||||
|
"esModuleInterop": false,
|
||||||
|
"allowSyntheticDefaultImports": true,
|
||||||
|
"strict": true
|
||||||
|
},
|
||||||
|
"files": [],
|
||||||
|
"include": [],
|
||||||
|
"references": [
|
||||||
|
{
|
||||||
|
"path": "./tsconfig.lib.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "./tsconfig.spec.json"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"extends": "../../tsconfig.base.json"
|
||||||
|
}
|
||||||
24
nx-dev/shared-ui-fence/tsconfig.lib.json
Normal file
24
nx-dev/shared-ui-fence/tsconfig.lib.json
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
"extends": "./tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "../../dist/out-tsc",
|
||||||
|
"types": [
|
||||||
|
"node",
|
||||||
|
"@nx/react/typings/cssmodule.d.ts",
|
||||||
|
"@nx/react/typings/image.d.ts"
|
||||||
|
],
|
||||||
|
"lib": ["DOM", "es2019"]
|
||||||
|
},
|
||||||
|
"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"]
|
||||||
|
}
|
||||||
20
nx-dev/shared-ui-fence/tsconfig.spec.json
Normal file
20
nx-dev/shared-ui-fence/tsconfig.spec.json
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"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"
|
||||||
|
]
|
||||||
|
}
|
||||||
12
nx-dev/shared-ui-selector/.babelrc
Normal file
12
nx-dev/shared-ui-selector/.babelrc
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"presets": [
|
||||||
|
[
|
||||||
|
"@nx/react/babel",
|
||||||
|
{
|
||||||
|
"runtime": "automatic",
|
||||||
|
"useBuiltIns": "usage"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"plugins": []
|
||||||
|
}
|
||||||
18
nx-dev/shared-ui-selector/.eslintrc.json
Normal file
18
nx-dev/shared-ui-selector/.eslintrc.json
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"extends": ["plugin:@nx/react", "../../.eslintrc.json"],
|
||||||
|
"ignorePatterns": ["!**/*"],
|
||||||
|
"overrides": [
|
||||||
|
{
|
||||||
|
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
|
||||||
|
"rules": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"files": ["*.ts", "*.tsx"],
|
||||||
|
"rules": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"files": ["*.js", "*.jsx"],
|
||||||
|
"rules": {}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
7
nx-dev/shared-ui-selector/README.md
Normal file
7
nx-dev/shared-ui-selector/README.md
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
# shared-ui-selector
|
||||||
|
|
||||||
|
This library was generated with [Nx](https://nx.dev).
|
||||||
|
|
||||||
|
## Running unit tests
|
||||||
|
|
||||||
|
Run `nx test shared-ui-selector` to execute the unit tests via [Jest](https://jestjs.io).
|
||||||
10
nx-dev/shared-ui-selector/jest.config.ts
Normal file
10
nx-dev/shared-ui-selector/jest.config.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
/* eslint-disable */
|
||||||
|
export default {
|
||||||
|
displayName: 'shared-ui-selector',
|
||||||
|
preset: '../../jest.preset.js',
|
||||||
|
transform: {
|
||||||
|
'^.+\\.[tj]sx?$': ['babel-jest', { presets: ['@nx/react/babel'] }],
|
||||||
|
},
|
||||||
|
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'],
|
||||||
|
coverageDirectory: '../../coverage/nx-dev/shared-ui-selector',
|
||||||
|
};
|
||||||
20
nx-dev/shared-ui-selector/project.json
Normal file
20
nx-dev/shared-ui-selector/project.json
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"name": "shared-ui-selector",
|
||||||
|
"$schema": "../../node_modules/nx/schemas/project-schema.json",
|
||||||
|
"sourceRoot": "nx-dev/shared-ui-selector/src",
|
||||||
|
"projectType": "library",
|
||||||
|
"tags": [],
|
||||||
|
"targets": {
|
||||||
|
"lint": {
|
||||||
|
"executor": "@nx/eslint:lint"
|
||||||
|
},
|
||||||
|
"test": {
|
||||||
|
"executor": "@nx/jest:jest",
|
||||||
|
"outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
|
||||||
|
"options": {
|
||||||
|
"jestConfig": "nx-dev/shared-ui-selector/jest.config.ts",
|
||||||
|
"passWithNoTests": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
1
nx-dev/shared-ui-selector/src/index.ts
Normal file
1
nx-dev/shared-ui-selector/src/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './lib/selector';
|
||||||
20
nx-dev/shared-ui-selector/tsconfig.json
Normal file
20
nx-dev/shared-ui-selector/tsconfig.json
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"jsx": "react-jsx",
|
||||||
|
"allowJs": false,
|
||||||
|
"esModuleInterop": false,
|
||||||
|
"allowSyntheticDefaultImports": true,
|
||||||
|
"strict": true
|
||||||
|
},
|
||||||
|
"files": [],
|
||||||
|
"include": [],
|
||||||
|
"references": [
|
||||||
|
{
|
||||||
|
"path": "./tsconfig.lib.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "./tsconfig.spec.json"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"extends": "../../tsconfig.base.json"
|
||||||
|
}
|
||||||
24
nx-dev/shared-ui-selector/tsconfig.lib.json
Normal file
24
nx-dev/shared-ui-selector/tsconfig.lib.json
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
"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"
|
||||||
|
],
|
||||||
|
"include": ["src/**/*.js", "src/**/*.jsx", "src/**/*.ts", "src/**/*.tsx"]
|
||||||
|
}
|
||||||
20
nx-dev/shared-ui-selector/tsconfig.spec.json
Normal file
20
nx-dev/shared-ui-selector/tsconfig.spec.json
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"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"
|
||||||
|
]
|
||||||
|
}
|
||||||
@ -1,6 +1,7 @@
|
|||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import { CopyToClipboard } from 'react-copy-to-clipboard';
|
import { CopyToClipboard } from 'react-copy-to-clipboard';
|
||||||
|
// @ts-ignore
|
||||||
import SyntaxHighlighter from 'react-syntax-highlighter';
|
import SyntaxHighlighter from 'react-syntax-highlighter';
|
||||||
|
|
||||||
/* eslint-disable-next-line */
|
/* eslint-disable-next-line */
|
||||||
|
|||||||
@ -7,7 +7,6 @@ export * from './lib/champion-perks';
|
|||||||
export * from './lib/header';
|
export * from './lib/header';
|
||||||
export * from './lib/flip-card';
|
export * from './lib/flip-card';
|
||||||
export * from './lib/footer';
|
export * from './lib/footer';
|
||||||
export * from './lib/selector';
|
|
||||||
export * from './lib/sidebar-container';
|
export * from './lib/sidebar-container';
|
||||||
export * from './lib/sidebar';
|
export * from './lib/sidebar';
|
||||||
export * from './lib/nx-users-showcase';
|
export * from './lib/nx-users-showcase';
|
||||||
|
|||||||
@ -8,8 +8,6 @@ import {
|
|||||||
} from '@markdoc/markdoc';
|
} from '@markdoc/markdoc';
|
||||||
import { load as yamlLoad } from 'js-yaml';
|
import { load as yamlLoad } from 'js-yaml';
|
||||||
import React, { ReactNode } from 'react';
|
import React, { ReactNode } from 'react';
|
||||||
import { Fence } from './lib/nodes/fence.component';
|
|
||||||
import { fence } from './lib/nodes/fence.schema';
|
|
||||||
import { Heading } from './lib/nodes/heading.component';
|
import { Heading } from './lib/nodes/heading.component';
|
||||||
import { heading } from './lib/nodes/heading.schema';
|
import { heading } from './lib/nodes/heading.schema';
|
||||||
import { getImageSchema } from './lib/nodes/image.schema';
|
import { getImageSchema } from './lib/nodes/image.schema';
|
||||||
@ -55,6 +53,8 @@ import { VideoLink, videoLink } from './lib/tags/video-link.component';
|
|||||||
import { Pill } from './lib/tags/pill.component';
|
import { Pill } from './lib/tags/pill.component';
|
||||||
import { pill } from './lib/tags/pill.schema';
|
import { pill } from './lib/tags/pill.schema';
|
||||||
import { frameworkIcons } from './lib/icons';
|
import { frameworkIcons } from './lib/icons';
|
||||||
|
import { fence } from './lib/nodes/fence.schema';
|
||||||
|
import { FenceWrapper } from './lib/nodes/fence-wrapper.component';
|
||||||
|
|
||||||
// TODO fix this export
|
// TODO fix this export
|
||||||
export { GithubRepository } from './lib/tags/github-repository.component';
|
export { GithubRepository } from './lib/tags/github-repository.component';
|
||||||
@ -103,7 +103,7 @@ export const getMarkdocCustomConfig = (
|
|||||||
Disclosure,
|
Disclosure,
|
||||||
LinkCard,
|
LinkCard,
|
||||||
CustomLink,
|
CustomLink,
|
||||||
Fence,
|
FenceWrapper,
|
||||||
GithubRepository,
|
GithubRepository,
|
||||||
StackblitzButton,
|
StackblitzButton,
|
||||||
Graph,
|
Graph,
|
||||||
|
|||||||
47
nx-dev/ui-markdoc/src/lib/nodes/fence-wrapper.component.tsx
Normal file
47
nx-dev/ui-markdoc/src/lib/nodes/fence-wrapper.component.tsx
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
import { Fence, FenceProps } from '@nx/shared-ui-fence';
|
||||||
|
import { useRouter } from 'next/router';
|
||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
|
||||||
|
const useUrlHash = (initialValue: string) => {
|
||||||
|
const router = useRouter();
|
||||||
|
const [hash, setHash] = useState(initialValue);
|
||||||
|
|
||||||
|
const updateHash = (str: string) => {
|
||||||
|
if (!str) return;
|
||||||
|
setHash(str.split('#')[1]);
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const onWindowHashChange = () => updateHash(window.location.hash);
|
||||||
|
const onNextJSHashChange = (url: string) => updateHash(url);
|
||||||
|
|
||||||
|
router.events.on('hashChangeStart', onNextJSHashChange);
|
||||||
|
window.addEventListener('hashchange', onWindowHashChange);
|
||||||
|
window.addEventListener('load', onWindowHashChange);
|
||||||
|
return () => {
|
||||||
|
router.events.off('hashChangeStart', onNextJSHashChange);
|
||||||
|
window.removeEventListener('load', onWindowHashChange);
|
||||||
|
window.removeEventListener('hashchange', onWindowHashChange);
|
||||||
|
};
|
||||||
|
}, [router.asPath, router.events]);
|
||||||
|
|
||||||
|
return hash;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function FenceWrapper(props: FenceProps) {
|
||||||
|
const { push, asPath } = useRouter();
|
||||||
|
const hash = decodeURIComponent(useUrlHash(''));
|
||||||
|
|
||||||
|
const modifiedProps: FenceProps = {
|
||||||
|
...props,
|
||||||
|
selectedLineGroup: hash,
|
||||||
|
onLineGroupSelectionChange: (selection: string) => {
|
||||||
|
push(asPath.split('#')[0] + '#' + selection);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<div className="my-8 w-full">
|
||||||
|
<Fence {...modifiedProps} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -1,7 +1,7 @@
|
|||||||
import { Schema, Tag } from '@markdoc/markdoc';
|
import { Schema, Tag } from '@markdoc/markdoc';
|
||||||
|
|
||||||
export const fence: Schema = {
|
export const fence: Schema = {
|
||||||
render: 'Fence',
|
render: 'FenceWrapper',
|
||||||
attributes: {
|
attributes: {
|
||||||
content: { type: 'String', render: false, required: true },
|
content: { type: 'String', render: false, required: true },
|
||||||
language: { type: 'String' },
|
language: { type: 'String' },
|
||||||
@ -18,6 +18,6 @@ export const fence: Schema = {
|
|||||||
const children = node.children.length
|
const children = node.children.length
|
||||||
? node.transformChildren(config)
|
? node.transformChildren(config)
|
||||||
: [node.attributes['content']];
|
: [node.attributes['content']];
|
||||||
return new Tag('Fence', attributes, children);
|
return new Tag('FenceWrapper', attributes, children);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
|
import { TerminalShellWrapper } from '@nx/shared-ui-fence';
|
||||||
import { VideoLoop } from './video-loop.component';
|
import { VideoLoop } from './video-loop.component';
|
||||||
import { Schema } from '@markdoc/markdoc';
|
import { Schema } from '@markdoc/markdoc';
|
||||||
import { TerminalShellWrapper } from '../nodes/fences/terminal-shell.component';
|
|
||||||
|
|
||||||
export const terminalVideo: Schema = {
|
export const terminalVideo: Schema = {
|
||||||
render: 'TerminalVideo',
|
render: 'TerminalVideo',
|
||||||
|
|||||||
15
package.json
15
package.json
@ -106,7 +106,7 @@
|
|||||||
"@swc/cli": "0.1.62",
|
"@swc/cli": "0.1.62",
|
||||||
"@swc/core": "^1.3.85",
|
"@swc/core": "^1.3.85",
|
||||||
"@swc/jest": "^0.2.20",
|
"@swc/jest": "^0.2.20",
|
||||||
"@testing-library/react": "13.4.0",
|
"@testing-library/react": "14.0.0",
|
||||||
"@types/cytoscape": "^3.18.2",
|
"@types/cytoscape": "^3.18.2",
|
||||||
"@types/detect-port": "^1.3.2",
|
"@types/detect-port": "^1.3.2",
|
||||||
"@types/ejs": "3.1.2",
|
"@types/ejs": "3.1.2",
|
||||||
@ -123,8 +123,8 @@
|
|||||||
"@types/node": "18.16.9",
|
"@types/node": "18.16.9",
|
||||||
"@types/npm-package-arg": "6.1.1",
|
"@types/npm-package-arg": "6.1.1",
|
||||||
"@types/prettier": "^2.6.2",
|
"@types/prettier": "^2.6.2",
|
||||||
"@types/react": "18.2.24",
|
"@types/react": "18.2.33",
|
||||||
"@types/react-dom": "18.2.9",
|
"@types/react-dom": "18.2.14",
|
||||||
"@types/semver": "^7.5.2",
|
"@types/semver": "^7.5.2",
|
||||||
"@types/tar-stream": "^2.2.2",
|
"@types/tar-stream": "^2.2.2",
|
||||||
"@types/tmp": "^0.2.0",
|
"@types/tmp": "^0.2.0",
|
||||||
@ -169,10 +169,10 @@
|
|||||||
"eslint-config-next": "13.1.1",
|
"eslint-config-next": "13.1.1",
|
||||||
"eslint-config-prettier": "9.0.0",
|
"eslint-config-prettier": "9.0.0",
|
||||||
"eslint-plugin-cypress": "2.14.0",
|
"eslint-plugin-cypress": "2.14.0",
|
||||||
"eslint-plugin-import": "2.26.0",
|
"eslint-plugin-import": "2.27.5",
|
||||||
"eslint-plugin-jsx-a11y": "6.6.1",
|
"eslint-plugin-jsx-a11y": "6.7.1",
|
||||||
"eslint-plugin-playwright": "^0.15.3",
|
"eslint-plugin-playwright": "^0.15.3",
|
||||||
"eslint-plugin-react": "7.31.11",
|
"eslint-plugin-react": "7.32.2",
|
||||||
"eslint-plugin-react-hooks": "4.6.0",
|
"eslint-plugin-react-hooks": "4.6.0",
|
||||||
"eslint-plugin-storybook": "^0.6.12",
|
"eslint-plugin-storybook": "^0.6.12",
|
||||||
"express": "^4.18.1",
|
"express": "^4.18.1",
|
||||||
@ -249,7 +249,7 @@
|
|||||||
"react-markdown": "^8.0.7",
|
"react-markdown": "^8.0.7",
|
||||||
"react-redux": "8.0.5",
|
"react-redux": "8.0.5",
|
||||||
"react-refresh": "^0.10.0",
|
"react-refresh": "^0.10.0",
|
||||||
"react-router-dom": "^6.11.2",
|
"react-router-dom": "^6.21.2",
|
||||||
"react-textarea-autosize": "^8.5.3",
|
"react-textarea-autosize": "^8.5.3",
|
||||||
"regenerator-runtime": "0.13.7",
|
"regenerator-runtime": "0.13.7",
|
||||||
"resolve.exports": "1.1.0",
|
"resolve.exports": "1.1.0",
|
||||||
@ -371,4 +371,3 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -9,7 +9,12 @@ describe('createWatchPaths', () => {
|
|||||||
const testDir = joinPathFragments(workspaceRoot, 'e2e/remix');
|
const testDir = joinPathFragments(workspaceRoot, 'e2e/remix');
|
||||||
|
|
||||||
const paths = await createWatchPaths(testDir);
|
const paths = await createWatchPaths(testDir);
|
||||||
expect(paths).toEqual(['../../packages', '../../graph', '../../e2e/utils']);
|
expect(paths).toEqual([
|
||||||
|
'../../packages',
|
||||||
|
'../../graph',
|
||||||
|
'../../nx-dev',
|
||||||
|
'../../e2e/utils',
|
||||||
|
]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
1849
pnpm-lock.yaml
generated
1849
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@ -102,6 +102,8 @@
|
|||||||
"@nx/remix/*": ["packages/remix/*"],
|
"@nx/remix/*": ["packages/remix/*"],
|
||||||
"@nx/rollup": ["packages/rollup"],
|
"@nx/rollup": ["packages/rollup"],
|
||||||
"@nx/rollup/*": ["packages/rollup/*"],
|
"@nx/rollup/*": ["packages/rollup/*"],
|
||||||
|
"@nx/shared-ui-fence": ["nx-dev/shared-ui-fence/src/index.ts"],
|
||||||
|
"@nx/shared-ui-selector": ["nx-dev/shared-ui-selector/src/index.ts"],
|
||||||
"@nx/storybook": ["packages/storybook"],
|
"@nx/storybook": ["packages/storybook"],
|
||||||
"@nx/storybook/*": ["packages/storybook/*"],
|
"@nx/storybook/*": ["packages/storybook/*"],
|
||||||
"@nx/typedoc-theme": ["typedoc-theme/src/index.ts"],
|
"@nx/typedoc-theme": ["typedoc-theme/src/index.ts"],
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user