Skip to content

Commit dfae1d3

Browse files
authored
Merge pull request #97 from DGouron/feat/69-extract-dashboard-utility-modules
feat(dashboard): extract utility modules and add i18n support
2 parents 4ccaa93 + 3df84fd commit dfae1d3

File tree

12 files changed

+1077
-307
lines changed

12 files changed

+1077
-307
lines changed

src/interface-adapters/views/dashboard/index.html

Lines changed: 328 additions & 307 deletions
Large diffs are not rendered by default.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export const MAX_RECONNECT_ATTEMPTS = 10;
2+
export const RECONNECT_DELAY = 3000;
3+
export const STORAGE_KEY_PROJECTS = 'review-flow-projects';
4+
export const STORAGE_KEY_CURRENT = 'review-flow-current-project';
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import { t, getLanguage } from './i18n.js';
2+
3+
/**
4+
* @param {string | null | undefined} dateStr
5+
* @returns {string}
6+
*/
7+
export function formatTime(dateStr) {
8+
if (!dateStr) return '-';
9+
const date = new Date(dateStr);
10+
const now = new Date();
11+
const diff = now - date;
12+
if (diff < 60000) return t('time.justNow');
13+
if (diff < 3600000) return t('time.minutesAgo', { minutes: Math.floor(diff / 60000) });
14+
if (diff < 86400000) return t('time.hoursAgo', { hours: Math.floor(diff / 3600000) });
15+
const locale = getLanguage() === 'fr' ? 'fr-FR' : 'en-US';
16+
return date.toLocaleDateString(locale);
17+
}
18+
19+
/**
20+
* @param {string | null | undefined} startStr
21+
* @param {string | null | undefined} endStr
22+
* @param {number | null | undefined} totalMs
23+
* @returns {string}
24+
*/
25+
export function formatDuration(startStr, endStr, totalMs) {
26+
let diff;
27+
if (totalMs !== undefined && totalMs !== null) {
28+
diff = Math.floor(totalMs / 1000);
29+
} else if (startStr) {
30+
const start = new Date(startStr);
31+
const end = endStr ? new Date(endStr) : new Date();
32+
diff = Math.floor((end - start) / 1000);
33+
} else {
34+
return '';
35+
}
36+
if (diff < 60) return `${diff}s`;
37+
if (diff < 3600) return `${Math.floor(diff / 60)}m ${diff % 60}s`;
38+
return `${Math.floor(diff / 3600)}h ${Math.floor((diff % 3600) / 60)}m`;
39+
}
40+
41+
/**
42+
* @param {string} phase
43+
* @returns {string}
44+
*/
45+
export function formatPhase(phase) {
46+
return t(`phase.${phase}`);
47+
}
48+
49+
/**
50+
* @param {number} timestamp
51+
* @returns {string}
52+
*/
53+
export function formatLogTime(timestamp) {
54+
const date = new Date(timestamp);
55+
const locale = getLanguage() === 'fr' ? 'fr-FR' : 'en-US';
56+
return date.toLocaleTimeString(locale);
57+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/**
2+
* @param {string | null | undefined} text
3+
* @returns {string}
4+
*/
5+
export function escapeHtml(text) {
6+
if (!text) return '';
7+
return text
8+
.replace(/&/g, '&amp;')
9+
.replace(/</g, '&lt;')
10+
.replace(/>/g, '&gt;')
11+
.replace(/"/g, '&quot;')
12+
.replace(/'/g, '&#39;');
13+
}
14+
15+
/**
16+
* @param {string} md
17+
* @returns {string}
18+
*/
19+
export function markdownToHtml(md) {
20+
const html = md
21+
.replace(/&/g, '&amp;')
22+
.replace(/</g, '&lt;')
23+
.replace(/>/g, '&gt;')
24+
.replace(/```(\w*)\n([\s\S]*?)```/g, '<pre><code>$2</code></pre>')
25+
.replace(/`([^`]+)`/g, '<code>$1</code>')
26+
.replace(/^### (.+)$/gm, '<h3>$1</h3>')
27+
.replace(/^## (.+)$/gm, '<h2>$1</h2>')
28+
.replace(/^# (.+)$/gm, '<h1>$1</h1>')
29+
.replace(/\*\*([^*]+)\*\*/g, '<strong>$1</strong>')
30+
.replace(/\*([^*]+)\*/g, '<em>$1</em>')
31+
.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2" target="_blank">$1</a>')
32+
.replace(/^> (.+)$/gm, '<blockquote>$1</blockquote>')
33+
.replace(/^- (.+)$/gm, '<li>$1</li>')
34+
.replace(/^\d+\. (.+)$/gm, '<li>$1</li>')
35+
.replace(/^---$/gm, '<hr>')
36+
.replace(/^\|(.+)\|$/gm, (match, content) => {
37+
const cells = content.split('|').map((/** @type {string} */ c) => c.trim());
38+
if (cells.every((/** @type {string} */ c) => c.match(/^-+$/))) return '';
39+
const cellTag = match.includes('---') ? 'th' : 'td';
40+
return '<tr>' + cells.map((/** @type {string} */ c) => `<${cellTag}>${c}</${cellTag}>`).join('') + '</tr>';
41+
})
42+
.replace(/(<tr>[\s\S]*?<\/tr>)+/g, '<table>$&</table>')
43+
.replace(/(<li>[\s\S]*?<\/li>)+/g, '<ul>$&</ul>')
44+
.replace(/\n\n/g, '</p><p>')
45+
.replace(/\n/g, '<br>');
46+
47+
return '<p>' + html + '</p>';
48+
}

0 commit comments

Comments
 (0)