feat: 同步Jira、TAPD缺陷
This commit is contained in:
parent
ebf684edef
commit
47842c10bc
|
@ -272,7 +272,8 @@ public class ApiScenarioModuleService extends NodeTreeService<ApiScenarioModuleD
|
|||
checkApiScenarioModuleExist(request);
|
||||
List<ApiScenarioDTO> apiScenarios = queryByModuleIds(request);
|
||||
apiScenarios.forEach(apiScenario -> {
|
||||
StringBuilder path = new StringBuilder(apiScenario.getModulePath());
|
||||
String modulePath = apiScenario.getModulePath();
|
||||
StringBuilder path = new StringBuilder(modulePath == null ? "" : modulePath);
|
||||
List<String> pathLists = Arrays.asList(path.toString().split("/"));
|
||||
if (pathLists.size() > request.getLevel()) {
|
||||
pathLists.set(request.getLevel(), request.getName());
|
||||
|
|
|
@ -16,4 +16,6 @@ public interface ExtIssuesMapper {
|
|||
List<IssuesDao> getRelateIssues(@Param("request") IssuesRequest request);
|
||||
|
||||
Issues getNextNum(String projectId);
|
||||
|
||||
List<IssuesDao> getIssueForSync(String projectId);
|
||||
}
|
||||
|
|
|
@ -34,12 +34,20 @@
|
|||
and test_case_issues.issues_id is null
|
||||
<include refid="io.metersphere.base.mapper.ext.ExtBaseMapper.orders"/>
|
||||
</select>
|
||||
<select id="getIssueForSync" resultType="io.metersphere.base.domain.IssuesDao">
|
||||
select id,platform
|
||||
from issues
|
||||
where project_id = #{projectId} and platform != 'Local';
|
||||
</select>
|
||||
|
||||
<sql id="queryWhereCondition">
|
||||
<where>
|
||||
|
||||
<if test="request.name != null">
|
||||
and issues.title LIKE CONCAT('%', #{request.name}, '%')
|
||||
and (
|
||||
issues.title LIKE CONCAT('%', #{request.name}, '%')
|
||||
or issues.id LIKE CONCAT('%', #{request.name}, '%')
|
||||
)
|
||||
</if>
|
||||
|
||||
<if test="request.projectId != null and request.projectId != ''">
|
||||
|
|
|
@ -18,4 +18,5 @@ public interface ExtProjectMapper {
|
|||
|
||||
String getSystemIdByProjectId(String projectId);
|
||||
|
||||
List<String> getProjectIds();
|
||||
}
|
||||
|
|
|
@ -110,6 +110,9 @@
|
|||
<select id="getSystemIdByProjectId" resultType="java.lang.String">
|
||||
SELECT system_id FROM project WHERE id = #{0}
|
||||
</select>
|
||||
<select id="getProjectIds" resultType="java.lang.String">
|
||||
select id from project;
|
||||
</select>
|
||||
|
||||
|
||||
<update id="removeIssuePlatform">
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
package io.metersphere.commons.constants;
|
||||
|
||||
public enum ScheduleGroup {
|
||||
API_TEST, PERFORMANCE_TEST, API_SCENARIO_TEST, TEST_PLAN_TEST, SWAGGER_IMPORT
|
||||
API_TEST, PERFORMANCE_TEST, API_SCENARIO_TEST, TEST_PLAN_TEST, SWAGGER_IMPORT, ISSUE_SYNC
|
||||
}
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
package io.metersphere.job.sechedule;
|
||||
|
||||
import io.metersphere.commons.constants.ScheduleGroup;
|
||||
import io.metersphere.commons.utils.CommonBeanFactory;
|
||||
import io.metersphere.track.service.IssuesService;
|
||||
import org.quartz.JobExecutionContext;
|
||||
import org.quartz.JobKey;
|
||||
import org.quartz.TriggerKey;
|
||||
|
||||
public class IssueSyncJob extends MsScheduleJob {
|
||||
|
||||
private IssuesService issuesService;
|
||||
|
||||
public IssueSyncJob() {
|
||||
issuesService = CommonBeanFactory.getBean(IssuesService.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
void businessExecute(JobExecutionContext context) {
|
||||
issuesService.syncThirdPartyIssues();
|
||||
}
|
||||
|
||||
public static JobKey getJobKey(String projectId) {
|
||||
return new JobKey(projectId, ScheduleGroup.ISSUE_SYNC.name());
|
||||
}
|
||||
|
||||
public static TriggerKey getTriggerKey(String projectId) {
|
||||
return new TriggerKey(projectId, ScheduleGroup.ISSUE_SYNC.name());
|
||||
}
|
||||
}
|
||||
|
|
@ -451,4 +451,8 @@ public class ProjectService {
|
|||
return returnList.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
public List<String> getProjectIds() {
|
||||
return extProjectMapper.getProjectIds();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -92,10 +92,13 @@ public class IssuesController {
|
|||
return issuesService.getZentaoBuilds(request);
|
||||
}
|
||||
|
||||
@PostMapping("/get/platform/issue")
|
||||
public IssuesWithBLOBs getPlatformIssue(@RequestBody IssuesWithBLOBs issue) {
|
||||
return issuesService.getPlatformIssue(issue);
|
||||
}
|
||||
|
||||
// @PostMapping("/get/platform/issue")
|
||||
// public IssuesWithBLOBs getPlatformIssue(@RequestBody IssuesWithBLOBs issue) {
|
||||
// return issuesService.getPlatformIssue(issue);
|
||||
// }
|
||||
|
||||
@GetMapping("/sync/{projectId}")
|
||||
public void getPlatformIssue(@PathVariable String projectId) {
|
||||
issuesService.syncThirdPartyIssues(projectId);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package io.metersphere.track.issue;
|
||||
|
||||
import io.metersphere.base.domain.IssuesDao;
|
||||
import io.metersphere.base.domain.Project;
|
||||
import io.metersphere.track.dto.DemandDTO;
|
||||
import io.metersphere.track.issue.domain.PlatformUser;
|
||||
import io.metersphere.track.request.testcase.IssuesRequest;
|
||||
|
@ -56,4 +57,11 @@ public interface IssuesPlatform {
|
|||
* @return platform user list
|
||||
*/
|
||||
List<PlatformUser> getPlatformUser();
|
||||
|
||||
/**
|
||||
* 同步缺陷最新变更
|
||||
* @param project
|
||||
* @param tapdIssues
|
||||
*/
|
||||
void syncIssues(Project project, List<IssuesDao> tapdIssues);
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ import org.springframework.http.HttpEntity;
|
|||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.client.HttpClientErrorException;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
@ -64,8 +65,6 @@ public class JiraPlatform extends AbstractIssuePlatform {
|
|||
|
||||
@Override
|
||||
public List<IssuesDao> getIssue(IssuesRequest issuesRequest) {
|
||||
List<IssuesDao> list = new ArrayList<>();
|
||||
|
||||
issuesRequest.setPlatform(IssuesManagePlatform.Jira.toString());
|
||||
List<IssuesDao> issues;
|
||||
if (StringUtils.isNotBlank(issuesRequest.getProjectId())) {
|
||||
|
@ -73,26 +72,26 @@ public class JiraPlatform extends AbstractIssuePlatform {
|
|||
} else {
|
||||
issues = extIssuesMapper.getIssuesByCaseId(issuesRequest);
|
||||
}
|
||||
setConfig(issuesRequest.getOrganizationId());
|
||||
issues.forEach(item -> {
|
||||
String issuesId = item.getId();
|
||||
parseIssue(item, jiraClientV2.getIssues(issuesId));
|
||||
if (StringUtils.isBlank(item.getId())) {
|
||||
// 缺陷不存在,解除用例和缺陷的关联
|
||||
TestCaseIssuesExample issuesExample = new TestCaseIssuesExample();
|
||||
issuesExample.createCriteria()
|
||||
.andTestCaseIdEqualTo(testCaseId)
|
||||
.andIssuesIdEqualTo(issuesId);
|
||||
testCaseIssuesMapper.deleteByExample(issuesExample);
|
||||
issuesMapper.deleteByPrimaryKey(issuesId);
|
||||
} else {
|
||||
// 缺陷状态为 完成,则不显示
|
||||
if (!StringUtils.equals("done", item.getStatus())) {
|
||||
list.add(item);
|
||||
}
|
||||
}
|
||||
});
|
||||
return list;
|
||||
// setConfig(issuesRequest.getOrganizationId());
|
||||
// issues.forEach(item -> {
|
||||
// String issuesId = item.getId();
|
||||
// parseIssue(item, jiraClientV2.getIssues(issuesId));
|
||||
// if (StringUtils.isBlank(item.getId())) {
|
||||
// // 缺陷不存在,解除用例和缺陷的关联
|
||||
// TestCaseIssuesExample issuesExample = new TestCaseIssuesExample();
|
||||
// issuesExample.createCriteria()
|
||||
// .andTestCaseIdEqualTo(testCaseId)
|
||||
// .andIssuesIdEqualTo(issuesId);
|
||||
// testCaseIssuesMapper.deleteByExample(issuesExample);
|
||||
// issuesMapper.deleteByPrimaryKey(issuesId);
|
||||
// } else {
|
||||
// // 缺陷状态为 完成,则不显示
|
||||
// if (!StringUtils.equals("done", item.getStatus())) {
|
||||
// list.add(item);
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
return issues;
|
||||
}
|
||||
|
||||
public void parseIssue(IssuesWithBLOBs item, JiraIssue jiraIssue) {
|
||||
|
@ -296,6 +295,27 @@ public class JiraPlatform extends AbstractIssuePlatform {
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void syncIssues(Project project, List<IssuesDao> tapdIssues) {
|
||||
tapdIssues.forEach(item -> {
|
||||
setConfig(null);
|
||||
try {
|
||||
parseIssue(item, jiraClientV2.getIssues(item.getId()));
|
||||
// 缺陷状态为 完成,则不显示
|
||||
if (StringUtils.equals("done", item.getStatus())) {
|
||||
item.setStatus(IssuesStatus.RESOLVED.toString());
|
||||
}
|
||||
issuesMapper.updateByPrimaryKeySelective(item);
|
||||
} catch (HttpClientErrorException e) {
|
||||
if (e.getRawStatusCode() == 404) {
|
||||
// 标记成删除
|
||||
item.setStatus(IssuesStatus.DELETE.toString());
|
||||
issuesMapper.deleteByPrimaryKey(item.getId());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
String getProjectId(String projectId) {
|
||||
if (StringUtils.isNotBlank(projectId)) {
|
||||
|
|
|
@ -2,6 +2,7 @@ package io.metersphere.track.issue;
|
|||
|
||||
import io.metersphere.base.domain.IssuesDao;
|
||||
import io.metersphere.base.domain.IssuesWithBLOBs;
|
||||
import io.metersphere.base.domain.Project;
|
||||
import io.metersphere.commons.constants.IssuesManagePlatform;
|
||||
import io.metersphere.commons.user.SessionUser;
|
||||
import io.metersphere.commons.utils.BeanUtils;
|
||||
|
@ -81,6 +82,11 @@ public class LocalPlatform extends AbstractIssuePlatform {
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void syncIssues(Project project, List<IssuesDao> tapdIssues) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
String getProjectId(String projectId) {
|
||||
return null;
|
||||
|
|
|
@ -3,16 +3,24 @@ package io.metersphere.track.issue;
|
|||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import io.metersphere.base.domain.*;
|
||||
import io.metersphere.base.domain.Issues;
|
||||
import io.metersphere.base.domain.IssuesDao;
|
||||
import io.metersphere.base.domain.Project;
|
||||
import io.metersphere.base.domain.TestCaseWithBLOBs;
|
||||
import io.metersphere.commons.constants.IssuesManagePlatform;
|
||||
import io.metersphere.commons.constants.IssuesStatus;
|
||||
import io.metersphere.commons.exception.MSException;
|
||||
import io.metersphere.commons.utils.BeanUtils;
|
||||
import io.metersphere.commons.utils.LogUtil;
|
||||
import io.metersphere.commons.utils.SessionUtils;
|
||||
import io.metersphere.controller.ResultHolder;
|
||||
import io.metersphere.dto.CustomFieldItemDTO;
|
||||
import io.metersphere.dto.UserDTO;
|
||||
import io.metersphere.track.dto.DemandDTO;
|
||||
import io.metersphere.track.issue.client.TapdClient;
|
||||
import io.metersphere.track.issue.domain.PlatformUser;
|
||||
import io.metersphere.track.issue.domain.TapdConfig;
|
||||
import io.metersphere.track.issue.domain.TapdGetIssueResponse;
|
||||
import io.metersphere.track.request.testcase.IssuesRequest;
|
||||
import io.metersphere.track.request.testcase.IssuesUpdateRequest;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
|
@ -33,15 +41,17 @@ public class TapdPlatform extends AbstractIssuePlatform {
|
|||
|
||||
protected String key = IssuesManagePlatform.Tapd.toString();
|
||||
|
||||
private TapdClient tapdClient = new TapdClient();
|
||||
|
||||
|
||||
public TapdPlatform(IssuesRequest issueRequest) {
|
||||
super(issueRequest);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<IssuesDao> getIssue(IssuesRequest issuesRequest) {
|
||||
List<IssuesDao> list = new ArrayList<>();
|
||||
String tapdId = getProjectId(issuesRequest.getProjectId());
|
||||
|
||||
// List<IssuesDao> list = new ArrayList<>();
|
||||
// String tapdId = getProjectId(issuesRequest.getProjectId());
|
||||
issuesRequest.setPlatform(IssuesManagePlatform.Tapd.toString());
|
||||
List<IssuesDao> issues;
|
||||
if (StringUtils.isNotBlank(issuesRequest.getProjectId())) {
|
||||
|
@ -49,30 +59,29 @@ public class TapdPlatform extends AbstractIssuePlatform {
|
|||
} else {
|
||||
issues = extIssuesMapper.getIssuesByCaseId(issuesRequest);
|
||||
}
|
||||
|
||||
issues.forEach(item -> {
|
||||
String issuesId = item.getId();
|
||||
IssuesDao dto = getTapdIssues(tapdId, issuesId);
|
||||
dto.setNum(item.getNum());
|
||||
if (StringUtils.isBlank(dto.getId())) {
|
||||
// 缺陷不存在,解除用例和缺陷的关联
|
||||
TestCaseIssuesExample issuesExample = new TestCaseIssuesExample();
|
||||
TestCaseIssuesExample.Criteria criteria = issuesExample.createCriteria();
|
||||
if (StringUtils.isNotBlank(testCaseId)) {
|
||||
criteria.andTestCaseIdEqualTo(testCaseId);
|
||||
}
|
||||
criteria.andIssuesIdEqualTo(issuesId);
|
||||
testCaseIssuesMapper.deleteByExample(issuesExample);
|
||||
issuesMapper.deleteByPrimaryKey(issuesId);
|
||||
} else {
|
||||
dto.setPlatform(IssuesManagePlatform.Tapd.toString());
|
||||
// 缺陷状态为 关闭,则不显示
|
||||
if (!StringUtils.equals(IssuesStatus.CLOSED.toString(), dto.getStatus())) {
|
||||
list.add(dto);
|
||||
}
|
||||
}
|
||||
});
|
||||
return list;
|
||||
// issues.forEach(item -> {
|
||||
// String issuesId = item.getId();
|
||||
// IssuesDao dto = getTapdIssues(tapdId, issuesId);
|
||||
// dto.setNum(item.getNum());
|
||||
// if (StringUtils.isBlank(dto.getId())) {
|
||||
// // 缺陷不存在,解除用例和缺陷的关联
|
||||
// TestCaseIssuesExample issuesExample = new TestCaseIssuesExample();
|
||||
// TestCaseIssuesExample.Criteria criteria = issuesExample.createCriteria();
|
||||
// if (StringUtils.isNotBlank(testCaseId)) {
|
||||
// criteria.andTestCaseIdEqualTo(testCaseId);
|
||||
// }
|
||||
// criteria.andIssuesIdEqualTo(issuesId);
|
||||
// testCaseIssuesMapper.deleteByExample(issuesExample);
|
||||
// issuesMapper.deleteByPrimaryKey(issuesId);
|
||||
// } else {
|
||||
// dto.setPlatform(IssuesManagePlatform.Tapd.toString());
|
||||
// // 缺陷状态为 关闭,则不显示
|
||||
// if (!StringUtils.equals(IssuesStatus.CLOSED.toString(), dto.getStatus())) {
|
||||
// list.add(dto);
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
return issues;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -152,7 +161,6 @@ public class TapdPlatform extends AbstractIssuePlatform {
|
|||
List<CustomFieldItemDTO> customFields = getCustomFields(issuesRequest.getCustomFields());
|
||||
|
||||
String url = "https://api.tapd.cn/bugs";
|
||||
String testCaseId = issuesRequest.getTestCaseId();
|
||||
String tapdId = getProjectId(issuesRequest.getProjectId());
|
||||
|
||||
if (StringUtils.isBlank(tapdId)) {
|
||||
|
@ -240,6 +248,33 @@ public class TapdPlatform extends AbstractIssuePlatform {
|
|||
return users;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void syncIssues(Project project, List<IssuesDao> tapdIssues) {
|
||||
int pageNum = 1;
|
||||
int limit = 200;
|
||||
int count = 200;
|
||||
List<String> ids = tapdIssues.stream()
|
||||
.map(Issues::getId)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
setConfig(null);
|
||||
|
||||
while (count == limit) {
|
||||
count = 0;
|
||||
TapdGetIssueResponse result = tapdClient.getIssueForPageByIds(project.getTapdId(), pageNum, limit, ids);
|
||||
List<TapdGetIssueResponse.Data> data = result.getData();
|
||||
count = data.size();
|
||||
pageNum++;
|
||||
data.forEach(issue -> {
|
||||
TapdGetIssueResponse.Bug bug = issue.getBug();
|
||||
IssuesDao issuesDao = new IssuesDao();
|
||||
BeanUtils.copyBean(issuesDao, bug);
|
||||
// tapdClient.getStatusMap(projectId);
|
||||
issuesMapper.updateByPrimaryKeySelective(issuesDao);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
String getProjectId(String projectId) {
|
||||
if (StringUtils.isNotBlank(projectId)) {
|
||||
|
@ -250,6 +285,26 @@ public class TapdPlatform extends AbstractIssuePlatform {
|
|||
return project.getTapdId();
|
||||
}
|
||||
|
||||
public TapdConfig getConfig(String orgId) {
|
||||
TapdConfig tapdConfig = null;
|
||||
String config = getPlatformConfig(IssuesManagePlatform.Tapd.toString());
|
||||
if (StringUtils.isNotBlank(config)) {
|
||||
tapdConfig = JSONObject.parseObject(config, TapdConfig.class);
|
||||
UserDTO.PlatformInfo userPlatInfo = getUserPlatInfo(orgId, SessionUtils.getUserId());
|
||||
if (userPlatInfo != null && StringUtils.isNotBlank(userPlatInfo.getTapdUserName())) {
|
||||
// tapdConfig.setAccount(userPlatInfo.getTapdUserName());
|
||||
}
|
||||
}
|
||||
// validateConfig(tapdConfig);
|
||||
return tapdConfig;
|
||||
}
|
||||
|
||||
public TapdConfig setConfig(String orgId) {
|
||||
TapdConfig config = getConfig(orgId);
|
||||
tapdClient.setConfig(config);
|
||||
return config;
|
||||
}
|
||||
|
||||
private ResultHolder call(String url) {
|
||||
return call(url, HttpMethod.GET, null);
|
||||
}
|
||||
|
|
|
@ -371,6 +371,11 @@ public class ZentaoPlatform extends AbstractIssuePlatform {
|
|||
return users;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void syncIssues(Project project, List<IssuesDao> tapdIssues) {
|
||||
|
||||
}
|
||||
|
||||
public List<ZentaoBuild> getBuilds() {
|
||||
String session = login();
|
||||
String projectId1 = getProjectId(projectId);
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
package io.metersphere.track.issue.client;
|
||||
|
||||
import io.metersphere.commons.exception.MSException;
|
||||
import io.metersphere.track.issue.domain.TapdConfig;
|
||||
import io.metersphere.track.issue.domain.TapdGetIssueResponse;
|
||||
import io.metersphere.track.issue.domain.TapdStatusMapResponse;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class TapdClient extends BaseClient {
|
||||
|
||||
protected String ENDPOINT = "https://api.tapd.cn";
|
||||
|
||||
protected String USER_NAME;
|
||||
|
||||
protected String PASSWD;
|
||||
|
||||
// public JiraAddIssueResponse addIssue(String body) {
|
||||
// LogUtil.debug("addIssue: " + body);
|
||||
// HttpHeaders headers = getAuthHeader();
|
||||
// headers.setContentType(MediaType.APPLICATION_JSON);
|
||||
// HttpEntity<String> requestEntity = new HttpEntity<>(body, headers);
|
||||
// ResponseEntity<String> response = restTemplate.exchange(getBaseUrl() + "/issue", HttpMethod.POST, requestEntity, String.class);
|
||||
// return (JiraAddIssueResponse) getResultForObject(JiraAddIssueResponse.class, response);
|
||||
// }
|
||||
|
||||
public TapdGetIssueResponse getIssueForPage(String projectId, int pageNum, int limit) {
|
||||
return getIssueForPageByIds(projectId, pageNum, limit, null);
|
||||
}
|
||||
|
||||
public TapdStatusMapResponse getStatusMap(String projectId) {
|
||||
String url = getBaseUrl() + "/workflows/status_map?workspace_id={1}&system=bug";
|
||||
ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.GET, getAuthHttpEntity(), String.class, projectId);
|
||||
return (TapdStatusMapResponse) getResultForObject(TapdStatusMapResponse.class, response);
|
||||
}
|
||||
|
||||
public TapdGetIssueResponse getIssueForPageByIds(String projectId, int pageNum, int limit, List<String> ids) {
|
||||
String url = getBaseUrl() + "/bugs?workspace_id={1}&page={2}&limit={3}&fields={4}";
|
||||
StringBuilder idStr = new StringBuilder();
|
||||
ids.forEach(item -> {
|
||||
idStr.append(item + ",");
|
||||
});
|
||||
if (!CollectionUtils.isEmpty(ids)) {
|
||||
url += "&id={5}";
|
||||
}
|
||||
String fields = "id,title,description,priority,severity,reporter,status";
|
||||
ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.GET, getAuthHttpEntity(), String.class,
|
||||
projectId, pageNum, limit, fields, idStr);
|
||||
return (TapdGetIssueResponse) getResultForObject(TapdGetIssueResponse.class, response);
|
||||
}
|
||||
|
||||
protected HttpEntity<MultiValueMap> getAuthHttpEntity() {
|
||||
return new HttpEntity<>(getAuthHeader());
|
||||
}
|
||||
|
||||
protected HttpHeaders getAuthHeader() {
|
||||
return getBasicHttpHeaders(USER_NAME, PASSWD);
|
||||
}
|
||||
|
||||
protected String getBaseUrl() {
|
||||
return ENDPOINT;
|
||||
}
|
||||
|
||||
public void setConfig(TapdConfig config) {
|
||||
if (config == null) {
|
||||
MSException.throwException("config is null");
|
||||
}
|
||||
USER_NAME = config.getAccount();
|
||||
PASSWD = config.getPassword();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package io.metersphere.track.issue.domain;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class TapdConfig {
|
||||
private String account;
|
||||
private String password;
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package io.metersphere.track.issue.domain;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class TapdGetIssueResponse {
|
||||
|
||||
private int status;
|
||||
private List<Data> data;
|
||||
private String info;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public static class Data {
|
||||
private Bug bug;
|
||||
}
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public static class Bug {
|
||||
private String id;
|
||||
private String title;
|
||||
private String description;
|
||||
// private String priority;
|
||||
// private String severity;
|
||||
// private String reporter;
|
||||
// private String status;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package io.metersphere.track.issue.domain;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class TapdStatusMapResponse {
|
||||
|
||||
private int status;
|
||||
private Data data;
|
||||
private String info;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class Data {
|
||||
@JSONField(name = "new")
|
||||
private String create;
|
||||
@JSONField(name = "in_progress")
|
||||
private String inProgress;
|
||||
private String resolved;
|
||||
private String verified;
|
||||
private String reopened;
|
||||
private String rejected;
|
||||
private String closed;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,7 +1,6 @@
|
|||
package io.metersphere.track.service;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import io.metersphere.base.domain.*;
|
||||
import io.metersphere.base.mapper.IssueTemplateMapper;
|
||||
import io.metersphere.base.mapper.IssuesMapper;
|
||||
|
@ -42,6 +41,7 @@ import java.util.ArrayList;
|
|||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
|
@ -299,18 +299,6 @@ public class IssuesService {
|
|||
|
||||
public List<IssuesDao> list(IssuesRequest request) {
|
||||
request.setOrders(ServiceUtils.getDefaultOrder(request.getOrders()));
|
||||
|
||||
|
||||
// List<IssuesDao> list = new ArrayList<>();
|
||||
// String projectId = request.getProjectId();
|
||||
// Project project = projectService.getProjectById(projectId);
|
||||
// List<String> platforms = getPlatforms(project);
|
||||
// platforms.add(IssuesManagePlatform.Local.toString());
|
||||
// List<AbstractIssuePlatform> platformList = IssueFactory.createPlatforms(platforms, request);
|
||||
// platformList.forEach(platform -> {
|
||||
// List<IssuesDao> issue = platform.getIssue(request);
|
||||
// list.addAll(issue);
|
||||
// });
|
||||
List<IssuesDao> issues = extIssuesMapper.getIssuesByProjectId(request);
|
||||
|
||||
List<String> ids = issues.stream()
|
||||
|
@ -334,17 +322,7 @@ public class IssuesService {
|
|||
item.setResourceName(planMap.get(item.getResourceId()));
|
||||
}
|
||||
});
|
||||
|
||||
// Map<String, List<IssuesDao>> issueMap = getIssueMap(issues);
|
||||
// Map<String, AbstractIssuePlatform> platformMap = getPlatformMap(request);
|
||||
// issueMap.forEach((platformName, data) -> {
|
||||
// AbstractIssuePlatform platform = platformMap.get(platformName);
|
||||
// if (platform != null) {
|
||||
// platform.filter(data);
|
||||
// }
|
||||
// });
|
||||
return issues;
|
||||
// return list;
|
||||
}
|
||||
|
||||
public Map<String, List<IssuesDao>> getIssueMap(List<IssuesDao> issues) {
|
||||
|
@ -372,41 +350,101 @@ public class IssuesService {
|
|||
return IssueFactory.createPlatformsForMap(platforms, request);
|
||||
}
|
||||
|
||||
public IssuesWithBLOBs getPlatformIssue(IssuesWithBLOBs issue) {
|
||||
String platform = issue.getPlatform();
|
||||
if (StringUtils.isNotBlank(issue.getProjectId())) {
|
||||
Project project = projectService.getProjectById(issue.getProjectId());
|
||||
Workspace workspace = workspaceMapper.selectByPrimaryKey(project.getWorkspaceId());
|
||||
String orgId = workspace.getOrganizationId();
|
||||
try {
|
||||
if (StringUtils.equals(platform, IssuesManagePlatform.Tapd.name())) {
|
||||
TapdPlatform tapdPlatform = new TapdPlatform(new IssuesRequest());
|
||||
String tapdId = projectService.getProjectById(issue.getProjectId()).getTapdId();
|
||||
IssuesDao tapdIssues = tapdPlatform.getTapdIssues(tapdId, issue.getId());
|
||||
issue.setTitle(tapdIssues.getTitle());
|
||||
issue.setDescription(tapdIssues.getDescription());
|
||||
issue.setStatus(tapdIssues.getStatus());
|
||||
} else if (StringUtils.equals(platform, IssuesManagePlatform.Jira.name())) {
|
||||
JiraPlatform jiraPlatform = new JiraPlatform(new IssuesRequest());
|
||||
jiraPlatform.getJiraIssues(issue, issue.getId());
|
||||
} else if (StringUtils.equals(platform, IssuesManagePlatform.Zentao.name())) {
|
||||
String config = getConfig(orgId, IssuesManagePlatform.Zentao.toString());
|
||||
JSONObject object = JSON.parseObject(config);
|
||||
String account = object.getString("account");
|
||||
String password = object.getString("password");
|
||||
String url = object.getString("url");
|
||||
ZentaoPlatform zentaoPlatform = new ZentaoPlatform(account, password, url);
|
||||
IssuesDao zentaoIssues = zentaoPlatform.getZentaoIssues(issue.getId());
|
||||
issue.setTitle(zentaoIssues.getTitle());
|
||||
issue.setDescription(zentaoIssues.getDescription());
|
||||
issue.setStatus(zentaoIssues.getStatus());
|
||||
// public IssuesWithBLOBs getPlatformIssue(IssuesWithBLOBs issue) {
|
||||
// String platform = issue.getPlatform();
|
||||
// if (StringUtils.isNotBlank(issue.getProjectId())) {
|
||||
// Project project = projectService.getProjectById(issue.getProjectId());
|
||||
// Workspace workspace = workspaceMapper.selectByPrimaryKey(project.getWorkspaceId());
|
||||
// String orgId = workspace.getOrganizationId();
|
||||
// try {
|
||||
// if (StringUtils.equals(platform, IssuesManagePlatform.Tapd.name())) {
|
||||
// TapdPlatform tapdPlatform = new TapdPlatform(new IssuesRequest());
|
||||
// String tapdId = projectService.getProjectById(issue.getProjectId()).getTapdId();
|
||||
// IssuesDao tapdIssues = tapdPlatform.getTapdIssues(tapdId, issue.getId());
|
||||
// issue.setTitle(tapdIssues.getTitle());
|
||||
// issue.setDescription(tapdIssues.getDescription());
|
||||
// issue.setStatus(tapdIssues.getStatus());
|
||||
// } else if (StringUtils.equals(platform, IssuesManagePlatform.Jira.name())) {
|
||||
// JiraPlatform jiraPlatform = new JiraPlatform(new IssuesRequest());
|
||||
// jiraPlatform.getJiraIssues(issue, issue.getId());
|
||||
// } else if (StringUtils.equals(platform, IssuesManagePlatform.Zentao.name())) {
|
||||
// String config = getConfig(orgId, IssuesManagePlatform.Zentao.toString());
|
||||
// JSONObject object = JSON.parseObject(config);
|
||||
// String account = object.getString("account");
|
||||
// String password = object.getString("password");
|
||||
// String url = object.getString("url");
|
||||
// ZentaoPlatform zentaoPlatform = new ZentaoPlatform(account, password, url);
|
||||
// IssuesDao zentaoIssues = zentaoPlatform.getZentaoIssues(issue.getId());
|
||||
// issue.setTitle(zentaoIssues.getTitle());
|
||||
// issue.setDescription(zentaoIssues.getDescription());
|
||||
// issue.setStatus(zentaoIssues.getStatus());
|
||||
// }
|
||||
// } catch (Exception e) {
|
||||
// LogUtil.error(e.getMessage(), e);
|
||||
// }
|
||||
// }
|
||||
// return issue;
|
||||
// }
|
||||
|
||||
public void syncThirdPartyIssues() {
|
||||
List<String> projectIds = projectService.getProjectIds();
|
||||
projectIds.forEach(id -> {
|
||||
syncThirdPartyIssues(id);
|
||||
});
|
||||
}
|
||||
|
||||
public void syncThirdPartyIssues(String projectId) {
|
||||
if (StringUtils.isNotBlank(projectId)) {
|
||||
Project project = projectService.getProjectById(projectId);
|
||||
|
||||
List<IssuesDao> issues = extIssuesMapper.getIssueForSync(projectId);
|
||||
|
||||
if (CollectionUtils.isEmpty(issues)) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<IssuesDao> tapdIssues = issues.stream()
|
||||
.filter(item -> item.getPlatform().equals(IssuesManagePlatform.Tapd.name()))
|
||||
.collect(Collectors.toList());
|
||||
List<IssuesDao> jiraIssues = issues.stream()
|
||||
.filter(item -> item.getPlatform().equals(IssuesManagePlatform.Jira.name()))
|
||||
.collect(Collectors.toList());
|
||||
// List<IssuesDao> zentaoIssues = issues.stream()
|
||||
// .filter(item -> item.getPlatform().equals(IssuesManagePlatform.Zentao.name()))
|
||||
// .collect(Collectors.toList());
|
||||
|
||||
IssuesRequest issuesRequest = new IssuesRequest();
|
||||
issuesRequest.setProjectId(projectId);
|
||||
if (CollectionUtils.isNotEmpty(tapdIssues)) {
|
||||
TapdPlatform tapdPlatform = new TapdPlatform(issuesRequest);
|
||||
syncThirdPartyIssues(tapdPlatform::syncIssues, project, tapdIssues);
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(jiraIssues)) {
|
||||
JiraPlatform jiraPlatform = new JiraPlatform(new IssuesRequest());
|
||||
syncThirdPartyIssues(jiraPlatform::syncIssues, project, tapdIssues);
|
||||
}
|
||||
// if (CollectionUtils.isNotEmpty(zentaoIssues)) {
|
||||
// String config = getConfig(orgId, IssuesManagePlatform.Zentao.toString());
|
||||
// JSONObject object = JSON.parseObject(config);
|
||||
// String account = object.getString("account");
|
||||
// String password = object.getString("password");
|
||||
// String url = object.getString("url");
|
||||
// ZentaoPlatform zentaoPlatform = new ZentaoPlatform(account, password, url);
|
||||
// IssuesDao zentaoIssues = zentaoPlatform.getZentaoIssues(issue.getId());
|
||||
// issue.setTitle(zentaoIssues.getTitle());
|
||||
// issue.setDescription(zentaoIssues.getDescription());
|
||||
// issue.setStatus(zentaoIssues.getStatus());
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
public void syncThirdPartyIssues(BiConsumer<Project, List<IssuesDao>> syncFuc, Project project, List<IssuesDao> issues) {
|
||||
try {
|
||||
syncFuc.accept(project, issues);
|
||||
} catch (Exception e) {
|
||||
LogUtil.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
return issue;
|
||||
}
|
||||
|
||||
private String getConfig(String orgId, String platform) {
|
||||
IntegrationRequest request = new IntegrationRequest();
|
||||
|
|
|
@ -930,11 +930,6 @@ export default {
|
|||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
/deep/ .run-button {
|
||||
background-color: #409EFF;
|
||||
border-color: #409EFF;
|
||||
}
|
||||
|
||||
/deep/ .el-table__fixed-body-wrapper {
|
||||
z-index: auto !important;
|
||||
}
|
||||
|
|
|
@ -375,7 +375,7 @@ export default {
|
|||
this.createVisible = true;
|
||||
listenGoBack(this.handleClose);
|
||||
this.form = Object.assign({}, row);
|
||||
this.$get("/service/integration/all/" + getCurrentUser().lastOrganizationId, response => {
|
||||
this.$get("/service/integration/all/" + getCurrentOrganizationId(), response => {
|
||||
let data = response.data;
|
||||
let platforms = data.map(d => d.platform);
|
||||
if (platforms.indexOf("Tapd") !== -1) {
|
||||
|
|
|
@ -5,7 +5,14 @@
|
|||
<template v-slot:header>
|
||||
<ms-table-header :create-permission="['PROJECT_TRACK_ISSUE:READ+CREATE']" :condition.sync="page.condition" @search="getIssues" @create="handleCreate"
|
||||
:create-tip="$t('test_track.issue.create_issue')" :title="$t('test_track.issue.issue_list')"
|
||||
:tip="$t('issue.search_name')" :have-search="false"/>
|
||||
:tip="$t('commons.search_by_name_or_id')">
|
||||
<template v-slot:button>
|
||||
<el-tooltip v-if="hasThirdPart" :content="'更新第三方平台的缺陷内容'">
|
||||
<ms-table-button icon="el-icon-refresh" v-if="true"
|
||||
:content="'同步缺陷'" @click="syncIssues"/>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
</ms-table-header>
|
||||
</template>
|
||||
|
||||
<ms-table
|
||||
|
@ -40,6 +47,7 @@
|
|||
:label="$t('test_track.issue.id')"
|
||||
prop="num"
|
||||
:field="item"
|
||||
sortable
|
||||
:fields-width="fieldsWidth">
|
||||
</ms-table-column>
|
||||
|
||||
|
@ -47,6 +55,7 @@
|
|||
:field="item"
|
||||
:fields-width="fieldsWidth"
|
||||
:label="$t('test_track.issue.title')"
|
||||
sortable
|
||||
prop="title">
|
||||
</ms-table-column>
|
||||
|
||||
|
@ -136,7 +145,7 @@ import {
|
|||
import MsTableHeader from "@/business/components/common/components/MsTableHeader";
|
||||
import IssueDescriptionTableItem from "@/business/components/track/issue/IssueDescriptionTableItem";
|
||||
import IssueEdit from "@/business/components/track/issue/IssueEdit";
|
||||
import {getIssues} from "@/network/Issue";
|
||||
import {getIssues, syncIssues} from "@/network/Issue";
|
||||
import {
|
||||
getCustomFieldValue,
|
||||
getCustomTableWidth,
|
||||
|
@ -147,6 +156,7 @@ import MsMainContainer from "@/business/components/common/components/MsMainConta
|
|||
import {getCurrentProjectID} from "@/common/js/utils";
|
||||
import {getIssueTemplate} from "@/network/custom-field-template";
|
||||
import {getProjectMember} from "@/network/user";
|
||||
import {getIntegrationService} from "@/network/organization";
|
||||
|
||||
export default {
|
||||
name: "IssueList",
|
||||
|
@ -183,13 +193,17 @@ export default {
|
|||
}
|
||||
],
|
||||
issueTemplate: {},
|
||||
members: []
|
||||
members: [],
|
||||
platforms: []
|
||||
};
|
||||
},
|
||||
activated() {
|
||||
getProjectMember((data) => {
|
||||
this.members = data;
|
||||
});
|
||||
getIntegrationService((data) => {
|
||||
this.platforms = data.map(d => d.platform);
|
||||
});
|
||||
getIssueTemplate()
|
||||
.then((template) => {
|
||||
this.issueTemplate = template;
|
||||
|
@ -216,6 +230,14 @@ export default {
|
|||
},
|
||||
projectId() {
|
||||
return getCurrentProjectID();
|
||||
},
|
||||
hasThirdPart() {
|
||||
if (this.platforms.indexOf("Tapd") !== -1
|
||||
|| this.platforms.indexOf("Jira") !== -1
|
||||
|| this.platforms.indexOf("Zentao") !== -1) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
@ -258,6 +280,10 @@ export default {
|
|||
saveSortField(key,orders){
|
||||
saveLastTableSortField(key,JSON.stringify(orders));
|
||||
},
|
||||
syncIssues() {
|
||||
this.page.result = syncIssues();
|
||||
this.getIssues();
|
||||
},
|
||||
getSortField(){
|
||||
let orderJsonStr = getLastTableSortField(this.tableHeaderKey);
|
||||
let returnObj = null;
|
||||
|
|
|
@ -64,7 +64,6 @@
|
|||
import MsTablePagination from "@/business/components/common/pagination/TablePagination";
|
||||
import ShowMoreBtn from "@/business/components/track/case/components/ShowMoreBtn";
|
||||
import MsTag from "../../../../../common/components/MsTag";
|
||||
import {getUUID, getCurrentProjectID} from "@/common/js/utils";
|
||||
import MsApiReportDetail from "../../../../../api/automation/report/ApiReportDetail";
|
||||
import MsTableMoreBtn from "../../../../../api/automation/scenario/TableMoreBtn";
|
||||
import MsTestPlanList from "../../../../../api/automation/scenario/testplan/TestPlanList";
|
||||
|
|
|
@ -201,9 +201,4 @@
|
|||
margin: 5px 10px;
|
||||
}
|
||||
|
||||
/deep/ .run-button {
|
||||
background-color: #409EFF;
|
||||
border-color: #409EFF;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
|
@ -8,7 +8,8 @@
|
|||
@relevanceCase="$emit('relevanceCase', 'scenario')"/>
|
||||
</template>
|
||||
|
||||
<el-table ref="scenarioTable" border :data="tableData" class="test-content adjust-table ms-select-all-fixed"
|
||||
<el-table ref="scenarioTable"
|
||||
border :data="tableData" class="test-content adjust-table ms-select-all-fixed"
|
||||
@select-all="handleSelectAll"
|
||||
@sort-change="sort"
|
||||
@filter-change="filter"
|
||||
|
@ -35,6 +36,7 @@
|
|||
label="ID"
|
||||
:key="index"/>
|
||||
<el-table-column v-if="item.id == 'name'" prop="name" :label="$t('api_test.automation.scenario_name')" min-width="120px"
|
||||
sortable
|
||||
show-overflow-tooltip :key="index"/>
|
||||
<el-table-column v-if="item.id == 'level'" prop="level" :label="$t('api_test.automation.case_level')" min-width="100px"
|
||||
column-key="level"
|
||||
|
|
|
@ -495,10 +495,6 @@ export default {
|
|||
</script>
|
||||
|
||||
<style scoped>
|
||||
/deep/ .run-button {
|
||||
background-color: #409EFF;
|
||||
border-color: #409EFF;
|
||||
}
|
||||
/deep/ .el-table__fixed-body-wrapper {
|
||||
top: 59px !important;
|
||||
}
|
||||
|
|
|
@ -195,9 +195,4 @@ export default {
|
|||
margin: 5px 10px;
|
||||
}
|
||||
|
||||
/deep/ .run-button {
|
||||
background-color: #409EFF;
|
||||
border-color: #409EFF;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
|
@ -239,3 +239,8 @@ textarea {
|
|||
.el-button + .tooltip-btn, .tooltip-btn + .el-button, .tooltip-btn + .tooltip-btn {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.run-button .el-button {
|
||||
background-color: #409EFF;
|
||||
border-color: #409EFF;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import {post, get} from "@/common/js/ajax";
|
||||
import {getPageDate} from "@/common/js/tableUtils";
|
||||
import {getCurrentProjectID} from "@/common/js/utils";
|
||||
|
||||
export function buildIssues(page) {
|
||||
let data = page.data;
|
||||
|
@ -8,9 +9,9 @@ export function buildIssues(page) {
|
|||
if (data[i].customFields) {
|
||||
data[i].customFields = JSON.parse(data[i].customFields);
|
||||
}
|
||||
if (data[i].platform !== 'Local') {
|
||||
page.result = buildPlatformIssue(data[i]);
|
||||
}
|
||||
// if (data[i].platform !== 'Local') {
|
||||
// page.result = buildPlatformIssue(data[i]);
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -63,4 +64,10 @@ export function getRelateIssues(page) {
|
|||
});
|
||||
}
|
||||
|
||||
export function syncIssues() {
|
||||
return get('issues/sync/' + getCurrentProjectID(), (response) => {
|
||||
console.log('ok');
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@ import {get} from "@/common/js/ajax";
|
|||
|
||||
export function getIntegrationService(success) {
|
||||
return get("/service/integration/all/" + getCurrentOrganizationId(), response => {
|
||||
let data = response.data;
|
||||
if (success) {
|
||||
success(response.data);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue