feat(项目设置): 项目设置缺陷平台插件化
This commit is contained in:
parent
debc072829
commit
6c6fd3e2b3
|
@ -188,6 +188,7 @@ export default {
|
||||||
if (this.form) {
|
if (this.form) {
|
||||||
this.$set(this.form, this.data.name, this.data[this.prop]);
|
this.$set(this.form, this.data.name, this.data[this.prop]);
|
||||||
}
|
}
|
||||||
|
this.$emit('change', this.data.name);
|
||||||
this.$forceUpdate();
|
this.$forceUpdate();
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,6 @@ export const ZH_TW = 'zh_TW';
|
||||||
export const EN_US = 'en_US';
|
export const EN_US = 'en_US';
|
||||||
|
|
||||||
export const TAPD = 'Tapd';
|
export const TAPD = 'Tapd';
|
||||||
export const JIRA = 'Jira';
|
|
||||||
export const ZEN_TAO = 'Zentao';
|
export const ZEN_TAO = 'Zentao';
|
||||||
export const LOCAL = 'Local';
|
export const LOCAL = 'Local';
|
||||||
export const AZURE_DEVOPS = 'AzureDevops';
|
export const AZURE_DEVOPS = 'AzureDevops';
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// 模板
|
// 模板
|
||||||
import i18n from "../i18n";
|
import i18n from "../i18n";
|
||||||
import {AZURE_DEVOPS, JIRA, LOCAL, TAPD, ZEN_TAO} from "./constants";
|
import {AZURE_DEVOPS, LOCAL, TAPD, ZEN_TAO} from "./constants";
|
||||||
|
|
||||||
export const CUSTOM_FIELD_TYPE_OPTION = [
|
export const CUSTOM_FIELD_TYPE_OPTION = [
|
||||||
{value: 'input', text: 'workspace.custom_filed.input'},
|
{value: 'input', text: 'workspace.custom_filed.input'},
|
||||||
|
@ -68,7 +68,6 @@ export function CASE_TYPE_OPTION(){
|
||||||
export const ISSUE_PLATFORM_OPTION = [
|
export const ISSUE_PLATFORM_OPTION = [
|
||||||
{value: LOCAL, text: 'Local'},
|
{value: LOCAL, text: 'Local'},
|
||||||
{value: TAPD, text: 'Tapd'},
|
{value: TAPD, text: 'Tapd'},
|
||||||
{value: JIRA, text: 'JIRA'},
|
|
||||||
{value: ZEN_TAO, text: 'Zentao'},
|
{value: ZEN_TAO, text: 'Zentao'},
|
||||||
{value: AZURE_DEVOPS, text: 'Azure Devops'},
|
{value: AZURE_DEVOPS, text: 'Azure Devops'},
|
||||||
];
|
];
|
||||||
|
|
|
@ -4,6 +4,7 @@ import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
|
@ -37,4 +38,23 @@ public class RemoteService {
|
||||||
public Object post(String url, Object param) {
|
public Object post(String url, Object param) {
|
||||||
return Optional.ofNullable(microService.postForData(serviceName, url, param)).orElse(StringUtils.EMPTY);
|
return Optional.ofNullable(microService.postForData(serviceName, url, param)).orElse(StringUtils.EMPTY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Object get(HttpServletRequest request) {
|
||||||
|
// 返回null,前端会报错
|
||||||
|
return Optional.ofNullable(microService.getForData(serviceName, wrapperQuery(request))).orElse(StringUtils.EMPTY);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Object post(HttpServletRequest request, Object param) {
|
||||||
|
// 返回null,前端会报错
|
||||||
|
return Optional.ofNullable(microService.postForData(serviceName, wrapperQuery(request), param)).orElse(StringUtils.EMPTY);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String wrapperQuery(HttpServletRequest request) {
|
||||||
|
String url = request.getRequestURI();
|
||||||
|
if (StringUtils.isNotBlank(request.getQueryString())) {
|
||||||
|
url += "?" + request.getQueryString();
|
||||||
|
}
|
||||||
|
return url;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,8 +17,6 @@ import io.metersphere.dto.WorkspaceMemberDTO;
|
||||||
import io.metersphere.i18n.Translator;
|
import io.metersphere.i18n.Translator;
|
||||||
import io.metersphere.log.annotation.MsAuditLog;
|
import io.metersphere.log.annotation.MsAuditLog;
|
||||||
import io.metersphere.request.AddProjectRequest;
|
import io.metersphere.request.AddProjectRequest;
|
||||||
import io.metersphere.request.JiraIssueType;
|
|
||||||
import io.metersphere.request.JiraIssueTypeRequest;
|
|
||||||
import io.metersphere.request.ProjectRequest;
|
import io.metersphere.request.ProjectRequest;
|
||||||
import io.metersphere.request.member.AddMemberRequest;
|
import io.metersphere.request.member.AddMemberRequest;
|
||||||
import io.metersphere.request.member.QueryMemberRequest;
|
import io.metersphere.request.member.QueryMemberRequest;
|
||||||
|
@ -139,11 +137,6 @@ public class ProjectController {
|
||||||
return projectService.getAllServiceIntegration();
|
return projectService.getAllServiceIntegration();
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/issues/jira/issuetype")
|
|
||||||
public List<JiraIssueType> getJiraIssueType(@RequestBody JiraIssueTypeRequest request) {
|
|
||||||
return projectService.getJiraIssueType(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
@PostMapping("/member/add")
|
@PostMapping("/member/add")
|
||||||
public void addProjectMember(@RequestBody AddMemberRequest request) {
|
public void addProjectMember(@RequestBody AddMemberRequest request) {
|
||||||
projectService.addProjectMember(request);
|
projectService.addProjectMember(request);
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
package io.metersphere.controller.remote;
|
||||||
|
|
||||||
|
import io.metersphere.remote.service.PlatformPluginService;
|
||||||
|
import io.metersphere.remote.service.SystemSettingService;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping(path = {
|
||||||
|
"/platform/plugin",
|
||||||
|
})
|
||||||
|
public class SystemSettingController {
|
||||||
|
@Resource
|
||||||
|
SystemSettingService systemSettingService;
|
||||||
|
@Resource
|
||||||
|
PlatformPluginService platformPluginService;
|
||||||
|
|
||||||
|
@PostMapping("/**")
|
||||||
|
public Object list(HttpServletRequest request, @RequestBody Object param) {
|
||||||
|
return systemSettingService.post(request, param);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/**")
|
||||||
|
public Object get(HttpServletRequest request) {
|
||||||
|
return systemSettingService.get(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/resource/{pluginId}")
|
||||||
|
public void getPluginResource(@PathVariable("pluginId") String pluginId, @RequestParam("fileName") String fileName, HttpServletResponse response) {
|
||||||
|
platformPluginService.getPluginResource(pluginId, fileName, response);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
package io.metersphere.remote.service;
|
||||||
|
|
||||||
|
import io.metersphere.commons.constants.StorageConstants;
|
||||||
|
import io.metersphere.commons.utils.LogUtil;
|
||||||
|
import io.metersphere.metadata.service.FileManagerService;
|
||||||
|
import io.metersphere.metadata.vo.FileRequest;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class PlatformPluginService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
FileManagerService fileManagerService;
|
||||||
|
|
||||||
|
public static final String DIR_PATH = "system/plugin";
|
||||||
|
|
||||||
|
public void getPluginResource(String pluginId, String name, HttpServletResponse response) {
|
||||||
|
FileRequest request = new FileRequest();
|
||||||
|
request.setProjectId(DIR_PATH + "/" + pluginId);
|
||||||
|
request.setFileName(name);
|
||||||
|
request.setStorage(StorageConstants.MINIO.name());
|
||||||
|
InputStream inputStream = fileManagerService.downloadFileAsStream(request);
|
||||||
|
getImage(inputStream, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void getImage(InputStream in, HttpServletResponse response) {
|
||||||
|
response.setContentType("image/png");
|
||||||
|
try (OutputStream out = response.getOutputStream()) {
|
||||||
|
out.write(in.readAllBytes());
|
||||||
|
out.flush();
|
||||||
|
} catch (Exception e) {
|
||||||
|
LogUtil.error(e);
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
in.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
LogUtil.error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
package io.metersphere.remote.service;
|
||||||
|
|
||||||
|
import io.metersphere.commons.constants.MicroServiceName;
|
||||||
|
import io.metersphere.service.RemoteService;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class SystemSettingService extends RemoteService {
|
||||||
|
public SystemSettingService() {
|
||||||
|
super(MicroServiceName.SYSTEM_SETTING);
|
||||||
|
}
|
||||||
|
}
|
|
@ -428,10 +428,6 @@ public class ProjectService {
|
||||||
microService.postForData(MicroServiceName.TEST_TRACK, "/issues/check/third/project", project);
|
microService.postForData(MicroServiceName.TEST_TRACK, "/issues/check/third/project", project);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<JiraIssueType> getJiraIssueType(JiraIssueTypeRequest request) {
|
|
||||||
return microService.postForDataArray(MicroServiceName.TEST_TRACK, "/issues/jira/issuetype", request, JiraIssueType.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addOrUpdateCleanUpSchedule(AddProjectRequest project) {
|
public void addOrUpdateCleanUpSchedule(AddProjectRequest project) {
|
||||||
Boolean cleanTrackReport = project.getCleanTrackReport();
|
Boolean cleanTrackReport = project.getCleanTrackReport();
|
||||||
Boolean cleanApiReport = project.getCleanApiReport();
|
Boolean cleanApiReport = project.getCleanApiReport();
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
import {post, get} from "metersphere-frontend/src/plugins/request";
|
||||||
|
const BASE_URL = "/platform/plugin/";
|
||||||
|
|
||||||
|
export function getPlatformProjectInfo(key) {
|
||||||
|
return key ? get(BASE_URL + `project/info/${key}`) : new Promise(r => r({}));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function validateProjectConfig(pluginId, config) {
|
||||||
|
return post(BASE_URL + `project/validate/${pluginId}`, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getPlatformProjectOption(pluginId, request) {
|
||||||
|
return post(BASE_URL + 'project/option', request);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getPlatformOption() {
|
||||||
|
return get(BASE_URL + 'platform/option');
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getThirdPartTemplateSupportPlatform() {
|
||||||
|
return get(BASE_URL + 'template/support/list');
|
||||||
|
}
|
|
@ -26,10 +26,10 @@
|
||||||
:label="$t('workspace.issue_template_manage')" prop="issueTemplateId">
|
:label="$t('workspace.issue_template_manage')" prop="issueTemplateId">
|
||||||
<template-select :platform="form.platform" :data="form" scene="ISSUE" prop="issueTemplateId"
|
<template-select :platform="form.platform" :data="form" scene="ISSUE" prop="issueTemplateId"
|
||||||
:disabled="form.platform === 'Jira' && form.thirdPartTemplate"
|
:disabled="form.platform === 'Jira' && form.thirdPartTemplate"
|
||||||
:platformOptions="issueOptions" :project-id="form.id"
|
:platformOptions="platformOptions" :project-id="form.id"
|
||||||
ref="issueTemplate"/>
|
ref="issueTemplate"/>
|
||||||
|
|
||||||
<el-checkbox @change="thirdPartTemplateChange" v-if="form.platform === 'Jira'"
|
<el-checkbox @change="thirdPartTemplateChange" v-if="form.platform === 'Jira' && thirdPartTemplateSupport"
|
||||||
v-model="form.thirdPartTemplate" style="margin-left: 10px">
|
v-model="form.thirdPartTemplate" style="margin-left: 10px">
|
||||||
{{ $t('test_track.issue.use_third_party') }}
|
{{ $t('test_track.issue.use_third_party') }}
|
||||||
</el-checkbox>
|
</el-checkbox>
|
||||||
|
@ -51,13 +51,15 @@
|
||||||
</el-button>
|
</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<project-jira-config :result="jiraResult" v-if="jira" :label-width="labelWidth" :form="form" ref="jiraConfig">
|
<project-platform-config
|
||||||
<template #checkBtn>
|
v-if="form.platform === 'Jira'"
|
||||||
<el-button @click="check" type="primary" class="checkButton">
|
:result="jiraResult"
|
||||||
{{ $t('test_track.issue.check_id_exist') }}
|
:platform-key="form.platform"
|
||||||
</el-button>
|
:label-width="labelWidth"
|
||||||
</template>
|
:project-config="platformConfig"
|
||||||
</project-jira-config>
|
ref="platformConfig"
|
||||||
|
/>
|
||||||
|
|
||||||
<el-form-item :label-width="labelWidth" :label="$t('project.zentao_id')" v-if="zentao">
|
<el-form-item :label-width="labelWidth" :label="$t('project.zentao_id')" v-if="zentao">
|
||||||
<el-input v-model="form.zentaoId" autocomplete="off"></el-input>
|
<el-input v-model="form.zentaoId" autocomplete="off"></el-input>
|
||||||
<el-button @click="check" type="primary" class="checkButton">
|
<el-button @click="check" type="primary" class="checkButton">
|
||||||
|
@ -103,7 +105,7 @@ import {
|
||||||
getCurrentUserId,
|
getCurrentUserId,
|
||||||
getCurrentWorkspaceId
|
getCurrentWorkspaceId
|
||||||
} from "metersphere-frontend/src/utils/token";
|
} from "metersphere-frontend/src/utils/token";
|
||||||
import {AZURE_DEVOPS, JIRA, PROJECT_ID, TAPD, ZEN_TAO} from "metersphere-frontend/src/utils/constants";
|
import {AZURE_DEVOPS, PROJECT_ID, TAPD, ZEN_TAO} from "metersphere-frontend/src/utils/constants";
|
||||||
import {PROJECT_CONFIGS} from "metersphere-frontend/src/components/search/search-components";
|
import {PROJECT_CONFIGS} from "metersphere-frontend/src/components/search/search-components";
|
||||||
import MsInstructionsIcon from "metersphere-frontend/src/components/MsInstructionsIcon";
|
import MsInstructionsIcon from "metersphere-frontend/src/components/MsInstructionsIcon";
|
||||||
import TemplateSelect from "../menu/template/TemplateSelect";
|
import TemplateSelect from "../menu/template/TemplateSelect";
|
||||||
|
@ -117,7 +119,6 @@ import MsTablePagination from "metersphere-frontend/src/components/pagination/Ta
|
||||||
import MsTableHeader from "metersphere-frontend/src/components/MsTableHeader";
|
import MsTableHeader from "metersphere-frontend/src/components/MsTableHeader";
|
||||||
import MsDialogFooter from "metersphere-frontend/src/components/MsDialogFooter";
|
import MsDialogFooter from "metersphere-frontend/src/components/MsDialogFooter";
|
||||||
import {ISSUE_PLATFORM_OPTION} from "metersphere-frontend/src/utils/table-constants";
|
import {ISSUE_PLATFORM_OPTION} from "metersphere-frontend/src/utils/table-constants";
|
||||||
import ProjectJiraConfig from "./ProjectJiraConfig";
|
|
||||||
import {getAllServiceIntegration} from "../../api/project";
|
import {getAllServiceIntegration} from "../../api/project";
|
||||||
import {
|
import {
|
||||||
checkThirdPlatformProject,
|
checkThirdPlatformProject,
|
||||||
|
@ -126,11 +127,13 @@ import {
|
||||||
saveProject
|
saveProject
|
||||||
} from "../../api/project";
|
} from "../../api/project";
|
||||||
import {updateInfo} from "metersphere-frontend/src/api/user";
|
import {updateInfo} from "metersphere-frontend/src/api/user";
|
||||||
|
import ProjectPlatformConfig from "@/business/home/ProjectPlatformConfig";
|
||||||
|
import {getPlatformOption, getThirdPartTemplateSupportPlatform} from "@/api/platform-plugin";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "EditProject",
|
name: "EditProject",
|
||||||
components: {
|
components: {
|
||||||
ProjectJiraConfig,
|
ProjectPlatformConfig,
|
||||||
MsInstructionsIcon,
|
MsInstructionsIcon,
|
||||||
TemplateSelect,
|
TemplateSelect,
|
||||||
MsTableButton,
|
MsTableButton,
|
||||||
|
@ -152,6 +155,9 @@ export default {
|
||||||
jiraResult: {
|
jiraResult: {
|
||||||
loading: false
|
loading: false
|
||||||
},
|
},
|
||||||
|
platformProjectConfigs: [],
|
||||||
|
platformConfig: {},
|
||||||
|
thirdPartTemplateSupportPlatforms: [],
|
||||||
btnTips: this.$t('project.create'),
|
btnTips: this.$t('project.create'),
|
||||||
title: this.$t('project.create'),
|
title: this.$t('project.create'),
|
||||||
condition: {components: PROJECT_CONFIGS},
|
condition: {components: PROJECT_CONFIGS},
|
||||||
|
@ -171,7 +177,6 @@ export default {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
platformOptions: [],
|
platformOptions: [],
|
||||||
issueOptions: [],
|
|
||||||
issueTemplateId: "",
|
issueTemplateId: "",
|
||||||
ableEdit: true,
|
ableEdit: true,
|
||||||
};
|
};
|
||||||
|
@ -192,15 +197,15 @@ export default {
|
||||||
tapd() {
|
tapd() {
|
||||||
return this.showPlatform(TAPD);
|
return this.showPlatform(TAPD);
|
||||||
},
|
},
|
||||||
jira() {
|
|
||||||
return this.showPlatform(JIRA);
|
|
||||||
},
|
|
||||||
zentao() {
|
zentao() {
|
||||||
return this.showPlatform(ZEN_TAO);
|
return this.showPlatform(ZEN_TAO);
|
||||||
},
|
},
|
||||||
azuredevops() {
|
azuredevops() {
|
||||||
return this.showPlatform(AZURE_DEVOPS);
|
return this.showPlatform(AZURE_DEVOPS);
|
||||||
},
|
},
|
||||||
|
thirdPartTemplateSupport() {
|
||||||
|
return this.thirdPartTemplateSupportPlatforms.indexOf(this.form.platform) > -1;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
inject: ['reload'],
|
inject: ['reload'],
|
||||||
destroyed() {
|
destroyed() {
|
||||||
|
@ -230,6 +235,10 @@ export default {
|
||||||
if (this.$refs.apiTemplate) {
|
if (this.$refs.apiTemplate) {
|
||||||
this.$refs.apiTemplate.getTemplateOptions();
|
this.$refs.apiTemplate.getTemplateOptions();
|
||||||
}
|
}
|
||||||
|
getThirdPartTemplateSupportPlatform()
|
||||||
|
.then((r) => {
|
||||||
|
this.thirdPartTemplateSupportPlatforms = r.data;
|
||||||
|
});
|
||||||
},
|
},
|
||||||
thirdPartTemplateChange(val) {
|
thirdPartTemplateChange(val) {
|
||||||
if (val)
|
if (val)
|
||||||
|
@ -241,38 +250,26 @@ export default {
|
||||||
listenGoBack(this.handleClose);
|
listenGoBack(this.handleClose);
|
||||||
if (row) {
|
if (row) {
|
||||||
this.title = this.$t('project.edit');
|
this.title = this.$t('project.edit');
|
||||||
row.issueConfigObj = row.issueConfig ? JSON.parse(row.issueConfig) : {
|
this.platformConfig = row.issueConfig ? JSON.parse(row.issueConfig) : {};
|
||||||
jiraIssueTypeId: null,
|
|
||||||
jiraStoryTypeId: null
|
|
||||||
};
|
|
||||||
// 兼容性处理
|
|
||||||
if (!row.issueConfigObj.jiraIssueTypeId) {
|
|
||||||
row.issueConfigObj.jiraIssueTypeId = null;
|
|
||||||
}
|
|
||||||
if (!row.issueConfigObj.jiraStoryTypeId) {
|
|
||||||
row.issueConfigObj.jiraStoryTypeId = null;
|
|
||||||
}
|
|
||||||
this.form = Object.assign({}, row);
|
this.form = Object.assign({}, row);
|
||||||
this.issueTemplateId = row.issueTemplateId;
|
this.issueTemplateId = row.issueTemplateId;
|
||||||
} else {
|
|
||||||
this.form = {issueConfigObj: {jiraIssueTypeId: null, jiraStoryTypeId: null}};
|
|
||||||
}
|
|
||||||
if (this.$refs.jiraConfig) {
|
|
||||||
this.$refs.jiraConfig.getIssueTypeOption(this.form);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getPlatformOption()
|
||||||
|
.then((r) => {
|
||||||
this.platformOptions = [];
|
this.platformOptions = [];
|
||||||
|
this.platformOptions.push(...r.data);
|
||||||
this.platformOptions.push(...ISSUE_PLATFORM_OPTION);
|
this.platformOptions.push(...ISSUE_PLATFORM_OPTION);
|
||||||
this.loading = getAllServiceIntegration().then(res => {
|
this.loading = getAllServiceIntegration().then(res => {
|
||||||
let data = res.data;
|
let data = res.data;
|
||||||
let platforms = data.map(d => d.platform);
|
let platforms = data.map(d => d.platform);
|
||||||
this.filterPlatformOptions(platforms, TAPD);
|
this.filterPlatformOptions(platforms, TAPD);
|
||||||
this.filterPlatformOptions(platforms, JIRA);
|
|
||||||
this.filterPlatformOptions(platforms, ZEN_TAO);
|
this.filterPlatformOptions(platforms, ZEN_TAO);
|
||||||
this.filterPlatformOptions(platforms, AZURE_DEVOPS);
|
this.filterPlatformOptions(platforms, AZURE_DEVOPS);
|
||||||
this.issueOptions = this.platformOptions;
|
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
this.ableEdit = false;
|
this.ableEdit = false;
|
||||||
})
|
})
|
||||||
|
});
|
||||||
},
|
},
|
||||||
filterPlatformOptions(platforms, platform) {
|
filterPlatformOptions(platforms, platform) {
|
||||||
if (platforms.indexOf(platform) === -1) {
|
if (platforms.indexOf(platform) === -1) {
|
||||||
|
@ -289,13 +286,24 @@ export default {
|
||||||
if (!valid || !this.ableEdit) {
|
if (!valid || !this.ableEdit) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
let projectConfig = this.$refs.platformConfig;
|
||||||
|
if (projectConfig) {
|
||||||
|
projectConfig.validate()
|
||||||
|
.then(() => {
|
||||||
|
this.form.issueConfig = JSON.stringify(projectConfig.form);
|
||||||
|
this.handleSave()
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.handleSave();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
handleSave() {
|
||||||
let protocol = document.location.protocol;
|
let protocol = document.location.protocol;
|
||||||
protocol = protocol.substring(0, protocol.indexOf(":"));
|
protocol = protocol.substring(0, protocol.indexOf(":"));
|
||||||
this.form.protocal = protocol;
|
this.form.protocal = protocol;
|
||||||
this.form.workspaceId = getCurrentWorkspaceId();
|
this.form.workspaceId = getCurrentWorkspaceId();
|
||||||
this.form.createUser = getCurrentUserId();
|
this.form.createUser = getCurrentUserId();
|
||||||
this.form.issueConfig = JSON.stringify(this.form.issueConfigObj);
|
|
||||||
if (this.issueTemplateId !== this.form.issueTemplateId) {
|
if (this.issueTemplateId !== this.form.issueTemplateId) {
|
||||||
// 更换缺陷模版移除字段
|
// 更换缺陷模版移除字段
|
||||||
localStorage.removeItem("ISSUE_LIST");
|
localStorage.removeItem("ISSUE_LIST");
|
||||||
|
@ -304,9 +312,8 @@ export default {
|
||||||
let promise = this.form.id ? modifyProject(this.form) : saveProject(this.form);
|
let promise = this.form.id ? modifyProject(this.form) : saveProject(this.form);
|
||||||
this.loading = promise.then(() => {
|
this.loading = promise.then(() => {
|
||||||
this.createVisible = false;
|
this.createVisible = false;
|
||||||
this.reload();
|
|
||||||
this.$success(this.$t('commons.save_success'));
|
this.$success(this.$t('commons.save_success'));
|
||||||
});
|
this.reload();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
handleDelete(project) {
|
handleDelete(project) {
|
||||||
|
|
|
@ -0,0 +1,162 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<el-form :model="form" ref="form" label-width="100px" size="small" :rules="rules">
|
||||||
|
<el-form-item
|
||||||
|
:label-width="labelWidth"
|
||||||
|
v-for="item in config.formItems"
|
||||||
|
:key="item.name"
|
||||||
|
:label="item.i18n ? $t(item.label) : item.label"
|
||||||
|
:prop="item.name">
|
||||||
|
<custom-filed-component :form="form"
|
||||||
|
:data="item"
|
||||||
|
class="custom-filed"
|
||||||
|
prop="defaultValue"
|
||||||
|
@change="handleChange"/>
|
||||||
|
<el-button v-if="item.withProjectCheck"
|
||||||
|
:disabled="!form[item.name]"
|
||||||
|
@click="check"
|
||||||
|
type="primary"
|
||||||
|
class="checkButton">
|
||||||
|
{{ $t('test_track.issue.check_id_exist') }}
|
||||||
|
</el-button>
|
||||||
|
<ms-instructions-icon v-if="item.instructionsIcon" effect="light">
|
||||||
|
<template>
|
||||||
|
<img class="jira-image"
|
||||||
|
:src="'/platform/plugin/resource/' + config.id + '?fileName=' + item.instructionsIcon"/>
|
||||||
|
</template>
|
||||||
|
</ms-instructions-icon>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import MsInstructionsIcon from "metersphere-frontend/src/components/MsInstructionsIcon";
|
||||||
|
import {getCurrentWorkspaceId} from "metersphere-frontend/src/utils/token";
|
||||||
|
import {
|
||||||
|
getPlatformProjectInfo,
|
||||||
|
getPlatformProjectOption,
|
||||||
|
validateProjectConfig,
|
||||||
|
} from "@/api/platform-plugin";
|
||||||
|
import CustomFiledComponent from "metersphere-frontend/src/components/template/CustomFiledComponent";
|
||||||
|
import {getPlatformFormRules} from "@/business/home/platform";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "ProjectPlatformConfig",
|
||||||
|
components: {MsInstructionsIcon, CustomFiledComponent},
|
||||||
|
props: {
|
||||||
|
labelWidth: String,
|
||||||
|
result: {
|
||||||
|
type: Object,
|
||||||
|
default() {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
platformKey: String,
|
||||||
|
projectConfig: {
|
||||||
|
type: Object,
|
||||||
|
default() {
|
||||||
|
return {}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
issueTypes: [],
|
||||||
|
form: {},
|
||||||
|
rules: {},
|
||||||
|
config: {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
platformKey() {
|
||||||
|
this.getPlatformProjectInfo();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.getPlatformProjectInfo();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
getPlatformProjectInfo() {
|
||||||
|
getPlatformProjectInfo(this.platformKey)
|
||||||
|
.then(r => {
|
||||||
|
if (r.data) {
|
||||||
|
Object.assign(this.form, this.projectConfig);
|
||||||
|
r.data.formItems.forEach(item => {
|
||||||
|
if (!item.options) {
|
||||||
|
item.options = [];
|
||||||
|
}
|
||||||
|
// 设置默认值
|
||||||
|
if (this.form[item.name]) {
|
||||||
|
this.$set(item, 'defaultValue', this.form[item.name]);
|
||||||
|
}
|
||||||
|
// 获取级联选项值
|
||||||
|
if (item.cascade && this.form[item.name]) {
|
||||||
|
this.getCascadeOptions(item, () => {
|
||||||
|
// 没有选项值会被组件自动清空,获取下拉框选项之后,重新设置默认值
|
||||||
|
if (this.form[item.name]) {
|
||||||
|
this.$set(item, 'defaultValue', this.form[item.name]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.config = r.data;
|
||||||
|
this.rules = getPlatformFormRules(this.config);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
check() {
|
||||||
|
validateProjectConfig(this.config.id, this.form)
|
||||||
|
.then(() => {
|
||||||
|
this.$success(this.$t("system.check_third_project_success"));
|
||||||
|
});
|
||||||
|
},
|
||||||
|
validate() {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
this.$refs['form'].validate((valid) => {
|
||||||
|
if (!valid) {
|
||||||
|
reject();
|
||||||
|
}
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
handleChange(name) {
|
||||||
|
this.config.formItems.forEach(item => {
|
||||||
|
if (item.cascade === name) {
|
||||||
|
this.$set(item, 'options', []);
|
||||||
|
this.getCascadeOptions(item);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
getCascadeOptions(item, callback) {
|
||||||
|
getPlatformProjectOption(this.config.id, {
|
||||||
|
platform: this.platformKey,
|
||||||
|
optionMethod: item.optionMethod,
|
||||||
|
workspaceId: getCurrentWorkspaceId(),
|
||||||
|
projectConfig: JSON.stringify(this.form)
|
||||||
|
}).then((r) => {
|
||||||
|
this.$set(item, 'options', r.data);
|
||||||
|
if (callback) {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
.custom-filed :deep(.el-select) {
|
||||||
|
width: 260px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-filed :deep(.el-input, .el-textarea) {
|
||||||
|
width: 80% !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.checkButton {
|
||||||
|
margin-left: 5px;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,15 @@
|
||||||
|
import i18n from "@/i18n";
|
||||||
|
|
||||||
|
export function getPlatformFormRules(config) {
|
||||||
|
let rules = {};
|
||||||
|
if (config && config.formItems) {
|
||||||
|
config.formItems.forEach(item => {
|
||||||
|
rules[item.name] = {
|
||||||
|
required: item.required,
|
||||||
|
message: item.i18n ? i18n.t(item.message) : item.message,
|
||||||
|
trigger: ['change', 'blur']
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return rules;
|
||||||
|
}
|
|
@ -1,12 +1,14 @@
|
||||||
package io.metersphere.controller;
|
package io.metersphere.controller;
|
||||||
|
|
||||||
|
import io.metersphere.domain.SelectOption;
|
||||||
|
import io.metersphere.dto.PlatformProjectOptionRequest;
|
||||||
import io.metersphere.service.PlatformPluginService;
|
import io.metersphere.service.PlatformPluginService;
|
||||||
import org.springframework.http.ResponseEntity;
|
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import java.io.InputStream;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
|
@ -21,8 +23,37 @@ public class PlatformPluginController {
|
||||||
return platformPluginService.getIntegrationInfo();
|
return platformPluginService.getIntegrationInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("/project/info/{key}")
|
||||||
|
public Object getProjectInfo(@PathVariable("key") String key) {
|
||||||
|
return platformPluginService.getProjectInfo(key);
|
||||||
|
}
|
||||||
|
|
||||||
@GetMapping("/resource/{pluginId}")
|
@GetMapping("/resource/{pluginId}")
|
||||||
public void getPluginResource(@PathVariable("pluginId") String pluginId, @RequestParam("fileName") String fileName, HttpServletResponse response) {
|
public void getPluginResource(@PathVariable("pluginId") String pluginId, @RequestParam("fileName") String fileName, HttpServletResponse response) {
|
||||||
platformPluginService.getPluginResource(pluginId, fileName, response);
|
platformPluginService.getPluginResource(pluginId, fileName, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PostMapping("/integration/validate/{pluginId}")
|
||||||
|
public void validateIntegration(@PathVariable("pluginId") String pluginId, @RequestBody Map config) {
|
||||||
|
platformPluginService.validateIntegration(pluginId, config);
|
||||||
|
}
|
||||||
|
@PostMapping("/project/validate/{pluginId}")
|
||||||
|
public void validateProjectConfig(@PathVariable("pluginId") String pluginId, @RequestBody Map config) {
|
||||||
|
platformPluginService.validateProjectConfig(pluginId, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/project/option")
|
||||||
|
public List<SelectOption> getProjectOption(@RequestBody PlatformProjectOptionRequest request) {
|
||||||
|
return platformPluginService.getProjectOption(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/platform/option")
|
||||||
|
public List<SelectOption> getPlatformOptions() {
|
||||||
|
return platformPluginService.getPlatformOptions();
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/template/support/list")
|
||||||
|
public List<String> getThirdPartTemplateSupportPlatform() {
|
||||||
|
return platformPluginService.getThirdPartTemplateSupportPlatform();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,6 @@ package io.metersphere.controller;
|
||||||
|
|
||||||
import com.github.pagehelper.Page;
|
import com.github.pagehelper.Page;
|
||||||
import com.github.pagehelper.PageHelper;
|
import com.github.pagehelper.PageHelper;
|
||||||
import io.metersphere.base.domain.FileMetadata;
|
|
||||||
import io.metersphere.base.domain.Project;
|
import io.metersphere.base.domain.Project;
|
||||||
import io.metersphere.commons.constants.MicroServiceName;
|
import io.metersphere.commons.constants.MicroServiceName;
|
||||||
import io.metersphere.commons.constants.OperLogConstants;
|
import io.metersphere.commons.constants.OperLogConstants;
|
||||||
|
@ -17,14 +16,13 @@ import io.metersphere.dto.WorkspaceMemberDTO;
|
||||||
import io.metersphere.log.annotation.MsAuditLog;
|
import io.metersphere.log.annotation.MsAuditLog;
|
||||||
import io.metersphere.request.AddProjectRequest;
|
import io.metersphere.request.AddProjectRequest;
|
||||||
import io.metersphere.request.ProjectRequest;
|
import io.metersphere.request.ProjectRequest;
|
||||||
import io.metersphere.service.BaseProjectService;
|
|
||||||
import io.metersphere.service.BaseCheckPermissionService;
|
import io.metersphere.service.BaseCheckPermissionService;
|
||||||
|
import io.metersphere.service.BaseProjectService;
|
||||||
import io.metersphere.service.MicroService;
|
import io.metersphere.service.MicroService;
|
||||||
import io.metersphere.service.SystemProjectService;
|
import io.metersphere.service.SystemProjectService;
|
||||||
import org.apache.shiro.authz.annotation.Logical;
|
import org.apache.shiro.authz.annotation.Logical;
|
||||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
@ -131,9 +129,4 @@ public class SystemProjectController {
|
||||||
public void checkThirdProjectExist(@RequestBody Project project) {
|
public void checkThirdProjectExist(@RequestBody Project project) {
|
||||||
microService.postForData(MicroServiceName.TEST_TRACK, "/issues/check/third/project", project);
|
microService.postForData(MicroServiceName.TEST_TRACK, "/issues/check/third/project", project);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/issues/jira/issuetype")
|
|
||||||
public Object getJiraIssueType(@RequestBody Object request) {
|
|
||||||
return microService.postForData(MicroServiceName.TEST_TRACK, "/issues/jira/issuetype", request);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
package io.metersphere.dto;
|
||||||
|
|
||||||
|
import io.metersphere.request.IntegrationRequest;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class PlatformProjectOptionRequest extends IntegrationRequest {
|
||||||
|
private String optionMethod;
|
||||||
|
private String projectConfig;
|
||||||
|
}
|
|
@ -1,14 +1,23 @@
|
||||||
package io.metersphere.service;
|
package io.metersphere.service;
|
||||||
|
|
||||||
import im.metersphere.loader.PluginManager;
|
import io.metersphere.api.Platform;
|
||||||
import io.metersphere.api.PluginMetaInfo;
|
import io.metersphere.api.PluginMetaInfo;
|
||||||
import io.metersphere.base.domain.PluginWithBLOBs;
|
import io.metersphere.base.domain.PluginWithBLOBs;
|
||||||
|
import io.metersphere.base.domain.ServiceIntegration;
|
||||||
import io.metersphere.base.mapper.PluginMapper;
|
import io.metersphere.base.mapper.PluginMapper;
|
||||||
import io.metersphere.commons.constants.PluginScenario;
|
import io.metersphere.commons.constants.PluginScenario;
|
||||||
|
import io.metersphere.commons.utils.BeanUtils;
|
||||||
import io.metersphere.commons.utils.JSON;
|
import io.metersphere.commons.utils.JSON;
|
||||||
import io.metersphere.commons.utils.LogUtil;
|
import io.metersphere.commons.utils.LogUtil;
|
||||||
import io.metersphere.commons.utils.SessionUtils;
|
import io.metersphere.commons.utils.SessionUtils;
|
||||||
|
import io.metersphere.domain.GetOptionRequest;
|
||||||
|
import io.metersphere.domain.PlatformRequest;
|
||||||
|
import io.metersphere.domain.SelectOption;
|
||||||
|
import io.metersphere.dto.PlatformProjectOptionRequest;
|
||||||
|
import io.metersphere.loader.PlatformPluginManager;
|
||||||
|
import io.metersphere.request.IntegrationRequest;
|
||||||
import io.metersphere.utils.PluginManagerUtil;
|
import io.metersphere.utils.PluginManagerUtil;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
@ -22,6 +31,7 @@ import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
@ -31,12 +41,14 @@ public class PlatformPluginService {
|
||||||
private BasePluginService basePluginService;
|
private BasePluginService basePluginService;
|
||||||
@Resource
|
@Resource
|
||||||
private PluginMapper pluginMapper;
|
private PluginMapper pluginMapper;
|
||||||
|
@Resource
|
||||||
|
private BaseIntegrationService baseIntegrationService;
|
||||||
|
|
||||||
private PluginManager pluginManager;
|
private PlatformPluginManager pluginManager;
|
||||||
|
|
||||||
public PluginWithBLOBs addPlatformPlugin(MultipartFile file) {
|
public PluginWithBLOBs addPlatformPlugin(MultipartFile file) {
|
||||||
if (pluginManager != null) {
|
if (pluginManager != null) {
|
||||||
pluginManager = new PluginManager();
|
pluginManager = new PlatformPluginManager();
|
||||||
}
|
}
|
||||||
String id = UUID.randomUUID().toString();
|
String id = UUID.randomUUID().toString();
|
||||||
|
|
||||||
|
@ -51,7 +63,7 @@ public class PlatformPluginService {
|
||||||
plugin.setId(id);
|
plugin.setId(id);
|
||||||
plugin.setName(file.getOriginalFilename());
|
plugin.setName(file.getOriginalFilename());
|
||||||
plugin.setPluginId(pluginMetaInfo.getKey() + "-" + pluginMetaInfo.getVersion());
|
plugin.setPluginId(pluginMetaInfo.getKey() + "-" + pluginMetaInfo.getVersion());
|
||||||
plugin.setScriptId(plugin.getPluginId());
|
plugin.setScriptId(pluginMetaInfo.getKey());
|
||||||
plugin.setSourcePath("");
|
plugin.setSourcePath("");
|
||||||
// plugin.setFormOption(item.getFormOption());
|
// plugin.setFormOption(item.getFormOption());
|
||||||
plugin.setFormScript(JSON.toJSONString(map));
|
plugin.setFormScript(JSON.toJSONString(map));
|
||||||
|
@ -69,7 +81,7 @@ public class PlatformPluginService {
|
||||||
* 查询所有平台插件并加载
|
* 查询所有平台插件并加载
|
||||||
*/
|
*/
|
||||||
public void loadPlatFormPlugins() {
|
public void loadPlatFormPlugins() {
|
||||||
pluginManager = new PluginManager();
|
pluginManager = new PlatformPluginManager();
|
||||||
List<PluginWithBLOBs> plugins = basePluginService.getPlugins(PluginScenario.platform.name());
|
List<PluginWithBLOBs> plugins = basePluginService.getPlugins(PluginScenario.platform.name());
|
||||||
PluginManagerUtil.loadPlugins(pluginManager, plugins);
|
PluginManagerUtil.loadPlugins(pluginManager, plugins);
|
||||||
}
|
}
|
||||||
|
@ -83,19 +95,51 @@ public class PlatformPluginService {
|
||||||
public Object getIntegrationInfo() {
|
public Object getIntegrationInfo() {
|
||||||
List<PluginWithBLOBs> plugins = basePluginService.getPlugins(PluginScenario.platform.name());
|
List<PluginWithBLOBs> plugins = basePluginService.getPlugins(PluginScenario.platform.name());
|
||||||
List<Map> configs = new ArrayList<>();
|
List<Map> configs = new ArrayList<>();
|
||||||
plugins.forEach(item ->{
|
plugins.forEach(item -> configs.add(getFrontendMetaDataConfig(item, "serviceIntegration")));
|
||||||
Map metaData = JSON.parseMap(item.getFormScript());
|
return configs;
|
||||||
Map serviceIntegration = (Map) metaData.get("serviceIntegration");
|
}
|
||||||
|
|
||||||
|
public Map getProjectInfo(String key) {
|
||||||
|
List<PluginWithBLOBs> plugins = basePluginService.getPlugins(PluginScenario.platform.name());
|
||||||
|
for (PluginWithBLOBs plugin : plugins) {
|
||||||
|
if (StringUtils.equals(plugin.getScriptId(), key)) {
|
||||||
|
return getFrontendMetaDataConfig(plugin, "projectConfig");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<SelectOption> getProjectOption(PlatformProjectOptionRequest request) {
|
||||||
|
IntegrationRequest integrationRequest = new IntegrationRequest();
|
||||||
|
BeanUtils.copyBean(integrationRequest, request);
|
||||||
|
ServiceIntegration serviceIntegration = baseIntegrationService.get(integrationRequest);
|
||||||
|
|
||||||
|
PlatformRequest platformRequest = new PlatformRequest();
|
||||||
|
platformRequest.setIntegrationConfig(serviceIntegration.getConfiguration());
|
||||||
|
|
||||||
|
Platform platform = pluginManager.getPlatformByKey(request.getPlatform(), platformRequest);
|
||||||
|
GetOptionRequest getOptionRequest = new GetOptionRequest();
|
||||||
|
getOptionRequest.setOptionMethod(request.getOptionMethod());
|
||||||
|
getOptionRequest.setProjectConfig(request.getProjectConfig());
|
||||||
|
try {
|
||||||
|
return platform.getProjectOptions(getOptionRequest);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map getFrontendMetaDataConfig(PluginWithBLOBs plugin, String configName) {
|
||||||
|
Map metaData = JSON.parseMap(plugin.getFormScript());
|
||||||
|
Map serviceIntegration = (Map) metaData.get(configName);
|
||||||
serviceIntegration.put("id", metaData.get("id"));
|
serviceIntegration.put("id", metaData.get("id"));
|
||||||
serviceIntegration.put("key", metaData.get("key"));
|
serviceIntegration.put("key", metaData.get("key"));
|
||||||
configs.add(serviceIntegration);
|
return serviceIntegration;
|
||||||
});
|
|
||||||
return configs;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void getImage(InputStream in, HttpServletResponse response) {
|
public void getImage(InputStream in, HttpServletResponse response) {
|
||||||
response.setContentType("image/png");
|
response.setContentType("image/png");
|
||||||
try(OutputStream out = response.getOutputStream()) {
|
try (OutputStream out = response.getOutputStream()) {
|
||||||
out.write(in.readAllBytes());
|
out.write(in.readAllBytes());
|
||||||
out.flush();
|
out.flush();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@ -118,4 +162,54 @@ public class PlatformPluginService {
|
||||||
LogUtil.error(e);
|
LogUtil.error(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Platform getPlatFormInstance(String pluginId, Map IntegrationConfig) {
|
||||||
|
PlatformRequest request = new PlatformRequest();
|
||||||
|
request.setIntegrationConfig(JSON.toJSONString(IntegrationConfig));
|
||||||
|
return pluginManager.getPlatform(pluginId, request);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Platform getPlatFormInstance(String pluginId, String integrationConfig) {
|
||||||
|
PlatformRequest request = new PlatformRequest();
|
||||||
|
request.setIntegrationConfig(integrationConfig);
|
||||||
|
return pluginManager.getPlatform(pluginId, request);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void validateIntegration(String pluginId, Map integrationConfig) {
|
||||||
|
Platform platform = getPlatFormInstance(pluginId, integrationConfig);
|
||||||
|
platform.validateIntegrationConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void validateProjectConfig(String pluginId, Map projectConfig) {
|
||||||
|
PluginMetaInfo pluginMetaInfo = pluginManager.getPluginMetaInfo(pluginId);
|
||||||
|
IntegrationRequest integrationRequest = new IntegrationRequest();
|
||||||
|
integrationRequest.setPlatform(pluginMetaInfo.getKey());
|
||||||
|
integrationRequest.setWorkspaceId(SessionUtils.getCurrentWorkspaceId());
|
||||||
|
ServiceIntegration serviceIntegration = baseIntegrationService.get(integrationRequest);
|
||||||
|
Platform platform = getPlatFormInstance(pluginId, serviceIntegration.getConfiguration());
|
||||||
|
platform.validateProjectConfig(JSON.toJSONString(projectConfig));
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<SelectOption> getPlatformOptions() {
|
||||||
|
List<SelectOption> options = pluginManager.getPluginMetaInfoList()
|
||||||
|
.stream()
|
||||||
|
.map(pluginMetaInfo -> new SelectOption(pluginMetaInfo.getLabel(), pluginMetaInfo.getKey()))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
List<ServiceIntegration> integrations = baseIntegrationService.getAll(SessionUtils.getCurrentWorkspaceId());
|
||||||
|
// 过滤掉服务集成中没有的选项
|
||||||
|
return options.stream()
|
||||||
|
.filter(option ->
|
||||||
|
integrations.stream()
|
||||||
|
.filter(integration -> StringUtils.equals(integration.getPlatform(), option.getValue()))
|
||||||
|
.collect(Collectors.toList()).size() > 0
|
||||||
|
).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getThirdPartTemplateSupportPlatform() {
|
||||||
|
List<PluginMetaInfo> pluginMetaInfoList = pluginManager.getPluginMetaInfoList();
|
||||||
|
return pluginMetaInfoList.stream()
|
||||||
|
.filter(PluginMetaInfo::isThirdPartTemplateSupport)
|
||||||
|
.map(PluginMetaInfo::getKey)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,3 +4,27 @@ const BASE_URL = "/platform/plugin/";
|
||||||
export function getIntegrationInfo() {
|
export function getIntegrationInfo() {
|
||||||
return get(BASE_URL + 'integration/info');
|
return get(BASE_URL + 'integration/info');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getPlatformProjectInfo(key) {
|
||||||
|
return key ? get(BASE_URL + `project/info/${key}`) : new Promise(r => r({}));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function validateServiceIntegration(pluginId, config) {
|
||||||
|
return post(BASE_URL + `integration/validate/${pluginId}`, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function validateProjectConfig(pluginId, config) {
|
||||||
|
return post(BASE_URL + `project/validate/${pluginId}`, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getPlatformProjectOption(pluginId, request) {
|
||||||
|
return post(BASE_URL + 'project/option', request);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getPlatformOption() {
|
||||||
|
return get(BASE_URL + 'platform/option');
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getThirdPartTemplateSupportPlatform() {
|
||||||
|
return get(BASE_URL + 'template/support/list');
|
||||||
|
}
|
||||||
|
|
|
@ -46,11 +46,6 @@ export function getAllServiceIntegration() {
|
||||||
return get('/service/integration/all');
|
return get('/service/integration/all');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export function getJiraIssueType(param) {
|
|
||||||
return post('/project/issues/jira/issuetype', param);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getFieldTemplateCaseOption(projectId) {
|
export function getFieldTemplateCaseOption(projectId) {
|
||||||
return get(`/project/field/template/case/option/${projectId}`);
|
return get(`/project/field/template/case/option/${projectId}`);
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,7 +53,7 @@ export default {
|
||||||
platform: TAPD,
|
platform: TAPD,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created() {
|
activated() {
|
||||||
this.platformConfigs = [];
|
this.platformConfigs = [];
|
||||||
|
|
||||||
getIntegrationInfo()
|
getIntegrationInfo()
|
||||||
|
@ -62,7 +62,6 @@ export default {
|
||||||
});
|
});
|
||||||
|
|
||||||
this.platform = TAPD;
|
this.platform = TAPD;
|
||||||
this.platformConfigs[0].key;
|
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
tapdEnable() {
|
tapdEnable() {
|
||||||
|
|
|
@ -56,17 +56,17 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import BugManageBtn from "./BugManageBtn";
|
import BugManageBtn from "./BugManageBtn";
|
||||||
import {getCurrentUser, getCurrentWorkspaceId} from "metersphere-frontend/src/utils/token";
|
import {getCurrentUser} from "metersphere-frontend/src/utils/token";
|
||||||
import {JIRA} from "metersphere-frontend/src/utils/constants";
|
|
||||||
import MsInstructionsIcon from "metersphere-frontend/src/components/MsInstructionsIcon";
|
import MsInstructionsIcon from "metersphere-frontend/src/components/MsInstructionsIcon";
|
||||||
import MsPersonRouter from "metersphere-frontend/src/components/personal/PersonRouter";
|
import MsPersonRouter from "metersphere-frontend/src/components/personal/PersonRouter";
|
||||||
import CustomFiledComponent from "metersphere-frontend/src/components/template/CustomFiledComponent";
|
import CustomFiledComponent from "metersphere-frontend/src/components/template/CustomFiledComponent";
|
||||||
import {
|
import {
|
||||||
authServiceIntegration,
|
|
||||||
delServiceIntegration,
|
delServiceIntegration,
|
||||||
getServiceIntegration,
|
getServiceIntegration,
|
||||||
saveServiceIntegration
|
saveServiceIntegration
|
||||||
} from "../../../api/workspace";
|
} from "../../../api/workspace";
|
||||||
|
import {validateServiceIntegration} from "@/api/platform-plugin";
|
||||||
|
import {getPlatformFormRules} from "@/business/workspace/integration/platform";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "PlatformConfig",
|
name: "PlatformConfig",
|
||||||
|
@ -93,19 +93,11 @@ export default {
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
init() {
|
init() {
|
||||||
let rules = {};
|
this.rules = getPlatformFormRules(this.config);
|
||||||
this.config.formItems.forEach(item => {
|
|
||||||
rules[item.name] = {
|
|
||||||
required: item.required,
|
|
||||||
message: item.i18n ? this.$t(item.message) : item.message,
|
|
||||||
trigger: ['change', 'blur']
|
|
||||||
}
|
|
||||||
});
|
|
||||||
this.rules = rules;
|
|
||||||
|
|
||||||
const {lastWorkspaceId} = getCurrentUser();
|
const {lastWorkspaceId} = getCurrentUser();
|
||||||
let param = {};
|
let param = {};
|
||||||
param.platform = JIRA;
|
param.platform = this.config.key;
|
||||||
param.workspaceId = lastWorkspaceId;
|
param.workspaceId = lastWorkspaceId;
|
||||||
this.$parent.loading = getServiceIntegration(param).then(res => {
|
this.$parent.loading = getServiceIntegration(param).then(res => {
|
||||||
let data = res.data;
|
let data = res.data;
|
||||||
|
@ -116,7 +108,7 @@ export default {
|
||||||
this.form = form;
|
this.form = form;
|
||||||
// 设置默认值
|
// 设置默认值
|
||||||
this.config.formItems.forEach(item => {
|
this.config.formItems.forEach(item => {
|
||||||
item.defaultValue = this.form[item.name];
|
this.$set(item, 'defaultValue', this.form[item.name]);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
this.clear();
|
this.clear();
|
||||||
|
@ -156,19 +148,16 @@ export default {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
testConnection() {
|
testConnection() {
|
||||||
if (this.form.account && this.form.password) {
|
this.$refs['form'].validate(valid => {
|
||||||
// todo 插件改造
|
if (valid) {
|
||||||
this.$parent.loading = authServiceIntegration(getCurrentWorkspaceId(), JIRA).then(() => {
|
this.$parent.loading = validateServiceIntegration(this.config.id, this.form).then(() => {
|
||||||
this.$success(this.$t('organization.integration.verified'));
|
this.$success(this.$t('organization.integration.verified'));
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
this.$warning(this.$t('organization.integration.not_integrated'));
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
},
|
},
|
||||||
cancelIntegration() {
|
cancelIntegration() {
|
||||||
if (this.form.account && this.form.password) {
|
this.$alert(this.$t('organization.integration.cancel_confirm') + this.config.key + "?", '', {
|
||||||
this.$alert(this.$t('organization.integration.cancel_confirm') + JIRA + "?", '', {
|
|
||||||
confirmButtonText: this.$t('commons.confirm'),
|
confirmButtonText: this.$t('commons.confirm'),
|
||||||
callback: (action) => {
|
callback: (action) => {
|
||||||
if (action === 'confirm') {
|
if (action === 'confirm') {
|
||||||
|
@ -183,9 +172,6 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
this.$warning(this.$t('organization.integration.not_integrated'));
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
reloadPassInput() {
|
reloadPassInput() {
|
||||||
this.showInput = false;
|
this.showInput = false;
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
import i18n from "@/i18n";
|
||||||
|
|
||||||
|
export function getPlatformFormRules(config) {
|
||||||
|
let rules = {};
|
||||||
|
if (config && config.formItems) {
|
||||||
|
config.formItems.forEach(item => {
|
||||||
|
rules[item.name] = {
|
||||||
|
required: item.required,
|
||||||
|
message: item.i18n ? i18n.t(item.message) : item.message,
|
||||||
|
trigger: ['change', 'blur']
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return rules;
|
||||||
|
}
|
|
@ -26,10 +26,10 @@
|
||||||
:label="$t('workspace.issue_template_manage')" prop="issueTemplateId">
|
:label="$t('workspace.issue_template_manage')" prop="issueTemplateId">
|
||||||
<template-select :platform="form.platform" :data="form" scene="ISSUE" prop="issueTemplateId"
|
<template-select :platform="form.platform" :data="form" scene="ISSUE" prop="issueTemplateId"
|
||||||
:disabled="form.platform === 'Jira' && form.thirdPartTemplate"
|
:disabled="form.platform === 'Jira' && form.thirdPartTemplate"
|
||||||
:platformOptions="issueOptions" :project-id="form.id"
|
:platformOptions="platformOptions" :project-id="form.id"
|
||||||
ref="issueTemplate"/>
|
ref="issueTemplate"/>
|
||||||
|
|
||||||
<el-checkbox @change="thirdPartTemplateChange" v-if="form.platform === 'Jira'"
|
<el-checkbox @change="thirdPartTemplateChange" v-if="form.platform === 'Jira' && thirdPartTemplateSupport"
|
||||||
v-model="form.thirdPartTemplate" style="margin-left: 10px">
|
v-model="form.thirdPartTemplate" style="margin-left: 10px">
|
||||||
{{ $t('test_track.issue.use_third_party') }}
|
{{ $t('test_track.issue.use_third_party') }}
|
||||||
</el-checkbox>
|
</el-checkbox>
|
||||||
|
@ -51,13 +51,15 @@
|
||||||
</el-button>
|
</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<project-jira-config :result="jiraResult" v-if="jira" :label-width="labelWidth" :form="form" ref="jiraConfig">
|
<project-platform-config
|
||||||
<template #checkBtn>
|
v-if="form.platform === 'Jira'"
|
||||||
<el-button @click="check" type="primary" class="checkButton">
|
:result="jiraResult"
|
||||||
{{ $t('test_track.issue.check_id_exist') }}
|
:platform-key="form.platform"
|
||||||
</el-button>
|
:label-width="labelWidth"
|
||||||
</template>
|
:project-config="platformConfig"
|
||||||
</project-jira-config>
|
ref="platformConfig"
|
||||||
|
/>
|
||||||
|
|
||||||
<el-form-item :label-width="labelWidth" :label="$t('project.zentao_id')" v-if="zentao">
|
<el-form-item :label-width="labelWidth" :label="$t('project.zentao_id')" v-if="zentao">
|
||||||
<el-input v-model="form.zentaoId" autocomplete="off"></el-input>
|
<el-input v-model="form.zentaoId" autocomplete="off"></el-input>
|
||||||
<el-button @click="check" type="primary" class="checkButton">
|
<el-button @click="check" type="primary" class="checkButton">
|
||||||
|
@ -103,7 +105,7 @@ import {
|
||||||
getCurrentUserId,
|
getCurrentUserId,
|
||||||
getCurrentWorkspaceId
|
getCurrentWorkspaceId
|
||||||
} from "metersphere-frontend/src/utils/token";
|
} from "metersphere-frontend/src/utils/token";
|
||||||
import {AZURE_DEVOPS, JIRA, PROJECT_ID, TAPD, ZEN_TAO} from "metersphere-frontend/src/utils/constants";
|
import {AZURE_DEVOPS, PROJECT_ID, TAPD, ZEN_TAO} from "metersphere-frontend/src/utils/constants";
|
||||||
import {PROJECT_CONFIGS} from "metersphere-frontend/src/components/search/search-components";
|
import {PROJECT_CONFIGS} from "metersphere-frontend/src/components/search/search-components";
|
||||||
import MsInstructionsIcon from "metersphere-frontend/src/components/MsInstructionsIcon";
|
import MsInstructionsIcon from "metersphere-frontend/src/components/MsInstructionsIcon";
|
||||||
import TemplateSelect from "./TemplateSelect";
|
import TemplateSelect from "./TemplateSelect";
|
||||||
|
@ -115,7 +117,6 @@ import MsTablePagination from "metersphere-frontend/src/components/pagination/Ta
|
||||||
import MsTableHeader from "metersphere-frontend/src/components/MsTableHeader";
|
import MsTableHeader from "metersphere-frontend/src/components/MsTableHeader";
|
||||||
import MsDialogFooter from "metersphere-frontend/src/components/MsDialogFooter";
|
import MsDialogFooter from "metersphere-frontend/src/components/MsDialogFooter";
|
||||||
import {ISSUE_PLATFORM_OPTION} from "metersphere-frontend/src/utils/table-constants";
|
import {ISSUE_PLATFORM_OPTION} from "metersphere-frontend/src/utils/table-constants";
|
||||||
import ProjectJiraConfig from "./ProjectJiraConfig";
|
|
||||||
import {
|
import {
|
||||||
getAllServiceIntegration,
|
getAllServiceIntegration,
|
||||||
checkThirdPlatformProject,
|
checkThirdPlatformProject,
|
||||||
|
@ -124,11 +125,13 @@ import {
|
||||||
saveProject
|
saveProject
|
||||||
} from "../../../api/project";
|
} from "../../../api/project";
|
||||||
import {updateInfo} from "metersphere-frontend/src/api/user";
|
import {updateInfo} from "metersphere-frontend/src/api/user";
|
||||||
|
import {getPlatformOption, getPlatformProjectInfo, getThirdPartTemplateSupportPlatform} from "@/api/platform-plugin";
|
||||||
|
import ProjectPlatformConfig from "@/business/workspace/project/ProjectPlatformConfig";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "EditProject",
|
name: "EditProject",
|
||||||
components: {
|
components: {
|
||||||
ProjectJiraConfig,
|
ProjectPlatformConfig,
|
||||||
MsInstructionsIcon,
|
MsInstructionsIcon,
|
||||||
TemplateSelect,
|
TemplateSelect,
|
||||||
MsTableButton,
|
MsTableButton,
|
||||||
|
@ -148,6 +151,7 @@ export default {
|
||||||
jiraResult: {
|
jiraResult: {
|
||||||
loading: false
|
loading: false
|
||||||
},
|
},
|
||||||
|
platformProjectConfigs: [],
|
||||||
btnTips: this.$t('project.create'),
|
btnTips: this.$t('project.create'),
|
||||||
title: this.$t('project.create'),
|
title: this.$t('project.create'),
|
||||||
condition: {components: PROJECT_CONFIGS},
|
condition: {components: PROJECT_CONFIGS},
|
||||||
|
@ -167,9 +171,10 @@ export default {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
platformOptions: [],
|
platformOptions: [],
|
||||||
issueOptions: [],
|
|
||||||
issueTemplateId: "",
|
issueTemplateId: "",
|
||||||
ableEdit: true,
|
ableEdit: true,
|
||||||
|
platformConfig: {},
|
||||||
|
thirdPartTemplateSupportPlatforms: []
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
|
@ -188,15 +193,15 @@ export default {
|
||||||
tapd() {
|
tapd() {
|
||||||
return this.showPlatform(TAPD);
|
return this.showPlatform(TAPD);
|
||||||
},
|
},
|
||||||
jira() {
|
|
||||||
return this.showPlatform(JIRA);
|
|
||||||
},
|
|
||||||
zentao() {
|
zentao() {
|
||||||
return this.showPlatform(ZEN_TAO);
|
return this.showPlatform(ZEN_TAO);
|
||||||
},
|
},
|
||||||
azuredevops() {
|
azuredevops() {
|
||||||
return this.showPlatform(AZURE_DEVOPS);
|
return this.showPlatform(AZURE_DEVOPS);
|
||||||
},
|
},
|
||||||
|
thirdPartTemplateSupport() {
|
||||||
|
return this.thirdPartTemplateSupportPlatforms.indexOf(this.form.platform) > -1;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
inject: ['reload'],
|
inject: ['reload'],
|
||||||
destroyed() {
|
destroyed() {
|
||||||
|
@ -226,6 +231,10 @@ export default {
|
||||||
if (this.$refs.apiTemplate) {
|
if (this.$refs.apiTemplate) {
|
||||||
this.$refs.apiTemplate.getTemplateOptions();
|
this.$refs.apiTemplate.getTemplateOptions();
|
||||||
}
|
}
|
||||||
|
getThirdPartTemplateSupportPlatform()
|
||||||
|
.then((r) => {
|
||||||
|
this.thirdPartTemplateSupportPlatforms = r.data;
|
||||||
|
});
|
||||||
},
|
},
|
||||||
thirdPartTemplateChange(val) {
|
thirdPartTemplateChange(val) {
|
||||||
if (val)
|
if (val)
|
||||||
|
@ -237,38 +246,32 @@ export default {
|
||||||
listenGoBack(this.handleClose);
|
listenGoBack(this.handleClose);
|
||||||
if (row) {
|
if (row) {
|
||||||
this.title = this.$t('project.edit');
|
this.title = this.$t('project.edit');
|
||||||
row.issueConfigObj = row.issueConfig ? JSON.parse(row.issueConfig) : {
|
this.platformConfig = row.issueConfig ? JSON.parse(row.issueConfig) : {};
|
||||||
jiraIssueTypeId: null,
|
|
||||||
jiraStoryTypeId: null
|
|
||||||
};
|
|
||||||
// 兼容性处理
|
|
||||||
if (!row.issueConfigObj.jiraIssueTypeId) {
|
|
||||||
row.issueConfigObj.jiraIssueTypeId = null;
|
|
||||||
}
|
|
||||||
if (!row.issueConfigObj.jiraStoryTypeId) {
|
|
||||||
row.issueConfigObj.jiraStoryTypeId = null;
|
|
||||||
}
|
|
||||||
this.form = Object.assign({}, row);
|
this.form = Object.assign({}, row);
|
||||||
this.issueTemplateId = row.issueTemplateId;
|
this.issueTemplateId = row.issueTemplateId;
|
||||||
} else {
|
|
||||||
this.form = {issueConfigObj: {jiraIssueTypeId: null, jiraStoryTypeId: null}};
|
|
||||||
}
|
|
||||||
if (this.$refs.jiraConfig) {
|
|
||||||
this.$refs.jiraConfig.getIssueTypeOption(this.form);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getPlatformOption()
|
||||||
|
.then((r) => {
|
||||||
this.platformOptions = [];
|
this.platformOptions = [];
|
||||||
|
this.platformOptions.push(...r.data);
|
||||||
this.platformOptions.push(...ISSUE_PLATFORM_OPTION);
|
this.platformOptions.push(...ISSUE_PLATFORM_OPTION);
|
||||||
this.loading = getAllServiceIntegration().then(res => {
|
this.loading = getAllServiceIntegration().then(res => {
|
||||||
let data = res.data;
|
let data = res.data;
|
||||||
let platforms = data.map(d => d.platform);
|
let platforms = data.map(d => d.platform);
|
||||||
this.filterPlatformOptions(platforms, TAPD);
|
this.filterPlatformOptions(platforms, TAPD);
|
||||||
this.filterPlatformOptions(platforms, JIRA);
|
|
||||||
this.filterPlatformOptions(platforms, ZEN_TAO);
|
this.filterPlatformOptions(platforms, ZEN_TAO);
|
||||||
this.filterPlatformOptions(platforms, AZURE_DEVOPS);
|
this.filterPlatformOptions(platforms, AZURE_DEVOPS);
|
||||||
this.issueOptions = this.platformOptions;
|
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
this.ableEdit = false;
|
this.ableEdit = false;
|
||||||
})
|
})
|
||||||
|
});
|
||||||
|
},
|
||||||
|
getPlatformProjectInfo() {
|
||||||
|
getPlatformProjectInfo()
|
||||||
|
.then((r) => {
|
||||||
|
this.platformProjectConfigs = r.data;
|
||||||
|
});
|
||||||
},
|
},
|
||||||
filterPlatformOptions(platforms, platform) {
|
filterPlatformOptions(platforms, platform) {
|
||||||
if (platforms.indexOf(platform) === -1) {
|
if (platforms.indexOf(platform) === -1) {
|
||||||
|
@ -285,13 +288,24 @@ export default {
|
||||||
if (!valid || !this.ableEdit) {
|
if (!valid || !this.ableEdit) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
let projectConfig = this.$refs.platformConfig;
|
||||||
|
if (projectConfig) {
|
||||||
|
projectConfig.validate()
|
||||||
|
.then(() => {
|
||||||
|
this.form.issueConfig = JSON.stringify(projectConfig.form);
|
||||||
|
this.handleSave()
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.handleSave();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
handleSave() {
|
||||||
let protocol = document.location.protocol;
|
let protocol = document.location.protocol;
|
||||||
protocol = protocol.substring(0, protocol.indexOf(":"));
|
protocol = protocol.substring(0, protocol.indexOf(":"));
|
||||||
this.form.protocal = protocol;
|
this.form.protocal = protocol;
|
||||||
this.form.workspaceId = getCurrentWorkspaceId();
|
this.form.workspaceId = getCurrentWorkspaceId();
|
||||||
this.form.createUser = getCurrentUserId();
|
this.form.createUser = getCurrentUserId();
|
||||||
this.form.issueConfig = JSON.stringify(this.form.issueConfigObj);
|
|
||||||
if (this.issueTemplateId !== this.form.issueTemplateId) {
|
if (this.issueTemplateId !== this.form.issueTemplateId) {
|
||||||
// 更换缺陷模版移除字段
|
// 更换缺陷模版移除字段
|
||||||
localStorage.removeItem("ISSUE_LIST");
|
localStorage.removeItem("ISSUE_LIST");
|
||||||
|
@ -303,7 +317,6 @@ export default {
|
||||||
this.$success(this.$t('commons.save_success'));
|
this.$success(this.$t('commons.save_success'));
|
||||||
this.reload();
|
this.reload();
|
||||||
});
|
});
|
||||||
});
|
|
||||||
},
|
},
|
||||||
handleDelete(project) {
|
handleDelete(project) {
|
||||||
this.$refs.deleteConfirm.open(project);
|
this.$refs.deleteConfirm.open(project);
|
||||||
|
|
|
@ -0,0 +1,162 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<el-form :model="form" ref="form" label-width="100px" size="small" :rules="rules">
|
||||||
|
<el-form-item
|
||||||
|
:label-width="labelWidth"
|
||||||
|
v-for="item in config.formItems"
|
||||||
|
:key="item.name"
|
||||||
|
:label="item.i18n ? $t(item.label) : item.label"
|
||||||
|
:prop="item.name">
|
||||||
|
<custom-filed-component :form="form"
|
||||||
|
:data="item"
|
||||||
|
class="custom-filed"
|
||||||
|
prop="defaultValue"
|
||||||
|
@change="handleChange"/>
|
||||||
|
<el-button v-if="item.withProjectCheck"
|
||||||
|
:disabled="!form[item.name]"
|
||||||
|
@click="check"
|
||||||
|
type="primary"
|
||||||
|
class="checkButton">
|
||||||
|
{{ $t('test_track.issue.check_id_exist') }}
|
||||||
|
</el-button>
|
||||||
|
<ms-instructions-icon v-if="item.instructionsIcon" effect="light">
|
||||||
|
<template>
|
||||||
|
<img class="jira-image"
|
||||||
|
:src="'/platform/plugin/resource/' + config.id + '?fileName=' + item.instructionsIcon"/>
|
||||||
|
</template>
|
||||||
|
</ms-instructions-icon>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import MsInstructionsIcon from "metersphere-frontend/src/components/MsInstructionsIcon";
|
||||||
|
import {getCurrentWorkspaceId} from "metersphere-frontend/src/utils/token";
|
||||||
|
import {
|
||||||
|
getPlatformProjectInfo,
|
||||||
|
getPlatformProjectOption,
|
||||||
|
validateProjectConfig,
|
||||||
|
} from "@/api/platform-plugin";
|
||||||
|
import {getPlatformFormRules} from "@/business/workspace/integration/platform";
|
||||||
|
import CustomFiledComponent from "metersphere-frontend/src/components/template/CustomFiledComponent";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "ProjectPlatformConfig",
|
||||||
|
components: {MsInstructionsIcon, CustomFiledComponent},
|
||||||
|
props: {
|
||||||
|
labelWidth: String,
|
||||||
|
result: {
|
||||||
|
type: Object,
|
||||||
|
default() {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
platformKey: String,
|
||||||
|
projectConfig: {
|
||||||
|
type: Object,
|
||||||
|
default() {
|
||||||
|
return {}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
issueTypes: [],
|
||||||
|
form: {},
|
||||||
|
rules: {},
|
||||||
|
config: {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
platformKey() {
|
||||||
|
this.getPlatformProjectInfo();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.getPlatformProjectInfo();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
getPlatformProjectInfo() {
|
||||||
|
getPlatformProjectInfo(this.platformKey)
|
||||||
|
.then(r => {
|
||||||
|
if (r.data) {
|
||||||
|
Object.assign(this.form, this.projectConfig);
|
||||||
|
r.data.formItems.forEach(item => {
|
||||||
|
if (!item.options) {
|
||||||
|
item.options = [];
|
||||||
|
}
|
||||||
|
// 设置默认值
|
||||||
|
if (this.form[item.name]) {
|
||||||
|
this.$set(item, 'defaultValue', this.form[item.name]);
|
||||||
|
}
|
||||||
|
// 获取级联选项值
|
||||||
|
if (item.cascade && this.form[item.name]) {
|
||||||
|
this.getCascadeOptions(item, () => {
|
||||||
|
// 没有选项值会被组件自动清空,获取下拉框选项之后,重新设置默认值
|
||||||
|
if (this.form[item.name]) {
|
||||||
|
this.$set(item, 'defaultValue', this.form[item.name]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.config = r.data;
|
||||||
|
this.rules = getPlatformFormRules(this.config);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
check() {
|
||||||
|
validateProjectConfig(this.config.id, this.form)
|
||||||
|
.then(() => {
|
||||||
|
this.$success(this.$t("system.check_third_project_success"));
|
||||||
|
});
|
||||||
|
},
|
||||||
|
validate() {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
this.$refs['form'].validate((valid) => {
|
||||||
|
if (!valid) {
|
||||||
|
reject();
|
||||||
|
}
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
handleChange(name) {
|
||||||
|
this.config.formItems.forEach(item => {
|
||||||
|
if (item.cascade === name) {
|
||||||
|
this.$set(item, 'options', []);
|
||||||
|
this.getCascadeOptions(item);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
getCascadeOptions(item, callback) {
|
||||||
|
getPlatformProjectOption(this.config.id, {
|
||||||
|
platform: this.platformKey,
|
||||||
|
optionMethod: item.optionMethod,
|
||||||
|
workspaceId: getCurrentWorkspaceId(),
|
||||||
|
projectConfig: JSON.stringify(this.form)
|
||||||
|
}).then((r) => {
|
||||||
|
this.$set(item, 'options', r.data);
|
||||||
|
if (callback) {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
.custom-filed :deep(.el-select) {
|
||||||
|
width: 260px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-filed :deep(.el-input, .el-textarea) {
|
||||||
|
width: 80% !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.checkButton {
|
||||||
|
margin-left: 5px;
|
||||||
|
}
|
||||||
|
</style>
|
Loading…
Reference in New Issue