From 51bf70f463928e0f65a283f33ee49d9ebafe2f86 Mon Sep 17 00:00:00 2001 From: sfwn Date: Thu, 16 Dec 2021 17:38:11 +0800 Subject: [PATCH 1/5] issue-manage: remove useless issue-kanban/gantt/viewGroup --- .../issue-manage/issueGantt/gantt/gantt.go | 126 -- .../issue-manage/issueGantt/init.go | 30 - .../issue-manage/issueGantt/model.go | 418 ------ .../issue-manage/issueGantt/render.go | 224 --- .../issue-manage/issueGantt/render_test.go | 250 ---- .../issue-manage/issueKanban/issue_kanban.go | 1204 ----------------- .../issue-manage/issueKanban/render.go | 646 --------- .../issue-manage/issueKanban/render_test.go | 250 ---- .../issue-manage/issueViewGroup/model.go | 21 - .../issue-manage/issueViewGroup/render.go | 133 -- 10 files changed, 3302 deletions(-) delete mode 100644 modules/dop/component-protocol/components/issue-manage/issueGantt/gantt/gantt.go delete mode 100644 modules/dop/component-protocol/components/issue-manage/issueGantt/init.go delete mode 100644 modules/dop/component-protocol/components/issue-manage/issueGantt/model.go delete mode 100644 modules/dop/component-protocol/components/issue-manage/issueGantt/render.go delete mode 100644 modules/dop/component-protocol/components/issue-manage/issueGantt/render_test.go delete mode 100644 modules/dop/component-protocol/components/issue-manage/issueKanban/issue_kanban.go delete mode 100644 modules/dop/component-protocol/components/issue-manage/issueKanban/render.go delete mode 100644 modules/dop/component-protocol/components/issue-manage/issueKanban/render_test.go delete mode 100644 modules/dop/component-protocol/components/issue-manage/issueViewGroup/model.go delete mode 100644 modules/dop/component-protocol/components/issue-manage/issueViewGroup/render.go diff --git a/modules/dop/component-protocol/components/issue-manage/issueGantt/gantt/gantt.go b/modules/dop/component-protocol/components/issue-manage/issueGantt/gantt/gantt.go deleted file mode 100644 index bec41fe80a5..00000000000 --- a/modules/dop/component-protocol/components/issue-manage/issueGantt/gantt/gantt.go +++ /dev/null @@ -1,126 +0,0 @@ -// 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 gantt - -import ( - "github.com/erda-project/erda-infra/providers/component-protocol/cptype" - "github.com/erda-project/erda/apistructs" -) - -type CommonGantt struct { - Version string `json:"version,omitempty"` - Name string `json:"name,omitempty"` - Type string `json:"type,omitempty"` - Props Props `json:"props,omitempty"` - State State `json:"state,omitempty"` - Operations map[cptype.OperationKey]cptype.LegacyOperation `json:"operations,omitempty"` - Data Data `json:"data,omitempty"` -} - -type State struct { - // set after render - Total uint64 `json:"total,omitempty"` - PageNo uint64 `json:"pageNo,omitempty"` - PageSize uint64 `json:"pageSize,omitempty"` - IssueViewGroupValue string `json:"issueViewGroupValue,omitempty"` - IssueType string -} - -type Props struct { - Visible bool `json:"visible"` - RowKey string `json:"rowKey,omitempty"` - ClassName string `json:"className,omitempty"` - Columns []PropColumn `json:"columns,omitempty"` -} - -type PropColumn struct { - Title string `json:"title,omitempty"` - TitleRenderType string `json:"titleRenderType,omitempty"` - DataIndex string `json:"dataIndex,omitempty"` - Width uint64 `json:"width,omitempty"` - Data []PropColumnData `json:"data,omitempty"` - TitleTip []string `json:"titleTip,omitempty"` -} - -type PropColumnData struct { - Month uint64 `json:"month,omitempty"` - Date []uint64 `json:"date,omitempty"` -} - -var ( - OpChangePageNo cptype.OperationKey = "changePageNo" -) - -var Operations = map[cptype.OperationKey]cptype.LegacyOperation{ - OpChangePageNo: {Reload: true}, -} - -type Data struct { - List []DataItem `json:"list,omitempty"` -} - -type DataItem struct { - // 此ID全局唯一: autoID + issueID - ID uint64 `json:"id,omitempty"` - DateRange DateRange `json:"dateRange,omitempty"` - Tasks DataTask `json:"issues,omitempty"` - User User `json:"user,omitempty"` -} - -type DateRange struct { - RenderType RenderType `json:"renderType,omitempty"` - Value []DateRangeValue `json:"value,omitempty"` -} - -type DateRangeValue struct { - Tooltip string `json:"tooltip"` - // 单位天 - RestTime float64 `json:"restTime"` - Offset float64 `json:"offset"` - Delay float64 `json:"delay"` - ActualTime float64 `json:"actualTime"` -} - -type DataTask struct { - RenderType RenderType `json:"renderType,omitempty"` - Value []DataTaskValue `json:"value,omitempty"` -} - -type DataTaskValue struct { - Text string `json:"text,omitempty"` - ID int64 `json:"id,omitempty"` - Type apistructs.IssueType `json:"type,omitempty"` - IterationID int64 `json:"iterationID,omitempty"` // TODO not in common - LinkStyle bool `json:"linkStyle,omitempty"` -} - -type User struct { - Avatar string `json:"avatar,omitempty"` - Value uint64 `json:"value,omitempty"` - Name string `json:"name,omitempty"` - Nick string `json:"nick,omitempty"` - RenderType RenderType `json:"renderType,omitempty"` -} - -type RenderType string - -var ( - RenderTypeGantt RenderType = "gantt" - RenderTypeStringList RenderType = "string-list" - RenderTypeMemberAvatar RenderType = "userAvatar" - - DefaultPageNo = uint64(1) - DefaultPageSize = uint64(200) -) diff --git a/modules/dop/component-protocol/components/issue-manage/issueGantt/init.go b/modules/dop/component-protocol/components/issue-manage/issueGantt/init.go deleted file mode 100644 index be786c8c9ca..00000000000 --- a/modules/dop/component-protocol/components/issue-manage/issueGantt/init.go +++ /dev/null @@ -1,30 +0,0 @@ -// 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 issueGantt - -import ( - "github.com/erda-project/erda-infra/base/servicehub" - "github.com/erda-project/erda/modules/openapi/component-protocol/components/base" -) - -func init() { - base.InitProviderWithCreator("issue-manage", CompName, func() servicehub.Provider { - return &Gantt{} - }) -} - -var ( - CompName = "issueGantt" -) diff --git a/modules/dop/component-protocol/components/issue-manage/issueGantt/model.go b/modules/dop/component-protocol/components/issue-manage/issueGantt/model.go deleted file mode 100644 index ab98f8defea..00000000000 --- a/modules/dop/component-protocol/components/issue-manage/issueGantt/model.go +++ /dev/null @@ -1,418 +0,0 @@ -// 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 issueGantt - -import ( - "context" - "encoding/base64" - "encoding/json" - "fmt" - "strconv" - "time" - - "github.com/sirupsen/logrus" - - "github.com/erda-project/erda-infra/providers/component-protocol/cptype" - "github.com/erda-project/erda-infra/providers/component-protocol/utils/cputil" - "github.com/erda-project/erda/apistructs" - "github.com/erda-project/erda/bundle" - "github.com/erda-project/erda/modules/dop/component-protocol/components/issue-manage/issueGantt/gantt" - "github.com/erda-project/erda/modules/openapi/component-protocol/components/base" - "github.com/erda-project/erda/pkg/strutil" -) - -type Gantt struct { - sdk *cptype.SDK - bdl *bundle.Bundle - - // 从全局状态返回给框架 - Uids []string - - gantt.CommonGantt - - base.DefaultProvider -} - -type State struct { - // common state - gantt.State - - IssuePagingRequest apistructs.IssuePagingRequest `json:"issuePagingRequest,omitempty"` -} - -func getEdgeTime(issues []apistructs.Issue) (eMin, eMax *time.Time) { - var edgeMinTime, edgeMaxTime *time.Time - var minIssue, maxIssue apistructs.Issue - for _, v := range issues { - if edgeMinTime == nil && v.PlanStartedAt != nil { - edgeMinTime = v.PlanStartedAt - minIssue = v - } - if edgeMaxTime == nil && v.PlanFinishedAt != nil { - edgeMaxTime = v.PlanFinishedAt - maxIssue = v - } - if edgeMinTime != nil && v.PlanStartedAt != nil && v.PlanStartedAt.Before(*edgeMinTime) { - edgeMinTime = v.PlanStartedAt - minIssue = v - } - if edgeMaxTime != nil && v.PlanFinishedAt != nil && v.PlanFinishedAt.After(*edgeMaxTime) { - edgeMaxTime = v.PlanFinishedAt - maxIssue = v - } - } - logrus.Infof("raw edge issues, min:%+v, max:%+v", minIssue, maxIssue) - - now := time.Now() - nowDate := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location()) - //if edgeMinTime == nil && edgeMaxTime == nil { - tmp1 := nowDate.AddDate(0, 0, -15) - edgeMinTime = &tmp1 - tmp2 := nowDate.AddDate(0, 0, 10) - edgeMaxTime = &tmp2 - //} else if edgeMinTime == nil { - // tmp := edgeMaxTime.AddDate(0, 0, -24) - // edgeMinTime = &tmp - //} else if edgeMaxTime == nil { - // tmp := edgeMinTime.AddDate(0, 0, 24) - // edgeMaxTime = &tmp - //} else { - // if nowDate.After(*edgeMaxTime) { - // edgeMaxTime = &now - // } - // tmp := edgeMinTime.AddDate(0, 0, 24) - // if edgeMaxTime.Before(tmp) { - // edgeMaxTime = &tmp - // } - //} - logrus.Infof("edge issues times, min:%+v, max:%+v", *edgeMinTime, *edgeMaxTime) - return edgeMinTime, edgeMaxTime -} - -func (g *Gantt) genProps(ctx context.Context, edgeMinTime, edgeMaxTime *time.Time) { - props := gantt.Props{ - Visible: true, - RowKey: "id", - // ClassName: "task-gantt-table", - Columns: []gantt.PropColumn{ - {Title: cputil.I18n(ctx, "assignee"), DataIndex: "user", Width: 160}, - {Title: cputil.I18n(ctx, "title"), DataIndex: "issues", - TitleTip: []string{ - cputil.I18n(ctx, "issue-gante-tips1"), - cputil.I18n(ctx, "issue-gante-tips2"), - cputil.I18n(ctx, "issue-gante-tips3"), - cputil.I18n(ctx, "issue-gante-tips4"), - }, - }, - }} - ganColumn := gantt.PropColumn{Title: "甘特图", DataIndex: "dateRange", TitleRenderType: "gantt", Width: 800} - data := g.genGanPropColumn(edgeMinTime, edgeMaxTime) - ganColumn.Data = data - props.Columns = append(props.Columns, ganColumn) - g.setProps(props) -} - -func (g Gantt) getZhTaskName() string { - switch g.State.IssueType { - case apistructs.IssueTypeTask.String(): - return "任务" - case apistructs.IssueTypeBug.String(): - return "缺陷" - case apistructs.IssueTypeRequirement.String(): - return "需求" - default: - return "任务" - } -} - -// TODO: generate gantt prop column data based on issues -// 长度为25天 -func (g *Gantt) genGanPropColumn(edgeMinTime, edgeMaxTime *time.Time) []gantt.PropColumnData { - start := *edgeMinTime - end := *edgeMaxTime - mDays := make(map[uint64][]uint64) - var months []uint64 - // range: [start, end] - for !start.Equal(end) { - m := uint64(start.Month()) - d := uint64(start.Day()) - if months == nil || m != months[len(months)-1] { - months = append(months, m) - } - mDays[m] = append(mDays[m], d) - start = start.AddDate(0, 0, 1) - } - var data []gantt.PropColumnData - for _, m := range months { - data = append(data, gantt.PropColumnData{ - Month: m, - Date: mDays[m], - }) - } - return data -} - -func (g *Gantt) setProps(p gantt.Props) { - g.Props = p -} - -func (g *Gantt) genData(issues []apistructs.Issue, edgeMinTime, edgeMaxTime *time.Time) error { - // group by assignee - // test - //now := time.Now() - //nowDate := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location()) - //edgeMinTime = &nowDatedice-openapi-56979f5cb8-vm6pc - // === - - var uids []string - for _, v := range issues { - uids = append(uids, v.Assignee) - } - uInfos := genUserInfo(uids) - g.setUids(uids) - // range by assignee - var data []gantt.DataItem - autoID := uint64(10000000000000) - for _, v := range issues { - uInfo := uInfos[v.Assignee] - t := gantt.DataTask{RenderType: "string-list"} - r := gantt.DateRange{RenderType: "gantt"} - tInfo := genTaskInfo(v) - rInfo := genRangeInfo(edgeMinTime, edgeMaxTime, v) - t.Value = append(t.Value, tInfo) - r.Value = append(r.Value, rInfo) - item := gantt.DataItem{ID: autoID + uint64(v.ID), User: *uInfo, Tasks: t, DateRange: r} - data = append(data, item) - } - g.setData(data) - return nil -} - -// TODO: 如果总返回response透出了userInfos, 此处只需要userID即可, 不需要再查一次 -func genUserInfo(uids []string) map[string]*gantt.User { - gUserInfo := make(map[string]*gantt.User) - for _, v := range uids { - uid, _ := strconv.ParseUint(v, 10, 64) - gUserInfo[v] = &gantt.User{ - Value: uid, - RenderType: gantt.RenderTypeMemberAvatar, - } - } - //uInfo, err := posthandle.GetUsers(uids, false) - //if err != nil { - // logrus.Warnf("get user info failed, err:%v", err) - // return gUserInfo - //} - //for k, v := range uInfo { - // gUserInfo[k].Name = v.Name - // gUserInfo[k].Nick = v.Nick - //} - return gUserInfo -} - -func genTaskInfo(i apistructs.Issue) gantt.DataTaskValue { - return gantt.DataTaskValue{ - Text: i.Title, - ID: i.ID, - Type: i.Type, - IterationID: i.IterationID, - } -} - -func fix(x *time.Time, l time.Time, r time.Time) { - if x.Before(l) { - *x = l - } else if x.After(r) { - *x = r - } -} - -// TODO: -func genRangeInfo(edgeMinTime, edgeMaxTime *time.Time, i apistructs.Issue) gantt.DateRangeValue { - // 时间(天) - // offset 偏移时间(天),开始时间相对边界时间 - - var trueFinishDate time.Time - data := gantt.DateRangeValue{Tooltip: i.Title} - now := time.Now() - var startTime time.Time - if i.PlanFinishedAt != nil { - *i.PlanFinishedAt = (*i.PlanFinishedAt).Add(time.Hour * time.Duration(24)) - } - // PlanStartedAt为空,向上取整;不为空,向下取整 (单位: 天) - if i.PlanFinishedAt != nil && i.ManHour.EstimateTime > 0 { - startTime = (*i.PlanFinishedAt).Add(-time.Minute * time.Duration(i.ManHour.EstimateTime*3)) - } - - if i.ManHour.EstimateTime == 0 || i.PlanFinishedAt == nil { - return data - } - - e := edgeMinTime - s := &startTime - f := i.PlanFinishedAt - ts := i.PlanStartedAt - tf := i.FinishTime - // 非法数据不显示 - if ts != nil && tf != nil && tf.Before(*ts) { - return data - } - if ts != nil && now.Before(*ts) { - return data - } - if tf != nil && now.Before(*tf) { - return data - } - - edgeDate := time.Date(e.Year(), e.Month(), e.Day(), 0, 0, 0, 0, edgeMinTime.Location()) - fedgeData := time.Date(edgeMaxTime.Year(), edgeMaxTime.Month(), edgeMaxTime.Day(), 0, 0, 0, 0, edgeMinTime.Location()) - startDate := time.Date(s.Year(), s.Month(), s.Day(), 0, 0, 0, 0, edgeMinTime.Location()) - finishDate := time.Date(f.Year(), f.Month(), f.Day(), 0, 0, 0, 0, edgeMinTime.Location()) - nowData := time.Date(now.Year(), now.Month(), now.Day(), now.Hour(), 0, 0, 0, edgeMinTime.Location()) - if tf != nil { - trueFinishDate = time.Date(tf.Year(), tf.Month(), tf.Day(), tf.Hour(), 0, 0, 0, edgeMinTime.Location()) - } - - fix(&startDate, edgeDate, fedgeData) - fix(&finishDate, edgeDate, fedgeData) - if tf != nil { - fix(&trueFinishDate, edgeDate, fedgeData) - } - - if ts == nil { - // 无实际开始时间 - if tf == nil { - // 无实际结束时间 - if now.Before(*s) || now.Equal(*s) { - // 当前时间 <= 预计开始时间 - data.RestTime = finishDate.Sub(startDate).Hours() / 24.0 - data.Offset = startDate.Sub(edgeDate).Hours() / 24.0 - } else if now.Before(*f) || now.Equal(*f) { - // 预计开始时间 < 当前时间 <= 预计结束时间 - data.RestTime = finishDate.Sub(nowData).Hours() / 24.0 - data.Offset = nowData.Sub(edgeDate).Hours() / 24.0 - } else { - // 预计结束时间 < 当前时间 - data.Delay = now.Sub(finishDate).Hours() / 24.0 - data.Offset = finishDate.Sub(edgeDate).Hours() / 24.0 - } - } else { - // 有实际结束时间 - if tf.Before(*f) || tf.Equal(*f) { - // 实际结束时间 <= 预计结束时间 - data.RestTime = finishDate.Sub(trueFinishDate).Hours() / 24.0 - data.Offset = trueFinishDate.Sub(edgeDate).Hours() / 24.0 - } else { - // 预计结束时间 < 实际结束时间 - data.RestTime = finishDate.Sub(startDate).Hours() / 24.0 - data.Delay = trueFinishDate.Sub(finishDate).Hours() / 24.0 - data.Offset = startDate.Sub(edgeDate).Hours() / 24.0 - } - } - } else { - // 有实际开始时间 - trueStartDate := time.Date(ts.Year(), ts.Month(), ts.Day(), ts.Hour(), 0, 0, 0, edgeMinTime.Location()) - fix(&trueStartDate, edgeDate, fedgeData) - if tf == nil { - // 无实际结束时间 - if now.Before(*f) || now.Equal(*f) { - // 实际开始时间 <= 当前时间 <= 预计结束时间 - data.ActualTime = nowData.Sub(trueStartDate).Hours() / 24.0 - data.RestTime = finishDate.Sub(nowData).Hours() / 24.0 - data.Offset = trueStartDate.Sub(edgeDate).Hours() / 24.0 - } else { - if ts.Before(*f) || ts.Equal(*f) { - // 实际开始时间 < 预计结束时间 <= 当前时间 - data.ActualTime = finishDate.Sub(trueStartDate).Hours() / 24.0 - data.Delay = nowData.Sub(finishDate).Hours() / 24.0 - data.Offset = trueStartDate.Sub(edgeDate).Hours() / 24.0 - } - } - } else { - // 有实际结束时间 - if tf.Before(*f) || tf.Equal(*f) { - // 实际开始时间 <= 实际结束时间 <= 计划结束时间 - data.ActualTime = trueFinishDate.Sub(trueStartDate).Hours() / 24.0 - data.RestTime = finishDate.Sub(trueFinishDate).Hours() / 24.0 - data.Offset = trueStartDate.Sub(edgeDate).Hours() / 24.0 - } else { - if ts.Before(*f) || ts.Equal(*f) { - // 实际开始时间 < 预计结束时间 <= 实际结束时间 - data.ActualTime = finishDate.Sub(trueStartDate).Hours() / 24.0 - data.Offset = trueStartDate.Sub(edgeDate).Hours() / 24.0 - } else { - // 预计结束时间 <= 实际开始时间 < 实际结束时间 - data.Offset = finishDate.Sub(edgeDate).Hours() / 24.0 - } - data.Delay = trueFinishDate.Sub(finishDate).Hours() / 24.0 - - } - } - } - - ElapsedHour := float64(i.ManHour.ElapsedTime) / (60.0 * 8.0) - data.Tooltip = fmt.Sprintf("%s (实际用时: %.1f天)", data.Tooltip, ElapsedHour) - return data -} - -func (g *Gantt) setData(data []gantt.DataItem) { - g.Data = gantt.Data{List: data} -} - -func (g *Gantt) setOperations() { - ops := make(map[cptype.OperationKey]cptype.LegacyOperation) - ops[gantt.OpChangePageNo] = cptype.LegacyOperation{Key: gantt.OpChangePageNo.String(), Reload: true} - g.Operations = ops -} - -func (g *Gantt) setDefaultState(operation cptype.OperationKey) { - // default state - defaultState := gantt.State{ - PageNo: gantt.DefaultPageNo, - PageSize: gantt.DefaultPageSize, - } - - switch operation { - // global default state form url - case cptype.InitializeOperation: - if urlQueryI, ok := g.sdk.InParams[getStateUrlQueryKey()]; ok { - if urlQueryStr, ok := urlQueryI.(string); ok && urlQueryStr != "" { - var urlState gantt.State - b, err := base64.StdEncoding.DecodeString(urlQueryStr) - if err != nil { - logrus.Warnf("decode url query failed, request:%v, err:%v", urlQueryStr, err) - } - if err := json.Unmarshal(b, &urlState); err != nil { - logrus.Warnf("get url state failed, request:%v, err:%v", urlState, err) - } - if err == nil { - defaultState = urlState - } - } - } - } - - g.State.PageSize = defaultState.PageSize - g.State.PageNo = defaultState.PageNo -} - -func (g *Gantt) setStateTotal(total uint64) { - g.State.Total = total -} - -func (g *Gantt) setUids(uids []string) { - uids = strutil.DedupSlice(uids, true) - g.Uids = uids -} diff --git a/modules/dop/component-protocol/components/issue-manage/issueGantt/render.go b/modules/dop/component-protocol/components/issue-manage/issueGantt/render.go deleted file mode 100644 index 48780eabd4d..00000000000 --- a/modules/dop/component-protocol/components/issue-manage/issueGantt/render.go +++ /dev/null @@ -1,224 +0,0 @@ -// 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 issueGantt - -import ( - "context" - "encoding/base64" - "encoding/json" - "fmt" - "strconv" - - "github.com/sirupsen/logrus" - - "github.com/erda-project/erda-infra/providers/component-protocol/cptype" - "github.com/erda-project/erda-infra/providers/component-protocol/utils/cputil" - "github.com/erda-project/erda/apistructs" - "github.com/erda-project/erda/bundle" - "github.com/erda-project/erda/modules/dop/component-protocol/components/issue-manage/issueViewGroup" - "github.com/erda-project/erda/modules/dop/component-protocol/types" - protocol "github.com/erda-project/erda/modules/openapi/component-protocol" - "github.com/erda-project/erda/modules/openapi/component-protocol/components/gantt" -) - -func (g *Gantt) Render(ctx context.Context, c *cptype.Component, scenario cptype.Scenario, event cptype.ComponentEvent, gs *cptype.GlobalStateData) error { - // import component data - if err := g.Import(c); err != nil { - logrus.Errorf("import component failed, err:%v", err) - return err - } - g.sdk = cputil.SDK(ctx) - g.bdl = ctx.Value(types.GlobalCtxKeyBundle).(*bundle.Bundle) - - // check visible - visible := false - if v, ok := c.State["issueViewGroupValue"]; ok { - if viewType, ok := v.(string); ok { - if viewType != issueViewGroup.ViewTypeGantt { - visible = false - c.Props = cptype.ComponentProps{} - c.Props["visible"] = visible - return nil - } - } - g.Props.Visible = true - visible = true - } - if !visible { - c.Props = cptype.ComponentProps{} - c.Props["visible"] = visible - return nil - } - - issueType, _ := g.sdk.InParams["fixedIssueType"].(string) - g.State.IssueType = issueType - - // listen on operation - switch event.Operation.String() { - case apistructs.InitializeOperation.String(), apistructs.RenderingOperation.String(): - g.setDefaultState(event.Operation) - g.setOperations() - err := g.RenderOnFilter(ctx, c) - if err != nil { - logrus.Errorf("render on filter failed, err:%v", err) - return err - } - case gantt.OpChangePageNo.String(): - err := g.RenderOnFilter(ctx, c) - if err != nil { - logrus.Errorf("render on filter failed, err:%v", err) - return err - } - default: - logrus.Warnf("operation [%s] not support, scenario:%v, event:%v", event.Operation, scenario, event) - } - - // export rendered component data - if err := g.Export(c, gs); err != nil { - logrus.Errorf("export component failed, err:%v", err) - return err - } - return nil -} - -func (g *Gantt) RenderOnFilter(ctx context.Context, c *cptype.Component) error { - // get filter request - - req, err := g.getFilterReq(c) - if err != nil { - logrus.Errorf("get filter request failed, err:%v", err) - return err - } - g.State.PageSize = 10 - // query issues - req.PageSize = 10 - rsp, err := g.bdl.PageIssues(*req) - if err != nil { - logrus.Errorf("page issue failed, request: %v, err: %v", req, err) - return err - } - // get issues edge time - edgeMinTime, edgeMaxTime := getEdgeTime(rsp.Data.List) - - // generate gantt props - g.genProps(ctx, edgeMinTime, edgeMaxTime) - - // generate gantt data - err = g.genData(rsp.Data.List, edgeMinTime, edgeMaxTime) - if err != nil { - logrus.Errorf("generate data failed, request:%v, err:%v", req, err) - return err - } - g.setStateTotal(rsp.Data.Total) - return nil -} - -func (g Gantt) getFilterReq(c *cptype.Component) (req *apistructs.IssuePagingRequest, err error) { - projectid, err := strconv.ParseUint(g.sdk.InParams["projectId"].(string), 10, 64) - orgid, err := strconv.ParseUint(g.sdk.Identity.OrgID, 10, 64) - - cond := apistructs.IssuePagingRequest{} - filterCond, ok := c.State["filterConditions"] - if ok { - filterCondS, err := json.Marshal(filterCond) - if err != nil { - return nil, err - } - if err := json.Unmarshal(filterCondS, &cond); err != nil { - return nil, err - } - } else { - cond.OrgID = int64(orgid) - cond.ProjectID = projectid - cond.IssueListRequest.IdentityInfo.UserID = g.sdk.Identity.UserID - } - if g.State.PageSize == 0 { - cond.PageSize = gantt.DefaultPageSize - cond.PageNo = gantt.DefaultPageNo - g.State.PageSize = cond.PageSize - g.State.PageNo = cond.PageNo - } else { - cond.PageNo = g.State.PageNo - cond.PageSize = g.State.PageSize - } - // TODO: test remove - // cond.IDs = []int64{777, 663} - // cond.PageSize = 1 - cond.OrderBy = "assignee" - cond.Type = getIssueTypes(g.State.IssueType) - return &cond, nil -} - -func getIssueTypes(t string) []apistructs.IssueType { - switch t { - case "ALL": - return []apistructs.IssueType{apistructs.IssueTypeTask, apistructs.IssueTypeRequirement, apistructs.IssueTypeBug} - case apistructs.IssueTypeTask.String(): - return []apistructs.IssueType{apistructs.IssueTypeTask} - case apistructs.IssueTypeRequirement.String(): - return []apistructs.IssueType{apistructs.IssueTypeRequirement} - case apistructs.IssueTypeBug.String(): - return []apistructs.IssueType{apistructs.IssueTypeBug} - default: - logrus.Warnf("wrong issue type: %v, assign all", t) - return []apistructs.IssueType{apistructs.IssueTypeTask, apistructs.IssueTypeRequirement, apistructs.IssueTypeBug} - } -} - -func (g *Gantt) Import(c *cptype.Component) error { - b, err := json.Marshal(c) - if err != nil { - return err - } - if err := json.Unmarshal(b, g); err != nil { - return err - } - return nil -} - -func (g *Gantt) Export(c *cptype.Component, gs *cptype.GlobalStateData) error { - // set component data - b, err := json.Marshal(g) - if err != nil { - return err - } - c.Data = nil - if err := json.Unmarshal(b, c); err != nil { - return err - } - // set url query state - err = g.SetStateToUrlQuery(c) - if err != nil { - return err - } - // set global state: uids - (*gs)[protocol.GlobalInnerKeyUserIDs.String()] = g.Uids - return nil -} - -func getStateUrlQueryKey() string { - return fmt.Sprintf("%s__urlQuery", CompName) -} - -func (g Gantt) SetStateToUrlQuery(c *cptype.Component) error { - g.State.Total = 0 - b, err := json.Marshal(g.State) - if err != nil { - return err - } - urlQueryStr := base64.StdEncoding.EncodeToString(b) - c.State[getStateUrlQueryKey()] = urlQueryStr - return nil -} diff --git a/modules/dop/component-protocol/components/issue-manage/issueGantt/render_test.go b/modules/dop/component-protocol/components/issue-manage/issueGantt/render_test.go deleted file mode 100644 index eee9791e4b1..00000000000 --- a/modules/dop/component-protocol/components/issue-manage/issueGantt/render_test.go +++ /dev/null @@ -1,250 +0,0 @@ -// 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 issueGantt - -import ( - "context" - "net/http" - "os" - "testing" - "time" - - "github.com/alecthomas/assert" - - "github.com/erda-project/erda-infra/providers/component-protocol/cptype" - "github.com/erda-project/erda/apistructs" - "github.com/erda-project/erda/bundle" - "github.com/erda-project/erda/modules/dop/component-protocol/components/issue-manage/issueGantt/gantt" - protocol "github.com/erda-project/erda/modules/openapi/component-protocol" - "github.com/erda-project/erda/modules/openapi/component-protocol/components/base" - "github.com/erda-project/erda/modules/openapi/i18n" - "github.com/erda-project/erda/pkg/http/httpclient" -) - -func rend(req *apistructs.ComponentProtocolRequest) (cont *apistructs.ComponentProtocolRequest, err error) { - // bundle - os.Setenv("CMDB_ADDR", "cmdb.default.svc.cluster.local:9093") - bundleOpts := []bundle.Option{ - bundle.WithHTTPClient( - httpclient.New( - httpclient.WithTimeout(time.Second, time.Second*60), - )), - bundle.WithCoreServices(), - } - bdl := bundle.New(bundleOpts...) - - r := http.Request{} - i18nPrinter := i18n.I18nPrinter(&r) - inParams := req.InParams - identity := apistructs.Identity{UserID: "2", OrgID: "1"} - ctxBdl := protocol.ContextBundle{ - Bdl: bdl, - I18nPrinter: i18nPrinter, - InParams: inParams, - Identity: identity, - } - ctx := context.Background() - ctx1 := context.WithValue(ctx, protocol.GlobalInnerKeyCtxBundle.String(), ctxBdl) - - err = protocol.RunScenarioRender(ctx1, req) - if err != nil { - return - } - cont = req - return -} - -//func TestRender(t *testing.T) { -// req := apistructs.ComponentProtocolRequest{ -// Scenario: apistructs.ComponentProtocolScenario{ -// ScenarioKey: "issueGantt", -// ScenarioType: "issue-manage", -// }, -// Event: apistructs.ComponentEvent{ -// Component: "", -// GenerateOperation: "", -// }, -// InParams: map[string]interface{}{"projectId": "11"}, -// } -// content, err := rend(&req) -// ctxByte, err := json.Marshal(*content) -// if err != nil { -// t.Errorf("marshal error:%v", err) -// return -// } -// t.Logf("marshal content:%s", string(ctxByte)) -//} - -//func TestFilter(t *testing.T) { -// os.Setenv("CMDB_ADDR", "cmdb.default.svc.cluster.local:9093") -// bundleOpts := []bundle.Option{ -// bundle.WithHTTPClient( -// httpclient.New( -// httpclient.WithTimeout(time.Second, time.Second*60), -// )), -// bundle.WithCMDB(), -// } -// bdl := bundle.New(bundleOpts...) -// comp := Gantt{ -// CtxBdl: protocol.ContextBundle{ -// Bdl: bdl, -// I18nPrinter: i18n.I18nPrinter(nil), -// Identity: apistructs.Identity{}, -// InParams: nil, -// }, -// } -// req := IssueFilterRequest{ -// IssuePagingRequest: apistructs.IssuePagingRequest{ -// PageSize: 200, -// IssueListRequest: apistructs.IssueListRequest{ -// Title: "", -// Type: []apistructs.IssueType{apistructs.IssueTypeTask}, -// ProjectID: 35, -// IterationID: 0, -// IdentityInfo: apistructs.IdentityInfo{ -// UserID: "2", -// }, -// External: false, -// }, -// }, -// BoardType: BoardTypeCustom, -// } -// ib, err := comp.Filter(req) -// if err != nil { -// panic(err) -// } -// t.Logf("issue board:%v", ib) -//} - -// genData() results are the same every time -func TestGenData(t *testing.T) { - p := Gantt{} - issues := []apistructs.Issue{ - { - ID: 1, - Assignee: "1", - }, - { - ID: 2, - Assignee: "1", - }, - { - ID: 3, - Assignee: "1", - }, - { - ID: 4, - Assignee: "2", - }, - { - ID: 5, - Assignee: "2", - }, - { - ID: 6, - Assignee: "3", - }, - { - ID: 6, - Assignee: "3", - }, - } - t1 := time.Now() - t2 := time.Now() - res := map[int]interface{}{} - for i := 0; i < 10; i++ { - p.Data = gantt.Data{} - err := p.genData(issues, &t1, &t2) - assert.NoError(t, err) - res[i] = p.Data - if i > 0 { - assert.Equal(t, res[i-1], res[i]) - } - } -} - -func TestSetStateToUrlQuery(t *testing.T) { - state := gantt.State{ - Total: 11, - PageNo: 1, - PageSize: 10, - IssueViewGroupValue: "foo", - IssueType: "bar", - } - var g Gantt - g.State = state - c := &cptype.Component{ - State: make(map[string]interface{}), - } - if err := g.SetStateToUrlQuery(c); err != nil { - t.Error("fail") - } - // {"pageNo":1,"pageSize":10,"issueViewGroupValue":"foo","IssueType":"bar"} - if c.State["issueGantt__urlQuery"] != "eyJwYWdlTm8iOjEsInBhZ2VTaXplIjoxMCwiaXNzdWVWaWV3R3JvdXBWYWx1ZSI6ImZvbyIsIklzc3VlVHlwZSI6ImJhciJ9" { - t.Error("fail") - } -} - -func TestGantt_Export(t *testing.T) { - type fields struct { - sdk *cptype.SDK - bdl *bundle.Bundle - Uids []string - CommonGantt gantt.CommonGantt - DefaultProvider base.DefaultProvider - } - type args struct { - c *cptype.Component - gs *cptype.GlobalStateData - } - tests := []struct { - name string - fields fields - args args - wantErr bool - }{ - { - name: "with default value", - args: args{ - c: &cptype.Component{ - Data: map[string]interface{}{ - "list": []gantt.DataItem{ - { - ID: 2, - }, - }, - }, - }, - gs: &cptype.GlobalStateData{}, - }, - wantErr: false, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - g := &Gantt{ - sdk: tt.fields.sdk, - bdl: tt.fields.bdl, - Uids: tt.fields.Uids, - CommonGantt: tt.fields.CommonGantt, - DefaultProvider: tt.fields.DefaultProvider, - } - if err := g.Export(tt.args.c, tt.args.gs); (err != nil) != tt.wantErr { - t.Errorf("Gantt.Export() error = %v, wantErr %v", err, tt.wantErr) - } - assert.Equal(t, nil, tt.args.c.Data["list"]) - }) - } -} diff --git a/modules/dop/component-protocol/components/issue-manage/issueKanban/issue_kanban.go b/modules/dop/component-protocol/components/issue-manage/issueKanban/issue_kanban.go deleted file mode 100644 index a9af31c111c..00000000000 --- a/modules/dop/component-protocol/components/issue-manage/issueKanban/issue_kanban.go +++ /dev/null @@ -1,1204 +0,0 @@ -// 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 issueKanban - -import ( - "context" - "encoding/json" - "fmt" - "strconv" - "sync" - "time" - - "github.com/golang-collections/collections/set" - "github.com/sirupsen/logrus" - - "github.com/erda-project/erda-infra/base/servicehub" - "github.com/erda-project/erda-infra/providers/component-protocol/cptype" - "github.com/erda-project/erda-infra/providers/component-protocol/utils/cputil" - "github.com/erda-project/erda/apistructs" - "github.com/erda-project/erda/bundle" - "github.com/erda-project/erda/modules/dop/component-protocol/components/common" - issue_svc "github.com/erda-project/erda/modules/dop/services/issue" - "github.com/erda-project/erda/modules/dop/services/issuestate" - "github.com/erda-project/erda/modules/openapi/component-protocol/components/base" - "github.com/erda-project/erda/pkg/strutil" -) - -type IssueCart struct { - // i18nPrinter *message.Printer - ctx context.Context - Assignee string `json:"assignee"` - Priority apistructs.IssuePriority `json:"priority"` - ID int64 `json:"id"` - Title string `json:"title"` - Type apistructs.IssueType `json:"type"` - IssueButton []apistructs.IssueStateButton `json:"issueButton"` - IterationID int64 `json:"iterationID"` - PlanFinishedAt *time.Time `json:"planFinishedAt"` - Operations map[string]interface{} `json:"operations"` - - Status CardStatus `json:"status,omitempty"` - Labels *CardLabels `json:"labels,omitempty"` -} - -type CardStatus struct { - Text string `json:"text,omitempty"` - Status string `json:"status,omitempty"` -} -type CardLabels struct { - Value []CardLabel `json:"value,omitempty"` -} -type CardLabel struct { - Label string `json:"label,omitempty"` - Color string `json:"color,omitempty"` -} - -type CartList struct { - // i18nPrinter *message.Printer - ctx context.Context - // 分类类型: 状态,处理人,时间,自定义,优先级 - Label interface{} `json:"label"` - LabelKey interface{} `json:"labelKey"` - Total uint64 `json:"total"` - PageNo uint64 `json:"pageNo"` - PageSize uint64 `json:"pageSize"` - List []IssueCart `json:"list"` - Operations map[string]interface{} `json:"operations"` -} - -type IssueBoard struct { - RefreshBoard bool `json:"refreshBoard"` - Board []CartList `json:"board"` - UserIDs []string `json:"userIDs"` -} - -func (cl *CartList) Delete(issueID int64) { - for k, v := range cl.List { - if issueID == v.ID { - cl.List = append(cl.List[:k], cl.List[k+1:]...) - } - } -} - -func (cl *CartList) Add(c IssueCart) { - cl.List = append(cl.List, c) -} - -const ( - MoveOutConfirmMsg = "confirm-to-move-out-iteration" - CreateBoardConfirmMsg = "confirm-to-create-board" - DeleteBoardConfirmMsg = "confirm-to-delete-board" - UpdateBoardConfirmMsg = "confirm-to-update-board" - CreateBoardDisabledTip = "the-number-of-boards-cannot-exceed-15" - GuestCreateBoardDisabledTip = "no-permission-to-operate" -) - -type OperationBaseInfo struct { - // 操作展示名称 - Text string `json:"text"` - // 是否有权限操作 - Disabled bool `json:"disabled"` - // 确认提示 - Confirm string `json:"confirm,omitempty"` - // 前端操作是否需要触发后端 - Reload bool `json:"reload"` - DisabledTip string `json:"disabledTip"` -} - -type OpMetaInfo struct { - IssueID int64 `json:"ID"` - IssueAssignee string `json:"issueAssignee"` - IssuePriority apistructs.IssuePriority `json:"issuePriority"` - StateID int64 `json:"stateID"` - apistructs.IssuePanel -} - -type OperationInfo struct { - OperationBaseInfo - Meta OpMetaInfo `json:"meta"` -} - -type DragOperationInfo struct { - Meta OpMetaInfo `json:"meta"` - // 前端操作是否需要触发后端 - Reload bool `json:"reload"` - // 可拖拽的范围 - TargetKeys interface{} `json:"targetKeys"` - Async bool `json:"async,omitempty"` - Disabled bool `json:"disabled"` -} - -type MoveOutOperation OperationInfo - -// 状态 -type DragOperation DragOperationInfo -type MoveToOperation OperationInfo - -// 处理人 -//type DragToAssigneeOperation DragOperationInfo -type MoveToAssigneeOperation OperationInfo - -// 优先级 -type MoveToPriorityOperation OperationInfo - -// 自定义看板 -type CreateBoardOperation OperationInfo -type DeleteBoardOperation OperationInfo -type UpdateBoardOperation OperationInfo -type MoveToCustomOperation OperationInfo - -type ChangePageNoOperation struct { - Key string `json:"key"` - Reload bool `json:"reload"` - FillMeta string `json:"fillMeta"` - Meta struct { - KanbanKey string `json:"kanbanKey"` - } `json:"meta"` -} - -const MaxBoardNum = 15 - -//type DragToCustomOperation DragOperationInfo - -func (c *CartList) SetCtx(ctx context.Context) { - c.ctx = ctx -} - -func (c *IssueCart) SetCtx(ctx context.Context) { - c.ctx = ctx -} - -// 移除操作渲染生成 -func (c *IssueCart) RenderMoveOutOperation() { - // 已经move out iteration - if c.IterationID < 0 { - return - } - o := MoveOutOperation{} - o.Disabled = false - o.Confirm = cputil.I18n(c.ctx, MoveOutConfirmMsg) - o.Text = cputil.I18n(c.ctx, apistructs.MoveOutOperation.String()) - o.Reload = true - o.Meta = OpMetaInfo{IssueID: c.ID} - c.Operations[apistructs.MoveOutOperation.String()] = o -} - -// 拖拽操作渲染生成 -func (c *IssueCart) RenderDragOperation() { - targetKeys := make(map[int64]bool) - for _, v := range c.IssueButton { - if v.Permission == true { - targetKeys[v.StateID] = true - } - } - o := DragOperation{} - o.Reload = true - o.Meta = OpMetaInfo{IssueID: c.ID} - o.TargetKeys = targetKeys - o.Async = true - c.Operations[apistructs.DragOperation.String()] = o -} - -func (c *IssueCart) RenderMoveToOperation() { - for _, v := range c.IssueButton { - o := MoveToOperation{} - o.Disabled = !v.Permission - o.Text = cputil.I18n(c.ctx, apistructs.MoveToOperation.String()) + v.StateName - o.Reload = true - o.Meta = OpMetaInfo{IssueID: c.ID, StateID: v.StateID} - c.Operations[apistructs.MoveToOperation.String()+v.StateName] = o - } -} - -func (c *IssueCart) RenderMoveToCustomOperation(mp map[cptype.OperationKey]interface{}) { - p := mp[cptype.OperationKey(apistructs.MoveToCustomOperation)].([]apistructs.IssuePanelIssues) - for _, v := range p { - o := MoveToCustomOperation{} - o.Disabled = false - o.Text = cputil.I18n(c.ctx, apistructs.MoveToCustomOperation.String()) + v.PanelName - o.Reload = true - o.Meta = OpMetaInfo{ - IssueID: c.ID, - IssuePanel: v.IssuePanel, - } - c.Operations[apistructs.MoveToCustomOperation.String()+v.PanelName] = o - } -} - -func (c *IssueCart) RenderDragToCustomOperation(mp map[cptype.OperationKey]interface{}) { - targetKeys := make(map[int64]bool) - p := mp[cptype.OperationKey(apistructs.DragToCustomOperation)].([]apistructs.IssuePanelIssues) - for _, v := range p { - targetKeys[v.PanelID] = true - } - o := DragOperation{} - o.Reload = true - o.Meta = OpMetaInfo{ - IssueID: c.ID, - } - o.Async = true - o.TargetKeys = targetKeys - c.Operations[apistructs.DragOperation.String()] = o -} - -func (c *IssueCart) RenderMoveToAssigneeOperation(mp map[cptype.OperationKey]interface{}) { - p := mp[cptype.OperationKey(apistructs.MoveToAssigneeOperation)].([]apistructs.UserInfo) - for _, v := range p { - if v.Name == c.Assignee { - continue - } - o := MoveToAssigneeOperation{} - o.Disabled = false - o.Text = cputil.I18n(c.ctx, apistructs.MoveToAssigneeOperation.String()) + v.Nick - o.Reload = true - o.Meta = OpMetaInfo{ - IssueID: c.ID, - IssueAssignee: v.ID, - } - c.Operations[apistructs.MoveToAssigneeOperation.String()+v.Name] = o - } -} - -func (c *IssueCart) RenderDragToAssigneeOperation(mp map[cptype.OperationKey]interface{}) { - targetKeys := make(map[string]bool) - p := mp[cptype.OperationKey(apistructs.DragToAssigneeOperation)].([]apistructs.UserInfo) - for _, v := range p { - targetKeys[v.ID] = true - } - o := DragOperation{} - o.Reload = true - o.Meta = OpMetaInfo{ - IssueID: c.ID, - } - o.Async = true - o.TargetKeys = targetKeys - c.Operations[apistructs.DragOperation.String()] = o -} - -func (c *IssueCart) RenderMoveToPriorityOperation(i apistructs.Issue, mp map[cptype.OperationKey]interface{}) { - p := mp[cptype.OperationKey(apistructs.MoveToPriorityOperation)].([]apistructs.IssuePriority) - for _, v := range p { - o := MoveToPriorityOperation{} - o.Disabled = false - if v == i.Priority { - o.Disabled = true - } - o.Text = cputil.I18n(c.ctx, apistructs.MoveToPriorityOperation.String()) + v.GetZhName() - o.Reload = true - o.Meta = OpMetaInfo{ - IssueID: c.ID, - IssuePriority: v, - } - c.Operations[apistructs.MoveToPriorityOperation.String()+string(v)] = o - } -} - -func (c *IssueCart) RenderDragToPriorityOperation(i apistructs.Issue, mp map[cptype.OperationKey]interface{}) { - targetKeys := make(map[apistructs.IssuePriority]bool) - p := mp[cptype.OperationKey(apistructs.DragToPriorityOperation)].([]apistructs.IssuePriority) - for _, v := range p { - if v == i.Priority { - continue - } - targetKeys[v] = true - } - o := DragOperation{} - o.Reload = true - o.Async = true - o.Meta = OpMetaInfo{ - IssueID: c.ID, - } - o.TargetKeys = targetKeys - c.Operations[apistructs.DragOperation.String()] = o -} - -func (c *CartList) RenderChangePageNoOperation(kanbanKey string) { - if c.Operations == nil { - c.Operations = make(map[string]interface{}) - } - o := ChangePageNoOperation{ - Key: apistructs.ChangePageNoOperation.String(), - Reload: true, - FillMeta: "pageData", - Meta: struct { - KanbanKey string `json:"kanbanKey"` - }{kanbanKey}, - } - c.Operations[apistructs.ChangePageNoOperation.String()] = o -} - -func (c *IssueCart) RenderCartOperations(s ChartOperationSwitch, i apistructs.Issue, mp map[cptype.OperationKey]interface{}) { - if c.Operations == nil { - c.Operations = make(map[string]interface{}) - } - - // for task 60429. pd's roadmap, temporarily remove 'Move Out of Iteration', - // and add a button for more options later. - // if s.enableMoveOut { - // c.RenderMoveOutOperation() - // } - if s.enableMoveTo { - c.RenderMoveToOperation() - } - if s.enableDrag { - c.RenderDragOperation() - } - if s.enableMoveToCustom { - c.RenderMoveToCustomOperation(mp) - } - if s.enableDragToCustom { - c.RenderDragToCustomOperation(mp) - } - if s.enableMoveToAssignee { - c.RenderMoveToAssigneeOperation(mp) - } - if s.enableDragToAssignee { - c.RenderDragToAssigneeOperation(mp) - } - if s.enableMoveToPriority { - c.RenderMoveToPriorityOperation(i, mp) - } - if s.enableDragToPriority { - c.RenderDragToPriorityOperation(i, mp) - } -} - -func (cl *CartList) RenderCartListOperations(s ChartOperationSwitch) { - cl.Operations = make(map[string]interface{}) - // 删除看板 - if len(cl.List) == 0 && cl.LabelKey.(int64) != 0 { - o := DeleteBoardOperation{} - o.Disabled = false - o.Confirm = cputil.I18n(cl.ctx, DeleteBoardConfirmMsg) - o.Text = cputil.I18n(cl.ctx, apistructs.DeleteCustomOperation.String()) - o.Reload = true - o.Meta = OpMetaInfo{IssuePanel: apistructs.IssuePanel{PanelID: cl.LabelKey.(int64)}} - cl.Operations[apistructs.DeleteCustomOperation.String()] = o - } - // 更新看板 - if cl.LabelKey.(int64) != 0 { - o := UpdateBoardOperation{} - o.Disabled = false - o.Confirm = cputil.I18n(cl.ctx, UpdateBoardConfirmMsg) - o.Text = cputil.I18n(cl.ctx, apistructs.UpdateCustomOperation.String()) - o.Reload = true - o.Meta = OpMetaInfo{IssuePanel: apistructs.IssuePanel{PanelID: cl.LabelKey.(int64)}} - cl.Operations[apistructs.UpdateCustomOperation.String()] = o - } - if s.enableChangePageNo { - cl.RenderChangePageNoOperation(strconv.FormatInt(cl.LabelKey.(int64), 10)) - } -} - -// 根据完成时间(planFinishedAt)分为:未分类,已过期,1天内过期,2天内,3天内,30天,未来 -type ExpireType string - -func (e ExpireType) String() string { - return string(e) -} - -const ( - ExpireTypeUndefined ExpireType = "Undefined" - ExpireTypeExpired ExpireType = "Expired" - ExpireTypeExpireIn1Day ExpireType = "ExpireIn1Day" - ExpireTypeExpireIn2Days ExpireType = "ExpireIn2Days" - ExpireTypeExpireIn7Days ExpireType = "ExpireIn7Days" - ExpireTypeExpireIn30Days ExpireType = "ExpireIn30Days" - ExpireTypeExpireInFuture ExpireType = "ExpireInFuture" -) - -var ExpireTypes = []ExpireType{ExpireTypeUndefined, ExpireTypeExpired, ExpireTypeExpireIn1Day, ExpireTypeExpireIn2Days, ExpireTypeExpireIn7Days, ExpireTypeExpireIn30Days, ExpireTypeExpireInFuture} - -// FinishTime和now都是date;hour, min, sec 都为0 -func (c IssueCart) GetExpireType(now time.Time) ExpireType { - if c.PlanFinishedAt == nil { - return ExpireTypeUndefined - } - finishTime := *c.PlanFinishedAt - if finishTime.Before(now) { - return ExpireTypeExpired - } else if finishTime.Before(now.Add(1 * 24 * time.Hour)) { - return ExpireTypeExpireIn1Day - } else if finishTime.Before(now.Add(2 * 24 * time.Hour)) { - return ExpireTypeExpireIn2Days - } else if finishTime.Before(now.Add(7 * 24 * time.Hour)) { - return ExpireTypeExpireIn7Days - } else if finishTime.Before(now.Add(30 * 24 * time.Hour)) { - return ExpireTypeExpireIn30Days - } else { - return ExpireTypeExpireInFuture - } -} - -type ChartOperationSwitch struct { - // 所有迭代时,disable move out - enableMoveOut bool - // disable drag - enableDrag bool - // 按状态分类 - enableMoveTo bool - - // 按处理人分类 - enableMoveToAssignee bool - enableDragToAssignee bool - // 按自定义看板分类 - enableMoveToCustom bool - enableDragToCustom bool - // 按优先级分类 - enableMoveToPriority bool - enableDragToPriority bool - - enableChangePageNo bool -} - -func (c *ChartOperationSwitch) ClearAble() { - c.enableMoveOut = false - c.enableDrag = false - c.enableMoveTo = false - c.enableMoveToAssignee = false - c.enableDragToAssignee = false - c.enableMoveToCustom = false - c.enableDragToCustom = false - c.enableMoveToPriority = false - c.enableDragToPriority = false - c.enableChangePageNo = false -} - -type ComponentIssueBoard struct { - sdk *cptype.SDK - bdl *bundle.Bundle - - issueSvc *issue_svc.Issue - issueStateSvc *issuestate.IssueState - - boardType BoardType - swt ChartOperationSwitch - - CompName string `json:"name"` - Data IssueBoard `json:"data"` - Operations map[string]interface{} `json:"operations"` - State IssueBoardState `json:"state"` - - base.DefaultProvider -} - -type IssueBoardState struct { - DropTarget interface{} `json:"dropTarget"` - apistructs.IssuePanel - Priority apistructs.IssuePriority `json:"priority"` - FilterConditions apistructs.IssuePagingRequest `json:"filterConditions"` - IssueViewGroupChildrenValue map[string]string `json:"issueViewGroupChildrenValue"` - IssueViewGroupValue string `json:"issueViewGroupValue"` -} - -type IssueFilterRequest struct { - apistructs.IssuePagingRequest - BoardType BoardType `json:"boardType"` - KanbanKey string `json:"kanbanKey"` -} - -type issueRenderInparams struct { - ProjectID string `json:"projectID"` - BoardType BoardType `json:"boardType"` - FixedIssueType apistructs.IssueType `json:"fixedIssueType"` - FixedIssueIteration string `json:"fixedIssueIteration"` -} -type BoardType string - -func (b BoardType) String() string { - return string(b) -} - -const ( - BoardTypeStatus BoardType = "status" - BoardTypeTime BoardType = "deadline" - BoardTypeAssignee BoardType = "assignee" // 已经移除处理人看板 - BoardTypeCustom BoardType = "custom" - BoardTypePriority BoardType = "priority" -) - -var SupportBoardTypes = []BoardType{BoardTypeStatus, BoardTypeTime, BoardTypeAssignee, BoardTypeCustom} - -var IssueTypes = []apistructs.IssueType{apistructs.IssueTypeTask, apistructs.IssueTypeRequirement, apistructs.IssueTypeBug, apistructs.IssueTypeEpic} - -var IssueTypeStates = map[apistructs.IssueType][]apistructs.IssueState{ - apistructs.IssueTypeTask: {apistructs.IssueStateOpen, apistructs.IssueStateWorking, apistructs.IssueStateDone}, - apistructs.IssueTypeRequirement: {apistructs.IssueStateOpen, apistructs.IssueStateWorking, apistructs.IssueStateDone}, - apistructs.IssueTypeBug: {apistructs.IssueStateOpen, apistructs.IssueStateWontfix, apistructs.IssueStateReopen, apistructs.IssueStateResolved, apistructs.IssueStateClosed}, -} - -func uniq(in []string) []string { - var out []string - s := set.New() - for _, v := range in { - if !s.Has(v) { - s.Insert(v) - out = append(out, v) - } - } - return out -} - -func (i *ComponentIssueBoard) SetOperationSwitch(req *IssueFilterRequest) error { - i.swt.ClearAble() - switch i.boardType { - case BoardTypeAssignee: - i.swt.enableMoveToAssignee = true - i.swt.enableDragToAssignee = true - case BoardTypeTime: - case BoardTypeStatus: - i.swt.enableMoveTo = true - i.swt.enableDrag = true - case BoardTypePriority: - i.swt.enableMoveToPriority = true - i.swt.enableDragToPriority = true - case BoardTypeCustom: - i.swt.enableMoveToCustom = true - i.swt.enableDragToCustom = true - default: - return nil - } - // 全部看板都可以移出迭代 - i.swt.enableMoveOut = true - i.swt.enableChangePageNo = true - return nil -} - -func (i *ComponentIssueBoard) SetBoardDate(c cptype.Component) error { - var board []CartList - cont, err := json.Marshal(c.Data["board"].([]CartList)) - if err != nil { - logrus.Errorf("marshal component data failed, content:%v, err:%v", c.State, err) - return err - } - err = json.Unmarshal(cont, &board) - if err != nil { - logrus.Errorf("unmarshal component dat failed, content:%v, err:%v", cont, err) - return err - } - i.Data.Board = board - return nil -} - -func (i *ComponentIssueBoard) SetBoardType(bt BoardType) { - i.boardType = bt -} - -// GetUserPermission check Guest permission -func (i *ComponentIssueBoard) CheckUserPermission(projectID uint64) error { - isGuest := false - scopeRole, err := i.bdl.ScopeRoleAccess(i.sdk.Identity.UserID, &apistructs.ScopeRoleAccessRequest{ - Scope: apistructs.Scope{ - Type: apistructs.ProjectScope, - ID: strconv.FormatUint(projectID, 10), - }, - }) - if err != nil { - return err - } - for _, role := range scopeRole.Roles { - if role == "Guest" { - isGuest = true - } - } - if !isGuest { - return nil - } - // if the permission of user is guest , could't to do operation - for k, v := range i.Operations { - i.Operations[k] = i.disableOperationPermission(v) - } - for ib, board := range i.Data.Board { - for k, v := range board.Operations { - i.Data.Board[ib].Operations[k] = i.disableOperationPermission(v) - } - for ic, ca := range board.List { - for k, v := range ca.Operations { - i.Data.Board[ib].List[ic].Operations[k] = i.disableOperationPermission(v) - } - } - } - return nil -} - -func (i *ComponentIssueBoard) disableOperationPermission(op interface{}) interface{} { - switch op.(type) { - case MoveOutOperation: - o := op.(MoveOutOperation) - o.Disabled = true - return o - case DragOperation: - o := op.(DragOperation) - o.Disabled = true - return o - case MoveToOperation: - o := op.(MoveToOperation) - o.Disabled = true - return o - case MoveToPriorityOperation: - o := op.(MoveToPriorityOperation) - o.Disabled = true - return o - case CreateBoardOperation: - o := op.(CreateBoardOperation) - o.Disabled = true - o.DisabledTip = i.sdk.I18n(GuestCreateBoardDisabledTip) - return o - case DeleteBoardOperation: - o := op.(DeleteBoardOperation) - o.Disabled = true - return o - case UpdateBoardOperation: - o := op.(UpdateBoardOperation) - o.Disabled = true - return o - case MoveToCustomOperation: - o := op.(MoveToCustomOperation) - o.Disabled = true - return o - default: - panic("errors: invalid operationInfo type") - } - return nil -} - -func (i *ComponentIssueBoard) Filter(ctx context.Context, req IssueFilterRequest) (ib *IssueBoard, err error) { - // statuses - stateByIssueType, err := i.issueStateSvc.GetIssueStatesMap(&apistructs.IssueStatesGetRequest{ProjectID: req.ProjectID}) - if err != nil { - return nil, err - } - stateByStateID := make(map[int64]apistructs.IssueStatus) - for _, statuses := range stateByIssueType { - for _, status := range statuses { - stateByStateID[status.StateID] = status - } - } - - var ( - cls []CartList - board IssueBoard - uids []string - ) - i.Operations = make(map[string]interface{}) - // 事件分类: 所有,需求,任务,缺陷 - switch req.BoardType { - // 所有,不含此分类 - case BoardTypeStatus: - cls, uids, err = i.FilterByStatusConcurrent(ctx, req.IssuePagingRequest, req.KanbanKey, stateByStateID) - case BoardTypeTime: - cls, uids, err = i.FilterByTime(ctx, req.IssuePagingRequest, req.KanbanKey, stateByStateID) - case BoardTypePriority: - cls, uids, err = i.FilterByPriority(ctx, req.IssuePagingRequest, req.KanbanKey, stateByStateID) - // 所有,不含此分类 - case BoardTypeCustom: - cls, uids, err = i.FilterByCustom(ctx, req.IssuePagingRequest, req.KanbanKey, stateByStateID) - // Created custom board max num 15 - o := CreateBoardOperation{} - o.Disabled = false - o.Confirm = i.sdk.I18n(CreateBoardConfirmMsg) - o.Text = i.sdk.I18n(apistructs.CreateCustomOperation.String()) - o.Reload = true - o.DisabledTip = i.sdk.I18n(CreateBoardDisabledTip) - if len(cls) > MaxBoardNum { - o.Disabled = true - } - i.Operations[apistructs.CreateCustomOperation.String()] = o - default: - //err = fmt.Errorf("invalid board type [%s], must in [%v]", req.BoardType, SupportBoardTypes) - cls, uids, err = i.FilterByPriority(ctx, req.IssuePagingRequest, req.KanbanKey, stateByStateID) - } - if err != nil { - return - } - // 时间分类i18n - for k, v := range cls { - cls[k].Label = i.sdk.I18n(v.Label.(string)) - } - if req.KanbanKey != "" { - board.RefreshBoard = false - } else { - board.RefreshBoard = true - } - board.Board = cls - board.UserIDs = uniq(uids) - ib = &board - return -} - -func (i ComponentIssueBoard) GetByStatus(req apistructs.IssuePagingRequest, ignoreDone bool) (rsp *apistructs.IssuePagingResponse, err error) { - if len(req.Type) == 0 || len(req.Type) != 1 { - err = fmt.Errorf("issue type number is not 1, type: %v", req.Type) - return - } - if req.PageSize == 0 { - req.PageSize = 200 - } - // 获取当前项目,特定IssueType的IssueStates - //it := req.Type[0] - //isReq := apistructs.IssueStateRelationGetRequest{ProjectID: int64(req.ProjectID), IssueType: it} - //is, err := i.bdl.GetIssueStateBelong(isReq) - //if err != nil { - // logrus.Errorf("get issue state belong failed, request:%+v, err:%v", isReq, err) - // return - //} - - //var states []apistructs.IssueStateName - //var issueStates []int64 - //for _, v := range is { - // if ignoreDone && (v.StateBelong == apistructs.IssueStateBelongClosed || v.StateBelong == apistructs.IssueStateBelongDone) { - // continue - // } - // states = append(states, v.States...) - //} - - //for _, v := range states { - // issueStates = append(issueStates, v.ID) - //} - //if ignoreDone { - // req.State = issueStates - //} - - rsp, err = i.bdl.PageIssues(req) - if err != nil { - logrus.Errorf("page issues failed, request:%+v, err:%v", req, err) - return - } - return -} - -func (i ComponentIssueBoard) GetIssues(req apistructs.IssuePagingRequest, ignoreDone bool) (result []apistructs.Issue, uids []string, err error) { - if req.Type == nil { - req.Type = IssueTypes - } - var wg sync.WaitGroup - - wg.Add(len(req.Type)) - for _, v := range req.Type { - v := v - go func() { - defer func() { - wg.Done() - }() - if err != nil { - return - } - r := req - r.Type = []apistructs.IssueType{v} - rsp, err := i.GetByStatus(r, ignoreDone) - if err != nil { - return - } - result = append(result, rsp.Data.List...) - uids = append(uids, rsp.UserIDs...) - }() - } - wg.Wait() - return -} - -func GenCart(bt BoardType, i apistructs.Issue, ctx context.Context, s ChartOperationSwitch, mp map[cptype.OperationKey]interface{}, stateByStateID map[int64]apistructs.IssueStatus) IssueCart { - var c IssueCart - c.ID = i.ID - c.Title = i.Title - c.Type = i.Type - c.IssueButton = i.IssueButton - c.IterationID = i.IterationID - c.Assignee = i.Assignee - c.Priority = i.Priority - c.PlanFinishedAt = i.PlanFinishedAt - c.Status = func() (cardStatus CardStatus) { - if len(stateByStateID) == 0 { - return - } - status, ok := stateByStateID[i.State] - if !ok { - return - } - return CardStatus{ - Text: status.StateName, - Status: common.GetUIIssueState(status.StateBelong), - } - }() - c.Labels = func() *CardLabels { - var labels []CardLabel - for _, label := range i.LabelDetails { - labels = append(labels, CardLabel{ - Label: label.Name, - Color: label.Color, - }) - } - if len(labels) == 0 { - return nil - } - return &CardLabels{Value: labels} - }() - c.SetCtx(ctx) - c.RenderCartOperations(s, i, mp) - return c -} - -func (c *CartList) GenCartList(ctx context.Context, s ChartOperationSwitch) { - c.SetCtx(ctx) - c.RenderCartListOperations(s) -} - -// 按状态过滤 并发 -func (i ComponentIssueBoard) FilterByStatusConcurrent(ctx context.Context, req apistructs.IssuePagingRequest, kanbanKey string, stateByStateID map[int64]apistructs.IssueStatus) (cls []CartList, uids []string, err error) { - if len(req.Type) == 0 || len(req.Type) != 1 { - err = fmt.Errorf("issue type number is not 1, type: %v", req.Type) - return - } - // 获取当前项目,特定IssueType的IssueStates - it := req.Type[0] - isReq := apistructs.IssueStateRelationGetRequest{ProjectID: req.ProjectID, IssueType: it} - is, err := i.bdl.GetIssueStateBelong(isReq) - if err != nil { - logrus.Errorf("get issue state belong failed, request:%+v, err:%v", isReq, err) - return - } - - var states []apistructs.IssueStateName - if kanbanKey == "" { - for _, v := range is { - states = append(states, v.States...) - } - } else { - for _, v := range is { - for _, v2 := range v.States { - if strconv.FormatInt(v2.ID, 10) == kanbanKey { - states = append(states, v2) - goto loop - } - } - } - } -loop: - // filter by status is not avialble in status board - if len(req.StateBelongs) > 0 { - req.StateBelongs = nil - } - - date := struct { - Map map[int64]CartList - Lock sync.Mutex - }{ - Map: make(map[int64]CartList), - } - - var wg sync.WaitGroup - wg.Add(len(states)) - for _, v := range states { - go func(state apistructs.IssueStateName) { - defer func() { - wg.Done() - }() - if err != nil { - return - } - - r := req - // 按特定种类IssueType的一个IssueState并发查询 - r.State = []int64{state.ID} - rsp, e := i.bdl.PageIssues(r) - if e != nil { - err = e - logrus.Errorf("page issues failed, request:%+v, err:%v", r, e) - return - } - // 生成CartList - cl := CartList{} - cl.Label = state.Name - cl.LabelKey = state.ID - cl.Total = rsp.Data.Total - cl.PageNo = req.PageNo - cl.PageSize = req.PageSize - if i.swt.enableChangePageNo { - cl.RenderChangePageNoOperation(strconv.FormatInt(cl.LabelKey.(int64), 10)) - } - for _, v := range rsp.Data.List { - c := GenCart(i.boardType, v, ctx, i.swt, nil, stateByStateID) - cl.Add(c) - } - - date.Lock.Lock() - date.Map[state.ID] = cl - date.Lock.Unlock() - // uid - uids = append(uids, rsp.UserIDs...) - }(v) - } - wg.Wait() - - for _, v := range states { - cls = append(cls, date.Map[v.ID]) - } - return -} - -// FilterByPriority 按优先级过滤 去掉终态状态 [CLOSED, DONE] -func (i ComponentIssueBoard) FilterByPriority(ctx context.Context, req apistructs.IssuePagingRequest, kanbanKey string, stateByStateID map[int64]apistructs.IssueStatus) (cls []CartList, uids []string, err error) { - // 用于生成权限 - var priorityList []apistructs.IssuePriority - if kanbanKey != "" { - priorityList = append(priorityList, apistructs.IssuePriority(kanbanKey)) - } else { - priorityList = apistructs.IssuePriorityList - } - mp := make(map[cptype.OperationKey]interface{}) - mp[cptype.OperationKey(apistructs.MoveToPriorityOperation)] = priorityList - mp[cptype.OperationKey(apistructs.DragToPriorityOperation)] = priorityList - - date := struct { - Map map[apistructs.IssuePriority]CartList - Lock sync.Mutex - }{ - Map: make(map[apistructs.IssuePriority]CartList), - } - - var wg sync.WaitGroup - wg.Add(len(priorityList)) - for _, v := range priorityList { - go func(state apistructs.IssuePriority) { - defer func() { - wg.Done() - }() - if err != nil { - return - } - - r := req - // 按特定种类IssueType的一个IssueState并发查询 - r.Priority = []apistructs.IssuePriority{state} - rsp, e := i.bdl.PageIssues(r) - if e != nil { - err = e - logrus.Errorf("page issues failed, request:%+v, err:%v", r, e) - return - } - // 生成CartList - cl := CartList{} - cl.Label = string(state) - cl.LabelKey = cl.Label - cl.Total = rsp.Data.Total - cl.PageNo = req.PageNo - cl.PageSize = req.PageSize - if i.swt.enableChangePageNo { - cl.RenderChangePageNoOperation(cl.LabelKey.(string)) - } - for _, v := range rsp.Data.List { - c := GenCart(i.boardType, v, ctx, i.swt, mp, stateByStateID) - cl.Add(c) - } - date.Lock.Lock() - date.Map[state] = cl - date.Lock.Unlock() - // uid - uids = append(uids, rsp.UserIDs...) - }(v) - } - wg.Wait() - for _, v := range priorityList { - cls = append(cls, date.Map[v]) - } - - return -} - -// FilterByTime 根据完成时间(planFinishedAt)分为:未分类,已过期,1天内过期,2天内,7天内,30天,未来 -func (i ComponentIssueBoard) FilterByTime(ctx context.Context, req apistructs.IssuePagingRequest, kanbanKey string, stateByStateID map[int64]apistructs.IssueStatus) (cls []CartList, uids []string, err error) { - // 为减少事件数量,不需要展示终态的事项[CLOSED, DONE] - timeMap := getTimeMap() - // map并发写需要加锁 - date := struct { - Map map[ExpireType]CartList - Lock sync.Mutex - }{ - Map: make(map[ExpireType]CartList), - } - - var expireTypes []ExpireType - if kanbanKey != "" { - expireTypes = append(expireTypes, ExpireType(kanbanKey)) - } else { - expireTypes = ExpireTypes - } - - var wg sync.WaitGroup - wg.Add(len(expireTypes)) - - // 按特定PlanFinishedAt的一个并发查询、 - for _, et := range expireTypes { - go func(tm ExpireType) { - defer func() { - wg.Done() - }() - if err != nil { - return - } - - r := req - if tm == ExpireTypeUndefined { - r.IsEmptyPlanFinishedAt = true - } else { - r.StartFinishedAt = timeMap[tm][0] * 1000 - if req.StartFinishedAt != 0 && r.StartFinishedAt < req.StartFinishedAt { - r.StartFinishedAt = req.StartFinishedAt - } - r.EndFinishedAt = timeMap[tm][1] * 1000 - if req.EndFinishedAt != 0 && (r.EndFinishedAt > req.EndFinishedAt || tm == ExpireTypeExpireInFuture) { - r.EndFinishedAt = req.EndFinishedAt - } - } - rsp, e := i.bdl.PageIssues(r) - if e != nil { - err = e - logrus.Errorf("page issues failed, request:%+v, err:%v", r, e) - return - } - // 生成CartList - cl := CartList{} - cl.Label = string(tm) - cl.LabelKey = cl.Label - cl.Total = rsp.Data.Total - cl.PageNo = req.PageNo - cl.PageSize = req.PageSize - if i.swt.enableChangePageNo { - cl.RenderChangePageNoOperation(cl.LabelKey.(string)) - } - for _, v := range rsp.Data.List { - c := GenCart(i.boardType, v, ctx, i.swt, nil, stateByStateID) - cl.Add(c) - } - date.Lock.Lock() - date.Map[tm] = cl - date.Lock.Unlock() - // uid - uids = append(uids, rsp.UserIDs...) - }(et) - } - wg.Wait() - for _, v := range expireTypes { - cls = append(cls, date.Map[v]) - } - return -} - -// getTimeMap return timeMap,key: ExpireType,value: struct of startTime and endTime -func getTimeMap() map[ExpireType][]int64 { - nowTime := time.Date(time.Now().Year(), time.Now().Month(), time.Now().Day(), 0, 0, 0, 0, time.Now().Location()) - tomorrow := nowTime.Add(time.Hour * time.Duration(24)) - twoDay := nowTime.Add(time.Hour * time.Duration(24*2)) - sevenDay := nowTime.Add(time.Hour * time.Duration(24*7)) - thirtyDay := nowTime.Add(time.Hour * time.Duration(24*30)) - timeMap := map[ExpireType][]int64{ - ExpireTypeUndefined: {0, 0}, - ExpireTypeExpired: {1, nowTime.Add(time.Second * time.Duration(-1)).Unix()}, - ExpireTypeExpireIn1Day: {nowTime.Unix(), tomorrow.Add(time.Second * time.Duration(-1)).Unix()}, - ExpireTypeExpireIn2Days: {tomorrow.Unix(), twoDay.Add(time.Second * time.Duration(-1)).Unix()}, // 明天 - ExpireTypeExpireIn7Days: {twoDay.Unix(), sevenDay.Add(time.Second * time.Duration(-1)).Unix()}, // 7天 - ExpireTypeExpireIn30Days: {sevenDay.Unix(), thirtyDay.Add(time.Second * time.Duration(-1)).Unix()}, // 30天 - ExpireTypeExpireInFuture: {thirtyDay.Unix(), 0}, // 未来 - } - return timeMap -} - -// 按自定义看板 过滤 -func (i ComponentIssueBoard) FilterByCustom(ctx context.Context, req apistructs.IssuePagingRequest, kanbanKey string, stateByStateID map[int64]apistructs.IssueStatus) (cls []CartList, uids []string, err error) { - rsp, err := i.bdl.GetIssuePanel(apistructs.IssuePanelRequest{IssuePagingRequest: req}) - if err != nil { - return - } - var rspList []apistructs.IssuePanelIssues - if kanbanKey == "" { - rspList = rsp - } else { - for _, v := range rsp { - if strconv.FormatInt(v.PanelID, 10) == kanbanKey { - rspList = append(rspList, v) - break - } - } - } - - mp := make(map[cptype.OperationKey]interface{}) - mp[cptype.OperationKey(apistructs.MoveToCustomOperation)] = rspList - mp[cptype.OperationKey(apistructs.DragToCustomOperation)] = rspList - - date := struct { - Map map[apistructs.IssuePanelIssues]CartList - Lock sync.Mutex - }{ - Map: make(map[apistructs.IssuePanelIssues]CartList), - } - - var wg sync.WaitGroup - wg.Add(len(rspList)) - for _, pl := range rspList { - go func(panel apistructs.IssuePanelIssues) { - defer func() { - wg.Done() - }() - rsp, e := i.bdl.GetIssuePanelIssue(apistructs.IssuePanelRequest{ - IssuePanel: apistructs.IssuePanel{PanelID: panel.PanelID}, - IssuePagingRequest: req, - }) - if e != nil { - err = e - return - } - cl := CartList{} - cl.Label = panel.PanelName - cl.LabelKey = panel.PanelID - cl.Total = rsp.Total - cl.PageNo = req.PageNo - cl.PageSize = req.PageSize - if rsp.Total > 0 { - for _, v := range rsp.Issues { - c := GenCart(i.boardType, v, ctx, i.swt, mp, stateByStateID) - // 不能转移到自己 - cMove := c.Operations[apistructs.MoveToCustomOperation.String()+panel.PanelName].(MoveToCustomOperation) - cMove.Disabled = true - c.Operations[apistructs.MoveToCustomOperation.String()+panel.PanelName] = cMove - cDrag := c.Operations[apistructs.DragOperation.String()].(DragOperation) - tagget := cDrag.TargetKeys.(map[int64]bool) - tagget[panel.PanelID] = false - cDrag.TargetKeys = tagget - c.Operations[apistructs.DragOperation.String()] = cDrag - cl.Add(c) - uids = append(uids, v.Assignee) - } - } - - cl.GenCartList(ctx, i.swt) - date.Lock.Lock() - date.Map[panel] = cl - date.Lock.Unlock() - }(pl) - } - wg.Wait() - for _, v := range rspList { - cls = append(cls, date.Map[v]) - } - uids = strutil.DedupSlice(uids) - return -} - -func init() { - base.InitProviderWithCreator("issue-manage", "issueKanban", func() servicehub.Provider { - return &ComponentIssueBoard{} - }) -} diff --git a/modules/dop/component-protocol/components/issue-manage/issueKanban/render.go b/modules/dop/component-protocol/components/issue-manage/issueKanban/render.go deleted file mode 100644 index 754a38288d8..00000000000 --- a/modules/dop/component-protocol/components/issue-manage/issueKanban/render.go +++ /dev/null @@ -1,646 +0,0 @@ -// 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 issueKanban - -import ( - "context" - "encoding/json" - "fmt" - "strconv" - "strings" - - "github.com/sirupsen/logrus" - - "github.com/erda-project/erda-infra/providers/component-protocol/cptype" - "github.com/erda-project/erda-infra/providers/component-protocol/utils/cputil" - "github.com/erda-project/erda/apistructs" - "github.com/erda-project/erda/bundle" - "github.com/erda-project/erda/modules/dop/component-protocol/types" - issue_svc "github.com/erda-project/erda/modules/dop/services/issue" - "github.com/erda-project/erda/modules/dop/services/issuestate" - protocol "github.com/erda-project/erda/modules/openapi/component-protocol" -) - -const defaultPageSize = 50 - -type ChangePageNoOperationData struct { - FillMeta string `json:"fill_meta"` - Meta struct { - PageData struct { - PageNo uint64 `json:"pageNo"` - PageSize uint64 `json:"pageSize"` - } `json:"pageData"` - KanbanKey interface{} `json:"kanbanKey"` - } `json:"meta"` -} - -func GetCartOpsInfo(opsData interface{}, isDrag bool) (*OpMetaInfo, error) { - if opsData == nil { - err := fmt.Errorf("empty operation data") - return nil, err - } - var op OperationInfo - var dragOp DragOperationInfo - cont, err := json.Marshal(opsData) - if err != nil { - logrus.Errorf("marshal inParams failed, content:%v, err:%v", opsData, err) - return nil, err - } - if !isDrag { - err = json.Unmarshal(cont, &op) - } else { - err = json.Unmarshal(cont, &dragOp) - } - if err != nil { - logrus.Errorf("unmarshal move out request failed, content:%v, err:%v", cont, err) - return nil, err - } - if !isDrag { - meta := op.Meta - return &meta, nil - } - meta := dragOp.Meta - return &meta, nil -} - -func (i ComponentIssueBoard) GetFilterReq() (*IssueFilterRequest, error) { - var inParams issueRenderInparams - var req IssueFilterRequest - cont, err := json.Marshal(i.sdk.InParams) - if err != nil { - logrus.Errorf("marshal inParams failed, content:%v, err:%v", i.sdk.InParams, err) - return nil, err - } - err = json.Unmarshal(cont, &inParams) - if err != nil { - logrus.Errorf("unmarshal move out request failed, content:%v, err:%v", cont, err) - return nil, err - } - if i.sdk.Identity.UserID != "" { - req.UserID = i.sdk.Identity.UserID - } - req.IssuePagingRequest = i.State.FilterConditions - _, ok := i.State.IssueViewGroupChildrenValue["kanban"] - if ok { - value := i.State.IssueViewGroupChildrenValue["kanban"] - req.BoardType = BoardType(value) - } else { - req.BoardType = BoardTypeTime - } - req.PageSize = defaultPageSize - req.PageNo = 1 - req.OrderBy = "updated_at" - req.Asc = false - return &req, nil -} - -func (i ComponentIssueBoard) GetDefaultFilterReq(req *IssueFilterRequest) error { - var inParams issueRenderInparams - cont, err := json.Marshal(i.sdk.InParams) - if err != nil { - logrus.Errorf("marshal inParams failed, content:%v, err:%v", i.sdk.InParams, err) - return err - } - err = json.Unmarshal(cont, &inParams) - if err != nil { - logrus.Errorf("unmarshal move out request failed, content:%v, err:%v", cont, err) - return err - } - req.IterationID, err = strconv.ParseInt(inParams.FixedIssueIteration, 10, 64) - if inParams.FixedIssueType == "ALL" { - req.Type = []apistructs.IssueType{apistructs.IssueTypeRequirement, apistructs.IssueTypeTask, apistructs.IssueTypeBug, apistructs.IssueTypeEpic} - } else { - req.Type = append(req.Type, inParams.FixedIssueType) - } - if i.State.FilterConditions.IterationID != 0 { - req.IterationID = i.State.FilterConditions.IterationID - } - if i.State.FilterConditions.Type != nil && len(i.State.FilterConditions.Type) != 0 { - req.Type = i.State.FilterConditions.Type - } - return nil -} - -func (i *ComponentIssueBoard) GenComponentState(c *cptype.Component) error { - if c == nil || c.State == nil { - return nil - } - var state IssueBoardState - cont, err := json.Marshal(c.State) - if err != nil { - logrus.Errorf("marshal component state failed, content:%v, err:%v", c.State, err) - return err - } - err = json.Unmarshal(cont, &state) - if err != nil { - logrus.Errorf("unmarshal component state failed, content:%v, err:%v", cont, err) - return err - } - i.State = state - return nil -} - -// Issue过滤,分类 -func (i *ComponentIssueBoard) RenderOnFilter(ctx context.Context, req IssueFilterRequest) error { - ib, err := i.Filter(ctx, req) - if err != nil { - logrus.Errorf("issue filter failed, request:%+v, err:%v", req, err) - return err - } - i.Data = *ib - return nil -} - -func (i *ComponentIssueBoard) RenderOnMoveOut(opsData interface{}) error { - req, err := GetCartOpsInfo(opsData, false) - if err != nil { - logrus.Errorf("get ops data failed, state:%v, err:%v", opsData, err) - return err - } - - // get - is, err := i.bdl.GetIssue(uint64(req.IssueID)) - if err != nil { - logrus.Errorf("get issue failed, req:%v, err:%v", req, err) - return err - } - // update - is.IterationID = -1 - if err = i.bdl.UpdateIssueTicketUser(i.sdk.Identity.UserID, is.ConvertToIssueUpdateReq(), uint64(is.ID)); err != nil { - return err - } - - // refresh - //err = i.RefreshOnMoveOut(is.ID) - //if err != nil { - // logrus.Errorf("refresh on move out failed, issueID:%d", req.IssueID) - //} - return nil -} - -func (i *ComponentIssueBoard) RefreshOnMoveOut(issueID int64) error { - for k, v := range i.Data.Board { - for _, is := range v.List { - if is.ID == issueID { - i.Data.Board[k].Delete(issueID) - i.Data.Board[k].Total = i.Data.Board[k].Total - 1 - break - } - } - } - return nil -} - -func (i *ComponentIssueBoard) RenderOnDrag(opsData interface{}) error { - req, err := GetCartOpsInfo(opsData, true) - if err != nil { - logrus.Errorf("get ops data failed, state:%v, err:%v", opsData, err) - return err - } - - is, err := i.bdl.GetIssue(uint64(req.IssueID)) - if err != nil { - logrus.Errorf("get issue failed, req:%v, err:%v", req, err) - return err - } - - switch i.boardType { - case BoardTypeStatus: - currentState := is.State - is.State = int64(i.State.DropTarget.(float64)) - if currentState == is.State { - return nil - } - err = i.bdl.UpdateIssueTicketUser(i.sdk.Identity.UserID, is.ConvertToIssueUpdateReq(), uint64(is.ID)) - //err:=i.RefreshOnMoveTo(is.ID,currentState,is.State) - //if err!=nil{ - // return err - //} - case BoardTypeAssignee: - currentAssignee := is.Assignee - is.Assignee = i.State.DropTarget.(string) - if currentAssignee == is.Assignee { - return nil - } - err = i.bdl.UpdateIssueTicketUser(i.sdk.Identity.UserID, is.ConvertToIssueUpdateReq(), uint64(is.ID)) - case BoardTypePriority: - currentPriority := is.Priority - is.Priority = apistructs.IssuePriority(i.State.DropTarget.(string)) - if is.Priority == currentPriority { - return nil - } - err = i.bdl.UpdateIssueTicketUser(i.sdk.Identity.UserID, is.ConvertToIssueUpdateReq(), uint64(is.ID)) - case BoardTypeTime: - logrus.Infof("drag ignore board type: time") - case BoardTypeCustom: - err = i.bdl.UpdateIssuePanelIssue(i.sdk.Identity.UserID, int64(i.State.DropTarget.(float64)), is.ID, int64(i.State.FilterConditions.ProjectID)) - default: - err := fmt.Errorf("invalid board type, only support: [%v]", SupportBoardTypes) - logrus.Errorf(err.Error()) - return err - } - if err != nil { - logrus.Errorf("update issue failed, req:%v, err:%v", req, err) - return err - } - return nil -} - -func (i *ComponentIssueBoard) RenderOnMoveTo(opsData interface{}) error { - req, err := GetCartOpsInfo(opsData, false) - if err != nil { - logrus.Errorf("get ops data failed, state:%v, err:%v", opsData, err) - return err - } - - is, err := i.bdl.GetIssue(uint64(req.IssueID)) - if err != nil { - logrus.Errorf("get issue failed, req:%v, err:%v", req, err) - return err - } - //from := is.State - //to := req.StateID - is.State = req.StateID - err = i.bdl.UpdateIssueTicketUser(i.sdk.Identity.UserID, is.ConvertToIssueUpdateReq(), uint64(is.ID)) - if err != nil { - logrus.Errorf("update issue failed, req:%v, err:%v", req, err) - return err - } - //err = i.RefreshOnMoveTo(req.IssueID, from, to) - //if err != nil { - // logrus.Errorf("refresh on move to failed, issueID:%d, from:%d, to:%d", req.IssueID, from, to) - //} - return nil -} -func (i *ComponentIssueBoard) RenderOnMoveToAssignee(opsData interface{}) error { - req, err := GetCartOpsInfo(opsData, false) - if err != nil { - logrus.Errorf("get ops data failed, state:%v, err:%v", opsData, err) - return err - } - is, err := i.bdl.GetIssue(uint64(req.IssueID)) - if err != nil { - logrus.Errorf("get issue failed, req:%v, err:%v", req, err) - return err - } - //from := is.State - //to := req.StateID - is.Assignee = req.IssueAssignee - err = i.bdl.UpdateIssueTicketUser(i.sdk.Identity.UserID, is.ConvertToIssueUpdateReq(), uint64(is.ID)) - if err != nil { - logrus.Errorf("update issue failed, req:%v, err:%v", req, err) - return err - } - //err = i.RefreshOnMoveTo(req.IssueID, from, to) - //if err != nil { - // logrus.Errorf("refresh on move to failed, issueID:%d, from:%d, to:%d", req.IssueID, from, to) - //} - return nil -} - -func (i *ComponentIssueBoard) RenderOnMoveToPriority(opsData interface{}) error { - req, err := GetCartOpsInfo(opsData, false) - if err != nil { - logrus.Errorf("get ops data failed, state:%v, err:%v", opsData, err) - return err - } - is, err := i.bdl.GetIssue(uint64(req.IssueID)) - if err != nil { - logrus.Errorf("get issue failed, req:%v, err:%v", req, err) - return err - } - //from := is.State - //to := req.StateID - is.Priority = req.IssuePriority - err = i.bdl.UpdateIssueTicketUser(i.sdk.Identity.UserID, is.ConvertToIssueUpdateReq(), uint64(is.ID)) - if err != nil { - logrus.Errorf("update issue failed, req:%v, err:%v", req, err) - return err - } - //err = i.RefreshOnMoveTo(req.IssueID, from, to) - //if err != nil { - // logrus.Errorf("refresh on move to failed, issueID:%d, from:%d, to:%d", req.IssueID, from, to) - //} - return nil -} - -// 全量更新时间长,在改变状态时,可以直接move到另一个状态list,同时删掉当前list中的item -// func (i *ComponentIssueBoard) RefreshOnMoveTo(issueID, from, to int64) error { -// is, err := i.bdl.GetIssue(uint64(issueID)) -// if err != nil { -// logrus.Errorf("get issue failed, req:%v, err:%v", issueID, err) -// return err -// } -// c := GenCart(i.boardType, *is, i.ctxBdl.I18nPrinter, i.swt, nil) -// for k, v := range i.Data.Board { -// if v.LabelKey.(int64) == from { -// i.Data.Board[k].Delete(issueID) -// i.Data.Board[k].Total = i.Data.Board[k].Total - 1 -// } -// if v.LabelKey.(int64) == to { -// i.Data.Board[k].Add(c) -// i.Data.Board[k].Total = i.Data.Board[k].Total + 1 -// } -// } -// return nil -// } - -// TODO 增加自定义看板 -func (i *ComponentIssueBoard) RenderOnAddCustom() error { - var ipr apistructs.IssuePanelRequest - ipr.PanelName = i.State.PanelName - ipr.ProjectID = i.State.FilterConditions.ProjectID - ipr.UserID = i.sdk.Identity.UserID - _, err := i.bdl.CreateIssuePanel(ipr) - if err != nil { - logrus.Errorf("add panel failed, project:%v, err:%v", i.State.FilterConditions.ProjectID, err) - return err - } - return nil -} - -// RenderOnUpdateCustom 更新自定义看板 -func (i *ComponentIssueBoard) RenderOnUpdateCustom() error { - var req apistructs.IssuePanelRequest - req.IssuePanel = i.State.IssuePanel - req.ProjectID = i.State.FilterConditions.ProjectID - req.UserID = i.sdk.Identity.UserID - _, err := i.bdl.UpdateIssuePanel(req) - if err != nil { - logrus.Errorf("update panel failed, project:%v, err:%v", i.State.FilterConditions.ProjectID, err) - return err - } - return nil -} - -// RenderOnDeleteCustom 删除自定义看板 -func (i *ComponentIssueBoard) RenderOnDeleteCustom() error { - var req apistructs.IssuePanelRequest - req.IssuePanel = i.State.IssuePanel - req.ProjectID = i.State.FilterConditions.ProjectID - req.UserID = i.sdk.Identity.UserID - _, err := i.bdl.DeleteIssuePanel(req) - if err != nil { - logrus.Errorf("delete panel failed, project:%v, panelID:%v, err:%v", i.State.FilterConditions.ProjectID, i.State.PanelID, err) - return err - } - return nil -} - -func (i *ComponentIssueBoard) RenderOnMoveToCustom(opsData interface{}) error { - req, err := GetCartOpsInfo(opsData, false) - if err != nil { - logrus.Errorf("get ops data failed, state:%v, err:%v", opsData, err) - return err - } - is, err := i.bdl.GetIssue(uint64(req.IssueID)) - if err != nil { - logrus.Errorf("get issue failed, req:%v, err:%v", req, err) - return err - } - //from := i.State.PanelID - to := req.PanelID - err = i.bdl.UpdateIssuePanelIssue(i.sdk.Identity.UserID, to, is.ID, int64(i.State.FilterConditions.ProjectID)) - if err != nil { - logrus.Errorf("update panel issue failed, req:%v, err:%v", req, err) - return err - } - //err = i.RefreshOnMoveTo(req.IssueID, from, to) - //if err != nil { - // logrus.Errorf("refresh on move to failed, issueID:%d, from:%d, to:%d", req.IssueID, from, to) - //} - return nil -} - -func (i *ComponentIssueBoard) RenderDefault(c *cptype.Component, g *cptype.GlobalStateData) { - -} - -func (i *ComponentIssueBoard) RenderProtocol(c *cptype.Component, g *cptype.GlobalStateData) { - if c.Data == nil { - d := make(cptype.ComponentData) - c.Data = d - } - (*c).Data["board"] = i.Data.Board - (*c).Data["refreshBoard"] = i.Data.RefreshBoard - (*g)[protocol.GlobalInnerKeyUserIDs.String()] = i.Data.UserIDs -} - -func (i *ComponentIssueBoard) Render(ctx context.Context, c *cptype.Component, _ cptype.Scenario, event cptype.ComponentEvent, gs *cptype.GlobalStateData) (err error) { - err = i.GenComponentState(c) - if err != nil { - return - } - - i.sdk = cputil.SDK(ctx) - i.bdl = ctx.Value(types.GlobalCtxKeyBundle).(*bundle.Bundle) - i.issueSvc = ctx.Value(types.IssueService).(*issue_svc.Issue) - i.issueStateSvc = ctx.Value(types.IssueStateService).(*issuestate.IssueState) - - visable := cptype.ComponentProps{} - visable["visible"] = false - if i.State.IssueViewGroupValue != "kanban" { - visable["visible"] = false - c.Props = visable - return - } - visable["visible"] = true - visable["isLoadMore"] = true - c.Props = visable - - fReq, err := i.GetFilterReq() - if err != nil { - logrus.Errorf("get filter request failed, content:%+v, err:%v", *gs, err) - return - } - //err = i.SetBoardDate(*c) - //if err!=nil{ - // return - //} - - i.SetBoardType(fReq.BoardType) - err = i.SetOperationSwitch(fReq) - if err != nil { - logrus.Errorf("set operation switch failed, request:%+v, err:%v", fReq, err) - return - } - - if strings.HasPrefix(event.Operation.String(), apistructs.MoveToCustomOperation.String()) { - event.Operation = cptype.OperationKey(apistructs.MoveToCustomOperation) - } else if strings.HasPrefix(event.Operation.String(), apistructs.MoveToAssigneeOperation.String()) { - event.Operation = cptype.OperationKey(apistructs.MoveToAssigneeOperation) - } else if strings.HasPrefix(event.Operation.String(), apistructs.MoveToPriorityOperation.String()) { - event.Operation = cptype.OperationKey(apistructs.MoveToPriorityOperation) - } else if strings.HasPrefix(event.Operation.String(), apistructs.MoveToOperation.String()) { - event.Operation = cptype.OperationKey(apistructs.MoveToOperation) - } - - switch apistructs.OperationKey(event.Operation) { - case apistructs.InitializeOperation, apistructs.RenderingOperation: - err = i.GetDefaultFilterReq(fReq) - if err != nil { - return err - } - err = i.RenderOnFilter(ctx, *fReq) - if err != nil { - logrus.Errorf("render on filter failed, request:%+v, err:%v", *fReq, err) - return err - } - case apistructs.FilterOperation: - err = i.RenderOnFilter(ctx, *fReq) - if err != nil { - logrus.Errorf("render on filter failed, request:%+v, err:%v", *fReq, err) - return err - } - case apistructs.MoveOutOperation: - err = i.RenderOnMoveOut(event.OperationData) - if err != nil { - logrus.Errorf("generate action state failed, err:%v", err) - return err - } - err = i.RenderOnFilter(ctx, *fReq) - if err != nil { - logrus.Errorf("render on filter failed, request:%+v, err:%v", *fReq, err) - return err - } - case apistructs.MoveToOperation: - err = i.RenderOnMoveTo(event.OperationData) - if err != nil { - logrus.Errorf("generate action state failed, err:%v", err) - return err - } - err = i.RenderOnFilter(ctx, *fReq) - if err != nil { - logrus.Errorf("render on filter failed, request:%+v, err:%v", *fReq, err) - return err - } - case apistructs.MoveToAssigneeOperation: - err = i.RenderOnMoveToAssignee(event.OperationData) - if err != nil { - logrus.Errorf("generate action state failed, err:%v", err) - return err - } - err = i.RenderOnFilter(ctx, *fReq) - if err != nil { - logrus.Errorf("render on filter failed, request:%+v, err:%v", *fReq, err) - return err - } - case apistructs.MoveToCustomOperation: - err = i.RenderOnMoveToCustom(event.OperationData) - if err != nil { - logrus.Errorf("generate action custom failed, err:%v", err) - return err - } - err = i.RenderOnFilter(ctx, *fReq) - if err != nil { - logrus.Errorf("render on filter failed, request:%+v, err:%v", *fReq, err) - return err - } - case apistructs.MoveToPriorityOperation: - err = i.RenderOnMoveToPriority(event.OperationData) - if err != nil { - logrus.Errorf("generate action custom failed, err:%v", err) - return err - } - err = i.RenderOnFilter(ctx, *fReq) - if err != nil { - logrus.Errorf("render on filter failed, request:%+v, err:%v", *fReq, err) - return err - } - case apistructs.DragOperation: - err = i.RenderOnDrag(event.OperationData) - if err != nil { - logrus.Errorf("generate action custom failed, err:%v", err) - return err - } - err = i.RenderOnFilter(ctx, *fReq) - if err != nil { - logrus.Errorf("render on filter failed, request:%+v, err:%v", *fReq, err) - return err - } - case apistructs.CreateCustomOperation: - err = i.RenderOnAddCustom() - if err != nil { - logrus.Errorf("generate action custom failed, err:%v", err) - return err - } - err = i.RenderOnFilter(ctx, *fReq) - if err != nil { - logrus.Errorf("render on filter failed, request:%+v, err:%v", *fReq, err) - return err - } - case apistructs.UpdateCustomOperation: - // TODO - err = i.RenderOnUpdateCustom() - if err != nil { - logrus.Errorf("generate action custom failed, err:%v", err) - return err - } - err = i.RenderOnFilter(ctx, *fReq) - if err != nil { - logrus.Errorf("render on filter failed, request:%+v, err:%v", *fReq, err) - return err - } - case apistructs.DeleteCustomOperation: - err = i.RenderOnDeleteCustom() - if err != nil { - logrus.Errorf("generate action custom failed, err:%v", err) - return err - } - err = i.RenderOnFilter(ctx, *fReq) - if err != nil { - logrus.Errorf("render on filter failed, request:%+v, err:%v", *fReq, err) - return err - } - case apistructs.ChangePageNoOperation: - if err := i.setChangeNoOperationReq(fReq, event); err != nil { - logrus.Errorf("render on setChangeNoOperationReq failed, request:%+v, err:%v", *fReq, err) - return err - } - err = i.RenderOnFilter(ctx, *fReq) - if err != nil { - logrus.Errorf("render on filter failed, request:%+v, err:%v", *fReq, err) - return err - } - default: - logrus.Warnf("operation [%s] not support, use default operation instead", event.Operation) - } - if err = i.CheckUserPermission(fReq.ProjectID); err != nil { - return err - } - c.Operations = i.Operations - i.RenderProtocol(c, gs) - return -} - -// setChangeNoOperationReq set the pageNo,pageSize and kanbanKey of req and return kanbanKey -func (i *ComponentIssueBoard) setChangeNoOperationReq(req *IssueFilterRequest, event cptype.ComponentEvent) error { - dataStr, err := json.Marshal(event.OperationData) - if err != nil { - return err - } - data := ChangePageNoOperationData{} - if err = json.Unmarshal(dataStr, &data); err != nil { - return err - } - if data.Meta.PageData.PageNo != 0 && data.Meta.PageData.PageSize != 0 { - req.PageNo = data.Meta.PageData.PageNo - req.PageSize = data.Meta.PageData.PageSize - } - if data.Meta.KanbanKey != "" { - req.KanbanKey = data.Meta.KanbanKey.(string) - } - return nil -} diff --git a/modules/dop/component-protocol/components/issue-manage/issueKanban/render_test.go b/modules/dop/component-protocol/components/issue-manage/issueKanban/render_test.go deleted file mode 100644 index 276fd0761cb..00000000000 --- a/modules/dop/component-protocol/components/issue-manage/issueKanban/render_test.go +++ /dev/null @@ -1,250 +0,0 @@ -// 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 issueKanban - -import ( - "context" - "net/http" - "os" - "time" - - "github.com/erda-project/erda/apistructs" - "github.com/erda-project/erda/bundle" - protocol "github.com/erda-project/erda/modules/openapi/component-protocol" - "github.com/erda-project/erda/modules/openapi/i18n" - "github.com/erda-project/erda/pkg/http/httpclient" -) - -func rend(req *apistructs.ComponentProtocolRequest) (cont *apistructs.ComponentProtocolRequest, err error) { - // bundle - os.Setenv("CMDB_ADDR", "cmdb.default.svc.cluster.local:9093") - bundleOpts := []bundle.Option{ - bundle.WithHTTPClient( - httpclient.New( - httpclient.WithTimeout(time.Second, time.Second*60), - )), - bundle.WithCMDB(), - } - bdl := bundle.New(bundleOpts...) - - r := http.Request{} - i18nPrinter := i18n.I18nPrinter(&r) - inParams := req.InParams - identity := apistructs.Identity{UserID: "2", OrgID: "1"} - ctxBdl := protocol.ContextBundle{ - Bdl: bdl, - I18nPrinter: i18nPrinter, - InParams: inParams, - Identity: identity, - } - ctx := context.Background() - ctx1 := context.WithValue(ctx, protocol.GlobalInnerKeyCtxBundle.String(), ctxBdl) - err = protocol.RunScenarioRender(ctx1, req) - if err != nil { - return - } - cont = req - return -} - -//func TestFilter(t *testing.T) { -// req := apistructs.ComponentProtocolRequest{ -// Scenario: apistructs.ComponentProtocolScenario{ -// ScenarioKey: "issueKanban", -// ScenarioType: "issue-manage", -// }, -// Event: apistructs.ComponentEvent{ -// Component: "", -// GenerateOperation: "", -// }, -// InParams: map[string]interface{}{"projectId": "11"}, -// } -// content, err := rend(&req) -// ctxByte, err := json.Marshal(*content) -// if err != nil { -// t.Errorf("marshal error:%v", err) -// return -// } -// t.Logf("marshal content:%s", string(ctxByte)) -//} -//func TestTimeBoard(t *testing.T) { -// bundleOpts := []bundle.Option{} -// bdl := bundle.New(bundleOpts...) -// i := ComponentIssueBoard{} -// b := protocol.ContextBundle{ -// Bdl: bdl, -// } -// i.ctxBdl = b -// i.boardType = BoardTypeTime -// -// //获取 [今天,明天,两天,七天,一个月,未来] 的时间戳 -// nowTime := time.Date(time.Now().Year(), time.Now().Month(), time.Now().Day(), 0, 0, 0, 0, time.Now().Location()) -// tomorrow := nowTime.Add(time.Hour * time.Duration(24)) -// twoDay := nowTime.Add(time.Hour * time.Duration(24*2)) -// sevenDay := nowTime.Add(time.Hour * time.Duration(24*7)) -// thirtyDay := nowTime.Add(time.Hour * time.Duration(24*30)) -// type tableAssert struct { -// StartTime int64 -// EndTime int64 -// } -// var tables = []struct { -// reqTime []int64 // -// assert []tableAssert -// }{ -// { -// // 全选 -// reqTime: []int64{0, 0}, -// assert: []tableAssert{ -// {0, 0}, // 未定义 -// {1, nowTime.Add(time.Second * time.Duration(-1)).Unix()}, // 已过期 -// {nowTime.Unix(), tomorrow.Add(time.Second * time.Duration(-1)).Unix()}, // 今天 -// {tomorrow.Unix(), twoDay.Add(time.Second * time.Duration(-1)).Unix()}, // 明天 -// {twoDay.Unix(), sevenDay.Add(time.Second * time.Duration(-1)).Unix()}, // 7天 -// {sevenDay.Unix(), thirtyDay.Add(time.Second * time.Duration(-1)).Unix()}, // 30天 -// {thirtyDay.Unix(), 0}, // 未来 -// }, -// }, -// { -// // 今天 - 全选 -// reqTime: []int64{nowTime.Unix(), 0}, -// assert: []tableAssert{ -// {nowTime.Unix(), 0}, // 未定义 -// {nowTime.Unix(), nowTime.Add(time.Second * time.Duration(-1)).Unix()}, // 已过期 -// {nowTime.Unix(), tomorrow.Add(time.Second * time.Duration(-1)).Unix()}, // 今天 -// {tomorrow.Unix(), twoDay.Add(time.Second * time.Duration(-1)).Unix()}, // 明天 -// {twoDay.Unix(), sevenDay.Add(time.Second * time.Duration(-1)).Unix()}, // 7天 -// {sevenDay.Unix(), thirtyDay.Add(time.Second * time.Duration(-1)).Unix()}, // 30天 -// {thirtyDay.Unix(), 0}, // 未来 -// }, -// }, -// { -// // 明天 - 7天 -// reqTime: []int64{tomorrow.Unix(), sevenDay.Unix()}, assert: []tableAssert{ -// {tomorrow.Unix(), sevenDay.Unix()}, // 未定义 -// {tomorrow.Unix(), nowTime.Add(time.Second * time.Duration(-1)).Unix()}, // 已过期 -// {tomorrow.Unix(), tomorrow.Add(time.Second * time.Duration(-1)).Unix()}, // 今天 -// {tomorrow.Unix(), twoDay.Add(time.Second * time.Duration(-1)).Unix()}, // 明天 -// {twoDay.Unix(), sevenDay.Add(time.Second * time.Duration(-1)).Unix()}, // 7天 -// {sevenDay.Unix(), sevenDay.Unix()}, // 30天 -// {thirtyDay.Unix(), sevenDay.Unix()}, // 未来 -// }, -// }, -// { -// // 3天 - 8天 -// reqTime: []int64{nowTime.Add(time.Hour * time.Duration(24*3)).Unix(), nowTime.Add(time.Hour * time.Duration(24*8)).Unix()}, -// assert: []tableAssert{ -// {nowTime.Add(time.Hour * time.Duration(24*3)).Unix(), nowTime.Add(time.Hour * time.Duration(24*8)).Unix()}, // 未定义 -// {nowTime.Add(time.Hour * time.Duration(24*3)).Unix(), nowTime.Add(time.Second * time.Duration(-1)).Unix()}, // 已过期 -// {nowTime.Add(time.Hour * time.Duration(24*3)).Unix(), tomorrow.Add(time.Second * time.Duration(-1)).Unix()}, // 今天 -// {nowTime.Add(time.Hour * time.Duration(24*3)).Unix(), twoDay.Add(time.Second * time.Duration(-1)).Unix()}, // 明天 -// {nowTime.Add(time.Hour * time.Duration(24*3)).Unix(), sevenDay.Add(time.Second * time.Duration(-1)).Unix()}, // 7天 -// {sevenDay.Unix(), nowTime.Add(time.Hour * time.Duration(24*8)).Unix()}, // 30天 -// {thirtyDay.Unix(), nowTime.Add(time.Hour * time.Duration(24*8)).Unix()}, // 未来 -// }, -// }, -// { -// // 全选 - 今天 -// reqTime: []int64{0, nowTime.Unix()}, -// assert: []tableAssert{ -// {0, nowTime.Unix()}, // 未定义 -// {1, nowTime.Add(time.Second * time.Duration(-1)).Unix()}, // 已过期 -// {nowTime.Unix(), nowTime.Unix()}, // 今天 -// {tomorrow.Unix(), nowTime.Unix()}, // 明天 -// {twoDay.Unix(), nowTime.Unix()}, // 7天 -// {sevenDay.Unix(), nowTime.Unix()}, // 30天 -// {thirtyDay.Unix(), nowTime.Unix()}, // 未来 -// }, -// }, -// { -// // 今天 - 8天 -// reqTime: []int64{nowTime.Unix(), nowTime.Add(time.Hour * time.Duration(24*8)).Unix()}, -// assert: []tableAssert{ -// {nowTime.Unix(), nowTime.Add(time.Hour * time.Duration(24*8)).Unix()}, // 未定义 -// {nowTime.Unix(), nowTime.Add(time.Second * time.Duration(-1)).Unix()}, // 已过期 -// {nowTime.Unix(), tomorrow.Add(time.Second * time.Duration(-1)).Unix()}, // 今天 -// {tomorrow.Unix(), twoDay.Add(time.Second * time.Duration(-1)).Unix()}, // 明天 -// {twoDay.Unix(), sevenDay.Add(time.Second * time.Duration(-1)).Unix()}, // 七天 // 7天 -// {sevenDay.Unix(), nowTime.Add(time.Hour * time.Duration(24*8)).Unix()}, // 30天 -// {thirtyDay.Unix(), nowTime.Add(time.Hour * time.Duration(24*8)).Unix()}, // 未来 -// }, -// }, -// { -// // 3天 - 30天 -// reqTime: []int64{nowTime.Add(time.Hour * time.Duration(24*3)).Unix(), thirtyDay.Unix()}, -// assert: []tableAssert{ -// {nowTime.Add(time.Hour * time.Duration(24*3)).Unix(), thirtyDay.Unix()}, // 未定义 -// {nowTime.Add(time.Hour * time.Duration(24*3)).Unix(), nowTime.Add(time.Second * time.Duration(-1)).Unix()}, // 已过期 -// {nowTime.Add(time.Hour * time.Duration(24*3)).Unix(), tomorrow.Add(time.Second * time.Duration(-1)).Unix()}, // 今天 -// {nowTime.Add(time.Hour * time.Duration(24*3)).Unix(), twoDay.Add(time.Second * time.Duration(-1)).Unix()}, // 明天 -// {nowTime.Add(time.Hour * time.Duration(24*3)).Unix(), sevenDay.Add(time.Second * time.Duration(-1)).Unix()}, // 7天 -// {sevenDay.Unix(), thirtyDay.Add(time.Second * time.Duration(-1)).Unix()}, // 30天 -// {thirtyDay.Unix(), thirtyDay.Unix()}, // 未来 -// }, -// }, -// { -// // 今天 - 30天 -// reqTime: []int64{nowTime.Unix(), thirtyDay.Unix()}, -// assert: []tableAssert{ -// {nowTime.Unix(), thirtyDay.Unix()}, // 未定义 -// {nowTime.Unix(), nowTime.Add(time.Second * time.Duration(-1)).Unix()}, // 已过期 -// {nowTime.Unix(), tomorrow.Add(time.Second * time.Duration(-1)).Unix()}, // 今天 -// {tomorrow.Unix(), twoDay.Add(time.Second * time.Duration(-1)).Unix()}, // 明天 -// {twoDay.Unix(), sevenDay.Add(time.Second * time.Duration(-1)).Unix()}, // 7天 -// {sevenDay.Unix(), thirtyDay.Add(time.Second * time.Duration(-1)).Unix()}, // 30天 -// {thirtyDay.Unix(), thirtyDay.Unix()}, // 未来 -// }, -// }, -// { -// // 3天 - 50天 -// reqTime: []int64{nowTime.Add(time.Hour * time.Duration(24*3)).Unix(), nowTime.Add(time.Hour * time.Duration(24*50)).Unix()}, -// assert: []tableAssert{ -// {nowTime.Add(time.Hour * time.Duration(24*3)).Unix(), nowTime.Add(time.Hour * time.Duration(24*50)).Unix()}, // 未定义 -// {nowTime.Add(time.Hour * time.Duration(24*3)).Unix(), nowTime.Add(time.Second * time.Duration(-1)).Unix()}, // 已过期 -// {nowTime.Add(time.Hour * time.Duration(24*3)).Unix(), tomorrow.Add(time.Second * time.Duration(-1)).Unix()}, // 今天 -// {nowTime.Add(time.Hour * time.Duration(24*3)).Unix(), twoDay.Add(time.Second * time.Duration(-1)).Unix()}, // 明天 -// {nowTime.Add(time.Hour * time.Duration(24*3)).Unix(), sevenDay.Add(time.Second * time.Duration(-1)).Unix()}, // 7天 -// {sevenDay.Unix(), thirtyDay.Add(time.Second * time.Duration(-1)).Unix()}, // 30天 -// {thirtyDay.Unix(), nowTime.Add(time.Hour * time.Duration(24*50)).Unix()}, // 未来 -// }, -// }, -// } -// -// for tableIndex, tmlist := range tables { -// p := monkey.PatchInstanceMethod(reflect.TypeOf(bdl), "PageIssues", func(_ *bundle.Bundle, r apistructs.IssuePagingRequest) (*apistructs.IssuePagingResponse, error) { -// endTime := r.EndFinishedAt -// createdAt := r.StartFinishedAt -// return &apistructs.IssuePagingResponse{ -// Data: &apistructs.IssuePagingResponseData{ -// List: []apistructs.Issue{ -// { -// IterationID: endTime, -// ID: createdAt, -// }, -// }, -// }, -// }, nil -// }) -// defer p.Unpatch() -// var req apistructs.IssuePagingRequest -// req.StartFinishedAt = tmlist.reqTime[0] * 1000 -// req.EndFinishedAt = tmlist.reqTime[1] * 1000 -// list, _, _ := i.FilterByTime(req) -// for resultIndex, v := range list { -// issueCert := v.List[0] -// assert.Equal(t, tables[tableIndex].assert[resultIndex].EndTime, issueCert.IterationID/1000) -// assert.Equal(t, tables[tableIndex].assert[resultIndex].StartTime, issueCert.ID/1000) -// } -// } -//} diff --git a/modules/dop/component-protocol/components/issue-manage/issueViewGroup/model.go b/modules/dop/component-protocol/components/issue-manage/issueViewGroup/model.go deleted file mode 100644 index 47c6d41aa7e..00000000000 --- a/modules/dop/component-protocol/components/issue-manage/issueViewGroup/model.go +++ /dev/null @@ -1,21 +0,0 @@ -// 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 issueViewGroup - -var ( - ViewTypeTable = "table" - ViewTypeKanban = "kanban" - ViewTypeGantt = "gantt" -) diff --git a/modules/dop/component-protocol/components/issue-manage/issueViewGroup/render.go b/modules/dop/component-protocol/components/issue-manage/issueViewGroup/render.go deleted file mode 100644 index ebef68b3291..00000000000 --- a/modules/dop/component-protocol/components/issue-manage/issueViewGroup/render.go +++ /dev/null @@ -1,133 +0,0 @@ -// 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 issueViewGroup - -import ( - "context" - "encoding/base64" - "encoding/json" - - "github.com/erda-project/erda-infra/base/servicehub" - "github.com/erda-project/erda-infra/providers/component-protocol/cptype" - "github.com/erda-project/erda-infra/providers/component-protocol/utils/cputil" - "github.com/erda-project/erda/apistructs" - "github.com/erda-project/erda/modules/openapi/component-protocol/components/base" -) - -type ComponentAction struct{ base.DefaultProvider } - -type State struct { - Value string `json:"value,omitempty"` - ChildrenValue map[string]string `json:"childrenValue,omitempty"` -} - -func (ca *ComponentAction) Render(ctx context.Context, c *cptype.Component, scenario cptype.Scenario, event cptype.ComponentEvent, gs *cptype.GlobalStateData) error { - sdk := cputil.SDK(ctx) - - if c.State == nil { - c.State = map[string]interface{}{} - } - state := State{Value: "table", ChildrenValue: map[string]string{"kanban": "deadline"}} - - switch apistructs.OperationKey(event.Operation) { - case apistructs.InitializeOperation, apistructs.RenderingOperation: - if urlQueryI, ok := sdk.InParams[getStateUrlQueryKey()]; ok { - if urlQueryStr, ok := urlQueryI.(string); ok && urlQueryStr != "" { - var urlState State - b, err := base64.StdEncoding.DecodeString(urlQueryStr) - if err != nil { - return err - } - if err := json.Unmarshal(b, &urlState); err != nil { - return err - } - state = urlState - } - } - case "changeViewType": - b, err := json.Marshal(c.State) - if err != nil { - return err - } - if err := json.Unmarshal(b, &state); err != nil { - return err - } - } - - // props - props := make(map[string]interface{}) - props["radioType"] = "button" - props["buttonStyle"] = "solid" - props["size"] = "small" - optionTable := map[string]interface{}{ - "text": cputil.I18n(ctx, "list"), - "tooltip": "", - "prefixIcon": "default-list", - "key": "table", - } - optionKanban := map[string]interface{}{ - "text": cputil.I18n(ctx, "board"), - "tooltip": cputil.I18n(ctx, "board-view"), - "prefixIcon": "data-matrix", - "suffixIcon": "di", - "key": "kanban", - } - // optionGantt := map[string]interface{}{ - // "text": cputil.I18n(ctx, "gantt-chart"), - // "tooltip": "", - // "prefixIcon": "gantetu", - // "key": "gantt", - // } - optionKanbanChildren := []map[string]string{ - {"text": cputil.I18n(ctx, "priority"), "key": "priority"}, - //{"text": "处理人", "key": "assignee"}, - {"text": cputil.I18n(ctx, "deadline"), "key": "deadline"}, - {"text": cputil.I18n(ctx, "custom"), "key": "custom"}, - } - if sdk.InParams["fixedIssueType"].(string) != "ALL" { - optionKanbanChildren = append(optionKanbanChildren, map[string]string{"text": cputil.I18n(ctx, "state"), "key": "status"}) - } - optionKanban["children"] = optionKanbanChildren - props["options"] = []map[string]interface{}{optionTable, optionKanban} - c.Props = props - - // set state - if err := setState(c, state); err != nil { - return err - } - - return json.Unmarshal([]byte(`{"onChange":{"key":"changeViewType","reload":true}}`), &c.Operations) -} - -func getStateUrlQueryKey() string { - return "issueViewGroup__urlQuery" -} - -func setState(c *cptype.Component, state State) error { - b, err := json.Marshal(state) - if err != nil { - return err - } - c.State["value"] = state.Value - c.State["childrenValue"] = state.ChildrenValue - c.State[getStateUrlQueryKey()] = base64.StdEncoding.EncodeToString(b) - return nil -} - -func init() { - base.InitProviderWithCreator("issue-manage", "issueViewGroup", func() servicehub.Provider { - return &ComponentAction{} - }) -} From 3a67fd86e4dcc4e3d7b1d620d934a53abc461942 Mon Sep 17 00:00:00 2001 From: sfwn Date: Thu, 16 Dec 2021 17:40:26 +0800 Subject: [PATCH 2/5] issue-manage: adjust for issue-table --- conf/dop/dop.yaml | 3 - .../issue-manage/common/gshelper/helper.go | 62 ++++++++++++ .../issue-manage/issueFilter/init_filter.go | 6 +- .../issue-manage/issueFilter/model.go | 44 +-------- .../issue-manage/issueFilter/model_test.go | 5 +- .../issue-manage/issueFilter/render.go | 5 +- .../issue-manage/issueFilter/state.go | 3 - .../issue-manage/issueTable/render.go | 27 +---- .../scenarios/issue-manage.yml | 99 +------------------ 9 files changed, 78 insertions(+), 176 deletions(-) create mode 100644 modules/dop/component-protocol/components/issue-manage/common/gshelper/helper.go diff --git a/conf/dop/dop.yaml b/conf/dop/dop.yaml index b713e132fb6..a25ddb409a0 100644 --- a/conf/dop/dop.yaml +++ b/conf/dop/dop.yaml @@ -59,13 +59,10 @@ component-protocol.components.issue-manage.head: component-protocol.components.issue-manage.issueAddButton: component-protocol.components.issue-manage.issueExport: component-protocol.components.issue-manage.issueFilter: -component-protocol.components.issue-manage.issueGantt: component-protocol.components.issue-manage.issueImport: -component-protocol.components.issue-manage.issueKanban: component-protocol.components.issue-manage.issueManage: component-protocol.components.issue-manage.issueOperations: component-protocol.components.issue-manage.issueTable: -component-protocol.components.issue-manage.issueViewGroup: component-protocol.components.issue-manage.topHead: component-protocol.components.code-coverage.treeMapChart: diff --git a/modules/dop/component-protocol/components/issue-manage/common/gshelper/helper.go b/modules/dop/component-protocol/components/issue-manage/common/gshelper/helper.go new file mode 100644 index 00000000000..bd7203db57a --- /dev/null +++ b/modules/dop/component-protocol/components/issue-manage/common/gshelper/helper.go @@ -0,0 +1,62 @@ +// 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 gshelper + +import ( + "github.com/mitchellh/mapstructure" + + "github.com/erda-project/erda-infra/providers/component-protocol/cptype" + "github.com/erda-project/erda/apistructs" +) + +const ( + keyIssuePagingRequest = "IssuePagingRequest" +) + +type GSHelper struct { + gs *cptype.GlobalStateData +} + +func NewGSHelper(gs *cptype.GlobalStateData) *GSHelper { + return &GSHelper{gs: gs} +} + +func assign(src, dst interface{}) error { + if src == nil || dst == nil { + return nil + } + + return mapstructure.Decode(src, dst) +} + +func (h *GSHelper) SetIssuePagingRequest(req apistructs.IssuePagingRequest) { + if h.gs == nil { + return + } + (*h.gs)[keyIssuePagingRequest] = req +} + +func (h *GSHelper) GetIssuePagingRequest() (*apistructs.IssuePagingRequest, bool) { + if h.gs == nil { + return nil, false + } + v, ok := (*h.gs)[keyIssuePagingRequest] + if !ok { + return nil, false + } + var req apistructs.IssuePagingRequest + _ = assign(v, &req) + return &req, true +} diff --git a/modules/dop/component-protocol/components/issue-manage/issueFilter/init_filter.go b/modules/dop/component-protocol/components/issue-manage/issueFilter/init_filter.go index 39b5737837f..636c90637b2 100644 --- a/modules/dop/component-protocol/components/issue-manage/issueFilter/init_filter.go +++ b/modules/dop/component-protocol/components/issue-manage/issueFilter/init_filter.go @@ -21,12 +21,13 @@ import ( "github.com/erda-project/erda-infra/providers/component-protocol/cptype" "github.com/erda-project/erda-infra/providers/component-protocol/utils/cputil" "github.com/erda-project/erda/bundle" + "github.com/erda-project/erda/modules/dop/component-protocol/components/issue-manage/common/gshelper" "github.com/erda-project/erda/modules/dop/component-protocol/types" "github.com/erda-project/erda/modules/dop/services/issuefilterbm" "github.com/erda-project/erda/modules/dop/services/issuestate" ) -func (f *ComponentFilter) InitFromProtocol(ctx context.Context, c *cptype.Component) error { +func (f *ComponentFilter) InitFromProtocol(ctx context.Context, c *cptype.Component, gs *cptype.GlobalStateData) error { // component 序列化 b, err := json.Marshal(c) if err != nil { @@ -46,5 +47,8 @@ func (f *ComponentFilter) InitFromProtocol(ctx context.Context, c *cptype.Compon return err } + // gs + f.gsHelper = gshelper.NewGSHelper(gs) + return nil } diff --git a/modules/dop/component-protocol/components/issue-manage/issueFilter/model.go b/modules/dop/component-protocol/components/issue-manage/issueFilter/model.go index 29ff0fcd01d..03845cefd8c 100644 --- a/modules/dop/component-protocol/components/issue-manage/issueFilter/model.go +++ b/modules/dop/component-protocol/components/issue-manage/issueFilter/model.go @@ -22,6 +22,7 @@ import ( "github.com/erda-project/erda-infra/providers/component-protocol/utils/cputil" "github.com/erda-project/erda/apistructs" "github.com/erda-project/erda/bundle" + "github.com/erda-project/erda/modules/dop/component-protocol/components/issue-manage/common/gshelper" "github.com/erda-project/erda/modules/dop/services/issuefilterbm" "github.com/erda-project/erda/modules/dop/services/issuestate" "github.com/erda-project/erda/modules/openapi/component-protocol/components/base" @@ -39,6 +40,7 @@ type ComponentFilter struct { base.DefaultProvider Bms []issuefilterbm.MyFilterBm `json:"-"` // bookmarks FlushOptsFromBm string `json:"-"` // bm ID + gsHelper *gshelper.GSHelper } // FrontendConditions 前端支持的过滤参数 @@ -272,48 +274,6 @@ func (f *ComponentFilter) generateFrontendConditionProps(ctx context.Context, fi }) } - v, ok := state.IssueViewGroupChildrenValue["kanban"] - if state.IssueViewGroupValue != "kanban" || !ok || v != "status" { - statesMap, err := f.issueStateSvc.GetIssueStatesMap(&apistructs.IssueStatesGetRequest{ - ProjectID: f.InParams.ProjectID, - }) - if err != nil { - return nil - } - - status := filter.PropCondition{ - Key: PropConditionKeyStates, - Label: cputil.I18n(ctx, "state"), - EmptyText: cputil.I18n(ctx, "all"), - Fixed: true, - ShowIndex: 3, - HaveFilter: false, - Type: filter.PropConditionTypeSelect, - Placeholder: "", - Options: func() []filter.PropConditionOption { - // open := filter.PropConditionOption{Label: cputil.I18n(ctx, "open"), Value: apistructs.IssueStateBelongOpen, Icon: ""} - // reopen := filter.PropConditionOption{Label: cputil.I18n(ctx, "reopen"), Value: apistructs.IssueStateBelongReopen, Icon: ""} - // resolved := filter.PropConditionOption{Label: cputil.I18n(ctx, "resolved"), Value: apistructs.IssueStateBelongResolved, Icon: ""} - // wontfix := filter.PropConditionOption{Label: cputil.I18n(ctx, "wontfix"), Value: apistructs.IssueStateBelongWontfix, Icon: ""} - // closed := filter.PropConditionOption{Label: cputil.I18n(ctx, "closed"), Value: apistructs.IssueStateBelongClosed, Icon: ""} - // working := filter.PropConditionOption{Label: cputil.I18n(ctx, "working"), Value: apistructs.IssueStateBelongWorking, Icon: ""} - // done := filter.PropConditionOption{Label: cputil.I18n(ctx, "done"), Value: apistructs.IssueStateBelongDone, Icon: ""} - switch fixedIssueType { - case "ALL": - return convertAllConditions(ctx, statesMap) - case apistructs.IssueTypeRequirement.String(): - return convertConditions(statesMap[apistructs.IssueTypeRequirement]) - case apistructs.IssueTypeTask.String(): - return convertConditions(statesMap[apistructs.IssueTypeTask]) - case apistructs.IssueTypeBug.String(): - return convertConditions(statesMap[apistructs.IssueTypeBug]) - } - return nil - }(), - } - conditionProps = append(conditionProps[:2], append([]filter.PropCondition{status}, conditionProps[2:]...)...) - } - return conditionProps } diff --git a/modules/dop/component-protocol/components/issue-manage/issueFilter/model_test.go b/modules/dop/component-protocol/components/issue-manage/issueFilter/model_test.go index 2e2d6a31003..a63d28ff188 100644 --- a/modules/dop/component-protocol/components/issue-manage/issueFilter/model_test.go +++ b/modules/dop/component-protocol/components/issue-manage/issueFilter/model_test.go @@ -119,10 +119,7 @@ func Test_convertAllConditions(t *testing.T) { func Test_generateFrontendConditionProps(t *testing.T) { ctx := context.WithValue(context.Background(), cptype.GlobalInnerKeyCtxSDK, &cptype.SDK{Tran: &MockTran{}}) - f := ComponentFilter{State: State{ - IssueViewGroupValue: "kanban", - IssueViewGroupChildrenValue: map[string]string{"kanban": "status"}, - }} + f := ComponentFilter{State: State{}} props := f.generateFrontendConditionProps(ctx, "ALL", f.State) assert.True(t, len(props) > 0) } diff --git a/modules/dop/component-protocol/components/issue-manage/issueFilter/render.go b/modules/dop/component-protocol/components/issue-manage/issueFilter/render.go index 8897584007c..7058dd9e2bf 100644 --- a/modules/dop/component-protocol/components/issue-manage/issueFilter/render.go +++ b/modules/dop/component-protocol/components/issue-manage/issueFilter/render.go @@ -71,7 +71,7 @@ func getMeta(ori map[string]interface{}, dst interface{}) error { func (f *ComponentFilter) Render(ctx context.Context, c *cptype.Component, scenario cptype.Scenario, event cptype.ComponentEvent, gs *cptype.GlobalStateData) error { // init filter - if err := f.InitFromProtocol(ctx, c); err != nil { + if err := f.InitFromProtocol(ctx, c, gs); err != nil { return err } @@ -177,10 +177,11 @@ func (f *ComponentFilter) PostSetState() error { // condition values // issuePagingRequest - f.State.IssuePagingRequest, err = f.generateIssuePagingRequest() + issuePagingRequest, err := f.generateIssuePagingRequest() if err != nil { return err } + f.gsHelper.SetIssuePagingRequest(issuePagingRequest) return nil } diff --git a/modules/dop/component-protocol/components/issue-manage/issueFilter/state.go b/modules/dop/component-protocol/components/issue-manage/issueFilter/state.go index eb544e636ea..49e751c0ca4 100644 --- a/modules/dop/component-protocol/components/issue-manage/issueFilter/state.go +++ b/modules/dop/component-protocol/components/issue-manage/issueFilter/state.go @@ -33,9 +33,6 @@ type State struct { // 方便后端使用的 state IssuePagingRequest apistructs.IssuePagingRequest `json:"issuePagingRequest,omitempty"` - - IssueViewGroupValue string `json:"issueViewGroupValue"` - IssueViewGroupChildrenValue map[string]string `json:"issueViewGroupChildrenValue"` } // generateUrlQueryKey 实际上组件名在一个协议里是定义好的,即 issueFilter__urlQuery diff --git a/modules/dop/component-protocol/components/issue-manage/issueTable/render.go b/modules/dop/component-protocol/components/issue-manage/issueTable/render.go index f49b3dc7105..aeff0e954bc 100644 --- a/modules/dop/component-protocol/components/issue-manage/issueTable/render.go +++ b/modules/dop/component-protocol/components/issue-manage/issueTable/render.go @@ -32,7 +32,7 @@ import ( "github.com/erda-project/erda/apistructs" "github.com/erda-project/erda/modules/dop/bdl" "github.com/erda-project/erda/modules/dop/component-protocol/components/common" - "github.com/erda-project/erda/modules/dop/component-protocol/components/issue-manage/issueViewGroup" + "github.com/erda-project/erda/modules/dop/component-protocol/components/issue-manage/common/gshelper" "github.com/erda-project/erda/modules/openapi/component-protocol/components/base" "github.com/erda-project/erda/pkg/strutil" @@ -219,19 +219,6 @@ var ( ) func (ca *ComponentAction) Render(ctx context.Context, c *cptype.Component, scenario cptype.Scenario, event cptype.ComponentEvent, gs *cptype.GlobalStateData) error { - // visible - visible := true - if v, ok := c.State["issueViewGroupValue"]; ok { - if viewType, ok := v.(string); ok { - if viewType != issueViewGroup.ViewTypeTable { - visible = false - c.Props = map[string]interface{}{} - c.Props["visible"] = visible - return nil - } - } - } - sdk := cputil.SDK(ctx) isGuest, err := ca.CheckUserPermission(ctx) @@ -376,15 +363,10 @@ func (ca *ComponentAction) Render(ctx context.Context, c *cptype.Component, scen } userids := []string{} cond := apistructs.IssuePagingRequest{} - filterCond, ok := c.State["filterConditions"] + gh := gshelper.NewGSHelper(gs) + filterCond, ok := gh.GetIssuePagingRequest() if ok { - filterCondS, err := json.Marshal(filterCond) - if err != nil { - return err - } - if err := json.Unmarshal(filterCondS, &cond); err != nil { - return err - } + cond = *filterCond resetPageInfo(&cond, c.State) } else { issuetype := sdk.InParams["fixedIssueType"].(string) @@ -557,7 +539,6 @@ func (ca *ComponentAction) Render(ctx context.Context, c *cptype.Component, scen "reload": true, }, } - c.Props["visible"] = visible (*gs)[protocol.GlobalInnerKeyUserIDs.String()] = userids if c.State == nil { c.State = map[string]interface{}{} diff --git a/modules/dop/component-protocol/scenarios/issue-manage.yml b/modules/dop/component-protocol/scenarios/issue-manage.yml index f28bcdc0c31..f06ed1645b6 100644 --- a/modules/dop/component-protocol/scenarios/issue-manage.yml +++ b/modules/dop/component-protocol/scenarios/issue-manage.yml @@ -13,13 +13,10 @@ hierarchy: left: issueFilter right: issueOperations issueOperations: - - issueViewGroup - issueExport - issueImport content: - issueTable - - issueKanban - - issueGantt options: syncIntervalSecond: 0 @@ -29,7 +26,7 @@ components: type: Container head: type: LRContainer - props: + props: whiteBg: true content: type: Container @@ -43,105 +40,11 @@ components: type: Button issueImport: type: Button - issueViewGroup: - type: Radio issueAddButton: type: Button issueTable: type: Table - issueKanban: - type: IssueKanban - issueGantt: - type: Table rendering: - # 前端触发组件 - # 先渲染前端触发组件,再渲染关联组件 - issueViewGroup: - # 关联渲染组件列表 - - name: issueFilter - state: - - name: "issueViewGroupValue" - value: "{{ issueViewGroup.value }}" - - name: "issueViewGroupChildrenValue" - value: "{{ issueViewGroup.childrenValue }}" - - name: issueTable - state: - - name: "issueViewGroupValue" - value: "{{ issueViewGroup.value }}" - - name: "filterConditions" - value: "{{ issueFilter.issuePagingRequest }}" - - name: issueKanban - state: - - name: "issueViewGroupValue" - value: "{{ issueViewGroup.value }}" - - name: "issueViewGroupChildrenValue" - value: "{{ issueViewGroup.childrenValue }}" - - name: "filterConditions" - value: "{{ issueFilter.issuePagingRequest }}" - - name: issueGantt - state: - - name: "issueViewGroupValue" - value: "{{ issueViewGroup.value }}" - - name: "filterConditions" - value: "{{ issueFilter.issuePagingRequest }}" - issueFilter: - - name: issueViewGroup - - name: issueTable - state: - - name: "issueViewGroupValue" - value: "{{ issueViewGroup.value }}" - - name: "filterConditions" - value: "{{ issueFilter.issuePagingRequest }}" - - name: issueKanban - state: - - name: "issueViewGroupValue" - value: "{{ issueViewGroup.value }}" - - name: "issueViewGroupChildrenValue" - value: "{{ issueViewGroup.childrenValue }}" - - name: "filterConditions" - value: "{{ issueFilter.issuePagingRequest }}" - - name: issueGantt - state: - - name: "issueViewGroupValue" - value: "{{ issueViewGroup.value }}" - - name: "filterConditions" - value: "{{ issueFilter.issuePagingRequest }}" - - __DefaultRendering__: - - name: issueManage - - name: topHead - - name: issueAddButton - - name: head - - name: issueOperations - - name: issueViewGroup - - name: issueFilter - state: - - name: "issueViewGroupValue" - value: "{{ issueViewGroup.value }}" - - name: "issueViewGroupChildrenValue" - value: "{{ issueViewGroup.childrenValue }}" - - name: issueExport - - name: issueImport - - name: content - name: issueTable - state: - - name: "issueViewGroupValue" - value: "{{ issueViewGroup.value }}" - - name: "filterConditions" - value: "{{ issueFilter.issuePagingRequest }}" - - name: issueKanban - state: - - name: "issueViewGroupValue" - value: "{{ issueViewGroup.value }}" - - name: "issueViewGroupChildrenValue" - value: "{{ issueViewGroup.childrenValue }}" - - name: "filterConditions" - value: "{{ issueFilter.issuePagingRequest }}" - - name: issueGantt - state: - - name: "issueViewGroupValue" - value: "{{ issueViewGroup.value }}" - - name: "filterConditions" - value: "{{ issueFilter.issuePagingRequest }}" From db60ef4cd8db708a31884668615605ca73f0f083 Mon Sep 17 00:00:00 2001 From: sfwn Date: Fri, 17 Dec 2021 17:13:24 +0800 Subject: [PATCH 3/5] issue-table remove topHead and issueAddButton --- .../issue-manage/issueAddButton/render.go | 170 ------------------ .../components/issue-manage/scenario.go | 5 - .../components/issue-manage/topHead/render.go | 38 ---- .../scenarios/issue-manage.yml | 7 - 4 files changed, 220 deletions(-) delete mode 100644 modules/dop/component-protocol/components/issue-manage/issueAddButton/render.go delete mode 100644 modules/dop/component-protocol/components/issue-manage/topHead/render.go diff --git a/modules/dop/component-protocol/components/issue-manage/issueAddButton/render.go b/modules/dop/component-protocol/components/issue-manage/issueAddButton/render.go deleted file mode 100644 index 8d88d88ce11..00000000000 --- a/modules/dop/component-protocol/components/issue-manage/issueAddButton/render.go +++ /dev/null @@ -1,170 +0,0 @@ -// 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 issueAddButton - -import ( - "context" - - "github.com/erda-project/erda-infra/base/servicehub" - "github.com/erda-project/erda-infra/providers/component-protocol/cptype" - "github.com/erda-project/erda-infra/providers/component-protocol/utils/cputil" - "github.com/erda-project/erda/apistructs" - "github.com/erda-project/erda/modules/dop/bdl" - "github.com/erda-project/erda/modules/openapi/component-protocol/components/base" -) - -type AddButtonCandidateOp struct { - Click struct { - Reload bool `json:"reload"` - Key string `json:"key"` - } `json:"click"` -} -type AddButtonCandidate struct { - Disabled bool `json:"disabled"` - DisabledTip string `json:"disabledTip"` - Key string `json:"key"` - Operations AddButtonCandidateOp `json:"operations"` - PrefixIcon string `json:"prefixIcon"` - Text string `json:"text"` -} -type Props struct { - Menu []AddButtonCandidate `json:"menu"` - SuffixIcon string `json:"suffixIcon"` - Text string `json:"text"` - Type string `json:"type"` - Operations AddButtonCandidateOp `json:"operations"` - Disabled bool `json:"disabled"` -} - -type ComponentAction struct{ base.DefaultProvider } - -func (ca *ComponentAction) Render(ctx context.Context, c *cptype.Component, scenario cptype.Scenario, event cptype.ComponentEvent, gs *cptype.GlobalStateData) error { - sdk := cputil.SDK(ctx) - fixedIssueType := sdk.InParams["fixedIssueType"].(string) - - isGuest, err := ca.CheckUserPermission(ctx) - if err != nil { - return err - } - - requirementCandidate := AddButtonCandidate{ - Disabled: isGuest, - DisabledTip: "", - Key: "requirement", - Operations: AddButtonCandidateOp{Click: struct { - Reload bool `json:"reload"` - Key string `json:"key"` - }{Reload: false, Key: "createRequirement"}}, - PrefixIcon: "ISSUE_ICON.issue.REQUIREMENT", - Text: cputil.I18n(ctx, "requirement"), - } - taskCandidate := AddButtonCandidate{ - Disabled: isGuest, - DisabledTip: "", - Key: "task", - Operations: AddButtonCandidateOp{Click: struct { - Reload bool `json:"reload"` - Key string `json:"key"` - }{Reload: false, Key: "createTask"}}, - PrefixIcon: "ISSUE_ICON.issue.TASK", - Text: cputil.I18n(ctx, "task"), - } - bugCandidate := AddButtonCandidate{ - Disabled: isGuest, - DisabledTip: "", - Key: "bug", - Operations: AddButtonCandidateOp{Click: struct { - Reload bool `json:"reload"` - Key string `json:"key"` - }{Reload: false, Key: "createBug"}}, - PrefixIcon: "ISSUE_ICON.issue.BUG", - Text: cputil.I18n(ctx, "bug"), - } - props := Props{ - Menu: nil, - SuffixIcon: "di", - Text: cputil.I18n(ctx, "create-issue"), - Type: "primary", - Disabled: isGuest, - } - - prop := Props{ - Type: "primary", - } - - var menu []AddButtonCandidate - - switch fixedIssueType { - case "ALL": - menu = []AddButtonCandidate{requirementCandidate, taskCandidate, bugCandidate} - props.Menu = menu - c.Props = cputil.MustConvertProps(props) - case apistructs.IssueTypeRequirement.String(): - prop.Text = cputil.I18n(ctx, "create-requirement") - c.Operations = make(cptype.ComponentOperations) - c.Operations["click"] = struct { - Reload bool `json:"reload"` - Key string `json:"key"` - Disabled bool `json:"disabled"` - }{Reload: false, Key: "createRequirement", Disabled: isGuest} - case apistructs.IssueTypeTask.String(): - prop.Text = cputil.I18n(ctx, "create-task") - c.Operations = make(cptype.ComponentOperations) - c.Operations["click"] = struct { - Reload bool `json:"reload"` - Key string `json:"key"` - Disabled bool `json:"disabled"` - }{Reload: false, Key: "createTask", Disabled: isGuest} - case apistructs.IssueTypeBug.String(): - prop.Text = cputil.I18n(ctx, "create-bug") - c.Operations = make(cptype.ComponentOperations) - c.Operations["click"] = struct { - Reload bool `json:"reload"` - Key string `json:"key"` - Disabled bool `json:"disabled"` - }{Reload: false, Key: "createBug", Disabled: isGuest} - } - c.Props = cputil.MustConvertProps(prop) - - return nil -} - -// GetUserPermission check Guest permission -func (ca *ComponentAction) CheckUserPermission(ctx context.Context) (bool, error) { - sdk := cputil.SDK(ctx) - isGuest := false - projectID := cputil.GetInParamByKey(ctx, "projectId").(string) - scopeRole, err := bdl.Bdl.ScopeRoleAccess(sdk.Identity.UserID, &apistructs.ScopeRoleAccessRequest{ - Scope: apistructs.Scope{ - Type: apistructs.ProjectScope, - ID: projectID, - }, - }) - if err != nil { - return false, err - } - for _, role := range scopeRole.Roles { - if role == "Guest" { - isGuest = true - } - } - return isGuest, nil -} - -func init() { - base.InitProviderWithCreator("issue-manage", "issueAddButton", - func() servicehub.Provider { return &ComponentAction{} }, - ) -} diff --git a/modules/dop/component-protocol/components/issue-manage/scenario.go b/modules/dop/component-protocol/components/issue-manage/scenario.go index fd0ff32780e..68efd54b1b9 100644 --- a/modules/dop/component-protocol/components/issue-manage/scenario.go +++ b/modules/dop/component-protocol/components/issue-manage/scenario.go @@ -17,15 +17,10 @@ package issue_manage import ( _ "github.com/erda-project/erda/modules/dop/component-protocol/components/issue-manage/content" _ "github.com/erda-project/erda/modules/dop/component-protocol/components/issue-manage/head" - _ "github.com/erda-project/erda/modules/dop/component-protocol/components/issue-manage/issueAddButton" _ "github.com/erda-project/erda/modules/dop/component-protocol/components/issue-manage/issueExport" _ "github.com/erda-project/erda/modules/dop/component-protocol/components/issue-manage/issueFilter" - _ "github.com/erda-project/erda/modules/dop/component-protocol/components/issue-manage/issueGantt" _ "github.com/erda-project/erda/modules/dop/component-protocol/components/issue-manage/issueImport" - _ "github.com/erda-project/erda/modules/dop/component-protocol/components/issue-manage/issueKanban" _ "github.com/erda-project/erda/modules/dop/component-protocol/components/issue-manage/issueManage" _ "github.com/erda-project/erda/modules/dop/component-protocol/components/issue-manage/issueOperations" _ "github.com/erda-project/erda/modules/dop/component-protocol/components/issue-manage/issueTable" - _ "github.com/erda-project/erda/modules/dop/component-protocol/components/issue-manage/issueViewGroup" - _ "github.com/erda-project/erda/modules/dop/component-protocol/components/issue-manage/topHead" ) diff --git a/modules/dop/component-protocol/components/issue-manage/topHead/render.go b/modules/dop/component-protocol/components/issue-manage/topHead/render.go deleted file mode 100644 index 15dd8c913d5..00000000000 --- a/modules/dop/component-protocol/components/issue-manage/topHead/render.go +++ /dev/null @@ -1,38 +0,0 @@ -// 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 topHead - -import ( - "context" - "encoding/json" - - "github.com/erda-project/erda-infra/base/servicehub" - "github.com/erda-project/erda-infra/providers/component-protocol/cptype" - "github.com/erda-project/erda/modules/openapi/component-protocol/components/base" -) - -func init() { - base.InitProviderWithCreator("issue-manage", "topHead", - func() servicehub.Provider { - return &ComponentAction{} - }, - ) -} - -type ComponentAction struct{ base.DefaultProvider } - -func (ca *ComponentAction) Render(ctx context.Context, c *cptype.Component, scenario cptype.Scenario, event cptype.ComponentEvent, gs *cptype.GlobalStateData) error { - return json.Unmarshal([]byte(`{"isTopHead": true}`), &c.Props) -} diff --git a/modules/dop/component-protocol/scenarios/issue-manage.yml b/modules/dop/component-protocol/scenarios/issue-manage.yml index f06ed1645b6..59e3b3db525 100644 --- a/modules/dop/component-protocol/scenarios/issue-manage.yml +++ b/modules/dop/component-protocol/scenarios/issue-manage.yml @@ -4,11 +4,8 @@ hierarchy: root: issueManage structure: issueManage: - - topHead - head - content - topHead: - - issueAddButton head: left: issueFilter right: issueOperations @@ -30,8 +27,6 @@ components: whiteBg: true content: type: Container - topHead: - type: RowContainer issueOperations: type: RowContainer issueFilter: @@ -40,8 +35,6 @@ components: type: Button issueImport: type: Button - issueAddButton: - type: Button issueTable: type: Table From 1a5b78282eba8b56cf7dc889c6738c32a860383e Mon Sep 17 00:00:00 2001 From: sfwn Date: Fri, 17 Dec 2021 17:15:08 +0800 Subject: [PATCH 4/5] go.mod: update infra for cp --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 647a062b6d0..6a0bc1293c2 100644 --- a/go.mod +++ b/go.mod @@ -38,7 +38,7 @@ require ( github.com/dsnet/compress v0.0.1 // indirect github.com/dustin/go-humanize v1.0.0 github.com/elastic/cloud-on-k8s v0.0.0-20210205172912-5ce0eca90c60 - github.com/erda-project/erda-infra v0.0.0-20211217035131-14a9f37bb4dd + github.com/erda-project/erda-infra v0.0.0-20211217090749-0ceead758b74 github.com/erda-project/erda-oap-thirdparty-protocol v0.0.0-20210907135609-15886a136d5b github.com/erda-project/erda-proto-go v0.0.0 github.com/erda-project/erda-sourcecov v0.1.0 diff --git a/go.sum b/go.sum index 2c29633d2b4..15515d45ed4 100644 --- a/go.sum +++ b/go.sum @@ -480,8 +480,8 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7 github.com/erda-project/elastic v0.0.1-ex h1:5ajfxQ5S5YjpzFqY9LzL9hiKWCn6q/JDT4n8sNv7+pU= github.com/erda-project/elastic v0.0.1-ex/go.mod h1:iAVsas6fcmt9pxtge1+dErMhecv+RLSXlD4rnZRJVW0= github.com/erda-project/erda-infra v0.0.0-20211209074404-32e7888e4551/go.mod h1:JEXUFWDC/a97+3AgX/cL4xRlqL9vTDM+wVV3Ee5FXYI= -github.com/erda-project/erda-infra v0.0.0-20211217035131-14a9f37bb4dd h1:Eck8DpbYmjEP8ldYe0bZwjqGjAMKwNyZyvo+WYJ8d6E= -github.com/erda-project/erda-infra v0.0.0-20211217035131-14a9f37bb4dd/go.mod h1:JEXUFWDC/a97+3AgX/cL4xRlqL9vTDM+wVV3Ee5FXYI= +github.com/erda-project/erda-infra v0.0.0-20211217090749-0ceead758b74 h1:sMky2jlYdExMQaQ6xGaD0BnrqSil9yvEwP0fPOGGswc= +github.com/erda-project/erda-infra v0.0.0-20211217090749-0ceead758b74/go.mod h1:JEXUFWDC/a97+3AgX/cL4xRlqL9vTDM+wVV3Ee5FXYI= github.com/erda-project/erda-oap-thirdparty-protocol v0.0.0-20210907135609-15886a136d5b h1:GWf2ChasZFerFwQoTokIvjJLWH57ligTSLD2hUb7UWk= github.com/erda-project/erda-oap-thirdparty-protocol v0.0.0-20210907135609-15886a136d5b/go.mod h1:H/f81Thef2Tnz4nUeLt0r4VwHdOznthpyXBwT9vDWo0= github.com/erda-project/erda-sourcecov v0.1.0 h1:iLvoMsQ1xX81KNOW98BKr85Vs7sSazrIDEphLYdmgP4= From 100a0f0896eb3a8e0b76f9ec05570ee471f8df68 Mon Sep 17 00:00:00 2001 From: sfwn Date: Fri, 17 Dec 2021 17:18:04 +0800 Subject: [PATCH 5/5] remove useless comp in dop.yaml --- conf/dop/dop.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/conf/dop/dop.yaml b/conf/dop/dop.yaml index a25ddb409a0..33b091a7550 100644 --- a/conf/dop/dop.yaml +++ b/conf/dop/dop.yaml @@ -56,14 +56,12 @@ component-protocol: # components component-protocol.components.issue-manage.content: component-protocol.components.issue-manage.head: -component-protocol.components.issue-manage.issueAddButton: component-protocol.components.issue-manage.issueExport: component-protocol.components.issue-manage.issueFilter: component-protocol.components.issue-manage.issueImport: component-protocol.components.issue-manage.issueManage: component-protocol.components.issue-manage.issueOperations: component-protocol.components.issue-manage.issueTable: -component-protocol.components.issue-manage.topHead: component-protocol.components.code-coverage.treeMapChart: component-protocol.components.code-coverage.codeCoverChart: