Skip to content

Commit c623890

Browse files
authored
UI changes for devrev create tickets (#3743)
* create devrev ticket api * fix existing issues error * fix hostname handling * UI for creating devrev ticket * fix ticket id not showing in row * fix successful result * remove unused field * fix refresh issue
1 parent f2b90a3 commit c623890

File tree

12 files changed

+237
-39
lines changed

12 files changed

+237
-39
lines changed

apps/dashboard/src/main/java/com/akto/action/testing/StartTestAction.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -859,6 +859,9 @@ public enum QueryMode {
859859
@Getter
860860
private Map<String, String> jiraIssuesMapForResults;
861861

862+
@Getter
863+
private Map<String, String> devrevIssuesMapForResults;
864+
862865
public String fetchTestingRunResults() {
863866
ObjectId testingRunResultSummaryId;
864867
try {
@@ -900,6 +903,7 @@ public String fetchTestingRunResults() {
900903
removeTestingRunResultsByIssues(testingRunResults, (Map<String, String>) issueMetaDataMap.get("statuses"));
901904
this.issuesDescriptionMap = (Map<String, String>) issueMetaDataMap.get("descriptions");
902905
this.jiraIssuesMapForResults = (Map<String, String>) issueMetaDataMap.get("jiraIssues");
906+
this.devrevIssuesMapForResults = (Map<String, String>) issueMetaDataMap.get("devrevIssues");
903907
}
904908
loggerMaker.debugAndAddToDb("[" + (Context.now() - timeNow) + "] Removed ignored issues from testing run results. Current size of testing run results: " + testingRunResults.size(), LogDb.DASHBOARD);
905909
} catch (Exception e) {
@@ -929,7 +933,7 @@ private BasicDBObject prepareIssueMetaDataMap(List<TestingRunResult> testingRunR
929933
Filters.and(
930934
Filters.in(Constants.ID, idToResultMap.keySet())
931935
),
932-
Projections.include(TestingRunIssues.TEST_RUN_ISSUES_STATUS, TestingRunIssues.DESCRIPTION, TestingRunIssues.JIRA_ISSUE_URL)
936+
Projections.include(TestingRunIssues.TEST_RUN_ISSUES_STATUS, TestingRunIssues.DESCRIPTION, TestingRunIssues.JIRA_ISSUE_URL, TestingRunIssues.DEVREV_WORK_URL)
933937
);
934938

935939
return buildIssueMetaDataMap(issues, idToResultMap, ignoreStatuses);

apps/dashboard/src/main/java/com/akto/action/testing/Utils.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ public static BasicDBObject buildIssueMetaDataMap(List<TestingRunIssues> issues,
8787
BasicDBObject issueMetaDataMap = new BasicDBObject();
8888
Map<String, String> descriptionMap = new HashMap<>();
8989
Map<String, String> jiraIssueMap = new HashMap<>();
90+
Map<String, String> devrevIssueMap = new HashMap<>();
9091
Map<String, String> statusMap = new HashMap<>();
9192
for (TestingRunIssues issue : issues) {
9293
TestingRunResult result = idToResultMap.get(issue.getId());
@@ -96,13 +97,17 @@ public static BasicDBObject buildIssueMetaDataMap(List<TestingRunIssues> issues,
9697
if (StringUtils.isNotBlank(issue.getJiraIssueUrl())) {
9798
jiraIssueMap.put(result.getHexId(), issue.getJiraIssueUrl());
9899
}
100+
if (StringUtils.isNotBlank(issue.getDevrevWorkUrl())) {
101+
devrevIssueMap.put(result.getHexId(), issue.getDevrevWorkUrl());
102+
}
99103
if(issue.getTestRunIssueStatus() != null && (statusList == null || statusList.contains(issue.getTestRunIssueStatus()))) {
100104
statusMap.put(result.getHexId(), issue.getTestRunIssueStatus().name());
101105
}
102-
106+
103107
}
104108
issueMetaDataMap.put("descriptions", descriptionMap);
105109
issueMetaDataMap.put("jiraIssues", jiraIssueMap);
110+
issueMetaDataMap.put("devrevIssues", devrevIssueMap);
106111
issueMetaDataMap.put("statuses", statusMap);
107112
return issueMetaDataMap;
108113
}

apps/dashboard/web/pages/login.jsp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@
7272
window.JIRA_INTEGRATED ='${requestScope.jiraIntegrated}'
7373
window.AZURE_BOARDS_INTEGRATED ='${requestScope.azureBoardsIntegrated}'
7474
window.SERVICENOW_INTEGRATED ='${requestScope.servicenowIntegrated}'
75+
window.DEVREV_INTEGRATED ='${requestScope.devrevIntegrated}'
7576
window.USER_ROLE ='${requestScope.userRole}'
7677
window.TIME_ZONE = '${requestScope.currentTimeZone}'
7778
window.USER_FULL_NAME = '${requestScope.userFullName}'

apps/dashboard/web/polaris_web/web/src/apps/dashboard/components/shared/JiraTicketCreationModal.jsx

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ const DisplayABCreateWorkItemFields = ({ displayABWorkItemFieldMetadata }) => {
3939
)
4040
}
4141

42-
const JiraTicketCreationModal = ({ activator, modalActive, setModalActive, handleSaveAction, jiraProjectMaps, setProjId, setIssueType, projId, issueType, issueId, isAzureModal, isServiceNowModal, labelsText, setLabelsText }) => {
42+
const JiraTicketCreationModal = ({ activator, modalActive, setModalActive, handleSaveAction, jiraProjectMaps, setProjId, setIssueType, projId, issueType, issueId, isAzureModal, isServiceNowModal, isDevRevModal, labelsText, setLabelsText }) => {
4343
const [isCreatingTicket, setIsCreatingTicket] = useState(false)
4444
const [displayJiraIssueFieldMetadata, setDisplayJiraIssueFieldMetadata] = useState([])
4545
const [localLabelsText, setLocalLabelsText] = useState(labelsText || "")
@@ -58,7 +58,7 @@ const JiraTicketCreationModal = ({ activator, modalActive, setModalActive, handl
5858
}
5959

6060
useEffect(() => {
61-
if (!isAzureModal && !isServiceNowModal && projId && issueType) {
61+
if (!isAzureModal && !isServiceNowModal && !isDevRevModal && projId && issueType) {
6262
const initialFieldMetaData = createJiraIssueFieldMetaData?.[projId]?.[issueType] || [];
6363

6464
const filteredFieldMetaData = initialFieldMetaData.filter(field => {
@@ -75,7 +75,7 @@ const JiraTicketCreationModal = ({ activator, modalActive, setModalActive, handl
7575
}, {});
7676
setDisplayJiraIssueFieldValues(initialValues);
7777
}
78-
}, [isAzureModal, isServiceNowModal, projId, issueType, createJiraIssueFieldMetaData])
78+
}, [isAzureModal, isServiceNowModal, isDevRevModal, projId, issueType, createJiraIssueFieldMetaData, setDisplayJiraIssueFieldValues])
7979

8080
// Reset local state when modal opens
8181
useEffect(() => {
@@ -135,7 +135,7 @@ const JiraTicketCreationModal = ({ activator, modalActive, setModalActive, handl
135135
open={modalActive}
136136
onClose={() => setModalActive(false)}
137137
size="small"
138-
title={<Text variant="headingMd">{isServiceNowModal ? "Configure ServiceNow ticket details" : isAzureModal ? "Configure Azure Boards Work Item" : "Configure jira ticket details"}</Text>}
138+
title={<Text variant="headingMd">{isServiceNowModal ? "Configure ServiceNow ticket details" : isDevRevModal ? "Configure DevRev ticket details" : isAzureModal ? "Configure Azure Boards Work Item" : "Configure jira ticket details"}</Text>}
139139
primaryAction={{
140140
content: (isAzureModal ? 'Create work item' : 'Create ticket'),
141141
onAction: () => {
@@ -149,20 +149,34 @@ const JiraTicketCreationModal = ({ activator, modalActive, setModalActive, handl
149149
setIsCreatingTicket(false)
150150
setModalActive(false)
151151
},
152-
disabled: (isServiceNowModal ? (!projId || isCreatingTicket) : (!projId || !issueType || isCreatingTicket))
152+
disabled: ((isServiceNowModal || isDevRevModal) ? (!projId || isCreatingTicket) : (!projId || !issueType || isCreatingTicket))
153153
}}
154154
>
155155
<Modal.Section>
156156
<VerticalStack gap={"3"}>
157-
{isServiceNowModal ? (
158-
<DropdownSearch
159-
disabled={!jiraProjectMaps || jiraProjectMaps.length === 0}
160-
placeholder="Select ServiceNow table"
161-
optionsList={jiraProjectMaps ? jiraProjectMaps.map((x) => {return{label: x, value: x}}): []}
162-
setSelected={setProjId}
163-
preSelected={projId}
164-
value={projId}
165-
/>
157+
{(isServiceNowModal || isDevRevModal) ? (
158+
<>
159+
<DropdownSearch
160+
disabled={!jiraProjectMaps || jiraProjectMaps.length === 0}
161+
placeholder={isDevRevModal ? "Select DevRev part" : "Select ServiceNow table"}
162+
optionsList={jiraProjectMaps ? jiraProjectMaps.map((x) => {return{label: isDevRevModal ? x.name : x, value: isDevRevModal ? x.id : x}}): []}
163+
setSelected={setProjId}
164+
preSelected={projId}
165+
value={isDevRevModal && jiraProjectMaps ? (jiraProjectMaps.find(x => x.id === projId)?.name || projId) : projId}
166+
/>
167+
{isDevRevModal && (
168+
<DropdownSearch
169+
placeholder="Select work item type"
170+
optionsList={[
171+
{label: 'Issue', value: 'issue'},
172+
{label: 'Ticket', value: 'ticket'}
173+
]}
174+
setSelected={setIssueType}
175+
preSelected={issueType}
176+
value={issueType === 'issue' ? 'Issue' : issueType === 'ticket' ? 'Ticket' : issueType}
177+
/>
178+
)}
179+
</>
166180
) : (
167181
<>
168182
<DropdownSearch

apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/issues/IssuesPage/IssuesPage.jsx

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,11 @@ function IssuesPage() {
193193
const [serviceNowTable, setServiceNowTable] = useState('')
194194
const [labelsText, setLabelsText] = useState('')
195195

196+
const [devrevModalActive, setDevRevModalActive] = useState(false)
197+
const [devrevParts, setDevRevParts] = useState([])
198+
const [devrevPartId, setDevRevPartId] = useState('')
199+
const [devrevWorkItemType, setDevRevWorkItemType] = useState('issue')
200+
196201
// Compulsory description modal states
197202
const [compulsoryDescriptionModal, setCompulsoryDescriptionModal] = useState(false)
198203
const [pendingIgnoreAction, setPendingIgnoreAction] = useState(null)
@@ -386,6 +391,21 @@ function IssuesPage() {
386391
})
387392
}
388393

394+
const handleSaveBulkDevRevTicketsAction = () => {
395+
setToast(true, false, "Please wait while we create your DevRev tickets.")
396+
setDevRevModalActive(false)
397+
api.createDevRevTickets(selectedIssuesItems, devrevPartId, devrevWorkItemType, window.location.origin).then((res) => {
398+
if(res?.errorMessage) {
399+
setToast(true, false, res?.errorMessage)
400+
} else {
401+
setToast(true, false, `${selectedIssuesItems.length} DevRev ticket${selectedIssuesItems.length === 1 ? "" : "s"} created.`)
402+
}
403+
resetResourcesSelected()
404+
}).catch((err) => {
405+
setToast(true, true, err?.response?.data?.errorMessage || "Error creating DevRev tickets")
406+
})
407+
}
408+
389409
// Use keys directly for reasons and compulsorySettings
390410
const requiresDescription = (reasonKey) => {
391411
return compulsorySettings[reasonKey] || false;
@@ -492,7 +512,20 @@ function IssuesPage() {
492512
setServiceNowModalActive(true)
493513
})
494514
}
495-
515+
516+
function createDevRevTicketBulk() {
517+
setSelectedIssuesItems(items)
518+
settingFunctions.fetchDevRevIntegration().then((devrevIntegration) => {
519+
const partsMap = devrevIntegration.partsMap || {}
520+
const partsArray = Object.entries(partsMap).map(([id, name]) => ({id, name}))
521+
if(partsArray.length > 0){
522+
setDevRevParts(partsArray)
523+
setDevRevPartId(partsArray[0].id)
524+
}
525+
setDevRevModalActive(true)
526+
})
527+
}
528+
496529
let issues = [
497530
{
498531
content: 'False positive',
@@ -531,6 +564,11 @@ function IssuesPage() {
531564
content: 'Create ServiceNow ticket',
532565
onAction: () => { createServiceNowTicketBulk() },
533566
disabled: (window.SERVICENOW_INTEGRATED === 'false')
567+
},
568+
{
569+
content: 'Create DevRev ticket',
570+
onAction: () => { createDevRevTicketBulk() },
571+
disabled: (window.DEVREV_INTEGRATED === 'false')
534572
}
535573
];
536574

@@ -715,6 +753,7 @@ function IssuesPage() {
715753
id: item?.id ? JSON.stringify(item.id) : '',
716754
issueDescription: item?.description,
717755
jiraIssueUrl: item?.jiraIssueUrl || "",
756+
devrevWorkUrl: item?.devrevWorkUrl || "",
718757
}],
719758
numberOfEndpoints: 1
720759
})
@@ -731,7 +770,8 @@ function IssuesPage() {
731770
url: item?.id?.apiInfoKey?.url,
732771
id: item?.id ? JSON.stringify(item.id) : '',
733772
issueDescription: item?.description,
734-
jiraIssueUrl: item?.jiraIssueUrl || ""
773+
jiraIssueUrl: item?.jiraIssueUrl || "",
774+
devrevWorkUrl: item?.devrevWorkUrl || ""
735775
})
736776
existingIssue.numberOfEndpoints = (existingIssue.numberOfEndpoints || 1) + 1
737777
}
@@ -978,6 +1018,18 @@ function IssuesPage() {
9781018
isServiceNowModal={true}
9791019
/>
9801020

1021+
<JiraTicketCreationModal
1022+
modalActive={devrevModalActive}
1023+
setModalActive={setDevRevModalActive}
1024+
handleSaveAction={handleSaveBulkDevRevTicketsAction}
1025+
jiraProjectMaps={devrevParts}
1026+
setProjId={setDevRevPartId}
1027+
setIssueType={setDevRevWorkItemType}
1028+
projId={devrevPartId}
1029+
issueType={devrevWorkItemType}
1030+
isDevRevModal={true}
1031+
/>
1032+
9811033
<CompulsoryDescriptionModal
9821034
open={compulsoryDescriptionModal}
9831035
onClose={() => setCompulsoryDescriptionModal(false)}

apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/issues/api.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,5 +120,12 @@ export default {
120120
method: 'post',
121121
data: {testingIssuesIdList, tableName}
122122
})
123+
},
124+
createDevRevTickets(testingIssuesIdList, partId, workItemType, aktoDashboardHost) {
125+
return request({
126+
url: 'api/createDevRevTickets',
127+
method: 'post',
128+
data: {testingIssuesIdList, partId, workItemType, aktoDashboardHost}
129+
})
123130
}
124131
}

apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/issues/transform.js

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ const transform = {
3434
{urls.map((ele,index)=>{
3535
const borderStyle = index < (urls.length - 1) ? {borderBlockEndWidth : 1} : {}
3636
const jiraKey = ele?.jiraIssueUrl && ele.jiraIssueUrl.length > 0 ? /[^/]*$/.exec(ele.jiraIssueUrl)[0] : ""
37+
const devrevKey = ele?.devrevWorkUrl && ele.devrevWorkUrl.length > 0 ? /[^/]*$/.exec(ele.devrevWorkUrl)[0] : ""
3738
return(
3839
<Box padding={"2"} paddingInlineEnd={"4"} paddingInlineStart={"3"} key={index}
3940
borderColor="border-subdued" {...borderStyle}>
@@ -64,6 +65,18 @@ const transform = {
6465
</HorizontalStack>
6566
</Tag>
6667
}
68+
{devrevKey &&
69+
<Tag>
70+
<HorizontalStack gap={1}>
71+
<Avatar size="extraSmall" shape='round' source="/public/devrev-ai.svg" />
72+
<Link url={ele?.devrevWorkUrl} target="_blank">
73+
<Text>
74+
{devrevKey}
75+
</Text>
76+
</Link>
77+
</HorizontalStack>
78+
</Tag>
79+
}
6780
</HorizontalStack>
6881
</HorizontalStack>
6982
</Box>
@@ -111,7 +124,8 @@ const transform = {
111124
url: `${urlObj.method} ${urlObj.url}`,
112125
id: urlObj.id,
113126
issueDescription: urlObj.issueDescription,
114-
jiraIssueUrl: urlObj.jiraIssueUrl || ""
127+
jiraIssueUrl: urlObj.jiraIssueUrl || "",
128+
devrevWorkUrl: urlObj.devrevWorkUrl || ""
115129
})), isCompliancePage)
116130
}
117131
}))

apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/testing/SingleTestRunPage/SingleTestRunPage.js

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -454,16 +454,16 @@ function SingleTestRunPage() {
454454
const shouldFetchCount = !func.deepComparison(copyFilters, filters) || copyUpdateTable !== updateTable;
455455

456456
const fetchResultsPromise = api.fetchTestingRunResults(
457-
localSelectedTestRun.testingRunResultSummaryHexId,
458-
tableTabMap[selectedTab],
459-
sortKey,
460-
sortOrder,
461-
skip,
462-
limit,
463-
filters,
457+
localSelectedTestRun.testingRunResultSummaryHexId,
458+
tableTabMap[selectedTab],
459+
sortKey,
460+
sortOrder,
461+
skip,
462+
limit,
463+
filters,
464464
queryValue
465-
).then(({ testingRunResults, errorEnums, issuesDescriptionMap, jiraIssuesMapForResults }) => {
466-
testRunResultsRes = transform.prepareTestRunResults(hexId, testingRunResults, localSubCategoryMap, subCategoryFromSourceConfigMap, issuesDescriptionMap, jiraIssuesMapForResults)
465+
).then(({ testingRunResults, errorEnums, issuesDescriptionMap, jiraIssuesMapForResults, devrevIssuesMapForResults }) => {
466+
testRunResultsRes = transform.prepareTestRunResults(hexId, testingRunResults, localSubCategoryMap, subCategoryFromSourceConfigMap, issuesDescriptionMap, jiraIssuesMapForResults, devrevIssuesMapForResults)
467467
if (selectedTab === 'domain_unreachable' || selectedTab === 'skipped' || selectedTab === 'need_configurations') {
468468
errorEnums['UNKNOWN_ERROR_OCCURRED'] = "OOPS! Unknown error occurred."
469469
setErrorsObject(errorEnums)

0 commit comments

Comments
 (0)