From 2393f439db54286a95f2471e09c2edf721545518 Mon Sep 17 00:00:00 2001 From: prasanth-ideas2it Date: Thu, 19 Dec 2024 18:08:00 +0530 Subject: [PATCH 1/3] feat: Oso implementation --- app/projects/[id]/page.module.css | 2 + app/projects/[id]/page.tsx | 41 ++++++++- .../page/project-details/stats-card.tsx | 89 +++++++++++++++++++ components/page/project-details/stats.tsx | 69 ++++++++++++++ public/icons/contributors.svg | 4 + public/icons/fork.svg | 3 + public/icons/repos.svg | 6 ++ services/projects.service.ts | 11 +++ 8 files changed, 223 insertions(+), 2 deletions(-) create mode 100644 components/page/project-details/stats-card.tsx create mode 100644 components/page/project-details/stats.tsx create mode 100644 public/icons/contributors.svg create mode 100644 public/icons/fork.svg create mode 100644 public/icons/repos.svg diff --git a/app/projects/[id]/page.module.css b/app/projects/[id]/page.module.css index 5698f41d..918d995c 100644 --- a/app/projects/[id]/page.module.css +++ b/app/projects/[id]/page.module.css @@ -38,6 +38,7 @@ .project__container__details__additionalDetails, .project__container__info__contributors, .project__container__info__teams, +.project__container__details__stats, .project__container__info__contacts { padding: 16px; background-color: #ffffff; @@ -76,6 +77,7 @@ .project__container__details__additionalDetails, .project__container__info__contributors, .project__container__info__teams, + .project__container__details__stats, .project__container__info__contacts { padding: 16px; box-shadow: 0px 4px 4px 0px rgba(15, 23, 42, 0.04), 0px 0px 1px 0px rgba(15, 23, 42, 0.12); diff --git a/app/projects/[id]/page.tsx b/app/projects/[id]/page.tsx index 0deb0912..99586c86 100644 --- a/app/projects/[id]/page.tsx +++ b/app/projects/[id]/page.tsx @@ -8,7 +8,7 @@ import Header from '@/components/page/project-details/header'; import Hyperlinks from '@/components/page/project-details/hyper-links'; import KPIs from '@/components/page/project-details/kpis'; import TeamsInvolved from '@/components/page/project-details/teams-involved'; -import { getProject } from '@/services/projects.service'; +import { getProject, getProjectOsoDetails } from '@/services/projects.service'; import { getAllTeams } from '@/services/teams.service'; import { hasProjectDeleteAccess, hasProjectEditAccess } from '@/utils/common.utils'; import { getCookiesFromHeaders } from '@/utils/next-helpers'; @@ -18,10 +18,11 @@ import { IFocusArea } from '@/types/shared.types'; import SelectedFocusAreas from '@/components/core/selected-focus-area'; import { PAGE_ROUTES, SOCIAL_IMAGE_URL } from '@/utils/constants'; import { Metadata, ResolvingMetadata } from 'next'; +import ProjectStats from '@/components/page/project-details/stats'; export default async function ProjectDetails({ params }: any) { const projectId = params?.id; - const { isError, userInfo, hasEditAccess, hasDeleteAccess, project, focusAreas, authToken } = await getPageData(projectId); + const { isError, userInfo, hasEditAccess, hasDeleteAccess, project, focusAreas, authToken, osoInfo } = await getPageData(projectId); if (isError) { return ; @@ -58,6 +59,10 @@ export default async function ProjectDetails({ params }: any) { )} +
+ +
+
@@ -86,6 +91,7 @@ const getPageData = async (projectId: string) => { let isError = false; const { authToken, isLoggedIn, userInfo } = getCookiesFromHeaders(); let project = null; + let osoInfo = null; let hasEditAccess = false; let hasDeleteAccess = false; let loggedInMemberTeams = []; @@ -124,6 +130,35 @@ const getPageData = async (projectId: string) => { project = projectResponse?.data?.formattedData; focusAreas = focusAreaResponse?.data?.filter((data: IFocusArea) => !data.parentUid); + const osoResponse = await getProjectOsoDetails(project.name); + console.log("osoResponse", osoResponse); + if (!osoResponse?.error) { + osoInfo = osoResponse?.data ?? {}; + } + + // osoInfo = { + // activeDeveloperCount6Months: 0, + // closedIssueCount6Months: 0, + // commitCount6Months: 0, + // contributorCount: 80, + // contributorCount6Months: 10, + // displayName: "MonezoXyz", + // eventSource: "GITHUB", + // firstCommitDate: "1970-01-01 00:00:00", + // forkCount: "5", + // fulltimeDeveloperAverage6Months: 0, + // lastCommitDate: "1970-01-01 00:00:00", + // mergedPullRequestCount6Months: 0, + // newContributorCount6Months: 0, + // openedIssueCount6Months: 0, + // openedPullRequestCount6Months: 0, + // projectId: "Xwq2x0EpJca2tVoc-eLLhJ2cTXqb-3UgFO_NwV2d0GA=", + // projectName: "monezoxyz", + // projectNamespace: "oso", + // projectSource: "OSS_DIRECTORY", + // repositoryCount: "3", + // starCount: "0" + // } hasEditAccess = hasProjectEditAccess(userInfo, project, isLoggedIn, loggedInMemberTeams); hasDeleteAccess = hasProjectDeleteAccess(userInfo, project, isLoggedIn); @@ -137,6 +172,7 @@ const getPageData = async (projectId: string) => { project, focusAreas, authToken, + osoInfo }; } catch (error) { return { @@ -148,6 +184,7 @@ const getPageData = async (projectId: string) => { project, focusAreas, authToken, + osoInfo }; } }; diff --git a/components/page/project-details/stats-card.tsx b/components/page/project-details/stats-card.tsx new file mode 100644 index 00000000..964a5a5c --- /dev/null +++ b/components/page/project-details/stats-card.tsx @@ -0,0 +1,89 @@ +'use client'; + +import Image from 'next/image'; + +interface IStatsCard { + statsName: string; + count: number; + icon: string; + newContributors?: number; +} + +const StatsCard = (props: IStatsCard) => { + const statsName = props?.statsName; + const count = props?.count; + const icon = props?.icon; + const newContributors = props?.newContributors ?? 0; + + return ( + <> +
+

+ {count} {statsName === 'Contributors' && newContributors > 0 && {`(${newContributors} New)`}} +

+
+ icon + {statsName} +
+ {(statsName === 'Contributors' && newContributors > 0) && Last 6 months} +
+ + + ); +}; + +export default StatsCard; diff --git a/components/page/project-details/stats.tsx b/components/page/project-details/stats.tsx new file mode 100644 index 00000000..1bd13b2c --- /dev/null +++ b/components/page/project-details/stats.tsx @@ -0,0 +1,69 @@ +'use client'; + +import StatsCard from './stats-card'; + +interface IProjectStats { + stats: any; +} + +const ProjectStats = (props: IProjectStats) => { + const stats = props?.stats; + + return ( + <> +
+
Project Stats
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+ + + ); +}; + +export default ProjectStats; diff --git a/public/icons/contributors.svg b/public/icons/contributors.svg new file mode 100644 index 00000000..33efd6fb --- /dev/null +++ b/public/icons/contributors.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/icons/fork.svg b/public/icons/fork.svg new file mode 100644 index 00000000..a961c0d1 --- /dev/null +++ b/public/icons/fork.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/icons/repos.svg b/public/icons/repos.svg new file mode 100644 index 00000000..6b6699de --- /dev/null +++ b/public/icons/repos.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/services/projects.service.ts b/services/projects.service.ts index 303efb86..34051ff6 100644 --- a/services/projects.service.ts +++ b/services/projects.service.ts @@ -175,4 +175,15 @@ const formatToSave = (payload: any) => { objectToSave['contributions'] = payload?.contributions; objectToSave['focusAreas'] = []; return objectToSave; +} + +export const getProjectOsoDetails = async (name: string) => { + const requestOptions: RequestInit = { method: "GET", headers: getHeader(""), cache: "no-store" }; + const response = await fetch(`${process.env.DIRECTORY_API_URL}/v1/oso-code-metrics-by-project-v1/${name}`, requestOptions); + if (!response?.ok) { + return { error: { statusText: response?.statusText } } + } + + const result = await response?.json(); + return { data: result } } \ No newline at end of file From 3eae1f575711adf87ded91e29e1e48c0d1f231a2 Mon Sep 17 00:00:00 2001 From: prasanth-ideas2it Date: Fri, 20 Dec 2024 12:47:15 +0530 Subject: [PATCH 2/3] feat: Oso new changes --- app/projects/[id]/page.tsx | 50 ++++++++++-------------------------- services/projects.service.ts | 1 + 2 files changed, 15 insertions(+), 36 deletions(-) diff --git a/app/projects/[id]/page.tsx b/app/projects/[id]/page.tsx index 99586c86..72fc03ed 100644 --- a/app/projects/[id]/page.tsx +++ b/app/projects/[id]/page.tsx @@ -23,6 +23,7 @@ import ProjectStats from '@/components/page/project-details/stats'; export default async function ProjectDetails({ params }: any) { const projectId = params?.id; const { isError, userInfo, hasEditAccess, hasDeleteAccess, project, focusAreas, authToken, osoInfo } = await getPageData(projectId); + const showProjectStats = osoInfo?.forkCount > 0 || osoInfo?.starCount > 0 || osoInfo?.repositoryCount > 0 || osoInfo?.contributorCount > 0; if (isError) { return ; @@ -37,7 +38,7 @@ export default async function ProjectDetails({ params }: any) {
- +
{project?.projectLinks?.length > 0 && ( @@ -59,9 +60,11 @@ export default async function ProjectDetails({ params }: any) {
)} -
- -
+ {showProjectStats && ( +
+ +
+ )}
@@ -99,7 +102,6 @@ const getPageData = async (projectId: string) => { try { const [projectResponse, focusAreaResponse] = await Promise.all([getProject(projectId, {}), getFocusAreas('Project', {})]); - if (projectResponse?.error || focusAreaResponse?.error) { return { isError: true, @@ -130,36 +132,13 @@ const getPageData = async (projectId: string) => { project = projectResponse?.data?.formattedData; focusAreas = focusAreaResponse?.data?.filter((data: IFocusArea) => !data.parentUid); - const osoResponse = await getProjectOsoDetails(project.name); - console.log("osoResponse", osoResponse); - if (!osoResponse?.error) { - osoInfo = osoResponse?.data ?? {}; + if (project.osoProjectName) { + const osoResponse = await getProjectOsoDetails(project.osoProjectName); + if (!osoResponse?.error) { + osoInfo = osoResponse?.data ?? {}; + } } - // osoInfo = { - // activeDeveloperCount6Months: 0, - // closedIssueCount6Months: 0, - // commitCount6Months: 0, - // contributorCount: 80, - // contributorCount6Months: 10, - // displayName: "MonezoXyz", - // eventSource: "GITHUB", - // firstCommitDate: "1970-01-01 00:00:00", - // forkCount: "5", - // fulltimeDeveloperAverage6Months: 0, - // lastCommitDate: "1970-01-01 00:00:00", - // mergedPullRequestCount6Months: 0, - // newContributorCount6Months: 0, - // openedIssueCount6Months: 0, - // openedPullRequestCount6Months: 0, - // projectId: "Xwq2x0EpJca2tVoc-eLLhJ2cTXqb-3UgFO_NwV2d0GA=", - // projectName: "monezoxyz", - // projectNamespace: "oso", - // projectSource: "OSS_DIRECTORY", - // repositoryCount: "3", - // starCount: "0" - // } - hasEditAccess = hasProjectEditAccess(userInfo, project, isLoggedIn, loggedInMemberTeams); hasDeleteAccess = hasProjectDeleteAccess(userInfo, project, isLoggedIn); @@ -172,7 +151,7 @@ const getPageData = async (projectId: string) => { project, focusAreas, authToken, - osoInfo + osoInfo, }; } catch (error) { return { @@ -184,12 +163,11 @@ const getPageData = async (projectId: string) => { project, focusAreas, authToken, - osoInfo + osoInfo, }; } }; - type IGenerateMetadata = { params: { id: string }; searchParams: { [key: string]: string | string[] | undefined }; diff --git a/services/projects.service.ts b/services/projects.service.ts index 34051ff6..fd45a99c 100644 --- a/services/projects.service.ts +++ b/services/projects.service.ts @@ -73,6 +73,7 @@ const getFormattedProject = (project: any) => { formattedProject['createdBy'] = project.createdBy ?? null; formattedProject['score'] = project.score ?? null; formattedProject['projectFocusAreas']= project.projectFocusAreas ?? []; + formattedProject['osoProjectName'] = project.osoProjectName ?? null; const tempContributors: any = []; project?.contributions?.map((mem: any) => { From a2a50bd33c6a7e0e051a44ed6ef007e58853e7aa Mon Sep 17 00:00:00 2001 From: prasanth-ideas2it Date: Fri, 20 Dec 2024 15:25:39 +0530 Subject: [PATCH 3/3] fix: End point changes --- services/projects.service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/projects.service.ts b/services/projects.service.ts index fd45a99c..17eea237 100644 --- a/services/projects.service.ts +++ b/services/projects.service.ts @@ -180,7 +180,7 @@ const formatToSave = (payload: any) => { export const getProjectOsoDetails = async (name: string) => { const requestOptions: RequestInit = { method: "GET", headers: getHeader(""), cache: "no-store" }; - const response = await fetch(`${process.env.DIRECTORY_API_URL}/v1/oso-code-metrics-by-project-v1/${name}`, requestOptions); + const response = await fetch(`${process.env.DIRECTORY_API_URL}/v1/oso-metrics/${name}`, requestOptions); if (!response?.ok) { return { error: { statusText: response?.statusText } } }