jiraCloud/lib/requestTypeFields.js
jmcqueen 781b238a5b Simplify approval card workflow fields and format times in Eastern.
Remove moved-by and from-status, rename to-status to Status, and show Created/Updated in America/New_York with EDT/EST.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-28 13:24:18 -04:00

172 lines
5.5 KiB
JavaScript

import fs from 'fs';
import { formatJiraRichText } from './jiraRichText.js';
const SKIP_FIELD_IDS = new Set(['attachment']);
const EASTERN_TIME_ZONE = 'America/New_York';
export function formatEasternDateTime(value) {
const date = new Date(value);
if (Number.isNaN(date.getTime())) {
return String(value);
}
const formatted = new Intl.DateTimeFormat('en-US', {
timeZone: EASTERN_TIME_ZONE,
month: 'numeric',
day: 'numeric',
year: 'numeric',
hour: 'numeric',
minute: '2-digit',
second: '2-digit',
hour12: true,
}).format(date);
const timeZoneName = new Intl.DateTimeFormat('en-US', {
timeZone: EASTERN_TIME_ZONE,
timeZoneName: 'short',
}).formatToParts(date).find(part => part.type === 'timeZoneName')?.value || 'ET';
return `${formatted} ${timeZoneName}`;
}
export function formatEasternDate(value) {
const date = new Date(value);
if (Number.isNaN(date.getTime())) {
return String(value);
}
return new Intl.DateTimeFormat('en-US', {
timeZone: EASTERN_TIME_ZONE,
month: 'numeric',
day: 'numeric',
year: 'numeric',
}).format(date);
}
export function loadRequestTypeFields() {
const path = './config/requestTypeFields.json';
if (!fs.existsSync(path)) {
return { common: { displayFields: [] }, groups: {}, requestTypes: {} };
}
return JSON.parse(fs.readFileSync(path, 'utf8'));
}
function resolveFieldEntry(entry, groups) {
if (typeof entry === 'string' && groups[entry]) {
return groups[entry].displayFields || [];
}
return [entry];
}
export function getDisplayFieldsForRequestType(requestTypeId, fieldMap = loadRequestTypeFields()) {
const key = String(requestTypeId);
const typeConfig = fieldMap.requestTypes?.[key];
if (!typeConfig) {
return fieldMap.common?.displayFields || [];
}
const groups = fieldMap.groups || {};
const resolved = [];
if (typeConfig.includeCommon !== false) {
resolved.push(...(fieldMap.common?.displayFields || []));
}
for (const groupRef of typeConfig.groups || []) {
const groupFields = groups[groupRef]?.displayFields || [];
resolved.push(...groupFields);
}
for (const field of typeConfig.displayFields || []) {
resolved.push(...resolveFieldEntry(field, groups));
}
const seen = new Set();
return resolved.filter(field => {
const dedupeKey = field.path || field.fieldId;
if (!dedupeKey || seen.has(dedupeKey) || SKIP_FIELD_IDS.has(field.fieldId)) {
return false;
}
seen.add(dedupeKey);
return true;
});
}
export function formatFieldValue(value, format) {
if (value == null || value === '') {
return null;
}
switch (format) {
case 'option':
return value.value ?? value.name ?? String(value);
case 'user':
return value.displayName ?? value.emailAddress ?? String(value);
case 'users':
if (!Array.isArray(value)) {
return formatFieldValue(value, 'user');
}
return value.map(item => formatFieldValue(item, 'user')).filter(Boolean).join(', ');
case 'datetime':
return formatEasternDateTime(value);
case 'date':
return formatEasternDate(value);
case 'cmdb':
if (Array.isArray(value)) {
return value.map(item => item.label || item.name || item.objectKey || item.value).filter(Boolean).join(', ');
}
return value.label || value.name || value.objectKey || String(value);
case 'multiselect':
case 'multicheckboxes':
if (!Array.isArray(value)) {
return String(value);
}
return value.map(item => item.value || item.label || String(item)).join(', ');
case 'cascading':
if (value.child) {
return `${value.value}${value.child.value}`;
}
return value.value ?? String(value);
case 'textarea':
case 'text':
default:
if (typeof value === 'object') {
const richText = formatJiraRichText(value);
return richText || value.displayName || value.value || value.name || null;
}
return formatJiraRichText(value) || null;
}
}
export function getFieldValueFromTicket(jiraTicket, fieldDef) {
if (fieldDef.path) {
return fieldDef.path.split('.').reduce((current, part) => current?.[part], jiraTicket);
}
const fieldId = fieldDef.fieldId;
if (!fieldId) {
return null;
}
if (fieldId === 'summary' || fieldId === 'description' || fieldId === 'priority' || fieldId === 'created' || fieldId === 'updated') {
const fields = jiraTicket.issue?.fields || {};
return fields[fieldId];
}
return jiraTicket.issue?.fields?.[fieldId] ?? null;
}
export function buildDetailLinesForRequestType(jiraTicket, requestTypeId, fieldMap = loadRequestTypeFields()) {
const fields = getDisplayFieldsForRequestType(requestTypeId, fieldMap);
const lines = [];
for (const fieldDef of fields) {
const rawValue = getFieldValueFromTicket(jiraTicket, fieldDef);
const formatted = formatFieldValue(rawValue, fieldDef.format);
if (formatted) {
lines.push({ label: fieldDef.label, value: formatted, format: fieldDef.format });
}
}
return lines;
}