List latest commits from project repo in overview tab (#55)
This commit is contained in:
parent
1c9597739b
commit
7e522aa45d
@ -188,7 +188,7 @@ type Mutation {
|
|||||||
updateEnvironmentVariable(environmentVariableId: String!, data: UpdateEnvironmentVariableInput!): Boolean!
|
updateEnvironmentVariable(environmentVariableId: String!, data: UpdateEnvironmentVariableInput!): Boolean!
|
||||||
removeEnvironmentVariable(environmentVariableId: String!): Boolean!
|
removeEnvironmentVariable(environmentVariableId: String!): Boolean!
|
||||||
updateDeploymentToProd(deploymentId: String!): Boolean!
|
updateDeploymentToProd(deploymentId: String!): Boolean!
|
||||||
addProject(projectDetails: AddProjectInput): Boolean!
|
addProject(data: AddProjectInput): Boolean!
|
||||||
updateProject(projectId: String!, projectDetails: UpdateProjectInput): Boolean!
|
updateProject(projectId: String!, projectDetails: UpdateProjectInput): Boolean!
|
||||||
redeployToProd(deploymentId: String!): Boolean!
|
redeployToProd(deploymentId: String!): Boolean!
|
||||||
deleteProject(projectId: String!): Boolean!
|
deleteProject(projectId: String!): Boolean!
|
||||||
|
@ -3,31 +3,24 @@ import React from 'react';
|
|||||||
import { Typography, IconButton } from '@material-tailwind/react';
|
import { Typography, IconButton } from '@material-tailwind/react';
|
||||||
|
|
||||||
import { relativeTime } from '../../../utils/time';
|
import { relativeTime } from '../../../utils/time';
|
||||||
|
import { GitCommitDetails } from '../../../types/project';
|
||||||
interface ActivityDetails {
|
|
||||||
author: string;
|
|
||||||
authorAvatar: string;
|
|
||||||
createdAt: string;
|
|
||||||
branch: string;
|
|
||||||
message: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ActivityCardProps {
|
interface ActivityCardProps {
|
||||||
activity: ActivityDetails;
|
activity: GitCommitDetails;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ActivityCard = ({ activity }: ActivityCardProps) => {
|
const ActivityCard = ({ activity }: ActivityCardProps) => {
|
||||||
return (
|
return (
|
||||||
<div className="group flex hover:bg-gray-200 rounded mt-1">
|
<div className="group flex hover:bg-gray-200 rounded mt-1">
|
||||||
<div className="w-4">{activity.authorAvatar}</div>
|
<div className="w-4">^</div>
|
||||||
|
|
||||||
<div className="grow">
|
<div className="grow">
|
||||||
<Typography>{activity.author}</Typography>
|
<Typography>{activity.commit.author?.name}</Typography>
|
||||||
<Typography variant="small" color="gray">
|
<Typography variant="small" color="gray">
|
||||||
{relativeTime(activity.createdAt)} ^ {activity.branch}
|
{relativeTime(activity.commit.author!.date!)} ^ {activity.branch.name}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography variant="small" color="gray">
|
<Typography variant="small" color="gray">
|
||||||
{activity.message}
|
{activity.commit.message}
|
||||||
</Typography>
|
</Typography>
|
||||||
</div>
|
</div>
|
||||||
<div className="mr-2 self-center hidden group-hover:block">
|
<div className="mr-2 self-center hidden group-hover:block">
|
||||||
|
@ -1,11 +1,14 @@
|
|||||||
import React from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import { Project } from 'gql-client';
|
import { Project } from 'gql-client';
|
||||||
|
|
||||||
import { Typography, Button, Chip } from '@material-tailwind/react';
|
import { Typography, Button, Chip } from '@material-tailwind/react';
|
||||||
|
|
||||||
import ActivityCard from './ActivityCard';
|
import ActivityCard from './ActivityCard';
|
||||||
import activityDetails from '../../../assets/activities.json';
|
|
||||||
import { relativeTimeMs } from '../../../utils/time';
|
import { relativeTimeMs } from '../../../utils/time';
|
||||||
|
import { useOctokit } from '../../../context/OctokitContext';
|
||||||
|
import { GitCommitDetails } from '../../../types/project';
|
||||||
|
|
||||||
|
const COMMITS_PER_PAGE = 4;
|
||||||
|
|
||||||
interface OverviewProps {
|
interface OverviewProps {
|
||||||
project: Project;
|
project: Project;
|
||||||
@ -15,6 +18,58 @@ interface OverviewProps {
|
|||||||
const IS_DOMAIN_SETUP = false;
|
const IS_DOMAIN_SETUP = false;
|
||||||
|
|
||||||
const OverviewTabPanel = ({ project }: OverviewProps) => {
|
const OverviewTabPanel = ({ project }: OverviewProps) => {
|
||||||
|
const { octokit } = useOctokit();
|
||||||
|
const [activities, setActivities] = useState<GitCommitDetails[]>([]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!octokit) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Save repo commits in DB and avoid using GitHub API in frontend
|
||||||
|
// TODO: Figure out fetching latest commits for all branches
|
||||||
|
const fetchRepoActivity = async () => {
|
||||||
|
const [owner, repo] = project.repository.split('/');
|
||||||
|
|
||||||
|
// Get all branches in project repo
|
||||||
|
const result = await octokit.rest.repos.listBranches({
|
||||||
|
owner,
|
||||||
|
repo,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Get first 4 commits from repo branches
|
||||||
|
const commitsByBranchPromises = result.data.map(async (branch) => {
|
||||||
|
const result = await octokit.rest.repos.listCommits({
|
||||||
|
owner,
|
||||||
|
repo,
|
||||||
|
sha: branch.commit.sha,
|
||||||
|
per_page: COMMITS_PER_PAGE,
|
||||||
|
});
|
||||||
|
|
||||||
|
return result.data.map((data) => ({
|
||||||
|
...data,
|
||||||
|
branch,
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
const commitsByBranch = await Promise.all(commitsByBranchPromises);
|
||||||
|
const commitsWithBranch = commitsByBranch.flat();
|
||||||
|
|
||||||
|
// Order commits by date and set latest 4 commits in activity section
|
||||||
|
const orderedCommits = commitsWithBranch
|
||||||
|
.sort(
|
||||||
|
(a, b) =>
|
||||||
|
new Date(b.commit.author!.date!).getTime() -
|
||||||
|
new Date(a.commit.author!.date!).getTime(),
|
||||||
|
)
|
||||||
|
.slice(0, COMMITS_PER_PAGE);
|
||||||
|
|
||||||
|
setActivities(orderedCommits);
|
||||||
|
};
|
||||||
|
|
||||||
|
fetchRepoActivity();
|
||||||
|
}, [octokit, project]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="grid grid-cols-5">
|
<div className="grid grid-cols-5">
|
||||||
<div className="col-span-3 p-2">
|
<div className="col-span-3 p-2">
|
||||||
@ -86,8 +141,8 @@ const OverviewTabPanel = ({ project }: OverviewProps) => {
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div className="p-2">
|
<div className="p-2">
|
||||||
{activityDetails.map((activity, key) => {
|
{activities.map((activity, index) => {
|
||||||
return <ActivityCard activity={activity} key={key} />;
|
return <ActivityCard activity={activity} key={index} />;
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -44,6 +44,21 @@ export interface GitRepositoryDetails {
|
|||||||
default_branch?: string;
|
default_branch?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface GitBranchDetails {
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GitCommitDetails {
|
||||||
|
branch: GitBranchDetails;
|
||||||
|
commit: {
|
||||||
|
author: {
|
||||||
|
name?: string;
|
||||||
|
date?: string;
|
||||||
|
} | null;
|
||||||
|
message: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export enum GitSelect {
|
export enum GitSelect {
|
||||||
GITHUB = 'github',
|
GITHUB = 'github',
|
||||||
GITEA = 'gitea',
|
GITEA = 'gitea',
|
||||||
|
@ -194,15 +194,15 @@ export class GQLClient {
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
async addProject (projectDetails: AddProjectInput): Promise<AddProjectResponse> {
|
async addProject (data: AddProjectInput): Promise<AddProjectResponse> {
|
||||||
const { data } = await this.client.mutate({
|
const result = await this.client.mutate({
|
||||||
mutation: addProject,
|
mutation: addProject,
|
||||||
variables: {
|
variables: {
|
||||||
projectDetails
|
data
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return data;
|
return result.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
async updateProject (projectId: string, projectDetails: UpdateProjectInput): Promise<UpdateProjectResponse> {
|
async updateProject (projectId: string, projectDetails: UpdateProjectInput): Promise<UpdateProjectResponse> {
|
||||||
|
@ -43,8 +43,8 @@ mutation ($deploymentId: String!) {
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
export const addProject = gql`
|
export const addProject = gql`
|
||||||
mutation ($projectDetails: AddProjectInput) {
|
mutation ($data: AddProjectInput) {
|
||||||
addProject(projectDetails: $projectDetails)
|
addProject(data: $data)
|
||||||
}`;
|
}`;
|
||||||
|
|
||||||
export const updateProjectMutation = gql`
|
export const updateProjectMutation = gql`
|
||||||
|
Loading…
Reference in New Issue
Block a user