From 1d10a19abc76e576994cb64dde3b7bda1949e237 Mon Sep 17 00:00:00 2001
From: Emily Xiong
Date: Tue, 1 Oct 2024 15:00:01 -0700
Subject: [PATCH] feat(graph): show owners in pdv (#28211)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
## Current Behavior
## Expected Behavior
## Related Issue(s)
Fixes #
---
.../lib/owners-list/owners-list.stories.tsx | 42 ++++++++++
.../src/lib/owners-list/owners-list.tsx | 80 +++++++++++++++++++
.../lib/project-details/project-details.tsx | 8 ++
.../src/config/workspace-json-project-json.ts | 14 ++++
4 files changed, 144 insertions(+)
create mode 100644 graph/ui-project-details/src/lib/owners-list/owners-list.stories.tsx
create mode 100644 graph/ui-project-details/src/lib/owners-list/owners-list.tsx
diff --git a/graph/ui-project-details/src/lib/owners-list/owners-list.stories.tsx b/graph/ui-project-details/src/lib/owners-list/owners-list.stories.tsx
new file mode 100644
index 0000000000..5676694b86
--- /dev/null
+++ b/graph/ui-project-details/src/lib/owners-list/owners-list.stories.tsx
@@ -0,0 +1,42 @@
+import type { Meta, StoryObj } from '@storybook/react';
+import { OwnersList } from './owners-list';
+
+const meta: Meta = {
+ component: OwnersList,
+ title: 'OwnersList',
+};
+export default meta;
+
+type Story = StoryObj;
+
+export const FewOwners: Story = {
+ args: {
+ owners: ['owner1', 'owner2', 'owner3'],
+ },
+};
+export const ManyOwners: Story = {
+ args: {
+ owners: [
+ 'owner1',
+ 'owner2',
+ 'owner3',
+ 'owner4',
+ 'owner5',
+ 'owner6',
+ 'owner7',
+ 'owner8',
+ 'owner9',
+ 'owner10',
+ 'owner11',
+ 'owner12',
+ 'owner13',
+ 'owner14',
+ 'owner15',
+ 'owner16',
+ 'owner17',
+ 'owner18',
+ 'owner19',
+ 'owner20',
+ ],
+ },
+};
diff --git a/graph/ui-project-details/src/lib/owners-list/owners-list.tsx b/graph/ui-project-details/src/lib/owners-list/owners-list.tsx
new file mode 100644
index 0000000000..ede0bc8cf2
--- /dev/null
+++ b/graph/ui-project-details/src/lib/owners-list/owners-list.tsx
@@ -0,0 +1,80 @@
+import { useState, useRef, useEffect } from 'react';
+import { Pill } from '../pill';
+import { twMerge } from 'tailwind-merge';
+
+interface OwnersListProps {
+ owners: string[];
+ className?: string;
+}
+
+export function OwnersList({ owners, className }: OwnersListProps) {
+ const [isExpanded, _setIsExpanded] = useState(false);
+ const [isOverflowing, setIsOverflowing] = useState(false);
+ const ownersContainerRef = useRef(null);
+
+ const checkOverflow = () => {
+ requestAnimationFrame(() => {
+ if (ownersContainerRef.current) {
+ setIsOverflowing(
+ ownersContainerRef.current.scrollWidth >
+ ownersContainerRef.current.offsetWidth
+ );
+ }
+ });
+ };
+
+ const setExpanded = (value: boolean) => {
+ _setIsExpanded(value);
+ checkOverflow();
+ };
+
+ useEffect(() => {
+ checkOverflow();
+
+ window.addEventListener('resize', checkOverflow);
+ return () => window.removeEventListener('resize', checkOverflow);
+ }, [ownersContainerRef]);
+
+ return (
+
+
+ Owners:
+
+
+ {owners.map((tag) => (
+
+
+
+ ))}
+ {isExpanded && (
+
+ )}
+
+ {isOverflowing && !isExpanded && (
+
+ )}
+
+
+ );
+}
diff --git a/graph/ui-project-details/src/lib/project-details/project-details.tsx b/graph/ui-project-details/src/lib/project-details/project-details.tsx
index 026c984d4c..31fe2165ad 100644
--- a/graph/ui-project-details/src/lib/project-details/project-details.tsx
+++ b/graph/ui-project-details/src/lib/project-details/project-details.tsx
@@ -8,6 +8,7 @@ import { EyeIcon } from '@heroicons/react/24/outline';
import { PropertyInfoTooltip, Tooltip } from '@nx/graph/ui-tooltips';
import { twMerge } from 'tailwind-merge';
import { TagList } from '../tag-list/tag-list';
+import { OwnersList } from '../owners-list/owners-list';
import { TargetConfigurationGroupList } from '../target-configuration-details-group-list/target-configuration-details-group-list';
import { TooltipTriggerText } from '../target-configuration-details/tooltip-trigger-text';
import { TargetTechnologies } from '../target-technologies/target-technologies';
@@ -105,6 +106,13 @@ export const ProjectDetails = ({
{projectData.metadata?.description}
) : null}
+ {projectData.metadata?.owners &&
+ Object.keys(projectData.metadata?.owners).length ? (
+
+ ) : null}
{projectData.tags && projectData.tags.length ? (
) : null}
diff --git a/packages/nx/src/config/workspace-json-project-json.ts b/packages/nx/src/config/workspace-json-project-json.ts
index f10464a995..2ae7a8ddcd 100644
--- a/packages/nx/src/config/workspace-json-project-json.ts
+++ b/packages/nx/src/config/workspace-json-project-json.ts
@@ -122,6 +122,20 @@ export interface ProjectMetadata {
description?: string;
technologies?: string[];
targetGroups?: Record;
+ owners?: {
+ [ownerId: string]: {
+ ownedFiles: {
+ files: ['*'] | string[];
+ fromConfig?: {
+ filePath: string;
+ location: {
+ startLine: number;
+ endLine: number;
+ };
+ };
+ }[];
+ };
+ };
}
export interface TargetMetadata {