This is an automated email from the ASF dual-hosted git repository.
zhangliang2022 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-devlake.git
The following commit(s) were added to refs/heads/main by this push:
new 3a46af43 feat(tapd): add new entities (#2008)
3a46af43 is described below
commit 3a46af43749c3f8a09332064631ab7fa19291ac0
Author: Warren Chen <[email protected]>
AuthorDate: Wed May 25 22:28:33 2022 +0800
feat(tapd): add new entities (#2008)
closes #2007
---
plugins/tapd/models/bug_custom_field.go | 21 +++++
.../migrationscripts/archived/bug_custom_field.go | 21 +++++
.../archived/story_custom_field.go | 21 +++++
.../migrationscripts/archived/task_custom_field.go | 21 +++++
.../models/migrationscripts/archived/workspace.go | 1 +
.../tapd/models/migrationscripts/init_schema.go | 3 +
plugins/tapd/models/story_custom_field.go | 21 +++++
plugins/tapd/models/task_custom_field.go | 21 +++++
plugins/tapd/models/workspace.go | 1 +
plugins/tapd/tapd.go | 98 +++++++++++-----------
plugins/tapd/tasks/company_collector.go | 76 +++++++++++++++++
plugins/tapd/tasks/company_extractor.go | 67 +++++++++++++++
.../tapd/tasks/story_custom_fields_collector.go | 74 ++++++++++++++++
.../tapd/tasks/story_custom_fields_extractor.go | 72 ++++++++++++++++
14 files changed, 470 insertions(+), 48 deletions(-)
diff --git a/plugins/tapd/models/bug_custom_field.go
b/plugins/tapd/models/bug_custom_field.go
new file mode 100644
index 00000000..c2c5bbd9
--- /dev/null
+++ b/plugins/tapd/models/bug_custom_field.go
@@ -0,0 +1,21 @@
+package models
+
+import "github.com/apache/incubator-devlake/models/common"
+
+type TapdBugCustomFields struct {
+ ConnectionId uint64 `gorm:"primaryKey;type:BIGINT NOT NULL"`
+ ID uint64 `gorm:"primaryKey;type:BIGINT NOT NULL"
json:"id,string"`
+ WorkspaceID uint64 `json:"workspace_id,string"`
+ EntryType string `json:"entry_type"`
+ CustomField string `json:"custom_field"`
+ Type string `json:"type"`
+ Name string `json:"name"`
+ Options string `json:"options"`
+ Enabled string `json:"enabled"`
+ Sort string `json:"sort"`
+ common.NoPKModel
+}
+
+func (TapdBugCustomFields) TableName() string {
+ return "_tool_tapd_bug_custom_fields"
+}
diff --git a/plugins/tapd/models/migrationscripts/archived/bug_custom_field.go
b/plugins/tapd/models/migrationscripts/archived/bug_custom_field.go
new file mode 100644
index 00000000..41681c2d
--- /dev/null
+++ b/plugins/tapd/models/migrationscripts/archived/bug_custom_field.go
@@ -0,0 +1,21 @@
+package archived
+
+import "github.com/apache/incubator-devlake/models/common"
+
+type TapdBugCustomFields struct {
+ ConnectionId uint64 `gorm:"primaryKey;type:BIGINT NOT NULL"`
+ ID uint64 `gorm:"primaryKey;type:BIGINT NOT NULL"
json:"id,string"`
+ WorkspaceID uint64 `json:"workspace_id,string"`
+ EntryType string `json:"entry_type"`
+ CustomField string `json:"custom_field"`
+ Type string `json:"type"`
+ Name string `json:"name"`
+ Options string `json:"options"`
+ Enabled string `json:"enabled"`
+ Sort string `json:"sort"`
+ common.NoPKModel
+}
+
+func (TapdBugCustomFields) TableName() string {
+ return "_tool_tapd_bug_custom_fields"
+}
diff --git
a/plugins/tapd/models/migrationscripts/archived/story_custom_field.go
b/plugins/tapd/models/migrationscripts/archived/story_custom_field.go
new file mode 100644
index 00000000..e10b3943
--- /dev/null
+++ b/plugins/tapd/models/migrationscripts/archived/story_custom_field.go
@@ -0,0 +1,21 @@
+package archived
+
+import "github.com/apache/incubator-devlake/models/common"
+
+type TapdStoryCustomFields struct {
+ ConnectionId uint64 `gorm:"primaryKey;type:BIGINT NOT NULL"`
+ ID uint64 `gorm:"primaryKey;type:BIGINT NOT NULL"
json:"id,string"`
+ WorkspaceID uint64 `json:"workspace_id,string"`
+ EntryType string `json:"entry_type"`
+ CustomField string `json:"custom_field"`
+ Type string `json:"type"`
+ Name string `json:"name"`
+ Options string `json:"options"`
+ Enabled string `json:"enabled"`
+ Sort string `json:"sort"`
+ common.NoPKModel
+}
+
+func (TapdStoryCustomFields) TableName() string {
+ return "_tool_tapd_story_custom_fields"
+}
diff --git a/plugins/tapd/models/migrationscripts/archived/task_custom_field.go
b/plugins/tapd/models/migrationscripts/archived/task_custom_field.go
new file mode 100644
index 00000000..6350bc84
--- /dev/null
+++ b/plugins/tapd/models/migrationscripts/archived/task_custom_field.go
@@ -0,0 +1,21 @@
+package archived
+
+import "github.com/apache/incubator-devlake/models/common"
+
+type TapdTaskCustomFields struct {
+ ConnectionId uint64 `gorm:"primaryKey;type:BIGINT NOT NULL"`
+ ID uint64 `gorm:"primaryKey;type:BIGINT NOT NULL"
json:"id,string"`
+ WorkspaceID uint64 `json:"workspace_id,string"`
+ EntryType string `json:"entry_type"`
+ CustomField string `json:"custom_field"`
+ Type string `json:"type"`
+ Name string `json:"name"`
+ Options string `json:"options"`
+ Enabled string `json:"enabled"`
+ Sort string `json:"sort"`
+ common.NoPKModel
+}
+
+func (TapdTaskCustomFields) TableName() string {
+ return "_tool_tapd_task_custom_fields"
+}
diff --git a/plugins/tapd/models/migrationscripts/archived/workspace.go
b/plugins/tapd/models/migrationscripts/archived/workspace.go
index 7aeaa11c..2c5cb918 100644
--- a/plugins/tapd/models/migrationscripts/archived/workspace.go
+++ b/plugins/tapd/models/migrationscripts/archived/workspace.go
@@ -33,6 +33,7 @@ type TapdWorkspace struct {
BeginDate *helper.CSTTime `json:"begin_date"`
EndDate *helper.CSTTime `json:"end_date"`
ExternalOn string `gorm:"type:varchar(255)"
json:"external_on"`
+ ParentId uint64 `gorm:"type:BIGINT"
json:"parent_id,string"`
Creator string `gorm:"type:varchar(255)" json:"creator"`
Created *helper.CSTTime `json:"created"`
common.NoPKModel
diff --git a/plugins/tapd/models/migrationscripts/init_schema.go
b/plugins/tapd/models/migrationscripts/init_schema.go
index 543ffdef..65bf881b 100644
--- a/plugins/tapd/models/migrationscripts/init_schema.go
+++ b/plugins/tapd/models/migrationscripts/init_schema.go
@@ -57,6 +57,9 @@ func (*InitSchemas) Up(ctx context.Context, db *gorm.DB)
error {
&archived.TapdIterationBug{},
&archived.TapdIterationStory{},
&archived.TapdIterationTask{},
+ &archived.TapdStoryCustomFields{},
+ &archived.TapdBugCustomFields{},
+ &archived.TapdTaskCustomFields{},
)
}
diff --git a/plugins/tapd/models/story_custom_field.go
b/plugins/tapd/models/story_custom_field.go
new file mode 100644
index 00000000..02cbe9c5
--- /dev/null
+++ b/plugins/tapd/models/story_custom_field.go
@@ -0,0 +1,21 @@
+package models
+
+import "github.com/apache/incubator-devlake/models/common"
+
+type TapdStoryCustomFields struct {
+ ConnectionId uint64 `gorm:"primaryKey;type:BIGINT NOT NULL"`
+ ID uint64 `gorm:"primaryKey;type:BIGINT NOT NULL"
json:"id,string"`
+ WorkspaceID uint64 `json:"workspace_id,string"`
+ EntryType string `json:"entry_type"`
+ CustomField string `json:"custom_field"`
+ Type string `json:"type"`
+ Name string `json:"name"`
+ Options string `json:"options"`
+ Enabled string `json:"enabled"`
+ Sort string `json:"sort"`
+ common.NoPKModel
+}
+
+func (TapdStoryCustomFields) TableName() string {
+ return "_tool_tapd_story_custom_fields"
+}
diff --git a/plugins/tapd/models/task_custom_field.go
b/plugins/tapd/models/task_custom_field.go
new file mode 100644
index 00000000..4b4bf81b
--- /dev/null
+++ b/plugins/tapd/models/task_custom_field.go
@@ -0,0 +1,21 @@
+package models
+
+import "github.com/apache/incubator-devlake/models/common"
+
+type TapdTaskCustomFields struct {
+ ConnectionId uint64 `gorm:"primaryKey;type:BIGINT NOT NULL"`
+ ID uint64 `gorm:"primaryKey;type:BIGINT NOT NULL"
json:"id,string"`
+ WorkspaceID uint64 `json:"workspace_id,string"`
+ EntryType string `json:"entry_type"`
+ CustomField string `json:"custom_field"`
+ Type string `json:"type"`
+ Name string `json:"name"`
+ Options string `json:"options"`
+ Enabled string `json:"enabled"`
+ Sort string `json:"sort"`
+ common.NoPKModel
+}
+
+func (TapdTaskCustomFields) TableName() string {
+ return "_tool_tapd_task_custom_fields"
+}
diff --git a/plugins/tapd/models/workspace.go b/plugins/tapd/models/workspace.go
index aa0a817c..64665c9e 100644
--- a/plugins/tapd/models/workspace.go
+++ b/plugins/tapd/models/workspace.go
@@ -33,6 +33,7 @@ type TapdWorkspace struct {
BeginDate *helper.CSTTime `json:"begin_date"`
EndDate *helper.CSTTime `json:"end_date"`
ExternalOn string `gorm:"type:varchar(255)"
json:"external_on"`
+ ParentId uint64 `gorm:"type:BIGINT"
json:"parent_id,string"`
Creator string `gorm:"type:varchar(255)" json:"creator"`
Created *helper.CSTTime `json:"created"`
common.NoPKModel
diff --git a/plugins/tapd/tapd.go b/plugins/tapd/tapd.go
index 3729af3b..f0ffcded 100644
--- a/plugins/tapd/tapd.go
+++ b/plugins/tapd/tapd.go
@@ -54,50 +54,54 @@ func (plugin Tapd) Description() string {
func (plugin Tapd) SubTaskMetas() []core.SubTaskMeta {
return []core.SubTaskMeta{
- tasks.CollectWorkspaceMeta,
- tasks.ExtractWorkspaceMeta,
- tasks.CollectBugStatusMeta,
- tasks.ExtractBugStatusMeta,
- tasks.CollectUserMeta,
- tasks.ExtractUserMeta,
- tasks.CollectIterationMeta,
- tasks.ExtractIterationMeta,
- tasks.CollectStoryMeta,
- tasks.CollectBugMeta,
- tasks.CollectTaskMeta,
- tasks.ExtractStoryMeta,
- tasks.ExtractBugMeta,
- tasks.ExtractTaskMeta,
- tasks.CollectBugChangelogMeta,
- tasks.ExtractBugChangelogMeta,
- tasks.CollectStoryChangelogMeta,
- tasks.ExtractStoryChangelogMeta,
- tasks.CollectTaskChangelogMeta,
- tasks.ExtractTaskChangelogMeta,
- tasks.CollectWorklogMeta,
- tasks.ExtractWorklogMeta,
- tasks.CollectBugCommitMeta,
- tasks.ExtractBugCommitMeta,
- tasks.CollectStoryCommitMeta,
- tasks.ExtractStoryCommitMeta,
- tasks.CollectTaskCommitMeta,
- tasks.ExtractTaskCommitMeta,
- tasks.ConvertWorkspaceMeta,
- tasks.ConvertUserMeta,
- tasks.ConvertIterationMeta,
- tasks.ConvertStoryMeta,
- tasks.ConvertBugMeta,
- tasks.ConvertTaskMeta,
- tasks.ConvertWorklogMeta,
- tasks.ConvertBugChangelogMeta,
- tasks.ConvertStoryChangelogMeta,
- tasks.ConvertTaskChangelogMeta,
- tasks.ConvertBugCommitMeta,
- tasks.ConvertStoryCommitMeta,
- tasks.ConvertTaskCommitMeta,
- tasks.ConvertStoryLabelsMeta,
- tasks.ConvertTaskLabelsMeta,
- tasks.ConvertBugLabelsMeta,
+ //tasks.CollectCompanyMeta,
+ //tasks.ExtractCompanyMeta,
+ //tasks.CollectWorkspaceMeta,
+ //tasks.ExtractWorkspaceMeta,
+ tasks.CollectStoryCustomFieldsMeta,
+ tasks.ExtractStoryCustomFieldsMeta,
+ //tasks.CollectBugStatusMeta,
+ //tasks.ExtractBugStatusMeta,
+ //tasks.CollectUserMeta,
+ //tasks.ExtractUserMeta,
+ //tasks.CollectIterationMeta,
+ //tasks.ExtractIterationMeta,
+ //tasks.CollectStoryMeta,
+ //tasks.CollectBugMeta,
+ //tasks.CollectTaskMeta,
+ //tasks.ExtractStoryMeta,
+ //tasks.ExtractBugMeta,
+ //tasks.ExtractTaskMeta,
+ //tasks.CollectBugChangelogMeta,
+ //tasks.ExtractBugChangelogMeta,
+ //tasks.CollectStoryChangelogMeta,
+ //tasks.ExtractStoryChangelogMeta,
+ //tasks.CollectTaskChangelogMeta,
+ //tasks.ExtractTaskChangelogMeta,
+ //tasks.CollectWorklogMeta,
+ //tasks.ExtractWorklogMeta,
+ //tasks.CollectBugCommitMeta,
+ //tasks.ExtractBugCommitMeta,
+ //tasks.CollectStoryCommitMeta,
+ //tasks.ExtractStoryCommitMeta,
+ //tasks.CollectTaskCommitMeta,
+ //tasks.ExtractTaskCommitMeta,
+ //tasks.ConvertWorkspaceMeta,
+ //tasks.ConvertUserMeta,
+ //tasks.ConvertIterationMeta,
+ //tasks.ConvertStoryMeta,
+ //tasks.ConvertBugMeta,
+ //tasks.ConvertTaskMeta,
+ //tasks.ConvertWorklogMeta,
+ //tasks.ConvertBugChangelogMeta,
+ //tasks.ConvertStoryChangelogMeta,
+ //tasks.ConvertTaskChangelogMeta,
+ //tasks.ConvertBugCommitMeta,
+ //tasks.ConvertStoryCommitMeta,
+ //tasks.ConvertTaskCommitMeta,
+ //tasks.ConvertStoryLabelsMeta,
+ //tasks.ConvertTaskLabelsMeta,
+ //tasks.ConvertBugLabelsMeta,
}
}
@@ -182,14 +186,11 @@ func main() {
cmd := &cobra.Command{Use: "tapd"}
connectionId := cmd.Flags().Uint64P("connection", "c", 0, "tapd
connection id")
workspaceId := cmd.Flags().Uint64P("workspace", "w", 0, "tapd workspace
id")
+ companyId := cmd.Flags().Uint64P("company", "o", 0, "tapd company id")
err := cmd.MarkFlagRequired("connection")
if err != nil {
panic(err)
}
- //err = cmd.MarkFlagRequired("company")
- //if err != nil {
- // panic(err)
- //}
err = cmd.MarkFlagRequired("workspace")
if err != nil {
panic(err)
@@ -198,6 +199,7 @@ func main() {
runner.DirectRun(c, args, PluginEntry, map[string]interface{}{
"connectionId": *connectionId,
"workspaceId": *workspaceId,
+ "companyId": *companyId,
})
}
runner.RunCmd(cmd)
diff --git a/plugins/tapd/tasks/company_collector.go
b/plugins/tapd/tasks/company_collector.go
new file mode 100644
index 00000000..49678fb4
--- /dev/null
+++ b/plugins/tapd/tasks/company_collector.go
@@ -0,0 +1,76 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements. See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You 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 tasks
+
+import (
+ "encoding/json"
+ "fmt"
+ "github.com/apache/incubator-devlake/plugins/core"
+ "github.com/apache/incubator-devlake/plugins/helper"
+ "net/http"
+ "net/url"
+)
+
+const RAW_COMPANY_TABLE = "tapd_api_companies"
+
+var _ core.SubTaskEntryPoint = CollectCompanies
+
+func CollectCompanies(taskCtx core.SubTaskContext) error {
+ data := taskCtx.GetData().(*TapdTaskData)
+ logger := taskCtx.GetLogger()
+ logger.Info("collect companies")
+ collector, err := helper.NewApiCollector(helper.ApiCollectorArgs{
+ RawDataSubTaskArgs: helper.RawDataSubTaskArgs{
+ Ctx: taskCtx,
+ Params: TapdApiParams{
+ ConnectionId: data.Connection.ID,
+ CompanyId: data.Options.CompanyId,
+ },
+ Table: RAW_COMPANY_TABLE,
+ },
+ ApiClient: data.ApiClient,
+ //PageSize: 100,
+ UrlTemplate: "workspaces/projects",
+ Query: func(reqData *helper.RequestData) (url.Values, error) {
+ query := url.Values{}
+ query.Set("company_id", fmt.Sprintf("%v",
data.Options.CompanyId))
+ //query.Set("page", fmt.Sprintf("%v",
reqData.Pager.Page))
+ //query.Set("limit", fmt.Sprintf("%v",
reqData.Pager.Size))
+ return query, nil
+ },
+ ResponseParser: func(res *http.Response) ([]json.RawMessage,
error) {
+ var data struct {
+ Companies []json.RawMessage `json:"data"`
+ }
+ err := helper.UnmarshalResponse(res, &data)
+ return data.Companies, err
+ },
+ })
+ if err != nil {
+ logger.Error("collect company error:", err)
+ return err
+ }
+ return collector.Execute()
+}
+
+var CollectCompanyMeta = core.SubTaskMeta{
+ Name: "collectCompanies",
+ EntryPoint: CollectCompanies,
+ Required: true,
+ Description: "collect Tapd companies",
+}
diff --git a/plugins/tapd/tasks/company_extractor.go
b/plugins/tapd/tasks/company_extractor.go
new file mode 100644
index 00000000..4dd5eee7
--- /dev/null
+++ b/plugins/tapd/tasks/company_extractor.go
@@ -0,0 +1,67 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements. See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You 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 tasks
+
+import (
+ "encoding/json"
+ "github.com/apache/incubator-devlake/plugins/core"
+ "github.com/apache/incubator-devlake/plugins/helper"
+)
+
+var _ core.SubTaskEntryPoint = ExtractCompanies
+
+var ExtractCompanyMeta = core.SubTaskMeta{
+ Name: "extractCompanies",
+ EntryPoint: ExtractCompanies,
+ EnabledByDefault: true,
+ Description: "Extract raw company data into tool layer table
_tool_tapd_workspaces",
+}
+
+func ExtractCompanies(taskCtx core.SubTaskContext) error {
+ data := taskCtx.GetData().(*TapdTaskData)
+ extractor, err := helper.NewApiExtractor(helper.ApiExtractorArgs{
+ RawDataSubTaskArgs: helper.RawDataSubTaskArgs{
+ Ctx: taskCtx,
+ Params: TapdApiParams{
+ ConnectionId: data.Connection.ID,
+ CompanyId: data.Options.CompanyId,
+ },
+ Table: RAW_COMPANY_TABLE,
+ },
+ Extract: func(row *helper.RawData) ([]interface{}, error) {
+ var workspaceRes TapdWorkspaceRes
+ err := json.Unmarshal(row.Data, &workspaceRes)
+ if err != nil {
+ return nil, err
+ }
+
+ ws := workspaceRes.Workspace
+
+ ws.ConnectionId = data.Connection.ID
+ return []interface{}{
+ &ws,
+ }, nil
+ },
+ })
+
+ if err != nil {
+ return err
+ }
+
+ return extractor.Execute()
+}
diff --git a/plugins/tapd/tasks/story_custom_fields_collector.go
b/plugins/tapd/tasks/story_custom_fields_collector.go
new file mode 100644
index 00000000..888f8991
--- /dev/null
+++ b/plugins/tapd/tasks/story_custom_fields_collector.go
@@ -0,0 +1,74 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements. See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You 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 tasks
+
+import (
+ "encoding/json"
+ "fmt"
+ "github.com/apache/incubator-devlake/plugins/core"
+ "github.com/apache/incubator-devlake/plugins/helper"
+ "net/http"
+ "net/url"
+)
+
+const RAW_STORY_CUSTOM_FIELDS_TABLE = "tapd_api_story_story_custom_fields"
+
+var _ core.SubTaskEntryPoint = CollectStoryCustomFields
+
+func CollectStoryCustomFields(taskCtx core.SubTaskContext) error {
+ data := taskCtx.GetData().(*TapdTaskData)
+ logger := taskCtx.GetLogger()
+ logger.Info("collect story_custom_fields")
+ collector, err := helper.NewApiCollector(helper.ApiCollectorArgs{
+ RawDataSubTaskArgs: helper.RawDataSubTaskArgs{
+ Ctx: taskCtx,
+ Params: TapdApiParams{
+ ConnectionId: data.Connection.ID,
+ WorkspaceID: data.Options.WorkspaceID,
+ },
+ Table: RAW_STORY_CUSTOM_FIELDS_TABLE,
+ },
+ ApiClient: data.ApiClient,
+ //PageSize: 100,
+ UrlTemplate: "stories/custom_fields_settings",
+ Query: func(reqData *helper.RequestData) (url.Values, error) {
+ query := url.Values{}
+ query.Set("workspace_id", fmt.Sprintf("%v",
data.Options.WorkspaceID))
+ return query, nil
+ },
+ ResponseParser: func(res *http.Response) ([]json.RawMessage,
error) {
+ var data struct {
+ StoryCustomFields []json.RawMessage
`json:"data"`
+ }
+ err := helper.UnmarshalResponse(res, &data)
+ return data.StoryCustomFields, err
+ },
+ })
+ if err != nil {
+ logger.Error("collect story_custom_fields error:", err)
+ return err
+ }
+ return collector.Execute()
+}
+
+var CollectStoryCustomFieldsMeta = core.SubTaskMeta{
+ Name: "collectStoryCustomFields",
+ EntryPoint: CollectStoryCustomFields,
+ Required: true,
+ Description: "collect Tapd StoryCustomFields",
+}
diff --git a/plugins/tapd/tasks/story_custom_fields_extractor.go
b/plugins/tapd/tasks/story_custom_fields_extractor.go
new file mode 100644
index 00000000..6549485f
--- /dev/null
+++ b/plugins/tapd/tasks/story_custom_fields_extractor.go
@@ -0,0 +1,72 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements. See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You 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 tasks
+
+import (
+ "encoding/json"
+ "github.com/apache/incubator-devlake/plugins/core"
+ "github.com/apache/incubator-devlake/plugins/helper"
+ "github.com/apache/incubator-devlake/plugins/tapd/models"
+)
+
+var _ core.SubTaskEntryPoint = ExtractStoryCustomFields
+
+var ExtractStoryCustomFieldsMeta = core.SubTaskMeta{
+ Name: "extractStoryCustomFields",
+ EntryPoint: ExtractStoryCustomFields,
+ EnabledByDefault: true,
+ Description: "Extract raw company data into tool layer table
_tool_tapd_story_custom_fields",
+}
+
+type TapdStoryCustomFieldsRes struct {
+ CustomFieldConfig models.TapdStoryCustomFields
+}
+
+func ExtractStoryCustomFields(taskCtx core.SubTaskContext) error {
+ data := taskCtx.GetData().(*TapdTaskData)
+ extractor, err := helper.NewApiExtractor(helper.ApiExtractorArgs{
+ RawDataSubTaskArgs: helper.RawDataSubTaskArgs{
+ Ctx: taskCtx,
+ Params: TapdApiParams{
+ ConnectionId: data.Connection.ID,
+ WorkspaceID: data.Options.WorkspaceID,
+ },
+ Table: RAW_STORY_CUSTOM_FIELDS_TABLE,
+ },
+ Extract: func(row *helper.RawData) ([]interface{}, error) {
+ var customFields TapdStoryCustomFieldsRes
+ err := json.Unmarshal(row.Data, &customFields)
+ if err != nil {
+ return nil, err
+ }
+
+ toolL := customFields.CustomFieldConfig
+
+ toolL.ConnectionId = data.Connection.ID
+ return []interface{}{
+ &toolL,
+ }, nil
+ },
+ })
+
+ if err != nil {
+ return err
+ }
+
+ return extractor.Execute()
+}