@autocode-cli/autocode 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/dist/server/dashboard/pages/autocreate.js +3 -3
  2. package/dist/server/dashboard/pages/changelog.d.ts.map +1 -1
  3. package/dist/server/dashboard/pages/changelog.js +20 -11
  4. package/dist/server/dashboard/pages/changelog.js.map +1 -1
  5. package/dist/server/dashboard/pages/column-edit.js +2 -2
  6. package/dist/server/dashboard/pages/column-prompt.d.ts.map +1 -1
  7. package/dist/server/dashboard/pages/column-prompt.js +21 -0
  8. package/dist/server/dashboard/pages/column-prompt.js.map +1 -1
  9. package/dist/server/dashboard/pages/column-terminal.d.ts.map +1 -1
  10. package/dist/server/dashboard/pages/column-terminal.js +21 -0
  11. package/dist/server/dashboard/pages/column-terminal.js.map +1 -1
  12. package/dist/server/dashboard/pages/issue-graph.d.ts.map +1 -1
  13. package/dist/server/dashboard/pages/issue-graph.js +70 -22
  14. package/dist/server/dashboard/pages/issue-graph.js.map +1 -1
  15. package/dist/server/dashboard/pages/issue-shared.d.ts.map +1 -1
  16. package/dist/server/dashboard/pages/issue-shared.js +54 -122
  17. package/dist/server/dashboard/pages/issue-shared.js.map +1 -1
  18. package/dist/server/dashboard/pages/issue-view.js +1 -1
  19. package/dist/server/dashboard/pages/new-issue.d.ts.map +1 -1
  20. package/dist/server/dashboard/pages/new-issue.js +34 -128
  21. package/dist/server/dashboard/pages/new-issue.js.map +1 -1
  22. package/dist/server/dashboard/pages/pipeline-configurator.d.ts.map +1 -1
  23. package/dist/server/dashboard/pages/pipeline-configurator.js +39 -183
  24. package/dist/server/dashboard/pages/pipeline-configurator.js.map +1 -1
  25. package/dist/server/dashboard/pages/stats-page.d.ts.map +1 -1
  26. package/dist/server/dashboard/pages/stats-page.js +43 -109
  27. package/dist/server/dashboard/pages/stats-page.js.map +1 -1
  28. package/dist/server/dashboard/scripts/index.d.ts.map +1 -1
  29. package/dist/server/dashboard/scripts/index.js +48 -253
  30. package/dist/server/dashboard/scripts/index.js.map +1 -1
  31. package/dist/server/dashboard/shared/header.d.ts +88 -0
  32. package/dist/server/dashboard/shared/header.d.ts.map +1 -0
  33. package/dist/server/dashboard/shared/header.js +209 -0
  34. package/dist/server/dashboard/shared/header.js.map +1 -0
  35. package/dist/server/dashboard/shared/i18n-script.d.ts +45 -0
  36. package/dist/server/dashboard/shared/i18n-script.d.ts.map +1 -0
  37. package/dist/server/dashboard/shared/i18n-script.js +204 -0
  38. package/dist/server/dashboard/shared/i18n-script.js.map +1 -0
  39. package/dist/server/dashboard/shared/index.d.ts +19 -0
  40. package/dist/server/dashboard/shared/index.d.ts.map +1 -0
  41. package/dist/server/dashboard/shared/index.js +22 -0
  42. package/dist/server/dashboard/shared/index.js.map +1 -0
  43. package/dist/server/dashboard/shared/translations.d.ts +515 -0
  44. package/dist/server/dashboard/shared/translations.d.ts.map +1 -0
  45. package/dist/server/dashboard/shared/translations.js +591 -0
  46. package/dist/server/dashboard/shared/translations.js.map +1 -0
  47. package/package.json +1 -1
