reviewflow 3.19.2 → 3.21.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.
- package/CHANGELOG.md +14 -0
- package/dist/config/projectConfig.d.ts +7 -0
- package/dist/config/projectConfig.d.ts.map +1 -1
- package/dist/config/projectConfig.js +18 -0
- package/dist/config/projectConfig.js.map +1 -1
- package/dist/dashboard/index.html +452 -142
- package/dist/dashboard/modules/cardCounters.d.ts +32 -0
- package/dist/dashboard/modules/cardCounters.d.ts.map +1 -0
- package/dist/dashboard/modules/cardCounters.js +40 -0
- package/dist/dashboard/modules/cardCounters.js.map +1 -0
- package/dist/dashboard/modules/constants.d.ts +1 -0
- package/dist/dashboard/modules/constants.d.ts.map +1 -1
- package/dist/dashboard/modules/constants.js +1 -0
- package/dist/dashboard/modules/constants.js.map +1 -1
- package/dist/dashboard/modules/managePanel.d.ts +49 -0
- package/dist/dashboard/modules/managePanel.d.ts.map +1 -0
- package/dist/dashboard/modules/managePanel.js +123 -0
- package/dist/dashboard/modules/managePanel.js.map +1 -0
- package/dist/dashboard/modules/overview.d.ts +65 -0
- package/dist/dashboard/modules/overview.d.ts.map +1 -0
- package/dist/dashboard/modules/overview.js +260 -0
- package/dist/dashboard/modules/overview.js.map +1 -0
- package/dist/dashboard/modules/settingsModal.d.ts +77 -0
- package/dist/dashboard/modules/settingsModal.d.ts.map +1 -0
- package/dist/dashboard/modules/settingsModal.js +182 -0
- package/dist/dashboard/modules/settingsModal.js.map +1 -0
- package/dist/dashboard/modules/tabBar.d.ts +60 -0
- package/dist/dashboard/modules/tabBar.d.ts.map +1 -0
- package/dist/dashboard/modules/tabBar.js +103 -0
- package/dist/dashboard/modules/tabBar.js.map +1 -0
- package/dist/dashboard/styles.css +936 -0
- package/dist/frameworks/config/configLoader.d.ts +8 -0
- package/dist/frameworks/config/configLoader.d.ts.map +1 -1
- package/dist/frameworks/config/configLoader.js +18 -0
- package/dist/frameworks/config/configLoader.js.map +1 -1
- package/dist/main/routes.d.ts.map +1 -1
- package/dist/main/routes.js +67 -11
- package/dist/main/routes.js.map +1 -1
- package/dist/modules/cli-configuration/entities/projectConfig/projectConfig.gateway.d.ts +20 -0
- package/dist/modules/cli-configuration/entities/projectConfig/projectConfig.gateway.d.ts.map +1 -0
- package/dist/modules/cli-configuration/entities/projectConfig/projectConfig.gateway.js +2 -0
- package/dist/modules/cli-configuration/entities/projectConfig/projectConfig.gateway.js.map +1 -0
- package/dist/modules/cli-configuration/entities/repositoryEntry/repositoryEntry.d.ts +13 -0
- package/dist/modules/cli-configuration/entities/repositoryEntry/repositoryEntry.d.ts.map +1 -0
- package/dist/modules/cli-configuration/entities/repositoryEntry/repositoryEntry.js +2 -0
- package/dist/modules/cli-configuration/entities/repositoryEntry/repositoryEntry.js.map +1 -0
- package/dist/modules/cli-configuration/interface-adapters/controllers/http/projectConfig.routes.d.ts +6 -1
- package/dist/modules/cli-configuration/interface-adapters/controllers/http/projectConfig.routes.d.ts.map +1 -1
- package/dist/modules/cli-configuration/interface-adapters/controllers/http/projectConfig.routes.js +116 -13
- package/dist/modules/cli-configuration/interface-adapters/controllers/http/projectConfig.routes.js.map +1 -1
- package/dist/modules/cli-configuration/interface-adapters/controllers/http/repositories.routes.d.ts +43 -0
- package/dist/modules/cli-configuration/interface-adapters/controllers/http/repositories.routes.d.ts.map +1 -0
- package/dist/modules/cli-configuration/interface-adapters/controllers/http/repositories.routes.js +82 -0
- package/dist/modules/cli-configuration/interface-adapters/controllers/http/repositories.routes.js.map +1 -0
- package/dist/modules/cli-configuration/interface-adapters/gateways/projectConfig.fileSystem.gateway.d.ts +7 -0
- package/dist/modules/cli-configuration/interface-adapters/gateways/projectConfig.fileSystem.gateway.d.ts.map +1 -0
- package/dist/modules/cli-configuration/interface-adapters/gateways/projectConfig.fileSystem.gateway.js +48 -0
- package/dist/modules/cli-configuration/interface-adapters/gateways/projectConfig.fileSystem.gateway.js.map +1 -0
- package/dist/modules/cli-configuration/usecases/cli/addRepositoriesToConfig.usecase.d.ts +1 -6
- package/dist/modules/cli-configuration/usecases/cli/addRepositoriesToConfig.usecase.d.ts.map +1 -1
- package/dist/modules/cli-configuration/usecases/cli/addRepositoriesToConfig.usecase.js.map +1 -1
- package/dist/modules/cli-configuration/usecases/cli/removeRepositoryFromConfig.usecase.d.ts +21 -0
- package/dist/modules/cli-configuration/usecases/cli/removeRepositoryFromConfig.usecase.d.ts.map +1 -0
- package/dist/modules/cli-configuration/usecases/cli/removeRepositoryFromConfig.usecase.js +27 -0
- package/dist/modules/cli-configuration/usecases/cli/removeRepositoryFromConfig.usecase.js.map +1 -0
- package/dist/modules/cli-configuration/usecases/cli/toggleRepositoryEnabled.usecase.d.ts +22 -0
- package/dist/modules/cli-configuration/usecases/cli/toggleRepositoryEnabled.usecase.d.ts.map +1 -0
- package/dist/modules/cli-configuration/usecases/cli/toggleRepositoryEnabled.usecase.js +27 -0
- package/dist/modules/cli-configuration/usecases/cli/toggleRepositoryEnabled.usecase.js.map +1 -0
- package/dist/modules/cli-configuration/usecases/cli/writeInitConfig.usecase.d.ts +1 -6
- package/dist/modules/cli-configuration/usecases/cli/writeInitConfig.usecase.d.ts.map +1 -1
- package/dist/modules/cli-configuration/usecases/cli/writeInitConfig.usecase.js.map +1 -1
- package/dist/modules/cli-configuration/usecases/dashboardRepositories/addRepositoryFromDashboard.usecase.d.ts +19 -0
- package/dist/modules/cli-configuration/usecases/dashboardRepositories/addRepositoryFromDashboard.usecase.d.ts.map +1 -0
- package/dist/modules/cli-configuration/usecases/dashboardRepositories/addRepositoryFromDashboard.usecase.js +30 -0
- package/dist/modules/cli-configuration/usecases/dashboardRepositories/addRepositoryFromDashboard.usecase.js.map +1 -0
- package/dist/modules/cli-configuration/usecases/dashboardRepositories/removeRepositoryFromDashboard.usecase.d.ts +16 -0
- package/dist/modules/cli-configuration/usecases/dashboardRepositories/removeRepositoryFromDashboard.usecase.d.ts.map +1 -0
- package/dist/modules/cli-configuration/usecases/dashboardRepositories/removeRepositoryFromDashboard.usecase.js +27 -0
- package/dist/modules/cli-configuration/usecases/dashboardRepositories/removeRepositoryFromDashboard.usecase.js.map +1 -0
- package/dist/modules/cli-configuration/usecases/dashboardRepositories/updateRepositoryEnabledFromDashboard.usecase.d.ts +17 -0
- package/dist/modules/cli-configuration/usecases/dashboardRepositories/updateRepositoryEnabledFromDashboard.usecase.d.ts.map +1 -0
- package/dist/modules/cli-configuration/usecases/dashboardRepositories/updateRepositoryEnabledFromDashboard.usecase.js +28 -0
- package/dist/modules/cli-configuration/usecases/dashboardRepositories/updateRepositoryEnabledFromDashboard.usecase.js.map +1 -0
- package/dist/modules/cli-configuration/usecases/projectConfig/updateProjectConfig.usecase.d.ts +31 -0
- package/dist/modules/cli-configuration/usecases/projectConfig/updateProjectConfig.usecase.d.ts.map +1 -0
- package/dist/modules/cli-configuration/usecases/projectConfig/updateProjectConfig.usecase.js +102 -0
- package/dist/modules/cli-configuration/usecases/projectConfig/updateProjectConfig.usecase.js.map +1 -0
- package/dist/modules/statistics-insights/interface-adapters/controllers/http/overview.routes.d.ts +16 -0
- package/dist/modules/statistics-insights/interface-adapters/controllers/http/overview.routes.d.ts.map +1 -0
- package/dist/modules/statistics-insights/interface-adapters/controllers/http/overview.routes.js +53 -0
- package/dist/modules/statistics-insights/interface-adapters/controllers/http/overview.routes.js.map +1 -0
- package/dist/modules/statistics-insights/interface-adapters/presenters/overview.presenter.d.ts +93 -0
- package/dist/modules/statistics-insights/interface-adapters/presenters/overview.presenter.d.ts.map +1 -0
- package/dist/modules/statistics-insights/interface-adapters/presenters/overview.presenter.js +145 -0
- package/dist/modules/statistics-insights/interface-adapters/presenters/overview.presenter.js.map +1 -0
- package/dist/tests/acceptance/177-dashboard-add-project-ui.acceptance.test.d.ts +12 -0
- package/dist/tests/acceptance/177-dashboard-add-project-ui.acceptance.test.d.ts.map +1 -0
- package/dist/tests/acceptance/177-dashboard-add-project-ui.acceptance.test.js +304 -0
- package/dist/tests/acceptance/177-dashboard-add-project-ui.acceptance.test.js.map +1 -0
- package/dist/tests/acceptance/178-dashboard-tabs-reposition.acceptance.test.d.ts +12 -0
- package/dist/tests/acceptance/178-dashboard-tabs-reposition.acceptance.test.d.ts.map +1 -0
- package/dist/tests/acceptance/178-dashboard-tabs-reposition.acceptance.test.js +131 -0
- package/dist/tests/acceptance/178-dashboard-tabs-reposition.acceptance.test.js.map +1 -0
- package/dist/tests/acceptance/179-dashboard-project-settings-modal.acceptance.test.d.ts +12 -0
- package/dist/tests/acceptance/179-dashboard-project-settings-modal.acceptance.test.d.ts.map +1 -0
- package/dist/tests/acceptance/179-dashboard-project-settings-modal.acceptance.test.js +312 -0
- package/dist/tests/acceptance/179-dashboard-project-settings-modal.acceptance.test.js.map +1 -0
- package/dist/tests/acceptance/91-dashboard-multi-project-overview.acceptance.test.d.ts +10 -0
- package/dist/tests/acceptance/91-dashboard-multi-project-overview.acceptance.test.d.ts.map +1 -0
- package/dist/tests/acceptance/91-dashboard-multi-project-overview.acceptance.test.js +275 -0
- package/dist/tests/acceptance/91-dashboard-multi-project-overview.acceptance.test.js.map +1 -0
- package/dist/tests/factories/projectStatsApiResponse.factory.d.ts +16 -0
- package/dist/tests/factories/projectStatsApiResponse.factory.d.ts.map +1 -0
- package/dist/tests/factories/projectStatsApiResponse.factory.js +39 -0
- package/dist/tests/factories/projectStatsApiResponse.factory.js.map +1 -0
- package/dist/tests/factories/recentReviewFile.factory.d.ts +5 -0
- package/dist/tests/factories/recentReviewFile.factory.d.ts.map +1 -0
- package/dist/tests/factories/recentReviewFile.factory.js +16 -0
- package/dist/tests/factories/recentReviewFile.factory.js.map +1 -0
- package/dist/tests/factories/repositoryConfig.factory.d.ts +5 -0
- package/dist/tests/factories/repositoryConfig.factory.d.ts.map +1 -0
- package/dist/tests/factories/repositoryConfig.factory.js +14 -0
- package/dist/tests/factories/repositoryConfig.factory.js.map +1 -0
- package/dist/tests/stubs/projectConfigGateway.stub.d.ts +15 -0
- package/dist/tests/stubs/projectConfigGateway.stub.d.ts.map +1 -0
- package/dist/tests/stubs/projectConfigGateway.stub.js +40 -0
- package/dist/tests/stubs/projectConfigGateway.stub.js.map +1 -0
- package/dist/tests/units/config/projectConfig.test.js +43 -0
- package/dist/tests/units/config/projectConfig.test.js.map +1 -1
- package/dist/tests/units/dashboard/modules/cardCounters.test.d.ts +2 -0
- package/dist/tests/units/dashboard/modules/cardCounters.test.d.ts.map +1 -0
- package/dist/tests/units/dashboard/modules/cardCounters.test.js +106 -0
- package/dist/tests/units/dashboard/modules/cardCounters.test.js.map +1 -0
- package/dist/tests/units/dashboard/modules/constants.test.js +2 -1
- package/dist/tests/units/dashboard/modules/constants.test.js.map +1 -1
- package/dist/tests/units/dashboard/modules/managePanel.test.d.ts +2 -0
- package/dist/tests/units/dashboard/modules/managePanel.test.d.ts.map +1 -0
- package/dist/tests/units/dashboard/modules/managePanel.test.js +112 -0
- package/dist/tests/units/dashboard/modules/managePanel.test.js.map +1 -0
- package/dist/tests/units/dashboard/modules/overview.test.d.ts +2 -0
- package/dist/tests/units/dashboard/modules/overview.test.d.ts.map +1 -0
- package/dist/tests/units/dashboard/modules/overview.test.js +268 -0
- package/dist/tests/units/dashboard/modules/overview.test.js.map +1 -0
- package/dist/tests/units/dashboard/modules/settingsModal.test.d.ts +2 -0
- package/dist/tests/units/dashboard/modules/settingsModal.test.d.ts.map +1 -0
- package/dist/tests/units/dashboard/modules/settingsModal.test.js +166 -0
- package/dist/tests/units/dashboard/modules/settingsModal.test.js.map +1 -0
- package/dist/tests/units/dashboard/modules/tabBar.test.d.ts +2 -0
- package/dist/tests/units/dashboard/modules/tabBar.test.d.ts.map +1 -0
- package/dist/tests/units/dashboard/modules/tabBar.test.js +128 -0
- package/dist/tests/units/dashboard/modules/tabBar.test.js.map +1 -0
- package/dist/tests/units/frameworks/config/configLoader.test.js +35 -1
- package/dist/tests/units/frameworks/config/configLoader.test.js.map +1 -1
- package/dist/tests/units/modules/cli-configuration/interface-adapters/controllers/http/projectConfig.routes.test.js +111 -0
- package/dist/tests/units/modules/cli-configuration/interface-adapters/controllers/http/projectConfig.routes.test.js.map +1 -1
- package/dist/tests/units/modules/cli-configuration/interface-adapters/controllers/http/repositories.routes.test.d.ts +2 -0
- package/dist/tests/units/modules/cli-configuration/interface-adapters/controllers/http/repositories.routes.test.d.ts.map +1 -0
- package/dist/tests/units/modules/cli-configuration/interface-adapters/controllers/http/repositories.routes.test.js +298 -0
- package/dist/tests/units/modules/cli-configuration/interface-adapters/controllers/http/repositories.routes.test.js.map +1 -0
- package/dist/tests/units/modules/cli-configuration/interface-adapters/gateways/projectConfig.fileSystem.gateway.test.d.ts +2 -0
- package/dist/tests/units/modules/cli-configuration/interface-adapters/gateways/projectConfig.fileSystem.gateway.test.d.ts.map +1 -0
- package/dist/tests/units/modules/cli-configuration/interface-adapters/gateways/projectConfig.fileSystem.gateway.test.js +72 -0
- package/dist/tests/units/modules/cli-configuration/interface-adapters/gateways/projectConfig.fileSystem.gateway.test.js.map +1 -0
- package/dist/tests/units/modules/cli-configuration/usecases/cli/removeRepositoryFromConfig.usecase.test.d.ts +2 -0
- package/dist/tests/units/modules/cli-configuration/usecases/cli/removeRepositoryFromConfig.usecase.test.d.ts.map +1 -0
- package/dist/tests/units/modules/cli-configuration/usecases/cli/removeRepositoryFromConfig.usecase.test.js +76 -0
- package/dist/tests/units/modules/cli-configuration/usecases/cli/removeRepositoryFromConfig.usecase.test.js.map +1 -0
- package/dist/tests/units/modules/cli-configuration/usecases/cli/toggleRepositoryEnabled.usecase.test.d.ts +2 -0
- package/dist/tests/units/modules/cli-configuration/usecases/cli/toggleRepositoryEnabled.usecase.test.d.ts.map +1 -0
- package/dist/tests/units/modules/cli-configuration/usecases/cli/toggleRepositoryEnabled.usecase.test.js +84 -0
- package/dist/tests/units/modules/cli-configuration/usecases/cli/toggleRepositoryEnabled.usecase.test.js.map +1 -0
- package/dist/tests/units/modules/cli-configuration/usecases/projectConfig/updateProjectConfig.usecase.test.d.ts +2 -0
- package/dist/tests/units/modules/cli-configuration/usecases/projectConfig/updateProjectConfig.usecase.test.d.ts.map +1 -0
- package/dist/tests/units/modules/cli-configuration/usecases/projectConfig/updateProjectConfig.usecase.test.js +141 -0
- package/dist/tests/units/modules/cli-configuration/usecases/projectConfig/updateProjectConfig.usecase.test.js.map +1 -0
- package/dist/tests/units/modules/statistics-insights/interface-adapters/controllers/http/overview.routes.test.d.ts +2 -0
- package/dist/tests/units/modules/statistics-insights/interface-adapters/controllers/http/overview.routes.test.d.ts.map +1 -0
- package/dist/tests/units/modules/statistics-insights/interface-adapters/controllers/http/overview.routes.test.js +200 -0
- package/dist/tests/units/modules/statistics-insights/interface-adapters/controllers/http/overview.routes.test.js.map +1 -0
- package/dist/tests/units/modules/statistics-insights/interface-adapters/presenters/overview.presenter.test.d.ts +2 -0
- package/dist/tests/units/modules/statistics-insights/interface-adapters/presenters/overview.presenter.test.d.ts.map +1 -0
- package/dist/tests/units/modules/statistics-insights/interface-adapters/presenters/overview.presenter.test.js +331 -0
- package/dist/tests/units/modules/statistics-insights/interface-adapters/presenters/overview.presenter.test.js.map +1 -0
- package/package.json +1 -1
|
@@ -30,6 +30,20 @@
|
|
|
30
30
|
</div>
|
|
31
31
|
</header>
|
|
32
32
|
|
|
33
|
+
<div class="project-bar" role="region" aria-label="Project navigation">
|
|
34
|
+
<button type="button" id="manage-projects-toggle" class="manage-projects-toggle" aria-expanded="false" aria-controls="manage-panel">
|
|
35
|
+
<span class="manage-projects-toggle-label">// MANAGE PROJECTS</span>
|
|
36
|
+
<i data-lucide="chevron-down" class="manage-projects-toggle-icon"></i>
|
|
37
|
+
</button>
|
|
38
|
+
<section id="manage-panel" class="manage-panel" aria-label="Manage projects" data-open="false"></section>
|
|
39
|
+
<nav id="dashboard-tabs" class="dashboard-tab-bar-wrapper" aria-label="Project tabs"></nav>
|
|
40
|
+
</div>
|
|
41
|
+
|
|
42
|
+
<div id="cards-scope-marker" class="cards-scope-marker" data-scope-kind="overview">
|
|
43
|
+
<span class="cards-scope-prefix">// SCOPE</span>
|
|
44
|
+
<span class="cards-scope-label">TOUS LES PROJETS</span>
|
|
45
|
+
</div>
|
|
46
|
+
|
|
33
47
|
<div class="cards">
|
|
34
48
|
<div class="card card-priority">
|
|
35
49
|
<div class="card-label" id="i18n-card-running"></div>
|
|
@@ -78,19 +92,7 @@
|
|
|
78
92
|
</select>
|
|
79
93
|
</div>
|
|
80
94
|
|
|
81
|
-
<
|
|
82
|
-
<select id="project-select" class="project-input" onchange="onProjectSelect(this.value)">
|
|
83
|
-
<option value="" id="i18n-project-placeholder"></option>
|
|
84
|
-
</select>
|
|
85
|
-
<input type="text" id="project-path-input" class="project-input" value="">
|
|
86
|
-
<button class="btn btn-primary" onclick="loadProjectConfig()">
|
|
87
|
-
<i data-lucide="folder-open"></i> <span id="i18n-project-load"></span>
|
|
88
|
-
</button>
|
|
89
|
-
<button id="remove-project-btn" class="btn btn-secondary" onclick="removeCurrentProject()">
|
|
90
|
-
<i data-lucide="trash-2"></i>
|
|
91
|
-
</button>
|
|
92
|
-
<span id="config-status" class="config-status hidden"></span>
|
|
93
|
-
</div>
|
|
95
|
+
<span id="config-status" class="config-status hidden"></span>
|
|
94
96
|
|
|
95
97
|
<div class="focus-strip">
|
|
96
98
|
<div class="focus-chip focus-now">
|
|
@@ -118,9 +120,15 @@
|
|
|
118
120
|
</div>
|
|
119
121
|
|
|
120
122
|
<section id="worktree-section" aria-label="Worktree pool"></section>
|
|
123
|
+
|
|
124
|
+
<button type="button" id="open-settings-modal-btn" class="sidebar-settings-button" hidden>
|
|
125
|
+
<span class="sidebar-settings-button__prefix">// SETTINGS</span>
|
|
126
|
+
</button>
|
|
121
127
|
</aside>
|
|
122
128
|
|
|
123
129
|
<main class="dashboard-main">
|
|
130
|
+
<section id="overview-section" class="overview-section" aria-label="Multi-project overview"></section>
|
|
131
|
+
|
|
124
132
|
<div id="data-loading-state" class="data-loading hidden" role="status" aria-live="polite">
|
|
125
133
|
<i data-lucide="loader-circle"></i>
|
|
126
134
|
<span id="i18n-loading-data"></span>
|
|
@@ -313,14 +321,20 @@
|
|
|
313
321
|
<div id="dev-sheet-content" class="sheet-content"></div>
|
|
314
322
|
</div>
|
|
315
323
|
|
|
324
|
+
<dialog id="settings-modal" class="settings-modal" aria-labelledby="settings-modal-title"></dialog>
|
|
325
|
+
|
|
316
326
|
<script type="module">
|
|
317
327
|
import { t, setLanguage, getLanguage } from './modules/i18n.js';
|
|
318
328
|
import { formatTime, formatDuration, formatPhase, formatLogTime } from './modules/formatting.js';
|
|
319
329
|
import { escapeHtml, markdownToHtml, sanitizeHttpUrl } from './modules/html.js';
|
|
320
330
|
import { getAgentIcon, icon, refreshIcons } from './modules/icons.js';
|
|
321
|
-
import { MAX_RECONNECT_ATTEMPTS, RECONNECT_DELAY,
|
|
331
|
+
import { MAX_RECONNECT_ATTEMPTS, RECONNECT_DELAY, STORAGE_KEY_CURRENT, STORAGE_KEY_FOCUS_STRIP_MODE, QUALITY_TARGET_SCORE } from './modules/constants.js';
|
|
332
|
+
import { buildTabBarModel, renderTabBarHtml, readActiveTab, writeActiveTab } from './modules/tabBar.js';
|
|
333
|
+
import { buildManagePanelModel, renderManagePanelHtml, buildOptimisticAddedRow, validateLocalPathInput } from './modules/managePanel.js';
|
|
334
|
+
import { renderOverviewHtml } from './modules/overview.js';
|
|
322
335
|
import { getDesktopNotificationPayload, shouldNotifyDesktop } from './modules/desktopNotifications.js';
|
|
323
336
|
import { getLoadingPresentation, getQuietRefreshSectionIdentifiers } from './modules/loading.js';
|
|
337
|
+
import { computeCardCounters } from './modules/cardCounters.js';
|
|
324
338
|
import { collectReviewNotifications, createReviewNotificationState } from './modules/notifications.js';
|
|
325
339
|
import { resolveReviewAssigneeDisplay } from './modules/assignee.js';
|
|
326
340
|
import { buildQueueLanesModel } from './modules/queueLanes.js';
|
|
@@ -352,6 +366,12 @@
|
|
|
352
366
|
fetchBudgetStatus,
|
|
353
367
|
submitBudget,
|
|
354
368
|
} from './modules/budgetSettings.js';
|
|
369
|
+
import {
|
|
370
|
+
buildSettingsViewModel,
|
|
371
|
+
renderSettingsModalHtml,
|
|
372
|
+
validateExternalLink,
|
|
373
|
+
extractFormPayload,
|
|
374
|
+
} from './modules/settingsModal.js';
|
|
355
375
|
|
|
356
376
|
const API_URL = window.location.origin;
|
|
357
377
|
const WS_URL = `ws://${window.location.host}/ws`;
|
|
@@ -774,14 +794,12 @@
|
|
|
774
794
|
const reviews = currentData.activeReviews.filter(r => r.jobType !== 'followup');
|
|
775
795
|
const followups = currentData.activeReviews.filter(r => r.jobType === 'followup');
|
|
776
796
|
|
|
797
|
+
renderCardCounters();
|
|
798
|
+
const blocked = currentData.pendingFix.length;
|
|
777
799
|
const running = currentData.activeReviews.filter(r => r.status === 'running').length;
|
|
778
800
|
const queued = currentData.activeReviews.filter(r => r.status === 'queued').length;
|
|
779
|
-
const blocked = currentData.pendingFix.length;
|
|
780
801
|
const nowCount = running + blocked;
|
|
781
802
|
const nextCount = queued + currentData.pendingApproval.length;
|
|
782
|
-
document.getElementById('running-count').textContent = running;
|
|
783
|
-
document.getElementById('queued-count').textContent = queued;
|
|
784
|
-
document.getElementById('completed-count').textContent = currentData.reviewFiles.length;
|
|
785
803
|
document.getElementById('focus-now-count').textContent = String(nowCount);
|
|
786
804
|
document.getElementById('focus-next-count').textContent = String(nextCount);
|
|
787
805
|
document.getElementById('focus-blocked-count').textContent = String(blocked);
|
|
@@ -2088,6 +2106,9 @@
|
|
|
2088
2106
|
if (message.type === 'state') {
|
|
2089
2107
|
fetchMrTracking();
|
|
2090
2108
|
}
|
|
2109
|
+
if (activeTabId === 'overview') {
|
|
2110
|
+
refreshOverviewSection();
|
|
2111
|
+
}
|
|
2091
2112
|
break;
|
|
2092
2113
|
case 'progress':
|
|
2093
2114
|
handleProgressUpdate(message);
|
|
@@ -2277,69 +2298,6 @@
|
|
|
2277
2298
|
let currentProjectConfig = null;
|
|
2278
2299
|
let currentProjectPath = null;
|
|
2279
2300
|
|
|
2280
|
-
function getStoredProjects() {
|
|
2281
|
-
try {
|
|
2282
|
-
return JSON.parse(localStorage.getItem(STORAGE_KEY_PROJECTS) || '[]');
|
|
2283
|
-
} catch {
|
|
2284
|
-
return [];
|
|
2285
|
-
}
|
|
2286
|
-
}
|
|
2287
|
-
|
|
2288
|
-
function saveProjects(projects) {
|
|
2289
|
-
localStorage.setItem(STORAGE_KEY_PROJECTS, JSON.stringify(projects));
|
|
2290
|
-
}
|
|
2291
|
-
|
|
2292
|
-
function addProjectToHistory(path) {
|
|
2293
|
-
const projects = getStoredProjects();
|
|
2294
|
-
const filtered = projects.filter(p => p !== path);
|
|
2295
|
-
filtered.unshift(path);
|
|
2296
|
-
saveProjects(filtered.slice(0, 10));
|
|
2297
|
-
updateProjectSelect();
|
|
2298
|
-
}
|
|
2299
|
-
|
|
2300
|
-
function removeProjectFromHistory(path) {
|
|
2301
|
-
const projects = getStoredProjects().filter(p => p !== path);
|
|
2302
|
-
saveProjects(projects);
|
|
2303
|
-
updateProjectSelect();
|
|
2304
|
-
}
|
|
2305
|
-
|
|
2306
|
-
function updateProjectSelect() {
|
|
2307
|
-
const select = document.getElementById('project-select');
|
|
2308
|
-
const projects = getStoredProjects();
|
|
2309
|
-
const current = localStorage.getItem(STORAGE_KEY_CURRENT) || '';
|
|
2310
|
-
|
|
2311
|
-
select.innerHTML = `<option value="">${t('project.selectPlaceholder')}</option>`;
|
|
2312
|
-
for (const path of projects) {
|
|
2313
|
-
const shortName = path.split('/').slice(-2).join('/');
|
|
2314
|
-
const option = document.createElement('option');
|
|
2315
|
-
option.value = path;
|
|
2316
|
-
option.textContent = shortName;
|
|
2317
|
-
option.title = path;
|
|
2318
|
-
if (path === current) option.selected = true;
|
|
2319
|
-
select.appendChild(option);
|
|
2320
|
-
}
|
|
2321
|
-
}
|
|
2322
|
-
|
|
2323
|
-
function onProjectSelect(path) {
|
|
2324
|
-
if (path) {
|
|
2325
|
-
document.getElementById('project-path-input').value = '';
|
|
2326
|
-
loadProjectConfigFromPath(path);
|
|
2327
|
-
}
|
|
2328
|
-
}
|
|
2329
|
-
|
|
2330
|
-
async function loadProjectConfig() {
|
|
2331
|
-
const input = document.getElementById('project-path-input');
|
|
2332
|
-
const select = document.getElementById('project-select');
|
|
2333
|
-
const projectPath = input.value.trim() || select.value;
|
|
2334
|
-
|
|
2335
|
-
if (!projectPath) {
|
|
2336
|
-
showConfigStatus(t('error.selectOrEnterPath'), 'error');
|
|
2337
|
-
return;
|
|
2338
|
-
}
|
|
2339
|
-
|
|
2340
|
-
await loadProjectConfigFromPath(projectPath);
|
|
2341
|
-
}
|
|
2342
|
-
|
|
2343
2301
|
async function loadProjectConfigFromPath(projectPath) {
|
|
2344
2302
|
const status = document.getElementById('config-status');
|
|
2345
2303
|
const info = document.getElementById('config-info');
|
|
@@ -2355,12 +2313,8 @@
|
|
|
2355
2313
|
currentProjectConfig = data.config;
|
|
2356
2314
|
currentProjectPath = projectPath;
|
|
2357
2315
|
|
|
2358
|
-
addProjectToHistory(projectPath);
|
|
2359
2316
|
localStorage.setItem(STORAGE_KEY_CURRENT, projectPath);
|
|
2360
2317
|
|
|
2361
|
-
document.getElementById('project-select').value = projectPath;
|
|
2362
|
-
document.getElementById('project-path-input').value = '';
|
|
2363
|
-
|
|
2364
2318
|
const shortName = projectPath.split('/').slice(-2).join('/');
|
|
2365
2319
|
showConfigStatus(`<i data-lucide="check-circle"></i> ${escapeHtml(shortName)}`, 'success');
|
|
2366
2320
|
refreshIcons();
|
|
@@ -2413,59 +2367,434 @@
|
|
|
2413
2367
|
refreshIcons();
|
|
2414
2368
|
}
|
|
2415
2369
|
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2370
|
+
// SPEC-91 — Dashboard Multi-Project Overview
|
|
2371
|
+
let availableRepositories = [];
|
|
2372
|
+
let activeTabId = 'overview';
|
|
2373
|
+
|
|
2374
|
+
async function fetchAvailableRepositories() {
|
|
2375
|
+
try {
|
|
2376
|
+
const response = await fetch(`${API_URL}/api/repositories`);
|
|
2377
|
+
const data = await response.json();
|
|
2378
|
+
availableRepositories = Array.isArray(data.repositories) ? data.repositories : [];
|
|
2379
|
+
} catch {
|
|
2380
|
+
availableRepositories = [];
|
|
2381
|
+
}
|
|
2382
|
+
}
|
|
2383
|
+
|
|
2384
|
+
function syncAvailableRepositoriesFromResponse(payload) {
|
|
2385
|
+
availableRepositories = Array.isArray(payload?.repositories) ? payload.repositories : [];
|
|
2386
|
+
}
|
|
2387
|
+
|
|
2388
|
+
function renderCardCounters() {
|
|
2389
|
+
let scope;
|
|
2390
|
+
if (activeTabId === 'overview') {
|
|
2391
|
+
scope = { kind: 'overview' };
|
|
2392
|
+
} else {
|
|
2393
|
+
const repository = availableRepositories.find((r) => r.localPath === activeTabId);
|
|
2394
|
+
const projectName = repository?.name ?? activeTabId.split('/').filter(Boolean).pop() ?? activeTabId;
|
|
2395
|
+
scope = { kind: 'project', localPath: activeTabId, projectName };
|
|
2396
|
+
}
|
|
2397
|
+
const counters = computeCardCounters({
|
|
2398
|
+
activeReviews: currentData.activeReviews,
|
|
2399
|
+
reviewFiles: currentData.reviewFiles,
|
|
2400
|
+
scope,
|
|
2401
|
+
});
|
|
2402
|
+
const runningEl = document.getElementById('running-count');
|
|
2403
|
+
const queuedEl = document.getElementById('queued-count');
|
|
2404
|
+
const completedEl = document.getElementById('completed-count');
|
|
2405
|
+
if (runningEl) runningEl.textContent = counters.running;
|
|
2406
|
+
if (queuedEl) queuedEl.textContent = counters.queued;
|
|
2407
|
+
if (completedEl) completedEl.textContent = counters.completed;
|
|
2408
|
+
const markerEl = document.getElementById('cards-scope-marker');
|
|
2409
|
+
if (markerEl) {
|
|
2410
|
+
markerEl.dataset.scopeKind = counters.markerKind;
|
|
2411
|
+
const labelEl = markerEl.querySelector('.cards-scope-label');
|
|
2412
|
+
if (labelEl) labelEl.textContent = counters.markerLabel;
|
|
2413
|
+
}
|
|
2414
|
+
}
|
|
2415
|
+
|
|
2416
|
+
function renderDashboardTabs() {
|
|
2417
|
+
const container = document.getElementById('dashboard-tabs');
|
|
2418
|
+
if (!container) return;
|
|
2419
|
+
const model = buildTabBarModel({
|
|
2420
|
+
repositories: availableRepositories,
|
|
2421
|
+
activeTabId: activeTabId === 'overview' ? null : activeTabId,
|
|
2422
|
+
});
|
|
2423
|
+
container.innerHTML = renderTabBarHtml(model);
|
|
2424
|
+
container.querySelectorAll('.dashboard-tab').forEach((button) => {
|
|
2425
|
+
button.addEventListener('click', () => {
|
|
2426
|
+
const tabId = button.dataset.tabId;
|
|
2427
|
+
if (!tabId) return;
|
|
2428
|
+
handleTabClick(tabId);
|
|
2429
|
+
});
|
|
2430
|
+
});
|
|
2431
|
+
}
|
|
2432
|
+
|
|
2433
|
+
function handleTabClick(tabId) {
|
|
2434
|
+
if (tabId === 'overview') {
|
|
2435
|
+
activateOverviewTab();
|
|
2421
2436
|
return;
|
|
2422
2437
|
}
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2438
|
+
activateProjectTab(tabId);
|
|
2439
|
+
}
|
|
2440
|
+
|
|
2441
|
+
function activateOverviewTab() {
|
|
2442
|
+
activeTabId = 'overview';
|
|
2443
|
+
writeActiveTab('overview');
|
|
2444
|
+
document.body.classList.add('overview-tab-active');
|
|
2445
|
+
const overviewSection = document.getElementById('overview-section');
|
|
2446
|
+
if (overviewSection) overviewSection.classList.remove('hidden');
|
|
2447
|
+
renderDashboardTabs();
|
|
2448
|
+
renderCardCounters();
|
|
2449
|
+
syncSettingsButtonVisibility();
|
|
2450
|
+
refreshOverviewSection();
|
|
2451
|
+
}
|
|
2452
|
+
|
|
2453
|
+
function activateProjectTab(projectPath) {
|
|
2454
|
+
activeTabId = projectPath;
|
|
2455
|
+
writeActiveTab(projectPath);
|
|
2456
|
+
document.body.classList.remove('overview-tab-active');
|
|
2457
|
+
const overviewSection = document.getElementById('overview-section');
|
|
2458
|
+
if (overviewSection) overviewSection.classList.add('hidden');
|
|
2459
|
+
renderDashboardTabs();
|
|
2460
|
+
renderCardCounters();
|
|
2461
|
+
syncSettingsButtonVisibility();
|
|
2462
|
+
loadProjectConfigFromPath(projectPath);
|
|
2463
|
+
}
|
|
2464
|
+
|
|
2465
|
+
function syncSettingsButtonVisibility() {
|
|
2466
|
+
const button = document.getElementById('open-settings-modal-btn');
|
|
2467
|
+
if (!button) return;
|
|
2468
|
+
if (activeTabId === 'overview') {
|
|
2469
|
+
button.hidden = true;
|
|
2470
|
+
} else {
|
|
2471
|
+
button.hidden = false;
|
|
2431
2472
|
}
|
|
2432
2473
|
}
|
|
2433
2474
|
|
|
2434
|
-
|
|
2475
|
+
function resolveActiveProjectName() {
|
|
2476
|
+
if (activeTabId === 'overview') return '—';
|
|
2477
|
+
const repository = availableRepositories.find((r) => r.localPath === activeTabId);
|
|
2478
|
+
if (repository?.name) return repository.name;
|
|
2479
|
+
return activeTabId.split('/').filter(Boolean).pop() ?? activeTabId;
|
|
2480
|
+
}
|
|
2481
|
+
|
|
2482
|
+
async function openSettingsModal() {
|
|
2483
|
+
if (activeTabId === 'overview') return;
|
|
2484
|
+
const dialog = document.getElementById('settings-modal');
|
|
2485
|
+
if (!dialog || typeof dialog.showModal !== 'function') return;
|
|
2435
2486
|
try {
|
|
2436
|
-
const response = await fetch(
|
|
2437
|
-
|
|
2438
|
-
|
|
2487
|
+
const response = await fetch(
|
|
2488
|
+
`${API_URL}/api/project-config?path=${encodeURIComponent(activeTabId)}`,
|
|
2489
|
+
);
|
|
2490
|
+
const payload = await response.json();
|
|
2491
|
+
if (!payload?.success) {
|
|
2492
|
+
dialog.innerHTML = `<form method="dialog" class="settings-modal__form"><p class="settings-modal__error">${escapeHtml(payload?.error || 'Configuration projet illisible')}</p><div class="settings-modal__actions"><button type="submit" class="settings-modal__cancel">Fermer</button></div></form>`;
|
|
2493
|
+
dialog.showModal();
|
|
2494
|
+
return;
|
|
2495
|
+
}
|
|
2496
|
+
const viewModel = buildSettingsViewModel({
|
|
2497
|
+
config: payload.config,
|
|
2498
|
+
projectName: resolveActiveProjectName(),
|
|
2499
|
+
});
|
|
2500
|
+
dialog.innerHTML = renderSettingsModalHtml(viewModel);
|
|
2501
|
+
bindSettingsModalForm(dialog);
|
|
2502
|
+
dialog.showModal();
|
|
2503
|
+
} catch (error) {
|
|
2504
|
+
showToast(t('toast.error') || 'Erreur', 'error');
|
|
2505
|
+
}
|
|
2506
|
+
}
|
|
2439
2507
|
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2508
|
+
function closeSettingsModal() {
|
|
2509
|
+
const dialog = document.getElementById('settings-modal');
|
|
2510
|
+
if (dialog && dialog.open) dialog.close();
|
|
2511
|
+
}
|
|
2512
|
+
|
|
2513
|
+
function bindSettingsModalForm(dialog) {
|
|
2514
|
+
const form = dialog.querySelector('form.settings-modal__form');
|
|
2515
|
+
const cancelBtn = dialog.querySelector('.settings-modal__cancel');
|
|
2516
|
+
const errorEl = dialog.querySelector('.settings-modal__error');
|
|
2517
|
+
if (cancelBtn) {
|
|
2518
|
+
cancelBtn.addEventListener('click', (event) => {
|
|
2519
|
+
event.preventDefault();
|
|
2520
|
+
closeSettingsModal();
|
|
2521
|
+
});
|
|
2522
|
+
}
|
|
2523
|
+
if (!form) return;
|
|
2524
|
+
form.addEventListener('submit', async (event) => {
|
|
2525
|
+
event.preventDefault();
|
|
2526
|
+
if (errorEl) errorEl.textContent = '';
|
|
2527
|
+
const formData = new FormData(form);
|
|
2528
|
+
const payload = extractFormPayload(formData);
|
|
2529
|
+
const linkValidation = validateExternalLink(payload.externalLink ?? '');
|
|
2530
|
+
if (!linkValidation.ok) {
|
|
2531
|
+
if (errorEl) errorEl.textContent = linkValidation.message;
|
|
2532
|
+
return;
|
|
2533
|
+
}
|
|
2534
|
+
try {
|
|
2535
|
+
const response = await fetch(
|
|
2536
|
+
`${API_URL}/api/project-config?path=${encodeURIComponent(activeTabId)}`,
|
|
2537
|
+
{
|
|
2538
|
+
method: 'PATCH',
|
|
2539
|
+
headers: { 'Content-Type': 'application/json' },
|
|
2540
|
+
body: JSON.stringify(payload),
|
|
2541
|
+
},
|
|
2542
|
+
);
|
|
2543
|
+
if (!response.ok) {
|
|
2544
|
+
const errorPayload = await response.json().catch(() => ({ error: 'Échec de la sauvegarde' }));
|
|
2545
|
+
if (errorEl) errorEl.textContent = errorPayload?.error || 'Échec de la sauvegarde';
|
|
2546
|
+
return;
|
|
2444
2547
|
}
|
|
2548
|
+
closeSettingsModal();
|
|
2549
|
+
refreshOverviewSection();
|
|
2550
|
+
} catch {
|
|
2551
|
+
if (errorEl) errorEl.textContent = 'Échec de la sauvegarde';
|
|
2445
2552
|
}
|
|
2446
|
-
|
|
2447
|
-
|
|
2553
|
+
});
|
|
2554
|
+
}
|
|
2555
|
+
|
|
2556
|
+
function bindSettingsModalDismissals() {
|
|
2557
|
+
const dialog = document.getElementById('settings-modal');
|
|
2558
|
+
if (!dialog) return;
|
|
2559
|
+
dialog.addEventListener('click', (event) => {
|
|
2560
|
+
if (event.target === dialog) {
|
|
2561
|
+
closeSettingsModal();
|
|
2562
|
+
}
|
|
2563
|
+
});
|
|
2564
|
+
}
|
|
2565
|
+
|
|
2566
|
+
function bindSettingsModalTrigger() {
|
|
2567
|
+
const button = document.getElementById('open-settings-modal-btn');
|
|
2568
|
+
if (!button) return;
|
|
2569
|
+
button.addEventListener('click', () => {
|
|
2570
|
+
openSettingsModal();
|
|
2571
|
+
});
|
|
2572
|
+
}
|
|
2573
|
+
|
|
2574
|
+
async function refreshOverviewSection() {
|
|
2575
|
+
const container = document.getElementById('overview-section');
|
|
2576
|
+
if (!container) return;
|
|
2577
|
+
if (activeTabId !== 'overview') return;
|
|
2578
|
+
try {
|
|
2579
|
+
const response = await fetch(`${API_URL}/api/overview`);
|
|
2580
|
+
const viewModel = await response.json();
|
|
2581
|
+
container.innerHTML = renderOverviewHtml(viewModel);
|
|
2582
|
+
container.querySelectorAll('.overview-project-card').forEach((card) => {
|
|
2583
|
+
card.addEventListener('click', () => {
|
|
2584
|
+
const projectPath = card.dataset.projectPath;
|
|
2585
|
+
if (projectPath) activateProjectTab(projectPath);
|
|
2586
|
+
});
|
|
2587
|
+
});
|
|
2588
|
+
container.querySelectorAll('.project-card__external').forEach((anchor) => {
|
|
2589
|
+
anchor.addEventListener('click', (event) => event.stopPropagation());
|
|
2590
|
+
});
|
|
2448
2591
|
} catch {
|
|
2449
|
-
//
|
|
2592
|
+
// Silent: WS reconnection or next refresh will retry
|
|
2450
2593
|
}
|
|
2451
2594
|
}
|
|
2452
2595
|
|
|
2453
|
-
async function
|
|
2454
|
-
await
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2596
|
+
async function initOverviewAndTabs() {
|
|
2597
|
+
await fetchAvailableRepositories();
|
|
2598
|
+
renderManagePanel();
|
|
2599
|
+
bindManagePanelToggle();
|
|
2600
|
+
bindSettingsModalTrigger();
|
|
2601
|
+
bindSettingsModalDismissals();
|
|
2602
|
+
const persistedTab = readActiveTab();
|
|
2603
|
+
const repositoryPaths = availableRepositories.map((repository) => repository.localPath);
|
|
2604
|
+
if (persistedTab && persistedTab !== 'overview' && repositoryPaths.includes(persistedTab)) {
|
|
2605
|
+
activateProjectTab(persistedTab);
|
|
2459
2606
|
} else {
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2607
|
+
activateOverviewTab();
|
|
2608
|
+
}
|
|
2609
|
+
}
|
|
2610
|
+
|
|
2611
|
+
let isManagePanelOpen = false;
|
|
2612
|
+
|
|
2613
|
+
function renderManagePanel() {
|
|
2614
|
+
const panel = document.getElementById('manage-panel');
|
|
2615
|
+
if (!panel) return;
|
|
2616
|
+
const model = buildManagePanelModel({ repositories: availableRepositories, isOpen: isManagePanelOpen });
|
|
2617
|
+
panel.innerHTML = renderManagePanelHtml(model);
|
|
2618
|
+
panel.dataset.open = isManagePanelOpen ? 'true' : 'false';
|
|
2619
|
+
bindManagePanelHandlers();
|
|
2620
|
+
}
|
|
2621
|
+
|
|
2622
|
+
function bindManagePanelToggle() {
|
|
2623
|
+
const toggle = document.getElementById('manage-projects-toggle');
|
|
2624
|
+
if (!toggle || toggle.dataset.bound === 'true') return;
|
|
2625
|
+
toggle.dataset.bound = 'true';
|
|
2626
|
+
toggle.addEventListener('click', () => {
|
|
2627
|
+
isManagePanelOpen = !isManagePanelOpen;
|
|
2628
|
+
toggle.setAttribute('aria-expanded', isManagePanelOpen ? 'true' : 'false');
|
|
2629
|
+
renderManagePanel();
|
|
2630
|
+
});
|
|
2631
|
+
}
|
|
2632
|
+
|
|
2633
|
+
function bindManagePanelHandlers() {
|
|
2634
|
+
const panel = document.getElementById('manage-panel');
|
|
2635
|
+
if (!panel) return;
|
|
2636
|
+
const form = panel.querySelector('form.add-form');
|
|
2637
|
+
if (form) {
|
|
2638
|
+
form.addEventListener('submit', handleAddProjectSubmit);
|
|
2639
|
+
const input = form.querySelector('input.add-form-input');
|
|
2640
|
+
if (input) {
|
|
2641
|
+
input.addEventListener('keydown', (event) => {
|
|
2642
|
+
if (event.key === 'Escape') {
|
|
2643
|
+
input.value = '';
|
|
2644
|
+
clearManagePanelError();
|
|
2645
|
+
}
|
|
2646
|
+
});
|
|
2647
|
+
}
|
|
2648
|
+
}
|
|
2649
|
+
panel.querySelectorAll('.manage-row-delete').forEach((button) => {
|
|
2650
|
+
button.addEventListener('click', () => {
|
|
2651
|
+
const row = button.closest('.manage-row');
|
|
2652
|
+
const localPath = row?.dataset.localPath;
|
|
2653
|
+
if (localPath) handleDeleteProject(localPath, row);
|
|
2654
|
+
});
|
|
2655
|
+
});
|
|
2656
|
+
panel.querySelectorAll('.manage-row-toggle').forEach((button) => {
|
|
2657
|
+
button.addEventListener('click', () => {
|
|
2658
|
+
const row = button.closest('.manage-row');
|
|
2659
|
+
const localPath = row?.dataset.localPath;
|
|
2660
|
+
const currentlyEnabled = row?.dataset.enabled === 'true';
|
|
2661
|
+
if (localPath) handleToggleProject(localPath, !currentlyEnabled);
|
|
2662
|
+
});
|
|
2663
|
+
});
|
|
2664
|
+
}
|
|
2665
|
+
|
|
2666
|
+
function setManagePanelError(message) {
|
|
2667
|
+
const panel = document.getElementById('manage-panel');
|
|
2668
|
+
const target = panel?.querySelector('[data-role="error-message"]');
|
|
2669
|
+
if (!target) return;
|
|
2670
|
+
target.textContent = message;
|
|
2671
|
+
target.hidden = false;
|
|
2672
|
+
}
|
|
2673
|
+
|
|
2674
|
+
function clearManagePanelError() {
|
|
2675
|
+
const panel = document.getElementById('manage-panel');
|
|
2676
|
+
const target = panel?.querySelector('[data-role="error-message"]');
|
|
2677
|
+
if (!target) return;
|
|
2678
|
+
target.textContent = '';
|
|
2679
|
+
target.hidden = true;
|
|
2680
|
+
}
|
|
2681
|
+
|
|
2682
|
+
function flashAddFormError() {
|
|
2683
|
+
const form = document.querySelector('#manage-panel form.add-form');
|
|
2684
|
+
if (!form) return;
|
|
2685
|
+
form.classList.remove('is-error');
|
|
2686
|
+
requestAnimationFrame(() => form.classList.add('is-error'));
|
|
2687
|
+
setTimeout(() => form.classList.remove('is-error'), 320);
|
|
2688
|
+
}
|
|
2689
|
+
|
|
2690
|
+
function flashAddFormSuccess() {
|
|
2691
|
+
const input = document.querySelector('#manage-panel input.add-form-input');
|
|
2692
|
+
if (!input) return;
|
|
2693
|
+
input.classList.remove('is-success');
|
|
2694
|
+
requestAnimationFrame(() => input.classList.add('is-success'));
|
|
2695
|
+
setTimeout(() => input.classList.remove('is-success'), 1500);
|
|
2696
|
+
}
|
|
2697
|
+
|
|
2698
|
+
function flashTabEntering(localPath) {
|
|
2699
|
+
const tab = document.querySelector(`.dashboard-tab[data-tab-id="${CSS.escape(localPath)}"]`);
|
|
2700
|
+
if (!tab) return;
|
|
2701
|
+
tab.classList.add('is-entering');
|
|
2702
|
+
setTimeout(() => tab.classList.remove('is-entering'), 1500);
|
|
2703
|
+
}
|
|
2704
|
+
|
|
2705
|
+
async function handleAddProjectSubmit(event) {
|
|
2706
|
+
event.preventDefault();
|
|
2707
|
+
const form = event.currentTarget;
|
|
2708
|
+
const input = form.querySelector('input.add-form-input');
|
|
2709
|
+
const submit = form.querySelector('button.add-form-submit');
|
|
2710
|
+
const rawValue = input ? input.value : '';
|
|
2711
|
+
const validation = validateLocalPathInput(rawValue);
|
|
2712
|
+
clearManagePanelError();
|
|
2713
|
+
if (!validation.ok) {
|
|
2714
|
+
const message = validation.reason === 'empty' ? 'Chemin du projet requis' : 'Le chemin doit être absolu';
|
|
2715
|
+
setManagePanelError(message);
|
|
2716
|
+
flashAddFormError();
|
|
2717
|
+
return;
|
|
2718
|
+
}
|
|
2719
|
+
const trimmed = rawValue.trim();
|
|
2720
|
+
if (submit) submit.classList.add('is-busy');
|
|
2721
|
+
try {
|
|
2722
|
+
const response = await fetch(`${API_URL}/api/repositories`, {
|
|
2723
|
+
method: 'POST',
|
|
2724
|
+
headers: { 'Content-Type': 'application/json' },
|
|
2725
|
+
body: JSON.stringify({ localPath: trimmed }),
|
|
2726
|
+
});
|
|
2727
|
+
const body = await response.json().catch(() => ({}));
|
|
2728
|
+
if (!response.ok) {
|
|
2729
|
+
setManagePanelError(typeof body?.error === 'string' ? body.error : 'Erreur inconnue');
|
|
2730
|
+
flashAddFormError();
|
|
2731
|
+
return;
|
|
2732
|
+
}
|
|
2733
|
+
syncAvailableRepositoriesFromResponse(body);
|
|
2734
|
+
if (input) input.value = '';
|
|
2735
|
+
flashAddFormSuccess();
|
|
2736
|
+
renderManagePanel();
|
|
2737
|
+
renderDashboardTabs();
|
|
2738
|
+
flashTabEntering(trimmed);
|
|
2739
|
+
} catch {
|
|
2740
|
+
setManagePanelError('Erreur réseau');
|
|
2741
|
+
flashAddFormError();
|
|
2742
|
+
} finally {
|
|
2743
|
+
if (submit) submit.classList.remove('is-busy');
|
|
2744
|
+
}
|
|
2745
|
+
}
|
|
2746
|
+
|
|
2747
|
+
async function handleDeleteProject(localPath, rowElement) {
|
|
2748
|
+
try {
|
|
2749
|
+
const response = await fetch(`${API_URL}/api/repositories?localPath=${encodeURIComponent(localPath)}`, {
|
|
2750
|
+
method: 'DELETE',
|
|
2751
|
+
});
|
|
2752
|
+
const body = await response.json().catch(() => ({}));
|
|
2753
|
+
if (!response.ok) {
|
|
2754
|
+
setManagePanelError(typeof body?.error === 'string' ? body.error : 'Erreur inconnue');
|
|
2755
|
+
return;
|
|
2756
|
+
}
|
|
2757
|
+
syncAvailableRepositoriesFromResponse(body);
|
|
2758
|
+
if (rowElement) {
|
|
2759
|
+
rowElement.classList.add('is-leaving');
|
|
2760
|
+
setTimeout(() => {
|
|
2761
|
+
renderManagePanel();
|
|
2762
|
+
}, 250);
|
|
2763
|
+
} else {
|
|
2764
|
+
renderManagePanel();
|
|
2765
|
+
}
|
|
2766
|
+
const tab = document.querySelector(`.dashboard-tab[data-tab-id="${CSS.escape(localPath)}"]`);
|
|
2767
|
+
if (tab) {
|
|
2768
|
+
tab.classList.add('is-leaving');
|
|
2769
|
+
setTimeout(() => renderDashboardTabs(), 250);
|
|
2463
2770
|
} else {
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2771
|
+
renderDashboardTabs();
|
|
2772
|
+
}
|
|
2773
|
+
if (activeTabId === localPath) {
|
|
2774
|
+
activateOverviewTab();
|
|
2468
2775
|
}
|
|
2776
|
+
} catch {
|
|
2777
|
+
setManagePanelError('Erreur réseau');
|
|
2778
|
+
}
|
|
2779
|
+
}
|
|
2780
|
+
|
|
2781
|
+
async function handleToggleProject(localPath, enabled) {
|
|
2782
|
+
try {
|
|
2783
|
+
const response = await fetch(`${API_URL}/api/repositories?localPath=${encodeURIComponent(localPath)}`, {
|
|
2784
|
+
method: 'PATCH',
|
|
2785
|
+
headers: { 'Content-Type': 'application/json' },
|
|
2786
|
+
body: JSON.stringify({ enabled }),
|
|
2787
|
+
});
|
|
2788
|
+
const body = await response.json().catch(() => ({}));
|
|
2789
|
+
if (!response.ok) {
|
|
2790
|
+
setManagePanelError(typeof body?.error === 'string' ? body.error : 'Erreur inconnue');
|
|
2791
|
+
return;
|
|
2792
|
+
}
|
|
2793
|
+
syncAvailableRepositoriesFromResponse(body);
|
|
2794
|
+
renderManagePanel();
|
|
2795
|
+
renderDashboardTabs();
|
|
2796
|
+
} catch {
|
|
2797
|
+
setManagePanelError('Erreur réseau');
|
|
2469
2798
|
}
|
|
2470
2799
|
}
|
|
2471
2800
|
|
|
@@ -2608,19 +2937,6 @@
|
|
|
2608
2937
|
const modelSonnet = document.getElementById('i18n-model-sonnet');
|
|
2609
2938
|
if (modelSonnet) modelSonnet.textContent = t('model.sonnet');
|
|
2610
2939
|
|
|
2611
|
-
// Project loader
|
|
2612
|
-
const projectPlaceholder = document.getElementById('i18n-project-placeholder');
|
|
2613
|
-
if (projectPlaceholder) projectPlaceholder.textContent = t('project.selectPlaceholder');
|
|
2614
|
-
|
|
2615
|
-
const projectPathInput = document.getElementById('project-path-input');
|
|
2616
|
-
if (projectPathInput) projectPathInput.placeholder = t('project.inputPlaceholder');
|
|
2617
|
-
|
|
2618
|
-
const projectLoad = document.getElementById('i18n-project-load');
|
|
2619
|
-
if (projectLoad) projectLoad.textContent = t('project.load');
|
|
2620
|
-
|
|
2621
|
-
const removeProjectBtn = document.getElementById('remove-project-btn');
|
|
2622
|
-
if (removeProjectBtn) removeProjectBtn.title = t('project.removeTooltip');
|
|
2623
|
-
|
|
2624
2940
|
// Login sections
|
|
2625
2941
|
const claudeLoginTitle = document.getElementById('i18n-claude-login-title');
|
|
2626
2942
|
if (claudeLoginTitle) claudeLoginTitle.textContent = t('login.claude.title');
|
|
@@ -2719,9 +3035,6 @@
|
|
|
2719
3035
|
|
|
2720
3036
|
const modalConfirm = document.getElementById('cancel-modal-confirm');
|
|
2721
3037
|
if (modalConfirm) modalConfirm.textContent = t('modal.confirm');
|
|
2722
|
-
|
|
2723
|
-
// Update project select placeholder (re-render the select)
|
|
2724
|
-
updateProjectSelect();
|
|
2725
3038
|
}
|
|
2726
3039
|
|
|
2727
3040
|
async function checkForUpdates() {
|
|
@@ -2879,9 +3192,6 @@
|
|
|
2879
3192
|
window.toggleStats = toggleStats;
|
|
2880
3193
|
window.changeModel = changeModel;
|
|
2881
3194
|
window.changeLanguage = changeLanguage;
|
|
2882
|
-
window.onProjectSelect = onProjectSelect;
|
|
2883
|
-
window.loadProjectConfig = loadProjectConfig;
|
|
2884
|
-
window.removeCurrentProject = removeCurrentProject;
|
|
2885
3195
|
window.toggleReviewAccordion = toggleReviewAccordion;
|
|
2886
3196
|
window.toggleReviewDescription = toggleReviewDescription;
|
|
2887
3197
|
window.deleteReviewFile = deleteReviewFile;
|
|
@@ -2926,7 +3236,7 @@
|
|
|
2926
3236
|
checkClaudeStatus();
|
|
2927
3237
|
loadModelSetting();
|
|
2928
3238
|
loadLanguageSetting();
|
|
2929
|
-
|
|
3239
|
+
initOverviewAndTabs();
|
|
2930
3240
|
refreshBudgetTile();
|
|
2931
3241
|
initBudgetSlider();
|
|
2932
3242
|
|