jiraCloud/services/approvalCards.js
jmcqueen 225ca27c99 Render compact approval details in Adaptive Card FactSets.
Use a two-column FactSet for short fields and keep multi-line textarea values in separate blocks.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-28 12:45:14 -04:00

258 lines
7.6 KiB
JavaScript

import { buildDetailLinesForRequestType } from '../lib/requestTypeFields.js';
const PORTAL_BASE_URL = 'https://aeo.atlassian.net/servicedesk/customer/portal/135';
function getRequestTypeId(jiraTicket) {
return jiraTicket.issue.fields?.customfield_10010?.requestType?.id;
}
function getRequestTypeLabel(jiraTicket) {
const requestTypeField = jiraTicket.issue.fields?.customfield_10010;
if (!requestTypeField) {
return null;
}
return requestTypeField.errorMessage || requestTypeField.requestType?.name || null;
}
function buildHeaderBlocks(jiraTicket) {
const issueKey = jiraTicket.issue.key;
const blocks = [
{
type: 'TextBlock',
text: `[${issueKey}](${PORTAL_BASE_URL}/${issueKey})`,
wrap: true,
weight: 'Bolder',
size: 'Medium',
},
{
type: 'TextBlock',
text: jiraTicket.issue.fields.status.name,
wrap: true,
isSubtle: true,
spacing: 'None',
},
];
const requestTypeLabel = getRequestTypeLabel(jiraTicket);
if (requestTypeLabel) {
blocks.push({
type: 'TextBlock',
text: `**Request Type:** ${requestTypeLabel}`,
wrap: true,
spacing: 'Medium',
});
}
if (jiraTicket.issue.fields.summary) {
blocks.push({
type: 'TextBlock',
text: `**Summary:** ${jiraTicket.issue.fields.summary}`,
wrap: true,
spacing: 'Small',
});
}
return blocks;
}
function buildPlainTextHeader(jiraTicket) {
const issueKey = jiraTicket.issue.key;
let text = `[${issueKey}](${PORTAL_BASE_URL}/${issueKey})\n`;
text += `${jiraTicket.issue.fields.status.name}\n`;
const requestTypeLabel = getRequestTypeLabel(jiraTicket);
if (requestTypeLabel) {
text += `\n**Request Type:** ${requestTypeLabel}\n`;
}
if (jiraTicket.issue.fields.summary) {
text += `**Summary:** ${jiraTicket.issue.fields.summary}\n`;
}
return text;
}
function isLongDetailValue(line) {
if (line.format === 'textarea') {
return true;
}
return line.value.includes('\n') || line.value.length > 120;
}
function buildDetailBlocks(detailLines) {
if (!detailLines.length) {
return [];
}
const compactLines = detailLines.filter(line => !isLongDetailValue(line));
const longLines = detailLines.filter(line => isLongDetailValue(line));
const blocks = [
{
type: 'TextBlock',
text: 'Details',
weight: 'Bolder',
size: 'Medium',
separator: true,
spacing: 'Medium',
},
];
if (compactLines.length) {
blocks.push({
type: 'FactSet',
spacing: 'Small',
facts: compactLines.map(line => ({
title: line.label,
value: line.value,
})),
});
}
for (const line of longLines) {
blocks.push({
type: 'TextBlock',
text: `**${line.label}**`,
weight: 'Bolder',
spacing: 'Medium',
wrap: true,
});
blocks.push({
type: 'TextBlock',
text: line.value,
spacing: 'Small',
wrap: true,
});
}
return blocks;
}
function formatDetailLinesPlain(detailLines) {
let text = '**Details:**\n';
for (const line of detailLines) {
text += `- **${line.label}:** ${line.value.replace(/\n/g, '\n ')}\n`;
}
return text;
}
function buildFallbackChangeDetailLines(jiraTicket) {
const lines = [];
const fields = jiraTicket.issue.fields;
if (fields.customfield_10080) {
lines.push({ label: 'Risk', value: fields.customfield_10080.value });
}
if (fields.customfield_10004) {
lines.push({ label: 'Impact', value: fields.customfield_10004.value });
}
if (fields.customfield_10256) {
lines.push({ label: 'Business impact', value: fields.customfield_10256 });
}
if (fields.customfield_10252) {
lines.push({ label: 'Business justification', value: fields.customfield_10252 });
}
if (fields.customfield_10257) {
const changeDate = new Date(fields.customfield_10257).toLocaleDateString();
const changeTime = new Date(fields.customfield_10257).toLocaleTimeString([], {
hour: '2-digit',
minute: '2-digit',
hour12: true,
});
lines.push({ label: 'Implementation date', value: `${changeDate} ${changeTime}` });
}
return lines;
}
function buildCardPayload({ jiraTicket, detailLines = [], assignmentText = '' }) {
const body = [
...buildHeaderBlocks(jiraTicket),
...buildDetailBlocks(detailLines),
];
if (assignmentText.trim()) {
body.push({
type: 'TextBlock',
text: assignmentText.trim(),
wrap: true,
separator: true,
spacing: 'Medium',
});
}
const requestCard = {
type: 'AdaptiveCard',
$schema: 'http://adaptivecards.io/schemas/adaptive-card.json',
version: '1.2',
body,
actions: [
{
type: 'Action.OpenUrl',
title: 'Open Request',
url: `${PORTAL_BASE_URL}/${jiraTicket.issue.key}`,
},
{
type: 'Action.Submit',
title: 'Remove Card',
style: 'destructive',
data: { cardType: 'requestApproval', action: 'removeCard' },
},
],
};
let requestText = buildPlainTextHeader(jiraTicket);
if (detailLines.length) {
requestText += `---\n${formatDetailLinesPlain(detailLines)}`;
}
if (assignmentText.trim()) {
requestText += `---\n${assignmentText}`;
}
return { card: requestCard, message: requestText };
}
export function buildChangeApproval(jiraTicket, log) {
return new Promise(function (resolve) {
const requestTypeId = getRequestTypeId(jiraTicket);
const detailLines = requestTypeId
? buildDetailLinesForRequestType(jiraTicket, requestTypeId)
: buildFallbackChangeDetailLines(jiraTicket);
log.logDebug('buildChangeApproval', `Built card for ${jiraTicket.issue.key}`);
resolve(buildCardPayload({ jiraTicket, detailLines }));
});
}
export function buildRequestApproval(jiraTicket) {
return new Promise(function (resolve) {
const requestTypeId = getRequestTypeId(jiraTicket);
let detailLines = [];
if (requestTypeId) {
detailLines = buildDetailLinesForRequestType(jiraTicket, requestTypeId);
} else if (jiraTicket.issue.fields.customfield_10314) {
let person = `${jiraTicket.issue.fields.customfield_10346}, ${jiraTicket.issue.fields.customfield_10314}`;
if (jiraTicket.issue.fields.customfield_10310) {
person += ` (${jiraTicket.issue.fields.customfield_10310.value})`;
}
detailLines.push({ label: 'Person', value: person });
if (jiraTicket.issue.fields.customfield_10318) {
detailLines.push({
label: 'Position',
value: jiraTicket.issue.fields.customfield_10318,
});
}
}
let assignmentText = '';
if (jiraTicket.issue.fields.reporter) {
assignmentText += `**Reporter:** ${jiraTicket.issue.fields.reporter.displayName}\n`;
}
resolve(buildCardPayload({
jiraTicket,
detailLines,
assignmentText,
}));
});
}