Skip to content

Commit

Permalink
iteration support label relation
Browse files Browse the repository at this point in the history
  • Loading branch information
chengjoey committed Jul 20, 2023
1 parent 6581d3b commit 0e93695
Show file tree
Hide file tree
Showing 6 changed files with 184 additions and 16 deletions.
8 changes: 8 additions & 0 deletions apistructs/iteration.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ type IterationCreateRequest struct {

ManHour *IssueManHour `json:"manHour"`

Labels []string `json:"labels"`

// internal use, get from *http.Request
IdentityInfo
}
Expand Down Expand Up @@ -85,6 +87,8 @@ type IterationUpdateRequest struct {

ManHour *IssueManHour `json:"manHour"`

Labels []string `json:"labels"`

// internal use, get from *http.Request
IdentityInfo
}
Expand All @@ -110,6 +114,8 @@ type IterationPagingRequest struct {
WithoutIssueSummary bool `schema:"withoutIssueSummary"`
// +optional
IDs []uint64 `json:"ids" schema:"id"`
// +optional
Labels []uint64 `json:"labels" schema:"labels"`
}

type IterationPagingResponse struct {
Expand Down Expand Up @@ -143,6 +149,8 @@ type Iteration struct {
State IterationState `json:"state"`
IssueSummary ISummary `json:"issueSummary"`
ManHour *IssueManHour `json:"manHour"`
Labels []string `json:"labels"`
LabelDetails []ProjectLabel `json:"labelDetails"`
}

// ISummary 与迭代相关的事件完成状态的统计信息
Expand Down
5 changes: 3 additions & 2 deletions apistructs/label.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@ import (
type ProjectLabelType string

const (
LabelTypeIssue ProjectLabelType = "issue" // issue 标签类型
LabelTypeRelease ProjectLabelType = "release" // release 标签类型
LabelTypeIssue ProjectLabelType = "issue" // issue 标签类型
LabelTypeRelease ProjectLabelType = "release" // release 标签类型
LabelTypeIteration ProjectLabelType = "iteration" // iteration 标签类型
)

// ProjectLabel 标签
Expand Down
26 changes: 14 additions & 12 deletions internal/apps/dop/dao/iteration.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,19 +38,21 @@ func (Iteration) TableName() string {
return "dice_iterations"
}

func (i *Iteration) Convert() apistructs.Iteration {
func (i *Iteration) Convert(labels []string, labelDetails []apistructs.ProjectLabel) apistructs.Iteration {
return apistructs.Iteration{
ID: int64(i.ID),
CreatedAt: i.CreatedAt,
UpdatedAt: i.UpdatedAt,
StartedAt: i.StartedAt,
FinishedAt: i.FinishedAt,
ProjectID: i.ProjectID,
Title: i.Title,
Content: i.Content,
Creator: i.Creator,
State: i.State,
ManHour: new(apistructs.IssueManHour).FromString(i.ManHour),
ID: int64(i.ID),
CreatedAt: i.CreatedAt,
UpdatedAt: i.UpdatedAt,
StartedAt: i.StartedAt,
FinishedAt: i.FinishedAt,
ProjectID: i.ProjectID,
Title: i.Title,
Content: i.Content,
Creator: i.Creator,
State: i.State,
ManHour: new(apistructs.IssueManHour).FromString(i.ManHour),
Labels: labels,
LabelDetails: labelDetails,
}
}

Expand Down
41 changes: 41 additions & 0 deletions internal/apps/dop/dao/iteration_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Copyright (c) 2021 Terminus, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package dao

import (
"testing"

"github.com/stretchr/testify/assert"

"github.com/erda-project/erda/apistructs"
"github.com/erda-project/erda/pkg/database/dbengine"
)

func TestConvert(t *testing.T) {
i := &Iteration{
BaseModel: dbengine.BaseModel{
ID: 1,
},
ProjectID: 1,
Title: "iteration1",
}
iter := i.Convert([]string{"label1"}, []apistructs.ProjectLabel{
{
ID: 1,
Name: "label1",
},
})
assert.Equal(t, []string{"label1"}, iter.Labels)
}
90 changes: 88 additions & 2 deletions internal/apps/dop/endpoints/iteration.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,15 @@ import (
"context"
"encoding/json"
"net/http"
"reflect"
"strconv"
"time"

"github.com/pkg/errors"
"github.com/sirupsen/logrus"

"github.com/erda-project/erda/apistructs"
"github.com/erda-project/erda/internal/apps/dop/dao"
"github.com/erda-project/erda/internal/apps/dop/services/apierrors"
"github.com/erda-project/erda/internal/pkg/user"
"github.com/erda-project/erda/pkg/http/httpserver"
Expand Down Expand Up @@ -83,6 +85,21 @@ func (e *Endpoints) CreateIteration(ctx context.Context, r *http.Request, vars m
return errorresp.ErrResp(err)
}

labels, err := e.bdl.ListLabelByNameAndProjectID(createReq.ProjectID, createReq.Labels)
if err != nil {
return nil, apierrors.ErrCreateIteration.InternalError(err)

Check warning on line 90 in internal/apps/dop/endpoints/iteration.go

View check run for this annotation

Codecov / codecov/patch

internal/apps/dop/endpoints/iteration.go#L88-L90

Added lines #L88 - L90 were not covered by tests
}
for _, v := range labels {
lr := &dao.LabelRelation{
LabelID: uint64(v.ID),
RefType: apistructs.LabelTypeIteration,
RefID: strconv.FormatUint(id.ID, 10),

Check warning on line 96 in internal/apps/dop/endpoints/iteration.go

View check run for this annotation

Codecov / codecov/patch

internal/apps/dop/endpoints/iteration.go#L92-L96

Added lines #L92 - L96 were not covered by tests
}
if err := e.db.CreateLabelRelation(lr); err != nil {
return nil, apierrors.ErrCreateIssue.InternalError(err)

Check warning on line 99 in internal/apps/dop/endpoints/iteration.go

View check run for this annotation

Codecov / codecov/patch

internal/apps/dop/endpoints/iteration.go#L98-L99

Added lines #L98 - L99 were not covered by tests
}
}

// 更新项目活跃时间
if err := e.bdl.UpdateProjectActiveTime(apistructs.ProjectActiveTimeUpdateRequest{
ProjectID: createReq.ProjectID,
Expand Down Expand Up @@ -137,6 +154,37 @@ func (e *Endpoints) UpdateIteration(ctx context.Context, r *http.Request, vars m
return errorresp.ErrResp(err)
}

// update labels
currentLabelMap := make(map[string]bool)
newLabelMap := make(map[string]bool)
currentLabels, _ := e.getIterationLabelDetails(iterationID)
for _, v := range currentLabels {
currentLabelMap[v] = true

Check warning on line 162 in internal/apps/dop/endpoints/iteration.go

View check run for this annotation

Codecov / codecov/patch

internal/apps/dop/endpoints/iteration.go#L158-L162

Added lines #L158 - L162 were not covered by tests
}
for _, v := range updateReq.Labels {
newLabelMap[v] = true

Check warning on line 165 in internal/apps/dop/endpoints/iteration.go

View check run for this annotation

Codecov / codecov/patch

internal/apps/dop/endpoints/iteration.go#L164-L165

Added lines #L164 - L165 were not covered by tests
}
if len(updateReq.Labels) > 0 && !reflect.DeepEqual(currentLabelMap, newLabelMap) {
if err = e.db.DeleteLabelRelations(apistructs.LabelTypeIteration, strconv.FormatUint(iterationID, 10), nil); err != nil {
return apierrors.ErrUpdateIteration.InternalError(err).ToResp(), nil

Check warning on line 169 in internal/apps/dop/endpoints/iteration.go

View check run for this annotation

Codecov / codecov/patch

internal/apps/dop/endpoints/iteration.go#L167-L169

Added lines #L167 - L169 were not covered by tests
}
labels, err := e.bdl.ListLabelByNameAndProjectID(iteration.ProjectID, updateReq.Labels)
if err != nil {
return apierrors.ErrUpdateIteration.InternalError(err).ToResp(), nil

Check warning on line 173 in internal/apps/dop/endpoints/iteration.go

View check run for this annotation

Codecov / codecov/patch

internal/apps/dop/endpoints/iteration.go#L171-L173

Added lines #L171 - L173 were not covered by tests
}
labelRelations := make([]dao.LabelRelation, 0, len(labels))
for _, v := range labels {
labelRelations = append(labelRelations, dao.LabelRelation{
LabelID: uint64(v.ID),
RefType: apistructs.LabelTypeIteration,
RefID: strconv.FormatUint(iterationID, 10),
})

Check warning on line 181 in internal/apps/dop/endpoints/iteration.go

View check run for this annotation

Codecov / codecov/patch

internal/apps/dop/endpoints/iteration.go#L175-L181

Added lines #L175 - L181 were not covered by tests
}
if err := e.db.BatchCreateLabelRelations(labelRelations); err != nil {
return apierrors.ErrUpdateIteration.InternalError(err).ToResp(), nil

Check warning on line 184 in internal/apps/dop/endpoints/iteration.go

View check run for this annotation

Codecov / codecov/patch

internal/apps/dop/endpoints/iteration.go#L183-L184

Added lines #L183 - L184 were not covered by tests
}
}

// 更新项目活跃时间
if err := e.bdl.UpdateProjectActiveTime(apistructs.ProjectActiveTimeUpdateRequest{
ProjectID: iteration.ProjectID,
Expand Down Expand Up @@ -187,6 +235,11 @@ func (e *Endpoints) DeleteIteration(ctx context.Context, r *http.Request, vars m
return errorresp.ErrResp(err)
}

// delete relation labels
if err = e.db.DeleteLabelRelations(apistructs.LabelTypeIteration, strconv.FormatUint(iterationID, 10), nil); err != nil {
return apierrors.ErrDeleteIteration.InternalError(err).ToResp(), nil

Check warning on line 240 in internal/apps/dop/endpoints/iteration.go

View check run for this annotation

Codecov / codecov/patch

internal/apps/dop/endpoints/iteration.go#L239-L240

Added lines #L239 - L240 were not covered by tests
}

// 更新项目活跃时间
if err := e.bdl.UpdateProjectActiveTime(apistructs.ProjectActiveTimeUpdateRequest{
ProjectID: iteration.ProjectID,
Expand Down Expand Up @@ -238,7 +291,7 @@ func (e *Endpoints) GetIteration(ctx context.Context, r *http.Request, vars map[
}

userIDs := []string{iteration.Creator}
return httpserver.OkResp(iteration.Convert(), userIDs)
return httpserver.OkResp(iteration.Convert(e.getIterationLabelDetails(iterationID)), userIDs)

Check warning on line 294 in internal/apps/dop/endpoints/iteration.go

View check run for this annotation

Codecov / codecov/patch

internal/apps/dop/endpoints/iteration.go#L294

Added line #L294 was not covered by tests
}

// PagingIterations 分页查询迭代
Expand Down Expand Up @@ -291,14 +344,31 @@ func (e *Endpoints) PagingIterations(ctx context.Context, r *http.Request, vars
}
}
}
if len(pageReq.Labels) > 0 {
lrs, err := e.db.GetLabelRelationsByLabels(apistructs.LabelTypeIteration, pageReq.Labels)
if err != nil {
return apierrors.ErrPagingIterations.InternalError(err).ToResp(), nil

Check warning on line 350 in internal/apps/dop/endpoints/iteration.go

View check run for this annotation

Codecov / codecov/patch

internal/apps/dop/endpoints/iteration.go#L347-L350

Added lines #L347 - L350 were not covered by tests
}
if pageReq.IDs == nil {
pageReq.IDs = make([]uint64, 0)

Check warning on line 353 in internal/apps/dop/endpoints/iteration.go

View check run for this annotation

Codecov / codecov/patch

internal/apps/dop/endpoints/iteration.go#L352-L353

Added lines #L352 - L353 were not covered by tests
}
for _, v := range lrs {
id, err := strconv.ParseUint(v.RefID, 10, 64)
if err != nil {
logrus.Errorf("failed to parse refID for label relation %d, %v", v.ID, err)
continue

Check warning on line 359 in internal/apps/dop/endpoints/iteration.go

View check run for this annotation

Codecov / codecov/patch

internal/apps/dop/endpoints/iteration.go#L355-L359

Added lines #L355 - L359 were not covered by tests
}
pageReq.IDs = append(pageReq.IDs, id)

Check warning on line 361 in internal/apps/dop/endpoints/iteration.go

View check run for this annotation

Codecov / codecov/patch

internal/apps/dop/endpoints/iteration.go#L361

Added line #L361 was not covered by tests
}
}
// 分页查询
iterationModels, total, err := e.iteration.Paging(pageReq)
if err != nil {
return errorresp.ErrResp(err)
}
iterationMap := make(map[int64]*apistructs.Iteration, len(iterationModels))
for _, itr := range iterationModels {
iteration := itr.Convert()
iteration := itr.Convert(e.getIterationLabelDetails(itr.ID))

Check warning on line 371 in internal/apps/dop/endpoints/iteration.go

View check run for this annotation

Codecov / codecov/patch

internal/apps/dop/endpoints/iteration.go#L371

Added line #L371 was not covered by tests
iterationMap[iteration.ID] = &iteration
}
if !pageReq.WithoutIssueSummary {
Expand All @@ -324,3 +394,19 @@ func (e *Endpoints) PagingIterations(ctx context.Context, r *http.Request, vars
List: iterations,
}, userIDs)
}

func (e *Endpoints) getIterationLabelDetails(iterationID uint64) ([]string, []apistructs.ProjectLabel) {
lrs, _ := e.db.GetLabelRelationsByRef(apistructs.LabelTypeIteration, strconv.FormatUint(iterationID, 10))
labelIDs := make([]uint64, 0, len(lrs))
for _, v := range lrs {
labelIDs = append(labelIDs, v.LabelID)
}
var labelNames []string
var labels []apistructs.ProjectLabel
labels, _ = e.bdl.ListLabelByIDs(labelIDs)
labelNames = make([]string, 0, len(labels))
for _, v := range labels {
labelNames = append(labelNames, v.Name)
}
return labelNames, labels
}
30 changes: 30 additions & 0 deletions internal/apps/dop/endpoints/iteration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"github.com/stretchr/testify/assert"

"github.com/erda-project/erda/apistructs"
"github.com/erda-project/erda/bundle"
"github.com/erda-project/erda/internal/apps/dop/dao"
"github.com/erda-project/erda/internal/apps/dop/services/iteration"
"github.com/erda-project/erda/internal/pkg/user"
Expand Down Expand Up @@ -54,7 +55,36 @@ func TestPagingIterations(t *testing.T) {
r.Header.Set("Org-ID", "1")
q := r.URL.Query()
q.Add("projectID", "1")
q.Add("labels", "area")
r.URL.RawQuery = q.Encode()
_, err := ep.PagingIterations(context.Background(), r, map[string]string{"projectID": "1"})
assert.NoError(t, err)
}

func Test_getIterationLabelDetails(t *testing.T) {
bdl := bundle.New()
db := &dao.DBClient{}
pm1 := monkey.PatchInstanceMethod(reflect.TypeOf(db), "GetLabelRelationsByRef", func(db *dao.DBClient, refType apistructs.ProjectLabelType, refID string) ([]dao.LabelRelation, error) {
return []dao.LabelRelation{
{
LabelID: 1,
},
}, nil
})
defer pm1.Unpatch()

pm2 := monkey.PatchInstanceMethod(reflect.TypeOf(bdl), "ListLabelByIDs", func(bdl *bundle.Bundle, ids []uint64) ([]apistructs.ProjectLabel, error) {
return []apistructs.ProjectLabel{
{
ID: 1,
Name: "area",
},
}, nil
})
defer pm2.Unpatch()

e := &Endpoints{bdl: bdl, db: db}
labels, labelDetails := e.getIterationLabelDetails(1)
assert.Equal(t, []string{"area"}, labels)
assert.Equal(t, int64(1), labelDetails[0].ID)
}

0 comments on commit 0e93695

Please sign in to comment.