mirror of
https://github.com/harness/drone.git
synced 2025-05-07 23:01:10 +08:00
fix commit adn files changed counters
This commit is contained in:
parent
d2c04cf42c
commit
63145686f4
@ -9,6 +9,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/harness/gitness/gitrpc/rpc"
|
"github.com/harness/gitness/gitrpc/rpc"
|
||||||
@ -97,6 +98,7 @@ type RenameDetails struct {
|
|||||||
type ListCommitsOutput struct {
|
type ListCommitsOutput struct {
|
||||||
Commits []Commit
|
Commits []Commit
|
||||||
RenameDetails []*RenameDetails
|
RenameDetails []*RenameDetails
|
||||||
|
TotalCommits int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) ListCommits(ctx context.Context, params *ListCommitsParams) (*ListCommitsOutput, error) {
|
func (c *Client) ListCommits(ctx context.Context, params *ListCommitsParams) (*ListCommitsOutput, error) {
|
||||||
@ -122,6 +124,21 @@ func (c *Client) ListCommits(ctx context.Context, params *ListCommitsParams) (*L
|
|||||||
Commits: make([]Commit, 0, 16),
|
Commits: make([]Commit, 0, 16),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check for list commits header
|
||||||
|
header, err := stream.Header()
|
||||||
|
if err != nil {
|
||||||
|
return nil, processRPCErrorf(err, "failed to read list commits header from stream")
|
||||||
|
}
|
||||||
|
|
||||||
|
values := header.Get("total-commits")
|
||||||
|
if len(values) > 0 && values[0] != "" {
|
||||||
|
total, err := strconv.ParseInt(values[0], 10, 32)
|
||||||
|
if err != nil {
|
||||||
|
return nil, processRPCErrorf(err, "failed to convert header total-commits")
|
||||||
|
}
|
||||||
|
output.TotalCommits = int(total)
|
||||||
|
}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
var next *rpc.ListCommitsResponse
|
var next *rpc.ListCommitsResponse
|
||||||
next, err = stream.Recv()
|
next, err = stream.Recv()
|
||||||
|
@ -6,12 +6,14 @@ package service
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
"github.com/harness/gitness/gitrpc/internal/types"
|
"github.com/harness/gitness/gitrpc/internal/types"
|
||||||
"github.com/harness/gitness/gitrpc/rpc"
|
"github.com/harness/gitness/gitrpc/rpc"
|
||||||
|
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
"google.golang.org/grpc/codes"
|
"google.golang.org/grpc/codes"
|
||||||
|
"google.golang.org/grpc/metadata"
|
||||||
"google.golang.org/grpc/status"
|
"google.golang.org/grpc/status"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -65,7 +67,27 @@ func (s RepositoryService) ListCommits(request *rpc.ListCommitsRequest,
|
|||||||
return processGitErrorf(err, "failed to get list of commits")
|
return processGitErrorf(err, "failed to get list of commits")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// try to get total commits between gitref and After refs
|
||||||
|
totalCommits := 0
|
||||||
|
if request.Page == 1 && len(gitCommits) < int(request.Limit) {
|
||||||
|
totalCommits = len(gitCommits)
|
||||||
|
} else if request.After != "" && request.GitRef != request.After {
|
||||||
|
div, err := s.adapter.GetCommitDivergences(ctx, repoPath, []types.CommitDivergenceRequest{
|
||||||
|
{From: request.GitRef, To: request.After},
|
||||||
|
}, 0)
|
||||||
|
if err != nil {
|
||||||
|
return processGitErrorf(err, "failed to get total commits")
|
||||||
|
}
|
||||||
|
if len(div) > 0 {
|
||||||
|
totalCommits = int(div[0].Ahead)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
log.Ctx(ctx).Trace().Msgf("git adapter returned %d commits", len(gitCommits))
|
log.Ctx(ctx).Trace().Msgf("git adapter returned %d commits", len(gitCommits))
|
||||||
|
header := metadata.New(map[string]string{"total-commits": strconv.Itoa(totalCommits)})
|
||||||
|
if err := stream.SendHeader(header); err != nil {
|
||||||
|
return ErrInternalf("unable to send 'total-commits' header", err)
|
||||||
|
}
|
||||||
|
|
||||||
for i := range gitCommits {
|
for i := range gitCommits {
|
||||||
var commit *rpc.Commit
|
var commit *rpc.Commit
|
||||||
|
@ -20,14 +20,14 @@ import (
|
|||||||
* ListCommits lists the commits of a repo.
|
* ListCommits lists the commits of a repo.
|
||||||
*/
|
*/
|
||||||
func (c *Controller) ListCommits(ctx context.Context, session *auth.Session,
|
func (c *Controller) ListCommits(ctx context.Context, session *auth.Session,
|
||||||
repoRef string, gitRef string, filter *types.CommitFilter) ([]types.Commit, []types.RenameDetails, error) {
|
repoRef string, gitRef string, filter *types.CommitFilter) (types.ListCommitResponse, error) {
|
||||||
repo, err := c.repoStore.FindByRef(ctx, repoRef)
|
repo, err := c.repoStore.FindByRef(ctx, repoRef)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return types.ListCommitResponse{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = apiauth.CheckRepo(ctx, c.authorizer, session, repo, enum.PermissionRepoView, false); err != nil {
|
if err = apiauth.CheckRepo(ctx, c.authorizer, session, repo, enum.PermissionRepoView, false); err != nil {
|
||||||
return nil, nil, err
|
return types.ListCommitResponse{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// set gitRef to default branch in case an empty reference was provided
|
// set gitRef to default branch in case an empty reference was provided
|
||||||
@ -47,7 +47,7 @@ func (c *Controller) ListCommits(ctx context.Context, session *auth.Session,
|
|||||||
Committer: filter.Committer,
|
Committer: filter.Committer,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return types.ListCommitResponse{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
commits := make([]types.Commit, len(rpcOut.Commits))
|
commits := make([]types.Commit, len(rpcOut.Commits))
|
||||||
@ -55,7 +55,7 @@ func (c *Controller) ListCommits(ctx context.Context, session *auth.Session,
|
|||||||
var commit *types.Commit
|
var commit *types.Commit
|
||||||
commit, err = controller.MapCommit(&rpcOut.Commits[i])
|
commit, err = controller.MapCommit(&rpcOut.Commits[i])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, fmt.Errorf("failed to map commit: %w", err)
|
return types.ListCommitResponse{}, fmt.Errorf("failed to map commit: %w", err)
|
||||||
}
|
}
|
||||||
commits[i] = *commit
|
commits[i] = *commit
|
||||||
}
|
}
|
||||||
@ -64,9 +64,13 @@ func (c *Controller) ListCommits(ctx context.Context, session *auth.Session,
|
|||||||
for i := range rpcOut.RenameDetails {
|
for i := range rpcOut.RenameDetails {
|
||||||
renameDetails := controller.MapRenameDetails(rpcOut.RenameDetails[i])
|
renameDetails := controller.MapRenameDetails(rpcOut.RenameDetails[i])
|
||||||
if renameDetails == nil {
|
if renameDetails == nil {
|
||||||
return nil, nil, fmt.Errorf("rename details was nil")
|
return types.ListCommitResponse{}, fmt.Errorf("rename details was nil")
|
||||||
}
|
}
|
||||||
renameDetailList[i] = *renameDetails
|
renameDetailList[i] = *renameDetails
|
||||||
}
|
}
|
||||||
return commits, renameDetailList, nil
|
return types.ListCommitResponse{
|
||||||
|
Commits: commits,
|
||||||
|
RenameDetails: renameDetailList,
|
||||||
|
TotalCommits: rpcOut.TotalCommits,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
@ -43,3 +43,26 @@ func HandleDiff(repoCtrl *repo.Controller) http.HandlerFunc {
|
|||||||
render.JSONArrayDynamic(ctx, w, stream)
|
render.JSONArrayDynamic(ctx, w, stream)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HandleDiffStats how diff statistics of two commits, branches or tags.
|
||||||
|
func HandleDiffStats(repoCtrl *repo.Controller) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
ctx := r.Context()
|
||||||
|
session, _ := request.AuthSessionFrom(ctx)
|
||||||
|
repoRef, err := request.GetRepoRefFromPath(r)
|
||||||
|
if err != nil {
|
||||||
|
render.TranslatedUserError(w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
path := request.GetOptionalRemainderFromPath(r)
|
||||||
|
|
||||||
|
output, err := repoCtrl.DiffStats(ctx, session, repoRef, path)
|
||||||
|
if err != nil {
|
||||||
|
render.TranslatedUserError(w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
render.JSON(w, http.StatusOK, output)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -10,7 +10,6 @@ import (
|
|||||||
"github.com/harness/gitness/internal/api/controller/repo"
|
"github.com/harness/gitness/internal/api/controller/repo"
|
||||||
"github.com/harness/gitness/internal/api/render"
|
"github.com/harness/gitness/internal/api/render"
|
||||||
"github.com/harness/gitness/internal/api/request"
|
"github.com/harness/gitness/internal/api/request"
|
||||||
"github.com/harness/gitness/types"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -34,20 +33,15 @@ func HandleListCommits(repoCtrl *repo.Controller) http.HandlerFunc {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
commits, renameDetails, err := repoCtrl.ListCommits(ctx, session, repoRef, gitRef, filter)
|
list, err := repoCtrl.ListCommits(ctx, session, repoRef, gitRef, filter)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
render.TranslatedUserError(w, err)
|
render.TranslatedUserError(w, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
commitsResponse := types.ListCommitResponse{
|
|
||||||
Commits: commits,
|
|
||||||
RenameDetails: renameDetails,
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: get last page indicator explicitly - current check is wrong in case len % limit == 0
|
// TODO: get last page indicator explicitly - current check is wrong in case len % limit == 0
|
||||||
isLastPage := len(commits) < filter.Limit
|
isLastPage := len(list.Commits) < filter.Limit
|
||||||
render.PaginationNoTotal(r, w, filter.Page, filter.Limit, isLastPage)
|
render.PaginationNoTotal(r, w, filter.Page, filter.Limit, isLastPage)
|
||||||
render.JSON(w, http.StatusOK, commitsResponse)
|
render.JSON(w, http.StatusOK, list)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -661,13 +661,23 @@ func repoOperations(reflector *openapi3.Reflector) {
|
|||||||
opDiff.WithTags("repository")
|
opDiff.WithTags("repository")
|
||||||
opDiff.WithMapOfAnything(map[string]interface{}{"operationId": "rawDiff"})
|
opDiff.WithMapOfAnything(map[string]interface{}{"operationId": "rawDiff"})
|
||||||
_ = reflector.SetRequest(&opDiff, new(getRawDiffRequest), http.MethodGet)
|
_ = reflector.SetRequest(&opDiff, new(getRawDiffRequest), http.MethodGet)
|
||||||
_ = reflector.SetJSONResponse(&opDiff, new(types.DiffStats), http.StatusOK)
|
|
||||||
_ = reflector.SetStringResponse(&opDiff, http.StatusOK, "text/plain")
|
_ = reflector.SetStringResponse(&opDiff, http.StatusOK, "text/plain")
|
||||||
|
_ = reflector.SetJSONResponse(&opDiff, []gitrpc.FileDiff{}, http.StatusOK)
|
||||||
_ = reflector.SetJSONResponse(&opDiff, new(usererror.Error), http.StatusInternalServerError)
|
_ = reflector.SetJSONResponse(&opDiff, new(usererror.Error), http.StatusInternalServerError)
|
||||||
_ = reflector.SetJSONResponse(&opDiff, new(usererror.Error), http.StatusUnauthorized)
|
_ = reflector.SetJSONResponse(&opDiff, new(usererror.Error), http.StatusUnauthorized)
|
||||||
_ = reflector.SetJSONResponse(&opDiff, new(usererror.Error), http.StatusForbidden)
|
_ = reflector.SetJSONResponse(&opDiff, new(usererror.Error), http.StatusForbidden)
|
||||||
_ = reflector.Spec.AddOperation(http.MethodGet, "/repos/{repo_ref}/diff/{range}", opDiff)
|
_ = reflector.Spec.AddOperation(http.MethodGet, "/repos/{repo_ref}/diff/{range}", opDiff)
|
||||||
|
|
||||||
|
opDiffStats := openapi3.Operation{}
|
||||||
|
opDiffStats.WithTags("repository")
|
||||||
|
opDiffStats.WithMapOfAnything(map[string]interface{}{"operationId": "diffStats"})
|
||||||
|
_ = reflector.SetRequest(&opDiffStats, new(getRawDiffRequest), http.MethodGet)
|
||||||
|
_ = reflector.SetJSONResponse(&opDiffStats, new(types.DiffStats), http.StatusOK)
|
||||||
|
_ = reflector.SetJSONResponse(&opDiffStats, new(usererror.Error), http.StatusInternalServerError)
|
||||||
|
_ = reflector.SetJSONResponse(&opDiffStats, new(usererror.Error), http.StatusUnauthorized)
|
||||||
|
_ = reflector.SetJSONResponse(&opDiffStats, new(usererror.Error), http.StatusForbidden)
|
||||||
|
_ = reflector.Spec.AddOperation(http.MethodGet, "/repos/{repo_ref}/diff-stats/{range}", opDiffStats)
|
||||||
|
|
||||||
opMergeCheck := openapi3.Operation{}
|
opMergeCheck := openapi3.Operation{}
|
||||||
opMergeCheck.WithTags("repository")
|
opMergeCheck.WithTags("repository")
|
||||||
opMergeCheck.WithMapOfAnything(map[string]interface{}{"operationId": "mergeCheck"})
|
opMergeCheck.WithMapOfAnything(map[string]interface{}{"operationId": "mergeCheck"})
|
||||||
|
@ -271,6 +271,9 @@ func setupRepos(r chi.Router,
|
|||||||
r.Route("/diff", func(r chi.Router) {
|
r.Route("/diff", func(r chi.Router) {
|
||||||
r.Get("/*", handlerrepo.HandleDiff(repoCtrl))
|
r.Get("/*", handlerrepo.HandleDiff(repoCtrl))
|
||||||
})
|
})
|
||||||
|
r.Route("/diff-stats", func(r chi.Router) {
|
||||||
|
r.Get("/*", handlerrepo.HandleDiffStats(repoCtrl))
|
||||||
|
})
|
||||||
r.Route("/merge-check", func(r chi.Router) {
|
r.Route("/merge-check", func(r chi.Router) {
|
||||||
r.Post("/*", handlerrepo.HandleMergeCheck(repoCtrl))
|
r.Post("/*", handlerrepo.HandleMergeCheck(repoCtrl))
|
||||||
})
|
})
|
||||||
|
@ -74,4 +74,5 @@ type RenameDetails struct {
|
|||||||
type ListCommitResponse struct {
|
type ListCommitResponse struct {
|
||||||
Commits []Commit `json:"commits"`
|
Commits []Commit `json:"commits"`
|
||||||
RenameDetails []RenameDetails `json:"rename_details"`
|
RenameDetails []RenameDetails `json:"rename_details"`
|
||||||
|
TotalCommits int `json:"total_commits,omitempty"`
|
||||||
}
|
}
|
||||||
|
@ -76,11 +76,13 @@ export const Changes: React.FC<ChangesProps> = ({
|
|||||||
const [commitRange, setCommitRange] = useState<string[]>(defaultCommitRange || [])
|
const [commitRange, setCommitRange] = useState<string[]>(defaultCommitRange || [])
|
||||||
const { routes } = useAppContext()
|
const { routes } = useAppContext()
|
||||||
|
|
||||||
const { data: prCommits } = useGet<TypesCommit[]>({
|
const { data: prCommits } = useGet<{
|
||||||
path: `/api/v1/repos/${repoMetadata?.path}/+/pullreq/${pullRequestMetadata?.number}/commits`,
|
commits: TypesCommit[]
|
||||||
|
}>({
|
||||||
|
path: `/api/v1/repos/${repoMetadata?.path}/+/commits`,
|
||||||
queryParams: {
|
queryParams: {
|
||||||
git_ref: pullRequestMetadata?.source_branch,
|
git_ref: sourceRef,
|
||||||
after: pullRequestMetadata?.target_branch
|
after: targetRef
|
||||||
},
|
},
|
||||||
lazy: !pullRequestMetadata?.number
|
lazy: !pullRequestMetadata?.number
|
||||||
})
|
})
|
||||||
@ -118,8 +120,6 @@ export const Changes: React.FC<ChangesProps> = ({
|
|||||||
path: `/api/v1/repos/${repoMetadata?.path}/+/diff/${
|
path: `/api/v1/repos/${repoMetadata?.path}/+/diff/${
|
||||||
commitRangePath
|
commitRangePath
|
||||||
? commitRangePath
|
? commitRangePath
|
||||||
: pullRequestMetadata
|
|
||||||
? `${pullRequestMetadata.merge_base_sha}...${pullRequestMetadata.source_sha}`
|
|
||||||
: `${targetRef}...${sourceRef}`
|
: `${targetRef}...${sourceRef}`
|
||||||
}`,
|
}`,
|
||||||
requestOptions: {
|
requestOptions: {
|
||||||
@ -233,7 +233,7 @@ export const Changes: React.FC<ChangesProps> = ({
|
|||||||
<Container flex={{ alignItems: 'center' }}>
|
<Container flex={{ alignItems: 'center' }}>
|
||||||
<Render when={pullRequestMetadata?.number}>
|
<Render when={pullRequestMetadata?.number}>
|
||||||
<CommitRangeDropdown
|
<CommitRangeDropdown
|
||||||
allCommits={prCommits || []}
|
allCommits={prCommits?.commits || []}
|
||||||
selectedCommits={commitRange}
|
selectedCommits={commitRange}
|
||||||
setSelectedCommits={setCommitRange}
|
setSelectedCommits={setCommitRange}
|
||||||
/>
|
/>
|
||||||
@ -309,8 +309,8 @@ export const Changes: React.FC<ChangesProps> = ({
|
|||||||
repoMetadata={repoMetadata}
|
repoMetadata={repoMetadata}
|
||||||
pullRequestMetadata={pullRequestMetadata}
|
pullRequestMetadata={pullRequestMetadata}
|
||||||
onCommentUpdate={onCommentUpdate}
|
onCommentUpdate={onCommentUpdate}
|
||||||
targetRef={pullRequestMetadata ? pullRequestMetadata.merge_base_sha : targetRef}
|
targetRef={targetRef}
|
||||||
sourceRef={pullRequestMetadata ? pullRequestMetadata.source_sha : sourceRef}
|
sourceRef={sourceRef}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</Layout.Vertical>
|
</Layout.Vertical>
|
||||||
|
27
web/src/components/TabContentWrapper/TabContentWrapper.tsx
Normal file
27
web/src/components/TabContentWrapper/TabContentWrapper.tsx
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import { Container, PageError } from '@harness/uicore'
|
||||||
|
import { getErrorMessage } from 'utils/Utils'
|
||||||
|
import { LoadingSpinner } from 'components/LoadingSpinner/LoadingSpinner'
|
||||||
|
|
||||||
|
interface TabContentWrapperProps {
|
||||||
|
className?: string
|
||||||
|
loading?: boolean
|
||||||
|
error?: Unknown
|
||||||
|
onRetry: () => void
|
||||||
|
}
|
||||||
|
|
||||||
|
export const TabContentWrapper: React.FC<TabContentWrapperProps> = ({
|
||||||
|
className,
|
||||||
|
loading,
|
||||||
|
error,
|
||||||
|
onRetry,
|
||||||
|
children
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<Container className={className} padding="xlarge">
|
||||||
|
<LoadingSpinner visible={loading} withBorder={true} />
|
||||||
|
{error && <PageError message={getErrorMessage(error)} onClick={onRetry} />}
|
||||||
|
{!error && children}
|
||||||
|
</Container>
|
||||||
|
)
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
import { noop } from 'lodash-es'
|
import { noop } from 'lodash-es'
|
||||||
import React, { useCallback, useEffect, useMemo, useState } from 'react'
|
import React, { useCallback, useState } from 'react'
|
||||||
import {
|
import {
|
||||||
Container,
|
Container,
|
||||||
PageBody,
|
PageBody,
|
||||||
@ -20,19 +20,17 @@ import { useAppContext } from 'AppContext'
|
|||||||
import { useGetRepositoryMetadata } from 'hooks/useGetRepositoryMetadata'
|
import { useGetRepositoryMetadata } from 'hooks/useGetRepositoryMetadata'
|
||||||
import { useStrings } from 'framework/strings'
|
import { useStrings } from 'framework/strings'
|
||||||
import { RepositoryPageHeader } from 'components/RepositoryPageHeader/RepositoryPageHeader'
|
import { RepositoryPageHeader } from 'components/RepositoryPageHeader/RepositoryPageHeader'
|
||||||
import { voidFn, getErrorMessage, LIST_FETCHING_LIMIT, showToaster } from 'utils/Utils'
|
import { getErrorMessage, showToaster } from 'utils/Utils'
|
||||||
import { Images } from 'images'
|
import { Images } from 'images'
|
||||||
import { CodeIcon, isRefATag, makeDiffRefs } from 'utils/GitUtils'
|
import { CodeIcon, isRefATag, makeDiffRefs } from 'utils/GitUtils'
|
||||||
import { CommitsView } from 'components/CommitsView/CommitsView'
|
|
||||||
import { Changes } from 'components/Changes/Changes'
|
import { Changes } from 'components/Changes/Changes'
|
||||||
import type { OpenapiCreatePullReqRequest, TypesCommit, TypesPullReq } from 'services/code'
|
import type { OpenapiCreatePullReqRequest, TypesDiffStats, TypesPullReq, TypesRepository } from 'services/code'
|
||||||
import { LoadingSpinner } from 'components/LoadingSpinner/LoadingSpinner'
|
import { LoadingSpinner } from 'components/LoadingSpinner/LoadingSpinner'
|
||||||
import { usePageIndex } from 'hooks/usePageIndex'
|
|
||||||
import { ResourceListingPagination } from 'components/ResourceListingPagination/ResourceListingPagination'
|
|
||||||
import { TabTitleWithCount, tabContainerCSS } from 'components/TabTitleWithCount/TabTitleWithCount'
|
import { TabTitleWithCount, tabContainerCSS } from 'components/TabTitleWithCount/TabTitleWithCount'
|
||||||
import type { DiffFileEntry } from 'utils/types'
|
|
||||||
import { MarkdownEditorWithPreview } from 'components/MarkdownEditorWithPreview/MarkdownEditorWithPreview'
|
import { MarkdownEditorWithPreview } from 'components/MarkdownEditorWithPreview/MarkdownEditorWithPreview'
|
||||||
|
import { TabContentWrapper } from 'components/TabContentWrapper/TabContentWrapper'
|
||||||
import { CompareContentHeader, PRCreationType } from './CompareContentHeader/CompareContentHeader'
|
import { CompareContentHeader, PRCreationType } from './CompareContentHeader/CompareContentHeader'
|
||||||
|
import { CompareCommits } from './CompareCommits'
|
||||||
import css from './Compare.module.scss'
|
import css from './Compare.module.scss'
|
||||||
|
|
||||||
export default function Compare() {
|
export default function Compare() {
|
||||||
@ -42,29 +40,16 @@ export default function Compare() {
|
|||||||
const { repoMetadata, error, loading, diffRefs } = useGetRepositoryMetadata()
|
const { repoMetadata, error, loading, diffRefs } = useGetRepositoryMetadata()
|
||||||
const [sourceGitRef, setSourceGitRef] = useState(diffRefs.sourceGitRef)
|
const [sourceGitRef, setSourceGitRef] = useState(diffRefs.sourceGitRef)
|
||||||
const [targetGitRef, setTargetGitRef] = useState(diffRefs.targetGitRef)
|
const [targetGitRef, setTargetGitRef] = useState(diffRefs.targetGitRef)
|
||||||
const [page, setPage] = usePageIndex()
|
|
||||||
const limit = LIST_FETCHING_LIMIT
|
|
||||||
const {
|
|
||||||
data: commits,
|
|
||||||
error: commitsError,
|
|
||||||
refetch,
|
|
||||||
response
|
|
||||||
} = useGet<{
|
|
||||||
commits: TypesCommit[]
|
|
||||||
}>({
|
|
||||||
path: `/api/v1/repos/${repoMetadata?.path}/+/commits`,
|
|
||||||
queryParams: {
|
|
||||||
limit,
|
|
||||||
page,
|
|
||||||
git_ref: sourceGitRef,
|
|
||||||
after: targetGitRef
|
|
||||||
},
|
|
||||||
lazy: !repoMetadata
|
|
||||||
})
|
|
||||||
const [title, setTitle] = useState('')
|
const [title, setTitle] = useState('')
|
||||||
const [description, setDescription] = useState('')
|
const [description, setDescription] = useState('')
|
||||||
const [diffs, setDiffs] = useState<DiffFileEntry[]>([])
|
|
||||||
const { showError } = useToaster()
|
const { showError } = useToaster()
|
||||||
|
const {
|
||||||
|
data,
|
||||||
|
error: errorStats
|
||||||
|
} = useGet<TypesDiffStats>({
|
||||||
|
path: `/api/v1/repos/${repoMetadata?.path}/+/diff-stats/${targetGitRef}...${sourceGitRef}`,
|
||||||
|
lazy: !repoMetadata
|
||||||
|
})
|
||||||
const { mutate: createPullRequest, loading: creatingInProgress } = useMutate<TypesPullReq>({
|
const { mutate: createPullRequest, loading: creatingInProgress } = useMutate<TypesPullReq>({
|
||||||
verb: 'POST',
|
verb: 'POST',
|
||||||
path: `/api/v1/repos/${repoMetadata?.path}/+/pullreq`
|
path: `/api/v1/repos/${repoMetadata?.path}/+/pullreq`
|
||||||
@ -144,30 +129,6 @@ export default function Compare() {
|
|||||||
repoMetadata
|
repoMetadata
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
const ChangesTab = useMemo(() => {
|
|
||||||
if (repoMetadata) {
|
|
||||||
return (
|
|
||||||
<Container className={css.changesContainer}>
|
|
||||||
<Changes
|
|
||||||
readOnly
|
|
||||||
repoMetadata={repoMetadata}
|
|
||||||
targetRef={targetGitRef}
|
|
||||||
sourceRef={sourceGitRef}
|
|
||||||
emptyTitle={getString('noChanges')}
|
|
||||||
emptyMessage={getString('noChangesCompare')}
|
|
||||||
onCommentUpdate={noop}
|
|
||||||
onDataReady={setDiffs}
|
|
||||||
/>
|
|
||||||
</Container>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}, [repoMetadata, sourceGitRef, targetGitRef, getString])
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (commits?.commits?.length) {
|
|
||||||
setTitle(commits.commits[0].title as string)
|
|
||||||
}
|
|
||||||
}, [commits?.commits])
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container className={css.main}>
|
<Container className={css.main}>
|
||||||
@ -176,7 +137,7 @@ export default function Compare() {
|
|||||||
title={getString('comparingChanges')}
|
title={getString('comparingChanges')}
|
||||||
dataTooltipId="comparingChanges"
|
dataTooltipId="comparingChanges"
|
||||||
/>
|
/>
|
||||||
<PageBody error={getErrorMessage(error || commitsError)} retryOnError={voidFn(refetch)} className={css.pageBody}>
|
<PageBody error={getErrorMessage(error || errorStats)} className={css.pageBody}>
|
||||||
<LoadingSpinner visible={loading} />
|
<LoadingSpinner visible={loading} />
|
||||||
|
|
||||||
{repoMetadata && (
|
{repoMetadata && (
|
||||||
@ -219,7 +180,6 @@ export default function Compare() {
|
|||||||
id="prComparing"
|
id="prComparing"
|
||||||
defaultSelectedTabId="general"
|
defaultSelectedTabId="general"
|
||||||
large={false}
|
large={false}
|
||||||
onChange={() => setPage(1)}
|
|
||||||
tabList={[
|
tabList={[
|
||||||
{
|
{
|
||||||
id: 'general',
|
id: 'general',
|
||||||
@ -259,8 +219,6 @@ export default function Compare() {
|
|||||||
</Layout.Vertical>
|
</Layout.Vertical>
|
||||||
</Container>
|
</Container>
|
||||||
</Layout.Vertical>
|
</Layout.Vertical>
|
||||||
{/** Fake rendering Changes Tab to get changes count - no API has it now */}
|
|
||||||
<Container style={{ display: 'none' }}>{ChangesTab}</Container>
|
|
||||||
</Container>
|
</Container>
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
@ -270,21 +228,17 @@ export default function Compare() {
|
|||||||
<TabTitleWithCount
|
<TabTitleWithCount
|
||||||
icon={CodeIcon.Commit}
|
icon={CodeIcon.Commit}
|
||||||
title={getString('commits')}
|
title={getString('commits')}
|
||||||
count={commits?.commits?.length || 0}
|
count={data?.commits}
|
||||||
padding={{ left: 'medium' }}
|
padding={{ left: 'medium' }}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
panel: (
|
panel:
|
||||||
<Container padding="xlarge">
|
<CompareCommits
|
||||||
<CommitsView
|
repoMetadata={repoMetadata as TypesRepository}
|
||||||
commits={commits?.commits || []}
|
sourceSha={sourceGitRef}
|
||||||
repoMetadata={repoMetadata}
|
targetSha={targetGitRef}
|
||||||
emptyTitle={getString('compareEmptyDiffTitle')}
|
handleRefresh={()=>{}} // TODO: when to refresh
|
||||||
emptyMessage={getString('compareEmptyDiffMessage')}
|
/>
|
||||||
/>
|
|
||||||
<ResourceListingPagination response={response} page={page} setPage={setPage} />
|
|
||||||
</Container>
|
|
||||||
)
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'diff',
|
id: 'diff',
|
||||||
@ -292,11 +246,22 @@ export default function Compare() {
|
|||||||
<TabTitleWithCount
|
<TabTitleWithCount
|
||||||
icon={CodeIcon.File}
|
icon={CodeIcon.File}
|
||||||
title={getString('filesChanged')}
|
title={getString('filesChanged')}
|
||||||
count={diffs?.length || 0}
|
count={data?.files_changed || 0}
|
||||||
padding={{ left: 'medium' }}
|
padding={{ left: 'medium' }}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
panel: ChangesTab
|
panel:
|
||||||
|
<TabContentWrapper loading={loading} error={error} onRetry={()=>{}} className={css.changesContainer}>
|
||||||
|
<Changes
|
||||||
|
readOnly
|
||||||
|
repoMetadata={repoMetadata}
|
||||||
|
targetRef={targetGitRef}
|
||||||
|
sourceRef={sourceGitRef}
|
||||||
|
emptyTitle={getString('noChanges')}
|
||||||
|
emptyMessage={getString('noChangesCompare')}
|
||||||
|
onCommentUpdate={noop}
|
||||||
|
/>
|
||||||
|
</TabContentWrapper>
|
||||||
}
|
}
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
|
58
web/src/pages/Compare/CompareCommits.tsx
Normal file
58
web/src/pages/Compare/CompareCommits.tsx
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import { useGet } from 'restful-react'
|
||||||
|
import type { TypesCommit } from 'services/code'
|
||||||
|
import type { GitInfoProps } from 'utils/GitUtils'
|
||||||
|
import { voidFn, LIST_FETCHING_LIMIT } from 'utils/Utils'
|
||||||
|
import { usePageIndex } from 'hooks/usePageIndex'
|
||||||
|
import { useStrings } from 'framework/strings'
|
||||||
|
import { ResourceListingPagination } from 'components/ResourceListingPagination/ResourceListingPagination'
|
||||||
|
import { CommitsView } from 'components/CommitsView/CommitsView'
|
||||||
|
import { TabContentWrapper } from 'components/TabContentWrapper/TabContentWrapper'
|
||||||
|
|
||||||
|
interface CommitProps extends Pick<GitInfoProps, 'repoMetadata'> {
|
||||||
|
sourceSha? :string
|
||||||
|
targetSha? :string
|
||||||
|
handleRefresh: () => void
|
||||||
|
}
|
||||||
|
|
||||||
|
export const CompareCommits: React.FC<CommitProps> = ({
|
||||||
|
repoMetadata,
|
||||||
|
sourceSha,
|
||||||
|
targetSha,
|
||||||
|
handleRefresh
|
||||||
|
}) => {
|
||||||
|
const limit = LIST_FETCHING_LIMIT
|
||||||
|
const [page, setPage] = usePageIndex()
|
||||||
|
const { getString } = useStrings()
|
||||||
|
const {
|
||||||
|
data,
|
||||||
|
error,
|
||||||
|
loading,
|
||||||
|
refetch,
|
||||||
|
response
|
||||||
|
} = useGet<{
|
||||||
|
commits: TypesCommit[]
|
||||||
|
}>({
|
||||||
|
path: `/api/v1/repos/${repoMetadata?.path}/+/commits`,
|
||||||
|
queryParams: {
|
||||||
|
limit,
|
||||||
|
page,
|
||||||
|
git_ref: sourceSha,
|
||||||
|
after: targetSha
|
||||||
|
},
|
||||||
|
lazy: !repoMetadata
|
||||||
|
})
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TabContentWrapper loading={loading} error={error} onRetry={voidFn(refetch)}>
|
||||||
|
<CommitsView
|
||||||
|
commits={data?.commits || []}
|
||||||
|
repoMetadata={repoMetadata}
|
||||||
|
emptyTitle={getString('compareEmptyDiffTitle')}
|
||||||
|
emptyMessage={getString('compareEmptyDiffMessage')}
|
||||||
|
handleRefresh={voidFn(handleRefresh)}
|
||||||
|
/>
|
||||||
|
<ResourceListingPagination response={response} page={page} setPage={setPage} />
|
||||||
|
</TabContentWrapper>
|
||||||
|
)
|
||||||
|
}
|
@ -226,8 +226,8 @@ export default function PullRequest() {
|
|||||||
repoMetadata={repoMetadata as TypesRepository}
|
repoMetadata={repoMetadata as TypesRepository}
|
||||||
pullRequestMetadata={prData as TypesPullReq}
|
pullRequestMetadata={prData as TypesPullReq}
|
||||||
defaultCommitRange={compact(commitSHA?.split(/~1\.\.\.|\.\.\./g))}
|
defaultCommitRange={compact(commitSHA?.split(/~1\.\.\.|\.\.\./g))}
|
||||||
targetRef={prData?.target_branch}
|
targetRef={prData?.merge_base_sha}
|
||||||
sourceRef={prData?.source_branch}
|
sourceRef={prData?.source_sha}
|
||||||
emptyTitle={getString('noChanges')}
|
emptyTitle={getString('noChanges')}
|
||||||
emptyMessage={getString('noChangesPR')}
|
emptyMessage={getString('noChangesPR')}
|
||||||
onCommentUpdate={voidFn(refetchPullRequest)}
|
onCommentUpdate={voidFn(refetchPullRequest)}
|
||||||
|
@ -24,18 +24,20 @@ export const PullRequestCommits: React.FC<CommitProps> = ({
|
|||||||
const [page, setPage] = usePageIndex()
|
const [page, setPage] = usePageIndex()
|
||||||
const { getString } = useStrings()
|
const { getString } = useStrings()
|
||||||
const {
|
const {
|
||||||
data: commits,
|
data,
|
||||||
error,
|
error,
|
||||||
loading,
|
loading,
|
||||||
refetch,
|
refetch,
|
||||||
response
|
response
|
||||||
} = useGet<TypesCommit[]>({
|
} = useGet<{
|
||||||
path: `/api/v1/repos/${repoMetadata?.path}/+/pullreq/${pullRequestMetadata.number}/commits`,
|
commits: TypesCommit[]
|
||||||
|
}>({
|
||||||
|
path: `/api/v1/repos/${repoMetadata?.path}/+/commits`,
|
||||||
queryParams: {
|
queryParams: {
|
||||||
limit,
|
limit,
|
||||||
page,
|
page,
|
||||||
git_ref: pullRequestMetadata.source_branch,
|
git_ref: pullRequestMetadata.source_sha,
|
||||||
after: pullRequestMetadata.target_branch
|
after: pullRequestMetadata.merge_base_sha
|
||||||
},
|
},
|
||||||
lazy: !repoMetadata
|
lazy: !repoMetadata
|
||||||
})
|
})
|
||||||
@ -43,7 +45,7 @@ export const PullRequestCommits: React.FC<CommitProps> = ({
|
|||||||
return (
|
return (
|
||||||
<PullRequestTabContentWrapper loading={loading} error={error} onRetry={voidFn(refetch)}>
|
<PullRequestTabContentWrapper loading={loading} error={error} onRetry={voidFn(refetch)}>
|
||||||
<CommitsView
|
<CommitsView
|
||||||
commits={commits}
|
commits={data?.commits || []}
|
||||||
repoMetadata={repoMetadata}
|
repoMetadata={repoMetadata}
|
||||||
emptyTitle={getString('noCommits')}
|
emptyTitle={getString('noCommits')}
|
||||||
emptyMessage={getString('noCommitsPR')}
|
emptyMessage={getString('noCommitsPR')}
|
||||||
|
@ -530,6 +530,7 @@ export interface TypesIdentity {
|
|||||||
export interface TypesListCommitResponse {
|
export interface TypesListCommitResponse {
|
||||||
commits?: TypesCommit[] | null
|
commits?: TypesCommit[] | null
|
||||||
rename_details?: TypesRenameDetails[] | null
|
rename_details?: TypesRenameDetails[] | null
|
||||||
|
total_commits?: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TypesMembershipSpace {
|
export interface TypesMembershipSpace {
|
||||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user