@@ -80,7 +80,7 @@ export function generateAutocreatePage(lang) {
80
80
  .btn:disabled { opacity: 0.5; cursor: not-allowed; }
81
81
  .btn-large { padding: 12px 24px; font-size: 16px; }
82
82
 
83
- .lang-toggle {
83
+ .lang-switcher {
84
84
  display: flex;
85
85
  gap: 4px;
86
86
  }
@@ -416,7 +416,7 @@ export function generateAutocreatePage(lang) {
416
416
  <header class="header">
417
417
  <a href="/settings/pipeline/configurator" class="back-btn" id="backBtn">← Configurator</a>
418
418
  <h1 class="title"><span>Autocreate</span> Columns</h1>
419
- <div class="lang-toggle">
419
+ <div class="lang-switcher">
420
420
  <button class="btn btn-secondary lang-btn" data-lang="en" onclick="switchLang('en')">EN</button>
421
421
  <button class="btn btn-secondary lang-btn" data-lang="fr" onclick="switchLang('fr')">FR</button>
422
422
  </div>
@@ -492,7 +492,7 @@ export function generateAutocreatePage(lang) {
492
492
  <div class="modal-header">
493
493
  <h3 id="previewModalTitle">Column Preview</h3>
494
494
  <div style="display: flex; gap: 8px; align-items: center;">
495
- <div class="lang-toggle">
495
+ <div class="lang-switcher">
496
496
  <button class="btn btn-secondary lang-btn" data-lang="en" onclick="switchPreviewLang('en')">EN</button>
497
497
  <button class="btn btn-secondary lang-btn" data-lang="fr" onclick="switchPreviewLang('fr')">FR</button>
498
498
  </div>
@@ -1 +1 @@
1
- {"version":3,"file":"changelog.d.ts","sourceRoot":"","sources":["../../../../src/server/dashboard/pages/changelog.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AA+BxD;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,CAmH5D"}
1
+ {"version":3,"file":"changelog.d.ts","sourceRoot":"","sources":["../../../../src/server/dashboard/pages/changelog.ts"],"names":[],"mappings":"AAAA;;GAEG;AAOH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AA+BxD;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,CA0H5D"}
@@ -5,6 +5,7 @@ import { join } from 'node:path';
5
5
  import { getStyles } from '../styles/index.js';
6
6
  import { getConfig } from '../../../utils/config.js';
7
7
  import { readFileSafe } from '../../../utils/fs.js';
8
+ import { generateChangelogHeader } from '../shared/index.js';
8
9
  /**
9
10
  * Render markdown changelog to HTML
10
11
  */
@@ -46,7 +47,6 @@ export function generateChangelogPage(lang) {
46
47
  const content = readFileSafe(filepath) || '';
47
48
  const renderedContent = renderMarkdownChangelog(content);
48
49
  const title = lang === 'fr' ? 'Journal des modifications' : 'Changelog';
49
- const backText = lang === 'fr' ? 'Retour au dashboard' : 'Back to dashboard';
50
50
  const summaryPlaceholder = lang === 'fr' ? 'Génération du résumé...' : 'Generating summary...';
51
51
  return `<!DOCTYPE html>
52
52
  <html lang="${lang}">
@@ -81,14 +81,7 @@ export function generateChangelogPage(lang) {
81
81
  </head>
82
82
  <body>
83
83
  <div class="changelog-page">
84
- <header class="changelog-page-header">
85
- <a href="/" class="back-link">← ${backText}</a>
86
- <h1>${title}</h1>
87
- <div class="lang-switcher">
88
- <button class="lang-btn ${lang === 'en' ? 'active' : ''}" onclick="switchLang('en')">EN</button>
89
- <button class="lang-btn ${lang === 'fr' ? 'active' : ''}" onclick="switchLang('fr')">FR</button>
90
- </div>
91
- </header>
84
+ ${generateChangelogHeader(lang)}
92
85
  <div class="changelog-page-summary loading" id="summary-box">
93
86
  <div class="changelog-page-summary-icon">✨</div>
94
87
  <div class="changelog-page-summary-text" id="summary-text">${summaryPlaceholder}</div>
@@ -99,12 +92,28 @@ export function generateChangelogPage(lang) {
99
92
  </div>
100
93
  <script>
101
94
  const LANG = '${lang}';
95
+ const STORAGE_KEY = 'autocode-lang';
96
+ let currentLang = localStorage.getItem(STORAGE_KEY) || 'fr';
102
97
 
103
- function switchLang(lang) {
104
- localStorage.setItem('autocode-lang', lang);
98
+ /**
99
+ * Switch language - requires page reload because changelog content
100
+ * is loaded from different markdown files (CHANGELOG.md vs CHANGELOG.fr.md)
101
+ */
102
+ function switchLanguage(lang) {
103
+ if (lang === currentLang) return;
104
+ localStorage.setItem(STORAGE_KEY, lang);
105
+ // Reload required because markdown content is loaded server-side
105
106
  window.location.href = '/changelog?lang=' + lang;
106
107
  }
107
108
 
109
+ // Initialize language switcher
110
+ (function initLangSwitcher() {
111
+ document.querySelectorAll('.lang-switcher .lang-btn').forEach(btn => {
112
+ btn.classList.toggle('active', btn.dataset.lang === currentLang);
113
+ btn.addEventListener('click', () => switchLanguage(btn.dataset.lang));
114
+ });
115
+ })();
116
+
108
117
  // Load summary from API
109
118
  async function loadSummary() {
110
119
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"changelog.js","sourceRoot":"","sources":["../../../../src/server/dashboard/pages/changelog.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAGpD;;GAEG;AACH,SAAS,uBAAuB,CAAC,EAAU;IACzC,OAAO,EAAE;QACP,kBAAkB;SACjB,OAAO,CAAC,0CAA0C,EACjD,yFAAyF,CAAC;QAC5F,kBAAkB;SACjB,OAAO,CAAC,cAAc,EAAE,aAAa,CAAC;QACvC,6DAA6D;SAC5D,OAAO,CAAC,+BAA+B,EAAE,mCAAmC,CAAC;QAC9E,gBAAgB;SACf,OAAO,CAAC,YAAY,EAAE,aAAa,CAAC;QACrC,kCAAkC;SACjC,OAAO,CAAC,mCAAmC,EAAE,MAAM,CAAC;SACpD,OAAO,CAAC,iCAAiC,EAAE,aAAa,CAAC;QAC1D,gBAAgB;SACf,OAAO,CAAC,eAAe,EAAE,IAAI,CAAC;QAC/B,mBAAmB;SAClB,OAAO,CAAC,SAAS,EAAE,MAAM,CAAC;QAC3B,wBAAwB;SACvB,OAAO,CAAC,kBAAkB,EAAE,EAAE,CAAC;SAC/B,OAAO,CAAC,kCAAkC,EAAE,EAAE,CAAC;QAChD,sBAAsB;SACrB,OAAO,CAAC,mCAAmC,EAAE,EAAE,CAAC;SAChD,OAAO,CAAC,wCAAwC,EAAE,EAAE,CAAC,CAAC;AAC3D,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,qBAAqB,CAAC,IAAc;IAClD,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,kEAAkE;IAClE,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC;QAClD,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC;QACzB,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC;IAChB,MAAM,QAAQ,GAAG,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,cAAc,CAAC;IACpE,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;IAC7C,MAAM,OAAO,GAAG,YAAY,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;IAC7C,MAAM,eAAe,GAAG,uBAAuB,CAAC,OAAO,CAAC,CAAC;IAEzD,MAAM,KAAK,GAAG,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,2BAA2B,CAAC,CAAC,CAAC,WAAW,CAAC;IACxE,MAAM,QAAQ,GAAG,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,mBAAmB,CAAC;IAE7E,MAAM,kBAAkB,GAAG,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,yBAAyB,CAAC,CAAC,CAAC,uBAAuB,CAAC;IAE/F,OAAO;cACK,IAAI;;;;WAIP,KAAK;;MAEV,SAAS,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;wCA2BuB,QAAQ;YACpC,KAAK;;kCAEiB,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE;kCAC7B,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE;;;;;mEAKI,kBAAkB;;;QAG7E,eAAe;;;;oBAIH,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAgDhB,CAAC;AACT,CAAC"}
1
+ {"version":3,"file":"changelog.js","sourceRoot":"","sources":["../../../../src/server/dashboard/pages/changelog.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAG7D;;GAEG;AACH,SAAS,uBAAuB,CAAC,EAAU;IACzC,OAAO,EAAE;QACP,kBAAkB;SACjB,OAAO,CAAC,0CAA0C,EACjD,yFAAyF,CAAC;QAC5F,kBAAkB;SACjB,OAAO,CAAC,cAAc,EAAE,aAAa,CAAC;QACvC,6DAA6D;SAC5D,OAAO,CAAC,+BAA+B,EAAE,mCAAmC,CAAC;QAC9E,gBAAgB;SACf,OAAO,CAAC,YAAY,EAAE,aAAa,CAAC;QACrC,kCAAkC;SACjC,OAAO,CAAC,mCAAmC,EAAE,MAAM,CAAC;SACpD,OAAO,CAAC,iCAAiC,EAAE,aAAa,CAAC;QAC1D,gBAAgB;SACf,OAAO,CAAC,eAAe,EAAE,IAAI,CAAC;QAC/B,mBAAmB;SAClB,OAAO,CAAC,SAAS,EAAE,MAAM,CAAC;QAC3B,wBAAwB;SACvB,OAAO,CAAC,kBAAkB,EAAE,EAAE,CAAC;SAC/B,OAAO,CAAC,kCAAkC,EAAE,EAAE,CAAC;QAChD,sBAAsB;SACrB,OAAO,CAAC,mCAAmC,EAAE,EAAE,CAAC;SAChD,OAAO,CAAC,wCAAwC,EAAE,EAAE,CAAC,CAAC;AAC3D,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,qBAAqB,CAAC,IAAc;IAClD,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,kEAAkE;IAClE,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC;QAClD,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC;QACzB,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC;IAChB,MAAM,QAAQ,GAAG,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,cAAc,CAAC;IACpE,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;IAC7C,MAAM,OAAO,GAAG,YAAY,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;IAC7C,MAAM,eAAe,GAAG,uBAAuB,CAAC,OAAO,CAAC,CAAC;IAEzD,MAAM,KAAK,GAAG,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,2BAA2B,CAAC,CAAC,CAAC,WAAW,CAAC;IACxE,MAAM,kBAAkB,GAAG,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,yBAAyB,CAAC,CAAC,CAAC,uBAAuB,CAAC;IAE/F,OAAO;cACK,IAAI;;;;WAIP,KAAK;;MAEV,SAAS,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;MA0BX,uBAAuB,CAAC,IAAI,CAAC;;;mEAGgC,kBAAkB;;;QAG7E,eAAe;;;;oBAIH,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAgEhB,CAAC;AACT,CAAC"}
@@ -65,7 +65,7 @@ export function generateColumnEditPage(slug, lang) {
65
65
  font-weight: 600;
66
66
  }
67
67
  .title span { color: var(--muted); font-weight: 400; }
68
- .lang-selector {
68
+ .lang-switcher {
69
69
  display: flex;
70
70
  gap: 4px;
71
71
  }
@@ -151,7 +151,7 @@ export function generateColumnEditPage(slug, lang) {
151
151
  <header class="header">
152
152
  <a href="/" class="back-btn">← Dashboard</a>
153
153
  <h1 class="title">${escapeHtml(columnName)} <span>/ ACTION.md</span></h1>
154
- <div class="lang-selector" id="lang-selector">
154
+ <div class="lang-switcher" id="lang-switcher">
155
155
  <button class="lang-btn" data-lang="en">EN</button>
156
156
  <button class="lang-btn" data-lang="fr">FR</button>
157
157
  </div>
@@ -1 +1 @@
1
- {"version":3,"file":"column-prompt.d.ts","sourceRoot":"","sources":["../../../../src/server/dashboard/pages/column-prompt.ts"],"names":[],"mappings":"AAAA;;GAEG;AAOH;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CA0NnG"}
1
+ {"version":3,"file":"column-prompt.d.ts","sourceRoot":"","sources":["../../../../src/server/dashboard/pages/column-prompt.ts"],"names":[],"mappings":"AAAA;;GAEG;AAQH;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CA8OnG"}
@@ -5,6 +5,7 @@ import { getConfig } from '../../../utils/config.js';
5
5
  import { getIssue } from '../../../core/issue.js';
6
6
  import { escapeHtml } from '../utils.js';
7
7
  import { generate404Page } from './shared.js';
8
+ import { generateLangSwitcher, generateMinimalI18nScript } from '../shared/index.js';
8
9
  /**
9
10
  * Generate the column prompt page
10
11
  */
@@ -95,6 +96,22 @@ export function generateColumnPromptPage(issueKey, columnSlug, lang) {
95
96
  align-items: center;
96
97
  gap: 12px;
97
98
  }
99
+ .lang-switcher {
100
+ display: flex;
101
+ gap: 4px;
102
+ }
103
+ .lang-btn {
104
+ background: transparent;
105
+ border: 1px solid var(--border);
106
+ color: var(--muted);
107
+ padding: 6px 12px;
108
+ border-radius: 4px;
109
+ cursor: pointer;
110
+ font-size: 12px;
111
+ font-weight: 500;
112
+ }
113
+ .lang-btn:hover { border-color: var(--accent); color: var(--text); }
114
+ .lang-btn.active { background: var(--accent); border-color: var(--accent); color: white; }
98
115
  .main {
99
116
  flex: 1;
100
117
  padding: 24px;
@@ -172,6 +189,7 @@ export function generateColumnPromptPage(issueKey, columnSlug, lang) {
172
189
  <span>Prompt →</span>
173
190
  <span class="column-slug">${escapeHtml(columnSlug)}</span>
174
191
  </div>
192
+ ${generateLangSwitcher()}
175
193
  </header>
176
194
 
177
195
  <main class="main">
@@ -222,6 +240,9 @@ export function generateColumnPromptPage(issueKey, columnSlug, lang) {
222
240
  // Init
223
241
  fetchPrompt();
224
242
  </script>
243
+ <script>
244
+ ${generateMinimalI18nScript()}
245
+ </script>
225
246
  </body>
226
247
  </html>`;
227
248
  }
@@ -1 +1 @@
1
- {"version":3,"file":"column-prompt.js","sourceRoot":"","sources":["../../../../src/server/dashboard/pages/column-prompt.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACrD,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9C;;GAEG;AACH,MAAM,UAAU,wBAAwB,CAAC,QAAgB,EAAE,UAAkB,EAAE,IAAY;IACzF,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAE9C,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,eAAe,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IACzC,CAAC;IAED,OAAO;cACK,IAAI;;;;oBAIE,UAAU,CAAC,UAAU,CAAC,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;sBAmJlC,QAAQ;8BACA,QAAQ;;;kCAGJ,UAAU,CAAC,UAAU,CAAC;;;;;;;;;;;;;;;;yBAgB/B,QAAQ;2BACN,UAAU,CAAC,UAAU,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAoCzC,CAAC;AACT,CAAC"}
1
+ {"version":3,"file":"column-prompt.js","sourceRoot":"","sources":["../../../../src/server/dashboard/pages/column-prompt.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACrD,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,oBAAoB,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAC;AAErF;;GAEG;AACH,MAAM,UAAU,wBAAwB,CAAC,QAAgB,EAAE,UAAkB,EAAE,IAAY;IACzF,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAE9C,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,eAAe,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IACzC,CAAC;IAED,OAAO;cACK,IAAI;;;;oBAIE,UAAU,CAAC,UAAU,CAAC,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;sBAmKlC,QAAQ;8BACA,QAAQ;;;kCAGJ,UAAU,CAAC,UAAU,CAAC;;MAElD,oBAAoB,EAAE;;;;;;;;;;;;;;;yBAeH,QAAQ;2BACN,UAAU,CAAC,UAAU,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MAoC3C,yBAAyB,EAAE;;;QAGzB,CAAC;AACT,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"column-terminal.d.ts","sourceRoot":"","sources":["../../../../src/server/dashboard/pages/column-terminal.ts"],"names":[],"mappings":"AAAA;;GAEG;AAOH;;GAEG;AACH,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAugBrG"}
1
+ {"version":3,"file":"column-terminal.d.ts","sourceRoot":"","sources":["../../../../src/server/dashboard/pages/column-terminal.ts"],"names":[],"mappings":"AAAA;;GAEG;AAQH;;GAEG;AACH,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CA2hBrG"}
@@ -5,6 +5,7 @@ import { getConfig } from '../../../utils/config.js';
5
5
  import { getIssue } from '../../../core/issue.js';
6
6
  import { escapeHtml } from '../utils.js';
7
7
  import { generate404Page } from './shared.js';
8
+ import { generateLangSwitcher, generateMinimalI18nScript } from '../shared/index.js';
8
9
  /**
9
10
  * Generate the column terminal page
10
11
  */
@@ -95,6 +96,22 @@ export function generateColumnTerminalPage(issueKey, columnSlug, lang) {
95
96
  align-items: center;
96
97
  gap: 12px;
97
98
  }
99
+ .lang-switcher {
100
+ display: flex;
101
+ gap: 4px;
102
+ }
103
+ .lang-btn {
104
+ background: transparent;
105
+ border: 1px solid var(--border);
106
+ color: var(--muted);
107
+ padding: 6px 12px;
108
+ border-radius: 4px;
109
+ cursor: pointer;
110
+ font-size: 12px;
111
+ font-weight: 500;
112
+ }
113
+ .lang-btn:hover { border-color: var(--accent); color: var(--text); }
114
+ .lang-btn.active { background: var(--accent); border-color: var(--accent); color: white; }
98
115
  .main {
99
116
  flex: 1;
100
117
  padding: 24px;
@@ -283,6 +300,7 @@ export function generateColumnTerminalPage(issueKey, columnSlug, lang) {
283
300
  <span>Terminal →</span>
284
301
  <span class="column-slug">${escapeHtml(columnSlug)}</span>
285
302
  </div>
303
+ ${generateLangSwitcher()}
286
304
  </header>
287
305
 
288
306
  <main class="main">
@@ -522,6 +540,9 @@ export function generateColumnTerminalPage(issueKey, columnSlug, lang) {
522
540
  fetchLog();
523
541
  connectWebSocket();
524
542
  </script>
543
+ <script>
544
+ ${generateMinimalI18nScript()}
545
+ </script>
525
546
  <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
526
547
  </body>
527
548
  </html>`;
@@ -1 +1 @@
1
- {"version":3,"file":"column-terminal.js","sourceRoot":"","sources":["../../../../src/server/dashboard/pages/column-terminal.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACrD,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9C;;GAEG;AACH,MAAM,UAAU,0BAA0B,CAAC,QAAgB,EAAE,UAAkB,EAAE,IAAY;IAC3F,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAE9C,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,eAAe,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IACzC,CAAC;IAED,OAAO;cACK,IAAI;;;;sBAII,UAAU,CAAC,UAAU,CAAC,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;sBAkQpC,QAAQ;8BACA,QAAQ;;;kCAGJ,UAAU,CAAC,UAAU,CAAC;;;;;;;;;;;;;;;;yBAgB/B,QAAQ;2BACN,UAAU,CAAC,UAAU,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAkOzC,CAAC;AACT,CAAC"}
1
+ {"version":3,"file":"column-terminal.js","sourceRoot":"","sources":["../../../../src/server/dashboard/pages/column-terminal.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACrD,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,oBAAoB,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAC;AAErF;;GAEG;AACH,MAAM,UAAU,0BAA0B,CAAC,QAAgB,EAAE,UAAkB,EAAE,IAAY;IAC3F,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAE9C,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,eAAe,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IACzC,CAAC;IAED,OAAO;cACK,IAAI;;;;sBAII,UAAU,CAAC,UAAU,CAAC,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;sBAkRpC,QAAQ;8BACA,QAAQ;;;kCAGJ,UAAU,CAAC,UAAU,CAAC;;MAElD,oBAAoB,EAAE;;;;;;;;;;;;;;;yBAeH,QAAQ;2BACN,UAAU,CAAC,UAAU,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MAiO3C,yBAAyB,EAAE;;;;QAIzB,CAAC;AACT,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"issue-graph.d.ts","sourceRoot":"","sources":["../../../../src/server/dashboard/pages/issue-graph.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AA+BxD;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,CAwD7D"}
1
+ {"version":3,"file":"issue-graph.d.ts","sourceRoot":"","sources":["../../../../src/server/dashboard/pages/issue-graph.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAgCxD;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,CAyD7D"}
@@ -2,32 +2,34 @@
2
2
  * Issue Graph Page - Hierarchical tree visualization of issues
3
3
  */
4
4
  import { getStyles } from '../styles/index.js';
5
+ import { generateLangSwitcher, translations as sharedTranslations } from '../shared/index.js';
6
+ // Local translations for graph-specific keys (uses shared translations for common keys)
5
7
  const translations = {
6
8
  en: {
7
- title: 'Issue Hierarchy',
8
- backToDashboard: 'Back to Dashboard',
9
- noIssues: 'No issues found',
10
- rootIssues: 'Root issues',
11
- totalIssues: 'Total issues',
12
- maxDepth: 'Max depth',
13
- loading: 'Loading...',
14
- zoomIn: 'Zoom in',
15
- zoomOut: 'Zoom out',
16
- resetZoom: 'Reset',
17
- children: 'children',
9
+ title: sharedTranslations.en['graph.title'],
10
+ backToDashboard: sharedTranslations.en['graph.backToDashboard'],
11
+ noIssues: sharedTranslations.en['graph.noIssues'],
12
+ rootIssues: sharedTranslations.en['graph.rootIssues'],
13
+ totalIssues: sharedTranslations.en['graph.totalIssues'],
14
+ maxDepth: sharedTranslations.en['graph.maxDepth'],
15
+ loading: sharedTranslations.en['graph.loading'],
16
+ zoomIn: sharedTranslations.en['graph.zoomIn'],
17
+ zoomOut: sharedTranslations.en['graph.zoomOut'],
18
+ resetZoom: sharedTranslations.en['graph.resetZoom'],
19
+ children: sharedTranslations.en['graph.children'],
18
20
  },
19
21
  fr: {
20
- title: 'Hierarchie des tickets',
21
- backToDashboard: 'Retour au tableau',
22
- noIssues: 'Aucun ticket trouve',
23
- rootIssues: 'Tickets racines',
24
- totalIssues: 'Total tickets',
25
- maxDepth: 'Profondeur max',
26
- loading: 'Chargement...',
27
- zoomIn: 'Zoom +',
28
- zoomOut: 'Zoom -',
29
- resetZoom: 'Reset',
30
- children: 'enfants',
22
+ title: sharedTranslations.fr['graph.title'],
23
+ backToDashboard: sharedTranslations.fr['graph.backToDashboard'],
24
+ noIssues: sharedTranslations.fr['graph.noIssues'],
25
+ rootIssues: sharedTranslations.fr['graph.rootIssues'],
26
+ totalIssues: sharedTranslations.fr['graph.totalIssues'],
27
+ maxDepth: sharedTranslations.fr['graph.maxDepth'],
28
+ loading: sharedTranslations.fr['graph.loading'],
29
+ zoomIn: sharedTranslations.fr['graph.zoomIn'],
30
+ zoomOut: sharedTranslations.fr['graph.zoomOut'],
31
+ resetZoom: sharedTranslations.fr['graph.resetZoom'],
32
+ children: sharedTranslations.fr['graph.children'],
31
33
  },
32
34
  };
33
35
  /**
@@ -57,6 +59,7 @@ export function generateIssueGraphPage(lang) {
57
59
  <span class="stat"><span class="stat-label">${t.totalIssues}:</span> <span id="total-count">-</span></span>
58
60
  <span class="stat"><span class="stat-label">${t.maxDepth}:</span> <span id="max-depth">-</span></span>
59
61
  </div>
62
+ ${generateLangSwitcher()}
60
63
  <div class="zoom-controls">
61
64
  <button onclick="zoomIn()" title="${t.zoomIn}">+</button>
62
65
  <button onclick="resetZoom()" title="${t.resetZoom}">100%</button>
@@ -151,6 +154,33 @@ function getGraphStyles() {
151
154
  color: var(--text-muted);
152
155
  }
153
156
 
157
+ .lang-switcher {
158
+ display: flex;
159
+ gap: 4px;
160
+ }
161
+
162
+ .lang-btn {
163
+ padding: 6px 12px;
164
+ border: 1px solid var(--border-color);
165
+ background: transparent;
166
+ color: var(--text-secondary);
167
+ border-radius: 4px;
168
+ cursor: pointer;
169
+ font-size: 12px;
170
+ font-weight: 500;
171
+ }
172
+
173
+ .lang-btn:hover {
174
+ border-color: var(--accent-color);
175
+ color: var(--text-primary);
176
+ }
177
+
178
+ .lang-btn.active {
179
+ background: var(--accent-color);
180
+ border-color: var(--accent-color);
181
+ color: white;
182
+ }
183
+
154
184
  .zoom-controls {
155
185
  display: flex;
156
186
  gap: 4px;
@@ -306,6 +336,24 @@ function getGraphStyles() {
306
336
  */
307
337
  function getGraphScript(t) {
308
338
  return `
339
+ // Language switcher (page reload required because content is server-rendered)
340
+ const STORAGE_KEY = 'autocode-lang';
341
+ let currentLang = localStorage.getItem(STORAGE_KEY) || 'fr';
342
+
343
+ function switchLanguage(lang) {
344
+ if (lang === currentLang) return;
345
+ localStorage.setItem(STORAGE_KEY, lang);
346
+ window.location.href = '/issues/graph?lang=' + lang;
347
+ }
348
+
349
+ // Initialize language switcher
350
+ (function initLangSwitcher() {
351
+ document.querySelectorAll('.lang-switcher .lang-btn').forEach(btn => {
352
+ btn.classList.toggle('active', btn.dataset.lang === currentLang);
353
+ btn.addEventListener('click', () => switchLanguage(btn.dataset.lang));
354
+ });
355
+ })();
356
+
309
357
  const NODE_WIDTH = 180;
310
358
  const NODE_HEIGHT = 60;
311
359
  const NODE_H_GAP = 40;
@@ -1 +1 @@
1
- {"version":3,"file":"issue-graph.js","sourceRoot":"","sources":["../../../../src/server/dashboard/pages/issue-graph.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAG/C,MAAM,YAAY,GAAG;IACnB,EAAE,EAAE;QACF,KAAK,EAAE,iBAAiB;QACxB,eAAe,EAAE,mBAAmB;QACpC,QAAQ,EAAE,iBAAiB;QAC3B,UAAU,EAAE,aAAa;QACzB,WAAW,EAAE,cAAc;QAC3B,QAAQ,EAAE,WAAW;QACrB,OAAO,EAAE,YAAY;QACrB,MAAM,EAAE,SAAS;QACjB,OAAO,EAAE,UAAU;QACnB,SAAS,EAAE,OAAO;QAClB,QAAQ,EAAE,UAAU;KACrB;IACD,EAAE,EAAE;QACF,KAAK,EAAE,wBAAwB;QAC/B,eAAe,EAAE,mBAAmB;QACpC,QAAQ,EAAE,qBAAqB;QAC/B,UAAU,EAAE,iBAAiB;QAC7B,WAAW,EAAE,eAAe;QAC5B,QAAQ,EAAE,gBAAgB;QAC1B,OAAO,EAAE,eAAe;QACxB,MAAM,EAAE,QAAQ;QAChB,OAAO,EAAE,QAAQ;QACjB,SAAS,EAAE,OAAO;QAClB,QAAQ,EAAE,SAAS;KACpB;CACF,CAAC;AAEF;;GAEG;AACH,MAAM,UAAU,sBAAsB,CAAC,IAAc;IACnD,MAAM,CAAC,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,YAAY,CAAC,EAAE,CAAC;IAEhD,OAAO;cACK,IAAI;;;;WAIP,CAAC,CAAC,KAAK;;MAEZ,SAAS,EAAE;MACX,cAAc,EAAE;;;;;;6CAMuB,CAAC,CAAC,eAAe;YAClD,CAAC,CAAC,KAAK;;;oDAGiC,CAAC,CAAC,UAAU;oDACZ,CAAC,CAAC,WAAW;oDACb,CAAC,CAAC,QAAQ;;;0CAGpB,CAAC,CAAC,MAAM;6CACL,CAAC,CAAC,SAAS;2CACb,CAAC,CAAC,OAAO;;;;;wCAKZ,CAAC,CAAC,OAAO;;;;mEAIkB,CAAC,CAAC,QAAQ;;;;;;;;;;;;;;;MAevE,cAAc,CAAC,CAAC,CAAC;;;QAGf,CAAC;AACT,CAAC;AAED;;GAEG;AACH,SAAS,cAAc;IACrB,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8MN,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAS,cAAc,CAAC,CAAyB;IAC/C,OAAO;;;;;8BAKqB,CAAC,CAAC,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0QrC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"issue-graph.js","sourceRoot":"","sources":["../../../../src/server/dashboard/pages/issue-graph.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,oBAAoB,EAAE,YAAY,IAAI,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAG9F,wFAAwF;AACxF,MAAM,YAAY,GAAG;IACnB,EAAE,EAAE;QACF,KAAK,EAAE,kBAAkB,CAAC,EAAE,CAAC,aAAa,CAAC;QAC3C,eAAe,EAAE,kBAAkB,CAAC,EAAE,CAAC,uBAAuB,CAAC;QAC/D,QAAQ,EAAE,kBAAkB,CAAC,EAAE,CAAC,gBAAgB,CAAC;QACjD,UAAU,EAAE,kBAAkB,CAAC,EAAE,CAAC,kBAAkB,CAAC;QACrD,WAAW,EAAE,kBAAkB,CAAC,EAAE,CAAC,mBAAmB,CAAC;QACvD,QAAQ,EAAE,kBAAkB,CAAC,EAAE,CAAC,gBAAgB,CAAC;QACjD,OAAO,EAAE,kBAAkB,CAAC,EAAE,CAAC,eAAe,CAAC;QAC/C,MAAM,EAAE,kBAAkB,CAAC,EAAE,CAAC,cAAc,CAAC;QAC7C,OAAO,EAAE,kBAAkB,CAAC,EAAE,CAAC,eAAe,CAAC;QAC/C,SAAS,EAAE,kBAAkB,CAAC,EAAE,CAAC,iBAAiB,CAAC;QACnD,QAAQ,EAAE,kBAAkB,CAAC,EAAE,CAAC,gBAAgB,CAAC;KAClD;IACD,EAAE,EAAE;QACF,KAAK,EAAE,kBAAkB,CAAC,EAAE,CAAC,aAAa,CAAC;QAC3C,eAAe,EAAE,kBAAkB,CAAC,EAAE,CAAC,uBAAuB,CAAC;QAC/D,QAAQ,EAAE,kBAAkB,CAAC,EAAE,CAAC,gBAAgB,CAAC;QACjD,UAAU,EAAE,kBAAkB,CAAC,EAAE,CAAC,kBAAkB,CAAC;QACrD,WAAW,EAAE,kBAAkB,CAAC,EAAE,CAAC,mBAAmB,CAAC;QACvD,QAAQ,EAAE,kBAAkB,CAAC,EAAE,CAAC,gBAAgB,CAAC;QACjD,OAAO,EAAE,kBAAkB,CAAC,EAAE,CAAC,eAAe,CAAC;QAC/C,MAAM,EAAE,kBAAkB,CAAC,EAAE,CAAC,cAAc,CAAC;QAC7C,OAAO,EAAE,kBAAkB,CAAC,EAAE,CAAC,eAAe,CAAC;QAC/C,SAAS,EAAE,kBAAkB,CAAC,EAAE,CAAC,iBAAiB,CAAC;QACnD,QAAQ,EAAE,kBAAkB,CAAC,EAAE,CAAC,gBAAgB,CAAC;KAClD;CACF,CAAC;AAEF;;GAEG;AACH,MAAM,UAAU,sBAAsB,CAAC,IAAc;IACnD,MAAM,CAAC,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,YAAY,CAAC,EAAE,CAAC;IAEhD,OAAO;cACK,IAAI;;;;WAIP,CAAC,CAAC,KAAK;;MAEZ,SAAS,EAAE;MACX,cAAc,EAAE;;;;;;6CAMuB,CAAC,CAAC,eAAe;YAClD,CAAC,CAAC,KAAK;;;oDAGiC,CAAC,CAAC,UAAU;oDACZ,CAAC,CAAC,WAAW;oDACb,CAAC,CAAC,QAAQ;;MAExD,oBAAoB,EAAE;;0CAEc,CAAC,CAAC,MAAM;6CACL,CAAC,CAAC,SAAS;2CACb,CAAC,CAAC,OAAO;;;;;wCAKZ,CAAC,CAAC,OAAO;;;;mEAIkB,CAAC,CAAC,QAAQ;;;;;;;;;;;;;;;MAevE,cAAc,CAAC,CAAC,CAAC;;;QAGf,CAAC;AACT,CAAC;AAED;;GAEG;AACH,SAAS,cAAc;IACrB,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyON,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAS,cAAc,CAAC,CAAyB;IAC/C,OAAO;;;;;;;;;;;;;;;;;;;;;;;8BAuBqB,CAAC,CAAC,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0QrC,CAAC;AACJ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"issue-shared.d.ts","sourceRoot":"","sources":["../../../../src/server/dashboard/pages/issue-shared.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,wBAAgB,uBAAuB,IAAI,MAAM,CAiKhD;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,GAAG,UAAU,GAAG,SAAS,GAAG,UAAU,EAAE,IAAI,EAAE,aAAa,GAAG,MAAM,CAiBzI;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAc3E;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAyJhE"}
1
+ {"version":3,"file":"issue-shared.d.ts","sourceRoot":"","sources":["../../../../src/server/dashboard/pages/issue-shared.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,wBAAgB,uBAAuB,IAAI,MAAM,CAiKhD;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,GAAG,UAAU,GAAG,SAAS,GAAG,UAAU,EAAE,IAAI,EAAE,aAAa,GAAG,MAAM,CAiBzI;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAW3E;AA2CD;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAgDhE"}
@@ -2,6 +2,7 @@
2
2
  * Shared components for issue pages
3
3
  */
4
4
  import { escapeHtml } from '../utils.js';
5
+ import { generateI18nScript, generateLangSwitcher } from '../shared/index.js';
5
6
  /**
6
7
  * Generate the base CSS styles shared across all issue pages
7
8
  */
@@ -72,7 +73,7 @@ export function generateIssueBaseStyles() {
72
73
  text-overflow: ellipsis;
73
74
  white-space: nowrap;
74
75
  }
75
- .lang-selector {
76
+ .lang-switcher {
76
77
  display: flex;
77
78
  gap: 4px;
78
79
  }
@@ -198,102 +199,63 @@ export function generateIssueHeader(issueKey, title) {
198
199
  <span class="issue-key">${escapeHtml(issueKey)}</span>
199
200
  <span class="issue-title">${escapeHtml(title)}</span>
200
201
  </div>
201
- <div class="lang-selector" id="lang-selector">
202
- <button class="lang-btn" data-lang="en">EN</button>
203
- <button class="lang-btn" data-lang="fr">FR</button>
204
- </div>
202
+ ${generateLangSwitcher()}
205
203
  </header>
206
204
  `;
207
205
  }
206
+ /**
207
+ * Translation keys used by issue pages
208
+ */
209
+ const issuePageTranslationKeys = [
210
+ 'tabs.details',
211
+ 'tabs.comments',
212
+ 'tabs.history',
213
+ 'tabs.terminal',
214
+ 'issueView.meta',
215
+ 'issueView.labels',
216
+ 'issueView.description',
217
+ 'issueView.criteria',
218
+ 'issueView.history',
219
+ 'issueView.actions',
220
+ 'issueView.save',
221
+ 'issueView.moveNext',
222
+ 'issueView.archive',
223
+ 'issueView.confirmMove',
224
+ 'issueView.confirmArchive',
225
+ 'issueView.comments',
226
+ 'issueView.addComment',
227
+ 'issueView.noComments',
228
+ 'issueView.claudeTerminal',
229
+ 'issueView.noDescription',
230
+ 'issueView.noLog',
231
+ 'issueView.loadingPrompt',
232
+ 'issueView.promptError',
233
+ 'btn.add',
234
+ 'btn.sending',
235
+ 'btn.saving',
236
+ 'status.waiting',
237
+ 'status.processing',
238
+ 'status.completed',
239
+ 'status.failed',
240
+ 'notify.commentAdded',
241
+ 'notify.issueAdvanced',
242
+ 'notify.issueArchived',
243
+ 'notify.issueSaved',
244
+ 'notify.error',
245
+ ];
208
246
  /**
209
247
  * Generate the shared JavaScript for i18n and notifications
210
248
  */
211
249
  export function generateIssueBaseScript(issueKey) {
250
+ // Generate the centralized i18n script with only the keys needed for issue pages
251
+ const i18nScript = generateI18nScript({
252
+ keys: issuePageTranslationKeys,
253
+ onLangChangeCallback: 'onLangChange',
254
+ });
212
255
  return `
213
256
  const ISSUE_KEY = '${issueKey}';
214
- const STORAGE_KEY = 'autocode-lang';
215
- let currentLang = localStorage.getItem(STORAGE_KEY) || 'fr';
216
-
217
- const translations = {
218
- en: {
219
- 'tabs.details': 'Details',
220
- 'tabs.comments': 'Comments',
221
- 'tabs.history': 'History',
222
- 'tabs.terminal': 'Terminal',
223
- 'issueView.meta': 'Meta',
224
- 'issueView.labels': 'Labels',
225
- 'issueView.description': 'Description',
226
- 'issueView.criteria': 'Acceptance Criteria',
227
- 'issueView.history': 'History',
228
- 'issueView.actions': 'Actions',
229
- 'issueView.save': 'Save',
230
- 'issueView.moveNext': 'Move to next column',
231
- 'issueView.archive': 'Archive',
232
- 'issueView.confirmMove': 'Move this issue to the next column?',
233
- 'issueView.confirmArchive': 'Archive this issue?',
234
- 'issueView.comments': 'Comments',
235
- 'issueView.addComment': 'Add a comment...',
236
- 'issueView.noComments': 'No comments yet',
237
- 'issueView.claudeTerminal': 'Claude Terminal',
238
- 'issueView.noDescription': 'No description',
239
- 'issueView.noLog': 'No log yet. Waiting for Claude processing...',
240
- 'issueView.loadingPrompt': 'Loading prompt...',
241
- 'issueView.promptError': 'Error',
242
- 'btn.add': 'Add',
243
- 'btn.sending': 'Sending...',
244
- 'btn.saving': 'Saving...',
245
- 'status.waiting': 'Waiting',
246
- 'status.processing': 'Processing...',
247
- 'status.completed': 'Completed',
248
- 'status.failed': 'Failed',
249
- 'notify.commentAdded': 'Comment added',
250
- 'notify.issueAdvanced': 'Issue advanced',
251
- 'notify.issueArchived': 'Issue archived',
252
- 'notify.issueSaved': 'Issue saved',
253
- 'notify.error': 'Error'
254
- },
255
- fr: {
256
- 'tabs.details': 'Détails',
257
- 'tabs.comments': 'Commentaires',
258
- 'tabs.history': 'Historique',
259
- 'tabs.terminal': 'Terminal',
260
- 'issueView.meta': 'Méta',
261
- 'issueView.labels': 'Labels',
262
- 'issueView.description': 'Description',
263
- 'issueView.criteria': 'Critères d\\'acceptation',
264
- 'issueView.history': 'Historique',
265
- 'issueView.actions': 'Actions',
266
- 'issueView.save': 'Sauvegarder',
267
- 'issueView.moveNext': 'Déplacer vers la colonne suivante',
268
- 'issueView.archive': 'Archiver',
269
- 'issueView.confirmMove': 'Déplacer ce ticket vers la colonne suivante ?',
270
- 'issueView.confirmArchive': 'Archiver ce ticket ?',
271
- 'issueView.comments': 'Commentaires',
272
- 'issueView.addComment': 'Ajouter un commentaire...',
273
- 'issueView.noComments': 'Aucun commentaire',
274
- 'issueView.claudeTerminal': 'Terminal Claude',
275
- 'issueView.noDescription': 'Aucune description',
276
- 'issueView.noLog': 'Aucun log. En attente du traitement Claude...',
277
- 'issueView.loadingPrompt': 'Chargement du prompt...',
278
- 'issueView.promptError': 'Erreur',
279
- 'btn.add': 'Ajouter',
280
- 'btn.sending': 'Envoi...',
281
- 'btn.saving': 'Sauvegarde...',
282
- 'status.waiting': 'En attente',
283
- 'status.processing': 'En cours...',
284
- 'status.completed': 'Terminé',
285
- 'status.failed': 'Échec',
286
- 'notify.commentAdded': 'Commentaire ajouté',
287
- 'notify.issueAdvanced': 'Ticket avancé',
288
- 'notify.issueArchived': 'Ticket archivé',
289
- 'notify.issueSaved': 'Ticket sauvegardé',
290
- 'notify.error': 'Erreur'
291
- }
292
- };
293
257
 
294
- function t(key) {
295
- return translations[currentLang]?.[key] || translations['en'][key] || key;
296
- }
258
+ ${i18nScript}
297
259
 
298
260
  function escapeHtml(text) {
299
261
  if (!text) return '';
@@ -318,48 +280,18 @@ export function generateIssueBaseScript(issueKey) {
318
280
  return html;
319
281
  }
320
282
 
321
- function updateLangUI() {
322
- document.querySelectorAll('.lang-btn').forEach(btn => {
323
- btn.classList.toggle('active', btn.dataset.lang === currentLang);
324
- });
325
- document.querySelectorAll('[data-i18n]').forEach(el => {
326
- const key = el.dataset.i18n;
327
- const translated = t(key);
328
- // Keep badge if present
329
- const badge = el.querySelector('.tab-badge');
330
- if (badge) {
331
- el.innerHTML = translated + ' ' + badge.outerHTML;
332
- } else {
333
- el.textContent = translated;
334
- }
335
- });
336
- document.querySelectorAll('[data-i18n-placeholder]').forEach(el => {
337
- el.placeholder = t(el.dataset.i18nPlaceholder);
338
- });
339
- }
340
-
341
283
  function showNotification(msg, isError) {
342
284
  const notification = document.getElementById('notification');
285
+ if (!notification) return;
343
286
  notification.textContent = msg;
344
287
  notification.className = 'notification show' + (isError ? ' error' : '');
345
288
  setTimeout(() => notification.className = 'notification', 3000);
346
289
  }
347
290
 
348
- // Language switcher
349
- document.querySelectorAll('.lang-btn').forEach(btn => {
350
- btn.addEventListener('click', () => {
351
- const newLang = btn.dataset.lang;
352
- if (newLang !== currentLang) {
353
- currentLang = newLang;
354
- localStorage.setItem(STORAGE_KEY, newLang);
355
- updateLangUI();
356
- if (typeof onLangChange === 'function') onLangChange();
357
- }
358
- });
359
- });
360
-
361
- // Init lang
362
- updateLangUI();
291
+ // Optional callback for language change (can be defined by specific pages)
292
+ function onLangChange() {
293
+ // Override in specific pages if needed
294
+ }
363
295
  `;
364
296
  }
365
297
  //# sourceMappingURL=issue-shared.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"issue-shared.js","sourceRoot":"","sources":["../../../../src/server/dashboard/pages/issue-shared.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAUzC;;GAEG;AACH,MAAM,UAAU,uBAAuB;IACrC,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+JN,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,QAAgB,EAAE,SAA0D,EAAE,IAAmB;IAC/H,MAAM,IAAI,GAAG;QACX,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,UAAU,QAAQ,EAAE,EAAE,QAAQ,EAAE,cAAc,EAAE;QACvE,EAAE,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,QAAQ,WAAW,EAAE,QAAQ,EAAE,eAAe,EAAE,KAAK,EAAE,IAAI,CAAC,aAAa,EAAE;QAC7G,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,UAAU,QAAQ,UAAU,EAAE,QAAQ,EAAE,cAAc,EAAE,KAAK,EAAE,IAAI,CAAC,YAAY,EAAE;QACzG,EAAE,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,QAAQ,WAAW,EAAE,QAAQ,EAAE,eAAe,EAAE;KACnF,CAAC;IAEF,OAAO;;QAED,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE;QACf,MAAM,QAAQ,GAAG,GAAG,CAAC,EAAE,KAAK,SAAS,CAAC;QACtC,MAAM,SAAS,GAAG,GAAG,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,2BAA2B,GAAG,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/F,OAAO,YAAY,GAAG,CAAC,IAAI,oBAAoB,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,gBAAgB,GAAG,CAAC,QAAQ,KAAK,SAAS,MAAM,CAAC;IAC3H,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;;GAEd,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAAC,QAAgB,EAAE,KAAa;IACjE,OAAO;;;;gCAIuB,UAAU,CAAC,QAAQ,CAAC;kCAClB,UAAU,CAAC,KAAK,CAAC;;;;;;;GAOhD,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,uBAAuB,CAAC,QAAgB;IACtD,OAAO;yBACgB,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsJ9B,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"issue-shared.js","sourceRoot":"","sources":["../../../../src/server/dashboard/pages/issue-shared.ts"],"names":[],"mappings":"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"}
@@ -185,7 +185,7 @@ export function generateIssueViewPage(issueKey, lang) {
185
185
  <span class="issue-key">${escapeHtml(issueKey)}</span>
186
186
  <input type="text" class="issue-title-input" id="issue-title" value="${escapeHtml(issue.title)}" />
187
187
  </div>
188
- <div class="lang-selector" id="lang-selector">
188
+ <div class="lang-switcher" id="lang-switcher">
189
189
  <button class="lang-btn" data-lang="en">EN</button>
190
190
  <button class="lang-btn" data-lang="fr">FR</button>
191
191
  </div>