adobe-to-docusign-migrator/web/static/js/utils.js

98 lines
2.8 KiB
JavaScript

// Shared utility functions
export function escHtml(str) {
return String(str ?? '').replace(/[&<>"']/g, c => ({
'&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;'
})[c]);
}
export function formatDate(iso) {
if (!iso) return '—';
try {
return new Date(iso).toLocaleDateString('en-US', {
year: 'numeric', month: 'short', day: 'numeric'
});
} catch { return iso.slice(0, 10); }
}
export function formatDateTime(iso) {
if (!iso) return '—';
try {
return new Date(iso).toLocaleString('en-US', {
year: 'numeric', month: 'short', day: 'numeric',
hour: '2-digit', minute: '2-digit'
});
} catch { return iso.slice(0, 19).replace('T', ' '); }
}
export function formatRelative(iso) {
if (!iso) return '—';
const diff = Date.now() - new Date(iso).getTime();
const m = Math.floor(diff / 60000);
if (m < 1) return 'just now';
if (m < 60) return `${m}m ago`;
const h = Math.floor(m / 60);
if (h < 24) return `${h}h ago`;
const d = Math.floor(h / 24);
if (d < 7) return `${d}d ago`;
return formatDate(iso);
}
export function debounce(fn, ms = 300) {
let timer;
return (...args) => {
clearTimeout(timer);
timer = setTimeout(() => fn(...args), ms);
};
}
export function uuid() {
return crypto.randomUUID
? crypto.randomUUID()
: 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
const r = Math.random() * 16 | 0;
return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);
});
}
// Truncate a string to maxLen chars, appending ellipsis if needed
export function truncate(str, maxLen = 40) {
if (!str) return '';
return str.length > maxLen ? str.slice(0, maxLen - 1) + '…' : str;
}
// First letter of a name for avatar initials
export function initials(name) {
if (!name) return '?';
const parts = name.trim().split(/\s+/);
return parts.length >= 2
? (parts[0][0] + parts[parts.length - 1][0]).toUpperCase()
: name.slice(0, 2).toUpperCase();
}
// Download a string as a file
export function downloadText(filename, content, type = 'text/plain') {
const blob = new Blob([content], { type });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url; a.download = filename;
document.body.appendChild(a); a.click();
document.body.removeChild(a); URL.revokeObjectURL(url);
}
// Convert array of objects to CSV and download
export function downloadCsv(filename, rows) {
if (!rows.length) return;
const headers = Object.keys(rows[0]);
const csv = [
headers.join(','),
...rows.map(r => headers.map(h => JSON.stringify(r[h] ?? '')).join(','))
].join('\n');
downloadText(filename, csv, 'text/csv');
}
// Shorten a SHA-256 hash for display
export function shortHash(hash, len = 8) {
return hash ? hash.slice(0, len) : '—';
}