Skip to content

Commit

Permalink
fix(graph): update tooltip with addtl metadata
Browse files Browse the repository at this point in the history
  • Loading branch information
MaxKless committed Jun 24, 2024
1 parent d290708 commit c7b7bb1
Show file tree
Hide file tree
Showing 18 changed files with 169 additions and 60 deletions.
11 changes: 11 additions & 0 deletions graph/project-details/src/lib/project-details-wrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,14 @@ export function ProjectDetailsWrapper({
[externalApiService]
);

const handleNxConnect = useCallback(
() =>
externalApiService.postEvent({
type: 'nx-connect',
}),
[externalApiService]
);

const updateSearchParams = (
params: URLSearchParams,
targetNames: string[]
Expand Down Expand Up @@ -170,6 +178,9 @@ export function ProjectDetailsWrapper({
environment === 'nx-console' ? 'bottom' : 'top'
}
connectedToCloud={connectedToCloud}
nxConnectCallback={
environment === 'nx-console' ? handleNxConnect : undefined
}
/>
<ErrorToast errors={errors} />
</>
Expand Down
4 changes: 2 additions & 2 deletions graph/shared/src/lib/external-api-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ export function getExternalApiService() {
}

export class ExternalApiService {
private subscribers: Set<(event: { type: string; payload: any }) => void> =
private subscribers: Set<(event: { type: string; payload?: any }) => void> =
new Set();

postEvent(event: { type: string; payload: any }) {
postEvent(event: { type: string; payload?: any }) {
this.subscribers.forEach((subscriber) => {
subscriber(event);
});
Expand Down
1 change: 1 addition & 0 deletions graph/ui-icons/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from './lib/technology-icon';
export * from './lib/framework-icons';
export * from './lib/ nx-cloud-icon';
17 changes: 17 additions & 0 deletions graph/ui-icons/src/lib/ nx-cloud-icon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { FC, SVGProps } from 'react';

export const NxCloudIcon: FC<SVGProps<SVGSVGElement>> = (props) => (
<svg
role="img"
xmlns="http://www.w3.org/2000/svg"
stroke="currentColor"
fill="transparent"
viewBox="0 0 24 24"
{...props}
>
<path
d="M22.167 7.167v-2.5a2.5 2.5 0 0 0-2.5-2.5h-15a2.5 2.5 0 0 0-2.5 2.5v15a2.5 2.5 0 0 0 2.5 2.5h2.5m15-15c-2.76 0-5 2.24-5 5s-2.24 5-5 5-5 2.24-5 5m15-15V19.59a2.577 2.577 0 0 1-2.576 2.576H7.167"
strokeWidth="2"
/>
</svg>
);
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export interface ProjectDetailsProps {
targetName: string;
}) => void;
onRunTarget?: (data: { projectName: string; targetName: string }) => void;
nxConnectCallback?: () => void;
viewInProjectGraphPosition?: 'top' | 'bottom';
}

Expand All @@ -42,6 +43,7 @@ export const ProjectDetails = ({
onViewInProjectGraph,
onViewInTaskGraph,
onRunTarget,
nxConnectCallback,
viewInProjectGraphPosition = 'top',
connectedToCloud,
}: ProjectDetailsProps) => {
Expand Down Expand Up @@ -144,7 +146,7 @@ export const ProjectDetails = ({
</div>
</div>
</header>
<div>
<div className="z-0">
<h2 className={isCompact ? `mb-3 text-lg` : `mb-4 text-xl`}>
<Tooltip
openAction="hover"
Expand All @@ -164,6 +166,7 @@ export const ProjectDetails = ({
onRunTarget={onRunTarget}
onViewInTaskGraph={onViewInTaskGraph}
connectedToCloud={connectedToCloud}
nxConnectCallback={nxConnectCallback}
/>
</div>
</>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,28 @@ import { TargetConfigurationGroupHeader } from '../target-configuration-details-
export interface TargetConfigurationGroupContainerProps {
targetGroupName: string;
targetsNumber: number;
atomizer?: boolean;
nonAtomizedTarget?: string;
connectedToCloud?: boolean;
nxConnectCallback?: () => void;
children: React.ReactNode;
}

export function TargetConfigurationGroupContainer({
targetGroupName,
targetsNumber,
atomizer,
nonAtomizedTarget,
connectedToCloud,
nxConnectCallback,
children,
}: TargetConfigurationGroupContainerProps) {
return (
<div className="mb-4 w-full">
<TargetConfigurationGroupHeader
targetGroupName={targetGroupName}
targetsNumber={targetsNumber}
atomizer={atomizer}
nonAtomizedTarget={nonAtomizedTarget}
connectedToCloud={connectedToCloud}
nxConnectCallback={nxConnectCallback}
className="sticky top-0 z-10 bg-white dark:bg-slate-900"
/>
<div className="rounded-md border border-slate-200 p-2 dark:border-slate-700">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export const AtomizerCloud: Story = {
args: {
targetGroupName: 'Target Group Name',
targetsNumber: 5,
atomizer: true,
nonAtomizedTarget: 'e2e',
connectedToCloud: true,
},
};
Expand All @@ -29,7 +29,7 @@ export const AtomizerNoCloud: Story = {
args: {
targetGroupName: 'Target Group Name',
targetsNumber: 5,
atomizer: true,
nonAtomizedTarget: 'e2e',
connectedToCloud: false,
},
};
Original file line number Diff line number Diff line change
@@ -1,19 +1,25 @@
import { PropertyInfoTooltip, Tooltip } from '@nx/graph/ui-tooltips';
import {
AtomizerTooltip,
PropertyInfoTooltip,
Tooltip,
} from '@nx/graph/ui-tooltips';
import { Pill } from '../pill';

export interface TargetConfigurationGroupHeaderProps {
targetGroupName: string;
targetsNumber: number;
className?: string;
atomizer?: boolean;
nonAtomizedTarget?: string;
connectedToCloud?: boolean;
nxConnectCallback?: () => void;
}

export const TargetConfigurationGroupHeader = ({
targetGroupName,
targetsNumber,
atomizer,
nonAtomizedTarget,
connectedToCloud = true,
nxConnectCallback,
className = '',
}: TargetConfigurationGroupHeaderProps) => {
return (
Expand All @@ -27,14 +33,16 @@ export const TargetConfigurationGroupHeader = ({
(targetsNumber === 1 ? ' target' : ' targets')
}
/>
{atomizer && (
{nonAtomizedTarget && (
<Tooltip
openAction="hover"
strategy="fixed"
content={
(
<PropertyInfoTooltip
type={connectedToCloud ? 'atomizer-cloud' : 'atomizer-no-cloud'}
<AtomizerTooltip
connectedToCloud={connectedToCloud}
nonAtomizedTarget={nonAtomizedTarget}
nxConnectCallback={nxConnectCallback}
/>
) as any
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import type { ProjectGraphProjectNode } from '@nx/devkit';
import { TargetConfigurationDetailsListItem } from '../target-configuration-details-list-item/target-configuration-details-list-item';
import { TargetConfigurationGroupContainer } from '../target-configuration-details-group-container/target-configuration-details-group-container';
import {
getNonAtomizedTargetForGroup,
groupTargets,
targetGroupIsUsingAtomizer,
} from '../utils/group-targets';
import { useMemo } from 'react';

Expand All @@ -19,6 +19,7 @@ export interface TargetConfigurationGroupListProps {
projectName: string;
targetName: string;
}) => void;
nxConnectCallback?: () => void;
connectedToCloud?: boolean;
className?: string;
}
Expand All @@ -29,6 +30,7 @@ export function TargetConfigurationGroupList({
sourceMap,
onRunTarget,
onViewInTaskGraph,
nxConnectCallback,
className = '',
connectedToCloud,
}: TargetConfigurationGroupListProps) {
Expand All @@ -52,8 +54,12 @@ export function TargetConfigurationGroupList({
<TargetConfigurationGroupContainer
targetGroupName={targetGroupName}
targetsNumber={targets.length}
atomizer={targetGroupIsUsingAtomizer(project, targetGroupName)}
nonAtomizedTarget={getNonAtomizedTargetForGroup(
project,
targetGroupName
)}
connectedToCloud={connectedToCloud}
nxConnectCallback={nxConnectCallback}
key={targetGroupName}
>
<ul className={className}>
Expand Down
16 changes: 10 additions & 6 deletions graph/ui-project-details/src/lib/utils/group-targets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,17 @@ function sortNxReleasePublishLast(a: string, b: string) {
return a.localeCompare(b);
}

export function targetGroupIsUsingAtomizer(
export function getNonAtomizedTargetForGroup(
project: ProjectGraphProjectNode,
targetGroupName: string
) {
return (
project.data.metadata?.targetGroups?.[targetGroupName]?.some(
(target) => project.data.targets?.[target]?.metadata?.atomizer
) || false
): string | undefined {
const targetWithNonAtomizedEquivalent = project.data.metadata?.targetGroups?.[
targetGroupName
]?.find(
(target) => project.data.targets?.[target]?.metadata?.nonAtomizedTarget
);
return targetWithNonAtomizedEquivalent
? project.data.targets?.[targetWithNonAtomizedEquivalent]?.metadata
?.nonAtomizedTarget
: undefined;
}
1 change: 1 addition & 0 deletions graph/ui-tooltips/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ 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';
2 changes: 1 addition & 1 deletion graph/ui-tooltips/src/lib/atomizer-tooltip.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ type Story = StoryObj<typeof AtomizerTooltip>;

export const Primary: Story = {
args: {
isUsingCloud: true,
connectedToCloud: true,
nonAtomizedTarget: 'e2e',
} as AtomizerTooltipProps,
render: (args) => {
Expand Down
109 changes: 80 additions & 29 deletions graph/ui-tooltips/src/lib/atomizer-tooltip.tsx
Original file line number Diff line number Diff line change
@@ -1,47 +1,98 @@
import { twMerge } from 'tailwind-merge';
import { ExternalLink } from './external-link';
import { NxCloudIcon } from '@nx/graph/ui-icons';

export interface AtomizerTooltipProps {
isUsingCloud: boolean;
connectedToCloud: boolean;
nonAtomizedTarget: string;
nxConnectCallback?: () => void;
}
export function AtomizerTooltip(props: AtomizerTooltipProps) {
return (
<div className="max-w-lg text-sm text-slate-700 dark:text-slate-400">
<div className="z-20 max-w-lg text-sm text-slate-700 dark:text-slate-400">
<h4 className="flex items-center justify-between border-b border-slate-200 text-base dark:border-slate-700/60">
<span className="font-mono">Atomizer</span>
</h4>
<div className="flex flex-col py-2 font-mono">
<p className="flex grow items-center gap-2 whitespace-pre-wrap normal-case">
Nx{' '}
<ExternalLink href="https://nx.dev/ci/features/split-e2e-tasks">
automatically split
</ExternalLink>{' '}
this potentially slow task into separate tasks for each file. We
recommend enabling{' '}
<ExternalLink href="https://nx.app/">Nx Cloud</ExternalLink> and{' '}
<ExternalLink href="https://nx.dev/ci/features/distribute-task-execution">
Nx Agents
</ExternalLink>{' '}
to benefit from{' '}
<ExternalLink href="https://nx.dev/ci/features/distribute-task-execution">
task distribution
</ExternalLink>
,{' '}
<ExternalLink href="https://nx.dev/ci/features/remote-cache">
remote caching
</ExternalLink>{' '}
and{' '}
<ExternalLink href="https://nx.dev/ci/features/flaky-tasks">
flaky task re-runs
</ExternalLink>
<div className="flex flex-col border-b border-slate-200 py-2 font-mono dark:border-slate-700/60">
<p className="whitespace-pre-wrap normal-case">
{'Nx '}
<Link
href="https://nx.dev/ci/features/split-e2e-tasks"
text="automatically split"
/>
{
' this potentially slow task into separate tasks for each file. We recommend enabling '
}
{!props.connectedToCloud && (
<>
<Link href="https://nx.app/" text="Nx Cloud" />
{' and '}
</>
)}
<Link
href="https://nx.dev/ci/features/distribute-task-execution"
text="Nx Agents"
/>
{' to benefit from '}
<Link
href="https://nx.dev/ci/features/distribute-task-execution"
text="task distribution"
/>
{!props.connectedToCloud && (
<>
{', '}
<Link
href="https://nx.dev/ci/features/remote-cache"
text="remote caching"
/>
</>
)}
{' and '}
<Link
href="https://nx.dev/ci/features/flaky-tasks"
text="flaky task re-runs"
/>
. Use
<code className="ml-4 inline rounded bg-gray-100 px-2 py-1 font-mono text-gray-800 dark:bg-gray-700 dark:text-gray-300">
<code className="mx-2 inline rounded bg-gray-100 px-1 font-mono text-gray-800 dark:bg-gray-700 dark:text-gray-300">
{props.nonAtomizedTarget}
</code>
when running without Nx Agents.
</p>
</div>
{!props.connectedToCloud && (
<div className="flex py-2">
<p className="pr-4 normal-case">
{props.nxConnectCallback ? (
<button
className="inline-flex cursor-pointer items-center gap-2 rounded-md px-2 py-1 text-base text-slate-600 ring-2 ring-inset ring-slate-400/40 hover:bg-slate-50 dark:text-slate-300 dark:ring-slate-400/30 dark:hover:bg-slate-800/60"
onClick={() => props.nxConnectCallback!()}
>
<NxCloudIcon className="h-5 w-5 "></NxCloudIcon>
<span>Connect to Nx Cloud</span>
</button>
) : (
<>
{'Run'}
<code className="mx-2 inline rounded bg-gray-100 px-1 font-mono text-gray-800 dark:bg-gray-700 dark:text-gray-300">
nx connect
</code>
{'to connect to Nx Cloud'}
</>
)}
</p>
</div>
)}
</div>
);
}

function Link({ href, text }: { href: string; text: string }) {
return (
<a
href={href}
className="inline text-slate-500 underline decoration-slate-700/50 decoration-dotted decoration-2 dark:text-slate-400 dark:decoration-slate-400/50"
target="_blank"
rel="noreferrer"
>
{text}
</a>
);
}
Loading

0 comments on commit c7b7bb1

Please sign in to comment.