@nightkatana/kronosys-app 1.0.0-beta.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/README.md +81 -0
- package/app/api/action/route.ts +16 -0
- package/app/api/backup/route.ts +84 -0
- package/app/api/health/route.ts +22 -0
- package/app/api/state/route.ts +27 -0
- package/app/apple-icon.png +0 -0
- package/app/changelog/page.tsx +122 -0
- package/app/globals.css +210 -0
- package/app/guide/layout.tsx +11 -0
- package/app/guide/page.tsx +278 -0
- package/app/icon.png +0 -0
- package/app/layout.tsx +77 -0
- package/app/licenses/layout.tsx +11 -0
- package/app/licenses/page.tsx +246 -0
- package/app/manifest.ts +32 -0
- package/app/page.tsx +1610 -0
- package/app/reporting/page.tsx +2943 -0
- package/app/settings/layout.tsx +10 -0
- package/app/settings/page.tsx +3518 -0
- package/bin/kronosys.mjs +46 -0
- package/components/KronosysPackageVersionProvider.tsx +19 -0
- package/components/KronosysPayloadProvider.tsx +109 -0
- package/components/PwaRegister.tsx +25 -0
- package/components/SiteLegalFooter.tsx +21 -0
- package/components/ThemeProvider.tsx +78 -0
- package/components/dashboard/AppShellLiveSessionDrawer.tsx +394 -0
- package/components/dashboard/AppShellRouteNav.tsx +131 -0
- package/components/dashboard/AppVersionStamp.tsx +16 -0
- package/components/dashboard/DashboardCollapsibleSection.tsx +57 -0
- package/components/dashboard/DashboardColumnHintsBanner.tsx +159 -0
- package/components/dashboard/DashboardCommandCenter.tsx +470 -0
- package/components/dashboard/DashboardLangGateModal.tsx +118 -0
- package/components/dashboard/DashboardLoadingOverlay.tsx +42 -0
- package/components/dashboard/DashboardSimpleModal.tsx +337 -0
- package/components/dashboard/DashboardSuspenseFallback.tsx +52 -0
- package/components/dashboard/DashboardToastProvider.tsx +64 -0
- package/components/dashboard/DashboardTour.tsx +435 -0
- package/components/dashboard/DeferredDescriptionPopoverWrap.tsx +39 -0
- package/components/dashboard/DeleteSessionModal.tsx +130 -0
- package/components/dashboard/DescriptionTooltipPortaled.tsx +31 -0
- package/components/dashboard/GitIdentityQuickSetupModal.tsx +211 -0
- package/components/dashboard/HeaderIntegrationBadges.tsx +69 -0
- package/components/dashboard/InlineMetricHelpTrigger.tsx +102 -0
- package/components/dashboard/IssuePickerModal.tsx +168 -0
- package/components/dashboard/KronoFocusPanel.tsx +834 -0
- package/components/dashboard/KronosysDatetimePopoverField.tsx +357 -0
- package/components/dashboard/KronosysTimePopoverField.tsx +233 -0
- package/components/dashboard/LanguageMenu.tsx +123 -0
- package/components/dashboard/MongoMirrorSyncLine.tsx +57 -0
- package/components/dashboard/NewSessionScopeModal.tsx +410 -0
- package/components/dashboard/PageRefreshButton.tsx +130 -0
- package/components/dashboard/PlainHelpPopover.tsx +97 -0
- package/components/dashboard/ReportingPageToc.tsx +68 -0
- package/components/dashboard/ReportingTour.tsx +342 -0
- package/components/dashboard/SavedProjectPicker.tsx +92 -0
- package/components/dashboard/SavedTagPicker.tsx +115 -0
- package/components/dashboard/ScrollToTopFab.tsx +41 -0
- package/components/dashboard/SelectedSessionSidebarBlock.tsx +630 -0
- package/components/dashboard/SessionEndReasonEditor.tsx +114 -0
- package/components/dashboard/SessionListPanel.tsx +320 -0
- package/components/dashboard/SessionLocMetricsSection.tsx +128 -0
- package/components/dashboard/SettingsTagsProjectsSection.tsx +993 -0
- package/components/dashboard/SettingsTour.tsx +332 -0
- package/components/dashboard/TagPills.tsx +149 -0
- package/components/dashboard/TagsHelpTrigger.tsx +84 -0
- package/components/dashboard/TaskFocusPanel.tsx +1261 -0
- package/components/dashboard/TaskSessionLiveCard.tsx +832 -0
- package/components/dashboard/TaskSubtasksBlock.tsx +748 -0
- package/components/dashboard/ThemeToggle.test.tsx +26 -0
- package/components/dashboard/ThemeToggle.tsx +36 -0
- package/components/dashboard/UserGuideBodyText.tsx +62 -0
- package/components/dashboard/WorkspaceGitRepoCard.tsx +191 -0
- package/components/dashboard/taskFieldStyles.ts +139 -0
- package/components/dashboard/useAnchoredFloatingPortalStyle.ts +71 -0
- package/components/dashboard/useDescriptionPopoverAfterMs.ts +220 -0
- package/components/dashboard/useKronoFocusLiveSeconds.ts +36 -0
- package/components/dashboard/useSmoothStopwatchMs.ts +25 -0
- package/lib/appShellHeaderClasses.ts +12 -0
- package/lib/backupCsvExport.test.ts +149 -0
- package/lib/backupCsvExport.ts +392 -0
- package/lib/changelogCopy.ts +34 -0
- package/lib/concurrentTaskStartPreference.ts +29 -0
- package/lib/dashboardClockFormat.ts +13 -0
- package/lib/dashboardColumnChrome.ts +3 -0
- package/lib/dashboardColumnHintsStorage.ts +57 -0
- package/lib/dashboardCopy.ts +1831 -0
- package/lib/dashboardDetachedUrlHintStorage.ts +24 -0
- package/lib/dashboardGitIdentityBannerStorage.ts +36 -0
- package/lib/dashboardLangStorage.ts +72 -0
- package/lib/dashboardQuickSearch.ts +476 -0
- package/lib/dashboardQuickSearchQuery.test.ts +63 -0
- package/lib/dashboardQuickSearchQuery.ts +179 -0
- package/lib/dashboardSessionNav.ts +33 -0
- package/lib/dashboardShortcuts.ts +268 -0
- package/lib/dashboardTimeZone.ts +91 -0
- package/lib/dashboardTourStorage.ts +68 -0
- package/lib/dataDir.test.ts +87 -0
- package/lib/dataDir.ts +83 -0
- package/lib/devDataPreferenceFile.ts +55 -0
- package/lib/devDataRuntimeInfo.ts +34 -0
- package/lib/formatIsoShort.test.ts +46 -0
- package/lib/formatIsoShort.ts +29 -0
- package/lib/generatedUserChangelog.ts +34 -0
- package/lib/gitlabIssueSearch.ts +8 -0
- package/lib/kronoFocusDurationHistory.ts +71 -0
- package/lib/kronoFocusRhythm.test.ts +130 -0
- package/lib/kronoFocusRhythm.ts +46 -0
- package/lib/kronoFocusTimerUrgency.test.ts +74 -0
- package/lib/kronoFocusTimerUrgency.ts +24 -0
- package/lib/kronosysApi.ts +143 -0
- package/lib/legacyEditorPayloadKeys.ts +52 -0
- package/lib/legacyKronoFocusStorageKeys.test.ts +29 -0
- package/lib/legacyKronoFocusStorageKeys.ts +32 -0
- package/lib/licensesCopy.ts +128 -0
- package/lib/openPlainTextInNewTab.ts +49 -0
- package/lib/readKronosysPackageVersion.ts +10 -0
- package/lib/reportingAggregate.test.ts +325 -0
- package/lib/reportingAggregate.ts +819 -0
- package/lib/reportingDatePresets.ts +41 -0
- package/lib/reportingMetricHelp.ts +430 -0
- package/lib/reportingNonFinalIndicators.test.ts +157 -0
- package/lib/reportingNonFinalIndicators.ts +102 -0
- package/lib/reportingStrings.ts +491 -0
- package/lib/reportingTagWeekBreakdown.test.ts +141 -0
- package/lib/reportingTagWeekBreakdown.ts +181 -0
- package/lib/reportingWeekLayout.test.ts +239 -0
- package/lib/reportingWeekLayout.ts +313 -0
- package/lib/sessionAssiduity.test.ts +25 -0
- package/lib/sessionAssiduity.ts +33 -0
- package/lib/sessionEndReason.ts +55 -0
- package/lib/sessionEndWarnings.test.ts +200 -0
- package/lib/sessionEndWarnings.ts +125 -0
- package/lib/sessionListMerge.test.ts +101 -0
- package/lib/sessionListMerge.ts +70 -0
- package/lib/sessionTaskSidebarStats.test.ts +24 -0
- package/lib/sessionTaskSidebarStats.ts +54 -0
- package/lib/settingsCopy.ts +1276 -0
- package/lib/taskParsing.test.ts +153 -0
- package/lib/taskParsing.ts +737 -0
- package/lib/theme.ts +15 -0
- package/lib/translucentButtonClasses.ts +34 -0
- package/lib/usageProfile.test.ts +84 -0
- package/lib/usageProfile.ts +52 -0
- package/lib/userGuideCopy.ts +464 -0
- package/lib/workspaceLocDefaults.ts +21 -0
- package/next-env.d.ts +6 -0
- package/next.config.ts +15 -0
- package/package.json +87 -0
- package/postcss.config.mjs +12 -0
- package/public/apple-icon.png +0 -0
- package/public/favicon.ico +0 -0
- package/public/file.svg +1 -0
- package/public/globe.svg +1 -0
- package/public/icon-192.png +0 -0
- package/public/icon-512.png +0 -0
- package/public/icon.png +0 -0
- package/public/next.svg +1 -0
- package/public/sw.js +13 -0
- package/public/traceback.png +0 -0
- package/public/vercel.svg +1 -0
- package/public/window.svg +1 -0
- package/server/actionDispatch.test.ts +723 -0
- package/server/actionDispatch.ts +1476 -0
- package/server/actionTaskSession.test.ts +713 -0
- package/server/actionTaskSession.ts +717 -0
- package/server/db.ts +42 -0
- package/server/defaultCfg.ts +87 -0
- package/server/gitlabTokenStore.ts +34 -0
- package/server/kronoFocusHydrate.test.ts +142 -0
- package/server/kronoFocusHydrate.ts +69 -0
- package/server/kronoFocusMigrate.test.ts +53 -0
- package/server/kronoFocusMigrate.ts +78 -0
- package/server/mainTimerHydrate.test.ts +65 -0
- package/server/mainTimerHydrate.ts +53 -0
- package/server/payloadStore.test.ts +78 -0
- package/server/payloadStore.ts +83 -0
- package/server/sessionWallHydrate.test.ts +46 -0
- package/server/sessionWallHydrate.ts +88 -0
- package/tsconfig.json +41 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/** Date du calendrier local au format `YYYY-MM-DD` pour `<input type="date">`. */
|
|
2
|
+
export function toDateInputValue(d: Date): string {
|
|
3
|
+
const y = d.getFullYear();
|
|
4
|
+
const m = String(d.getMonth() + 1).padStart(2, "0");
|
|
5
|
+
const day = String(d.getDate()).padStart(2, "0");
|
|
6
|
+
return `${y}-${m}-${day}`;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/** Jour calendaire : début = fin = ce jour (référence : maintenant). */
|
|
10
|
+
export function reportingPresetDay(ref: Date = new Date()): { from: string; to: string } {
|
|
11
|
+
const d = toDateInputValue(ref);
|
|
12
|
+
return { from: d, to: d };
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Semaine du lundi au dimanche contenant `ref` (habitude ISO / Europe).
|
|
17
|
+
*/
|
|
18
|
+
export function reportingPresetWeek(ref: Date = new Date()): { from: string; to: string } {
|
|
19
|
+
const x = new Date(ref.getFullYear(), ref.getMonth(), ref.getDate());
|
|
20
|
+
const dow = x.getDay();
|
|
21
|
+
const mondayOffset = dow === 0 ? -6 : 1 - dow;
|
|
22
|
+
x.setDate(x.getDate() + mondayOffset);
|
|
23
|
+
const start = new Date(x.getFullYear(), x.getMonth(), x.getDate());
|
|
24
|
+
const end = new Date(start);
|
|
25
|
+
end.setDate(end.getDate() + 6);
|
|
26
|
+
return { from: toDateInputValue(start), to: toDateInputValue(end) };
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** Mois calendaire contenant `ref`. */
|
|
30
|
+
export function reportingPresetMonth(ref: Date = new Date()): { from: string; to: string } {
|
|
31
|
+
const start = new Date(ref.getFullYear(), ref.getMonth(), 1);
|
|
32
|
+
const end = new Date(ref.getFullYear(), ref.getMonth() + 1, 0);
|
|
33
|
+
return { from: toDateInputValue(start), to: toDateInputValue(end) };
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** Année civile contenant `ref`. */
|
|
37
|
+
export function reportingPresetYear(ref: Date = new Date()): { from: string; to: string } {
|
|
38
|
+
const start = new Date(ref.getFullYear(), 0, 1);
|
|
39
|
+
const end = new Date(ref.getFullYear(), 11, 31);
|
|
40
|
+
return { from: toDateInputValue(start), to: toDateInputValue(end) };
|
|
41
|
+
}
|
|
@@ -0,0 +1,430 @@
|
|
|
1
|
+
/** Textes d’aide (?) pour les métriques de la page Rapports — FR / EN. */
|
|
2
|
+
export type ReportingMetricHelpBlock = {
|
|
3
|
+
metricHelpSessionsAria: string;
|
|
4
|
+
metricHelpSessionsBody: string;
|
|
5
|
+
metricHelpTaskRowsAria: string;
|
|
6
|
+
metricHelpTaskRowsBody: string;
|
|
7
|
+
metricHelpKronoFocusCompletedAria: string;
|
|
8
|
+
metricHelpKronoFocusCompletedBody: string;
|
|
9
|
+
metricHelpKronoFocusTasksUsedAria: string;
|
|
10
|
+
metricHelpKronoFocusTasksUsedBody: string;
|
|
11
|
+
metricHelpKronoFocusCyclesAria: string;
|
|
12
|
+
metricHelpKronoFocusCyclesBody: string;
|
|
13
|
+
metricHelpTaskTimeAria: string;
|
|
14
|
+
metricHelpTaskTimeBody: string;
|
|
15
|
+
metricHelpSessionCodingAria: string;
|
|
16
|
+
metricHelpSessionCodingBody: string;
|
|
17
|
+
metricHelpSessionActiveAria: string;
|
|
18
|
+
metricHelpSessionActiveBody: string;
|
|
19
|
+
metricHelpLinesTotalAria: string;
|
|
20
|
+
metricHelpLinesTotalBody: string;
|
|
21
|
+
metricHelpLinesHumanAria: string;
|
|
22
|
+
metricHelpLinesHumanBody: string;
|
|
23
|
+
metricHelpLinesAiAria: string;
|
|
24
|
+
metricHelpLinesAiBody: string;
|
|
25
|
+
metricHelpLocByLangTitleAria: string;
|
|
26
|
+
metricHelpLocByLangTitleBody: string;
|
|
27
|
+
metricHelpCodingSignalsTitleAria: string;
|
|
28
|
+
metricHelpCodingSignalsTitleBody: string;
|
|
29
|
+
metricHelpChartSessionsAria: string;
|
|
30
|
+
metricHelpChartSessionsBody: string;
|
|
31
|
+
metricHelpChartTasksAria: string;
|
|
32
|
+
metricHelpChartTasksBody: string;
|
|
33
|
+
metricHelpChartTaskTimeAria: string;
|
|
34
|
+
metricHelpChartTaskTimeBody: string;
|
|
35
|
+
metricHelpChartSessionWallAria: string;
|
|
36
|
+
metricHelpChartSessionWallBody: string;
|
|
37
|
+
metricHelpTblDayAria: string;
|
|
38
|
+
metricHelpTblDayBody: string;
|
|
39
|
+
metricHelpTblSessionsAria: string;
|
|
40
|
+
metricHelpTblSessionsBody: string;
|
|
41
|
+
metricHelpTblDoneAria: string;
|
|
42
|
+
metricHelpTblDoneBody: string;
|
|
43
|
+
metricHelpTblActiveAria: string;
|
|
44
|
+
metricHelpTblActiveBody: string;
|
|
45
|
+
metricHelpTblTaskTimeAria: string;
|
|
46
|
+
metricHelpTblTaskTimeBody: string;
|
|
47
|
+
metricHelpTblSessionCodingAria: string;
|
|
48
|
+
metricHelpTblSessionCodingBody: string;
|
|
49
|
+
metricHelpTblSessionWallAria: string;
|
|
50
|
+
metricHelpTblSessionWallBody: string;
|
|
51
|
+
metricHelpSessionWallSummaryAria: string;
|
|
52
|
+
metricHelpSessionWallSummaryBody: string;
|
|
53
|
+
metricHelpTagTimeSectionAria: string;
|
|
54
|
+
metricHelpTagTimeSectionBody: string;
|
|
55
|
+
metricHelpTagTimeDayTableAria: string;
|
|
56
|
+
metricHelpTagTimeDayTableBody: string;
|
|
57
|
+
metricHelpTagTimeWeekTableAria: string;
|
|
58
|
+
metricHelpTagTimeWeekTableBody: string;
|
|
59
|
+
metricHelpTagWeekCalendarAria: string;
|
|
60
|
+
metricHelpTagWeekCalendarBody: string;
|
|
61
|
+
metricHelpTagWeekStartsOnAria: string;
|
|
62
|
+
metricHelpTagWeekStartsOnBody: string;
|
|
63
|
+
metricHelpWeekNavAria: string;
|
|
64
|
+
metricHelpWeekNavBody: string;
|
|
65
|
+
metricHelpTagTimeColTagAria: string;
|
|
66
|
+
metricHelpTagTimeColTagBody: string;
|
|
67
|
+
metricHelpTagTimeColDayAria: string;
|
|
68
|
+
metricHelpTagTimeColDayBody: string;
|
|
69
|
+
metricHelpTagTimeColWeekAria: string;
|
|
70
|
+
metricHelpTagTimeColWeekBody: string;
|
|
71
|
+
metricHelpTagTimeColMinutesAria: string;
|
|
72
|
+
metricHelpTagTimeColMinutesBody: string;
|
|
73
|
+
metricHelpProjectTitleAria: string;
|
|
74
|
+
metricHelpProjectTitleBody: string;
|
|
75
|
+
metricHelpProjectCalendarAria: string;
|
|
76
|
+
metricHelpProjectCalendarBody: string;
|
|
77
|
+
metricHelpProjectColProjAria: string;
|
|
78
|
+
metricHelpProjectColProjBody: string;
|
|
79
|
+
metricHelpProjectColTasksAria: string;
|
|
80
|
+
metricHelpProjectColTasksBody: string;
|
|
81
|
+
metricHelpProjectColTimeAria: string;
|
|
82
|
+
metricHelpProjectColTimeBody: string;
|
|
83
|
+
metricHelpWorkspaceTitleAria: string;
|
|
84
|
+
metricHelpWorkspaceTitleBody: string;
|
|
85
|
+
metricHelpWsTotalLinesAria: string;
|
|
86
|
+
metricHelpWsTotalLinesBody: string;
|
|
87
|
+
metricHelpWsFileCountAria: string;
|
|
88
|
+
metricHelpWsFileCountBody: string;
|
|
89
|
+
metricHelpWsColLangAria: string;
|
|
90
|
+
metricHelpWsColLangBody: string;
|
|
91
|
+
metricHelpWsColLinesAria: string;
|
|
92
|
+
metricHelpWsColLinesBody: string;
|
|
93
|
+
metricHelpWsColPercentAria: string;
|
|
94
|
+
metricHelpWsColPercentBody: string;
|
|
95
|
+
metricHelpAggLocColLangAria: string;
|
|
96
|
+
metricHelpAggLocColLangBody: string;
|
|
97
|
+
metricHelpAggLocColLinesAria: string;
|
|
98
|
+
metricHelpAggLocColLinesBody: string;
|
|
99
|
+
metricHelpAggSigColLangAria: string;
|
|
100
|
+
metricHelpAggSigColLangBody: string;
|
|
101
|
+
metricHelpAggSigColCountAria: string;
|
|
102
|
+
metricHelpAggSigColCountBody: string;
|
|
103
|
+
metricHelpLegendDoneAria: string;
|
|
104
|
+
metricHelpLegendDoneBody: string;
|
|
105
|
+
metricHelpLegendActiveAria: string;
|
|
106
|
+
metricHelpLegendActiveBody: string;
|
|
107
|
+
metricHelpLegendSessionsAria: string;
|
|
108
|
+
metricHelpLegendSessionsBody: string;
|
|
109
|
+
metricHelpAssiduityRefAria: string;
|
|
110
|
+
metricHelpAssiduityRefBody: string;
|
|
111
|
+
metricHelpAssiduityLateCountAria: string;
|
|
112
|
+
metricHelpAssiduityLateCountBody: string;
|
|
113
|
+
metricHelpAssiduityLateTotalAria: string;
|
|
114
|
+
metricHelpAssiduityLateTotalBody: string;
|
|
115
|
+
metricHelpAssiduityAvgLateAria: string;
|
|
116
|
+
metricHelpAssiduityAvgLateBody: string;
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
export const reportingMetricHelpEn: ReportingMetricHelpBlock = {
|
|
120
|
+
metricHelpSessionsAria: "Help: sessions in range",
|
|
121
|
+
metricHelpSessionsBody:
|
|
122
|
+
"Count of sessions whose calendar day (savedAt, or endAt, or startAt) falls inside the selected range. If you use tag filters, a session is included only when at least one of its tasks matches the tags.",
|
|
123
|
+
metricHelpTaskRowsAria: "Help: task rows in range",
|
|
124
|
+
metricHelpTaskRowsBody:
|
|
125
|
+
"Number of task records counted toward aggregates: task day (end or start) must fall in the range, and the task must pass the tag filter. Archived-session rules apply (unfinished tasks may be excluded).",
|
|
126
|
+
metricHelpKronoFocusCompletedAria: "Help: KronoFocus sessions completed",
|
|
127
|
+
metricHelpKronoFocusCompletedBody:
|
|
128
|
+
"Sum of the session-level “sessions completed” counter stored on each session snapshot, for sessions whose day is in the range. This is not per-task; it reflects the KronoFocus state saved with the session.",
|
|
129
|
+
metricHelpKronoFocusTasksUsedAria: "Help: tasks with KronoFocus used",
|
|
130
|
+
metricHelpKronoFocusTasksUsedBody:
|
|
131
|
+
"How many tasks in the range have usedKronoFocus set, after tag and archived-session filters.",
|
|
132
|
+
metricHelpKronoFocusCyclesAria: "Help: KronoFocus cycles (tasks)",
|
|
133
|
+
metricHelpKronoFocusCyclesBody:
|
|
134
|
+
"Sum of kronoFocusCycles over tasks included in the range (same filters as other task metrics).",
|
|
135
|
+
metricHelpTaskTimeAria: "Help: recorded task time",
|
|
136
|
+
metricHelpTaskTimeBody:
|
|
137
|
+
"Total recorded task duration (from durationMs) for included tasks, shown as hours/minutes. Task day and tag filters apply.",
|
|
138
|
+
metricHelpSessionCodingAria: "Help: session coding time",
|
|
139
|
+
metricHelpSessionCodingBody:
|
|
140
|
+
"Sum of coding minutes saved on each session (codingMinutesSession) for sessions whose day is in the range. Independent of task timers.",
|
|
141
|
+
metricHelpSessionActiveAria: "Help: session active time",
|
|
142
|
+
metricHelpSessionActiveBody:
|
|
143
|
+
"Sum of active minutes saved on each session (activeMinutes) for sessions in the range. Based on IDE activity signals, not task time.",
|
|
144
|
+
metricHelpLinesTotalAria: "Help: lines written (sessions in range)",
|
|
145
|
+
metricHelpLinesTotalBody:
|
|
146
|
+
"Sum of linesWrittenTotal from each session snapshot included in the range (net lines from tracked edits, same definition as the dashboard).",
|
|
147
|
+
metricHelpLinesHumanAria: "Help: lines — human (estimated)",
|
|
148
|
+
metricHelpLinesHumanBody:
|
|
149
|
+
"Sum of human-estimated lines (linesWrittenHuman) per session in the range. Split uses a heuristic on each edit, not exact attribution.",
|
|
150
|
+
metricHelpLinesAiAria: "Help: lines — AI (estimated)",
|
|
151
|
+
metricHelpLinesAiBody:
|
|
152
|
+
"Sum of AI-estimated lines (linesWrittenAi) per session in the range. Large or multi-range edits are more likely classified as AI-style.",
|
|
153
|
+
metricHelpLocByLangTitleAria: "Help: lines by language (aggregated)",
|
|
154
|
+
metricHelpLocByLangTitleBody:
|
|
155
|
+
"Merges each session’s locByLanguage tuples for sessions in the range: total net lines attributed to each language id.",
|
|
156
|
+
metricHelpCodingSignalsTitleAria: "Help: coding signals by language (aggregated)",
|
|
157
|
+
metricHelpCodingSignalsTitleBody:
|
|
158
|
+
"Merges codingSignalsByLanguage from included sessions: counts of coding-context events (open, save, edit, active editor, etc.) per language.",
|
|
159
|
+
metricHelpChartSessionsAria: "Help: sessions per day",
|
|
160
|
+
metricHelpChartSessionsBody:
|
|
161
|
+
"For each calendar day in the chart, how many sessions had their session day in that bucket. Range and tag rules match the summary cards.",
|
|
162
|
+
metricHelpChartTasksAria: "Help: tasks per day by status",
|
|
163
|
+
metricHelpChartTasksBody:
|
|
164
|
+
"Per day: green = tasks marked done in the range; amber = tasks still in progress. Task day and filters apply; archived sessions use stricter completion rules.",
|
|
165
|
+
metricHelpChartTaskTimeAria: "Help: recorded task time per day",
|
|
166
|
+
metricHelpChartTaskTimeBody:
|
|
167
|
+
"For each day, sum of recorded task durations (durationMs → minutes) for tasks whose task day falls in that bucket. Same tag and archived-session rules as task counts. Bar height scales to the largest day in view.",
|
|
168
|
+
metricHelpChartSessionWallAria: "Help: session wall-clock time per day",
|
|
169
|
+
metricHelpChartSessionWallBody:
|
|
170
|
+
"Per calendar day, sum of session wall-clock minutes: saved sessionDurationMinutes when present, otherwise time span from startAt to endAt. Bucketed by session day (same as the session count). Not the same as coding time (pauses when idle).",
|
|
171
|
+
metricHelpTblDayAria: "Help: table column — day",
|
|
172
|
+
metricHelpTblDayBody: "Calendar day key (local date) or “undated” when no date could be derived.",
|
|
173
|
+
metricHelpTblSessionsAria: "Help: table column — sessions",
|
|
174
|
+
metricHelpTblSessionsBody: "Number of sessions attributed to that day (same rules as the sessions chart).",
|
|
175
|
+
metricHelpTblDoneAria: "Help: table column — done",
|
|
176
|
+
metricHelpTblDoneBody: "Count of completed tasks attributed to that day.",
|
|
177
|
+
metricHelpTblActiveAria: "Help: table column — active",
|
|
178
|
+
metricHelpTblActiveBody: "Count of in-progress tasks attributed to that day.",
|
|
179
|
+
metricHelpTblTaskTimeAria: "Help: table column — recorded task time",
|
|
180
|
+
metricHelpTblTaskTimeBody:
|
|
181
|
+
"Sum of durationMs (as minutes) for tasks attributed to that calendar day — the same basis as “Recorded task time” in the summary and as Jira-style worklog totals per day.",
|
|
182
|
+
metricHelpTblSessionCodingAria: "Help: table column — session coding time",
|
|
183
|
+
metricHelpTblSessionCodingBody:
|
|
184
|
+
"Sum of codingMinutesSession for sessions whose session day is that row. Uses session day (not task day), matching the session count column.",
|
|
185
|
+
metricHelpTblSessionWallAria: "Help: table column — session wall-clock",
|
|
186
|
+
metricHelpTblSessionWallBody:
|
|
187
|
+
"Total wall-clock minutes for sessions on that session day: persisted session duration or startAt→endAt. Compare with “Session coding” (active coding only).",
|
|
188
|
+
metricHelpSessionWallSummaryAria: "Help: session wall-clock (summary)",
|
|
189
|
+
metricHelpSessionWallSummaryBody:
|
|
190
|
+
"Sum of wall-clock minutes for every session included in the range (session day and tag rules). Independent of task timers; complements coding/active minutes.",
|
|
191
|
+
metricHelpTagTimeSectionAria: "Help: time by tag (SAP / WBS style)",
|
|
192
|
+
metricHelpTagTimeSectionBody:
|
|
193
|
+
"Recorded task time (durationMs) attributed to each task’s #tags. The full duration is counted for every tag on the task (summing tag rows can exceed the KPI total when tasks carry multiple tags). Tasks without explicit tags roll into the default bucket (shown as “default” in English). Same date, tag filter, and archived-session rules as other task metrics.",
|
|
194
|
+
metricHelpTagTimeDayTableAria: "Help: tag time by day table",
|
|
195
|
+
metricHelpTagTimeDayTableBody:
|
|
196
|
+
"One row per tag and task calendar day with the summed minutes for that bucket. Rows are grouped by calendar day; several `project#code` tags for the same project on the same day appear under one @project summary row—expand to see each tag line.",
|
|
197
|
+
metricHelpTagTimeWeekTableAria: "Help: weekly tag calendar",
|
|
198
|
+
metricHelpTagTimeWeekTableBody:
|
|
199
|
+
"Seven day cells plus a week total: recorded task minutes per calendar day within each row’s week, in column order from the chosen week start (Monday, Sunday, or Saturday). The date quick filter “Week” still uses Monday–Sunday; only this grid follows your week-start preference.",
|
|
200
|
+
metricHelpTagWeekCalendarAria: "Help: weekly calendar columns",
|
|
201
|
+
metricHelpTagWeekCalendarBody:
|
|
202
|
+
"For each calendar week, the period is shown once above a single table: one row per tag, columns are the seven local days (from your week-start setting) plus a week total. Each column header shows the weekday and the real calendar date; hover a header or a day cell for the exact date (YYYY-MM-DD). When several tags use the same `project#code` pattern for one project, they are grouped under one @project summary row; use the chevron to expand and see each tag’s row and minutes.",
|
|
203
|
+
metricHelpTagWeekStartsOnAria: "Help: week start preference",
|
|
204
|
+
metricHelpTagWeekStartsOnBody:
|
|
205
|
+
"Chooses which weekday begins the 7-day strip: Monday (ISO-style), Sunday (US-style), or Saturday. Saved in this browser only (localStorage).",
|
|
206
|
+
metricHelpWeekNavAria: "Help: week navigation",
|
|
207
|
+
metricHelpWeekNavBody:
|
|
208
|
+
"Previous / next move one week at a time through weeks that have session wall-clock time or at least one session in the filtered range. If none qualify, weeks come from recorded task time by tag or by @project. All bar charts, the day-by-day table, and both weekly calendars (tags and projects) show only the selected week (seven local days from your week-start setting).",
|
|
209
|
+
metricHelpTagTimeColTagAria: "Help: tag column",
|
|
210
|
+
metricHelpTagTimeColTagBody: "Kronosys #tag; use as a label for your external posting key (e.g. WBS).",
|
|
211
|
+
metricHelpTagTimeColDayAria: "Help: day column",
|
|
212
|
+
metricHelpTagTimeColDayBody: "Task day (end or start timestamp), YYYY-MM-DD.",
|
|
213
|
+
metricHelpTagTimeColWeekAria: "Help: week period line",
|
|
214
|
+
metricHelpTagTimeColWeekBody:
|
|
215
|
+
"This line names the calendar week once for the table below (local dates). The week boundary matches your “week starts on” setting.",
|
|
216
|
+
metricHelpTagTimeColMinutesAria: "Help: minutes column",
|
|
217
|
+
metricHelpTagTimeColMinutesBody:
|
|
218
|
+
"Sum of attributed task minutes for that tag and period. Minutes are not split across tags: a multi-tag task contributes its full duration to each tag row.",
|
|
219
|
+
metricHelpProjectTitleAria: "Help: recorded time by project",
|
|
220
|
+
metricHelpProjectTitleBody:
|
|
221
|
+
"Recorded task duration (durationMs) split by each task’s @project, shown as a weekly calendar: one period line per week, then one table with a row per project and seven day columns plus a week total. Same date range, tag filter, archived-session rules, and week navigation as the tag calendar.",
|
|
222
|
+
metricHelpProjectCalendarAria: "Help: project weekly calendar",
|
|
223
|
+
metricHelpProjectCalendarBody:
|
|
224
|
+
"Same layout as the tag calendar: for each week, the date span appears once; each row is one @project. Column headers show weekday and calendar date; day cells use task day (end or start); hover a header or cell for YYYY-MM-DD.",
|
|
225
|
+
metricHelpProjectColProjAria: "Help: project column",
|
|
226
|
+
metricHelpProjectColProjBody: "Project name from the task, or “no project” when none is set.",
|
|
227
|
+
metricHelpProjectColTasksAria: "Help: tasks column",
|
|
228
|
+
metricHelpProjectColTasksBody: "Number of task rows summed into that project row.",
|
|
229
|
+
metricHelpProjectColTimeAria: "Help: recorded time column",
|
|
230
|
+
metricHelpProjectColTimeBody:
|
|
231
|
+
"Total recorded task minutes for that @project over the seven days of the row (from durationMs).",
|
|
232
|
+
metricHelpWorkspaceTitleAria: "Help: open folder snapshot",
|
|
233
|
+
metricHelpWorkspaceTitleBody:
|
|
234
|
+
"Snapshot of the first workspace folder: line counts by language from Git-tracked files or a folder walk. Not tied to Kronosys sessions; cached ~5 minutes. See the paragraph below for details.",
|
|
235
|
+
metricHelpWsTotalLinesAria: "Help: total lines (approx.)",
|
|
236
|
+
metricHelpWsTotalLinesBody:
|
|
237
|
+
"Approximate total lines read from source files (known extensions), summed for the snapshot.",
|
|
238
|
+
metricHelpWsFileCountAria: "Help: files scanned",
|
|
239
|
+
metricHelpWsFileCountBody: "Number of files that contributed to the snapshot (after size and type filters).",
|
|
240
|
+
metricHelpWsColLangAria: "Help: language column",
|
|
241
|
+
metricHelpWsColLangBody: "Language id (TextMate-style) inferred from the file extension.",
|
|
242
|
+
metricHelpWsColLinesAria: "Help: lines column",
|
|
243
|
+
metricHelpWsColLinesBody: "Line count for that language in the scanned files.",
|
|
244
|
+
metricHelpWsColPercentAria: "Help: share column",
|
|
245
|
+
metricHelpWsColPercentBody: "Percentage of total lines in the snapshot for that language (may not add to exactly 100% after rounding).",
|
|
246
|
+
metricHelpAggLocColLangAria: "Help: language (aggregated lines)",
|
|
247
|
+
metricHelpAggLocColLangBody: "Language id (TextMate-style); values are summed across sessions in the range.",
|
|
248
|
+
metricHelpAggLocColLinesAria: "Help: lines (aggregated)",
|
|
249
|
+
metricHelpAggLocColLinesBody: "Total net lines written in that language for included sessions.",
|
|
250
|
+
metricHelpAggSigColLangAria: "Help: language (signals)",
|
|
251
|
+
metricHelpAggSigColLangBody: "Language id for aggregated coding-signal counts.",
|
|
252
|
+
metricHelpAggSigColCountAria: "Help: signals count",
|
|
253
|
+
metricHelpAggSigColCountBody: "Total coding-context signals for that language across included sessions.",
|
|
254
|
+
metricHelpLegendDoneAria: "Help: legend — done tasks",
|
|
255
|
+
metricHelpLegendDoneBody: "Green segment: tasks with isDone in that day’s bucket (same filters as the chart).",
|
|
256
|
+
metricHelpLegendActiveAria: "Help: legend — in progress",
|
|
257
|
+
metricHelpLegendActiveBody: "Amber segment: tasks not done in that day’s bucket.",
|
|
258
|
+
metricHelpLegendSessionsAria: "Help: legend — sessions",
|
|
259
|
+
metricHelpLegendSessionsBody: "Each bar’s height is the number of sessions whose session day matches that column (same range and tag rules).",
|
|
260
|
+
metricHelpAssiduityRefAria: "Help: sessions with a scheduled start reference",
|
|
261
|
+
metricHelpAssiduityRefBody:
|
|
262
|
+
"Sessions in the range whose host recorded a planned start instant when the session was opened (optional `scheduledStartAt` on `newSession`). The dashboard action alone does not set this: the value comes from the integration that starts sessions from your work schedule. Same session-day and tag rules as the session count above.",
|
|
263
|
+
metricHelpAssiduityLateCountAria: "Help: late sessions (punctuality)",
|
|
264
|
+
metricHelpAssiduityLateCountBody:
|
|
265
|
+
"Of those with a reference time, how many started after the planned instant (strictly positive offset in minutes). Early or on-time starts are not counted here.",
|
|
266
|
+
metricHelpAssiduityLateTotalAria: "Help: cumulative late time",
|
|
267
|
+
metricHelpAssiduityLateTotalBody:
|
|
268
|
+
"Sum of positive per-session delays (minutes) in the range — the total time “behind” the planned start across late sessions. On-time and early starts contribute 0.",
|
|
269
|
+
metricHelpAssiduityAvgLateAria: "Help: average late when late",
|
|
270
|
+
metricHelpAssiduityAvgLateBody:
|
|
271
|
+
"Cumulative late minutes divided by the number of late sessions (unchanged if there are zero late sessions, shown as —). A simple punctuality read when a reference time was stored.",
|
|
272
|
+
};
|
|
273
|
+
|
|
274
|
+
export const reportingMetricHelpFr: ReportingMetricHelpBlock = {
|
|
275
|
+
metricHelpSessionsAria: "Aide : sessions dans la plage",
|
|
276
|
+
metricHelpSessionsBody:
|
|
277
|
+
"Nombre de sessions dont le jour calendaire (savedAt, ou endAt, ou startAt) tombe dans la plage choisie. Avec un filtre d’étiquettes, une session n’est comptée que si au moins une de ses tâches correspond.",
|
|
278
|
+
metricHelpTaskRowsAria: "Aide : lignes de tâches dans la plage",
|
|
279
|
+
metricHelpTaskRowsBody:
|
|
280
|
+
"Nombre d’enregistrements de tâches pris en compte : le jour de la tâche (fin ou début) doit être dans la plage et la tâche doit passer le filtre d’étiquettes. Les règles des sessions archivées s’appliquent (tâches non terminées parfois exclues).",
|
|
281
|
+
metricHelpKronoFocusCompletedAria: "Aide : sessions KronoFocus terminées",
|
|
282
|
+
metricHelpKronoFocusCompletedBody:
|
|
283
|
+
"Somme du compteur « sessions terminées » au niveau session enregistré sur chaque instantané, pour les sessions dont le jour est dans la plage. Ce n’est pas par tâche ; c’est l’état KronoFocus sauvegardé avec la session.",
|
|
284
|
+
metricHelpKronoFocusTasksUsedAria: "Aide : tâches avec KronoFocus utilisé",
|
|
285
|
+
metricHelpKronoFocusTasksUsedBody:
|
|
286
|
+
"Nombre de tâches dans la plage avec usedKronoFocus, après filtres d’étiquettes et règles d’archivage.",
|
|
287
|
+
metricHelpKronoFocusCyclesAria: "Aide : cycles KronoFocus (tâches)",
|
|
288
|
+
metricHelpKronoFocusCyclesBody:
|
|
289
|
+
"Somme des kronoFocusCycles sur les tâches incluses dans la plage (mêmes filtres que les autres métriques tâche).",
|
|
290
|
+
metricHelpTaskTimeAria: "Aide : temps enregistré sur les tâches",
|
|
291
|
+
metricHelpTaskTimeBody:
|
|
292
|
+
"Durée totale enregistrée (durationMs) des tâches incluses, affichée en heures/minutes. Filtres de jour et d’étiquettes appliqués.",
|
|
293
|
+
metricHelpSessionCodingAria: "Aide : temps de codage (sessions)",
|
|
294
|
+
metricHelpSessionCodingBody:
|
|
295
|
+
"Somme des minutes de codage sauvegardées par session (codingMinutesSession) pour les sessions dont le jour est dans la plage. Indépendant des minuteurs de tâche.",
|
|
296
|
+
metricHelpSessionActiveAria: "Aide : temps actif (sessions)",
|
|
297
|
+
metricHelpSessionActiveBody:
|
|
298
|
+
"Somme des minutes actives sauvegardées par session (activeMinutes) pour les sessions dans la plage. Basé sur les signaux d’activité de l’IDE, pas sur le temps tâche.",
|
|
299
|
+
metricHelpLinesTotalAria: "Aide : lignes écrites (sessions dans la plage)",
|
|
300
|
+
metricHelpLinesTotalBody:
|
|
301
|
+
"Somme des linesWrittenTotal de chaque session incluse dans la plage (lignes nettes des modifications suivies, même définition que le tableau de bord).",
|
|
302
|
+
metricHelpLinesHumanAria: "Aide : lignes — humain (estim.)",
|
|
303
|
+
metricHelpLinesHumanBody:
|
|
304
|
+
"Somme des lignes estimées « humain » (linesWrittenHuman) par session dans la plage. La répartition repose sur une heuristique par modification, pas sur une attribution exacte.",
|
|
305
|
+
metricHelpLinesAiAria: "Aide : lignes — IA (estim.)",
|
|
306
|
+
metricHelpLinesAiBody:
|
|
307
|
+
"Somme des lignes estimées « IA » (linesWrittenAi) par session dans la plage. Les gros blocs ou les modifications multi-plages sont plus souvent classés côté IA.",
|
|
308
|
+
metricHelpLocByLangTitleAria: "Aide : lignes par langage (agrégé)",
|
|
309
|
+
metricHelpLocByLangTitleBody:
|
|
310
|
+
"Fusion des couples locByLanguage de chaque session dans la plage : total de lignes nettes par identifiant de langage.",
|
|
311
|
+
metricHelpCodingSignalsTitleAria: "Aide : signaux de codage par langage (agrégé)",
|
|
312
|
+
metricHelpCodingSignalsTitleBody:
|
|
313
|
+
"Fusion des codingSignalsByLanguage des sessions incluses : nombre d’événements de contexte de codage (ouverture, enregistrement, édition, éditeur actif, etc.) par langage.",
|
|
314
|
+
metricHelpChartSessionsAria: "Aide : sessions par jour",
|
|
315
|
+
metricHelpChartSessionsBody:
|
|
316
|
+
"Pour chaque jour du graphique, combien de sessions ont leur jour de session dans ce compartiment. Mêmes règles de plage et d’étiquettes que les cartes récapitulatives.",
|
|
317
|
+
metricHelpChartTasksAria: "Aide : tâches par jour et par statut",
|
|
318
|
+
metricHelpChartTasksBody:
|
|
319
|
+
"Par jour : vert = tâches terminées dans la plage ; ambre = tâches encore en cours. Filtres de jour et d’étiquettes ; les sessions archivées ont des règles de complétion plus strictes.",
|
|
320
|
+
metricHelpChartTaskTimeAria: "Aide : temps enregistré sur les tâches par jour",
|
|
321
|
+
metricHelpChartTaskTimeBody:
|
|
322
|
+
"Pour chaque jour, somme des durées enregistrées sur les tâches (durationMs → minutes) dont le jour de tâche tombe dans ce compartiment. Mêmes règles d’étiquettes et d’archivage que les décomptes de tâches. La hauteur des barres est proportionnelle au jour le plus chargé dans la vue.",
|
|
323
|
+
metricHelpChartSessionWallAria: "Aide : durée murale des sessions par jour",
|
|
324
|
+
metricHelpChartSessionWallBody:
|
|
325
|
+
"Par jour calendaire, somme des minutes « murales » de session : sessionDurationMinutes enregistré si présent, sinon écart entre startAt et endAt. Rattachement au jour de session (comme le décompte des sessions). Diffère du temps de codage (les pauses inactivité ne comptent pas comme codage).",
|
|
326
|
+
metricHelpTblDayAria: "Aide : colonne jour",
|
|
327
|
+
metricHelpTblDayBody: "Clé de jour calendaire (date locale) ou « sans date » si aucune date n’a pu être dérivée.",
|
|
328
|
+
metricHelpTblSessionsAria: "Aide : colonne sessions",
|
|
329
|
+
metricHelpTblSessionsBody: "Nombre de sessions rattachées à ce jour (mêmes règles que le graphique des sessions).",
|
|
330
|
+
metricHelpTblDoneAria: "Aide : colonne terminées",
|
|
331
|
+
metricHelpTblDoneBody: "Nombre de tâches terminées rattachées à ce jour.",
|
|
332
|
+
metricHelpTblActiveAria: "Aide : colonne en cours",
|
|
333
|
+
metricHelpTblActiveBody: "Nombre de tâches encore en cours rattachées à ce jour.",
|
|
334
|
+
metricHelpTblTaskTimeAria: "Aide : colonne — temps enregistré (tâches)",
|
|
335
|
+
metricHelpTblTaskTimeBody:
|
|
336
|
+
"Somme des durationMs (en minutes) pour les tâches rattachées à ce jour calendaire — même base que « Temps enregistré sur les tâches » dans la synthèse et qu’un total type feuille de temps / Jira par jour.",
|
|
337
|
+
metricHelpTblSessionCodingAria: "Aide : colonne — temps de codage (sessions)",
|
|
338
|
+
metricHelpTblSessionCodingBody:
|
|
339
|
+
"Somme des codingMinutesSession pour les sessions dont le jour de session correspond à cette ligne. Repose sur le jour de session (pas le jour de tâche), comme la colonne « Sessions ».",
|
|
340
|
+
metricHelpTblSessionWallAria: "Aide : colonne — durée murale (sessions)",
|
|
341
|
+
metricHelpTblSessionWallBody:
|
|
342
|
+
"Total des minutes « murales » pour les sessions de ce jour de session : durée persistée ou startAt→endAt. À comparer au « Codage (sessions) » (temps de frappe actif seulement).",
|
|
343
|
+
metricHelpSessionWallSummaryAria: "Aide : durée murale des sessions (synthèse)",
|
|
344
|
+
metricHelpSessionWallSummaryBody:
|
|
345
|
+
"Somme des minutes murales pour chaque session incluse dans la plage (règles de jour de session et d’étiquettes). Indépendant des minuteurs de tâche ; complète les temps de codage et d’activité.",
|
|
346
|
+
metricHelpTagTimeSectionAria: "Aide : temps par étiquette (type WBS / SAP)",
|
|
347
|
+
metricHelpTagTimeSectionBody:
|
|
348
|
+
"Temps enregistré sur les tâches (durationMs) rattaché à chaque #tag. La durée complète est comptée pour chaque étiquette de la tâche (en additionnant les lignes par étiquette, le total peut dépasser celui des indicateurs lorsque des tâches portent plusieurs étiquettes). Les tâches sans étiquette explicite sont regroupées dans le compartiment par défaut (affiché « défaut » en français). Mêmes filtres de dates, d’étiquettes et règles d’archivage que les autres métriques tâche.",
|
|
349
|
+
metricHelpTagTimeDayTableAria: "Aide : tableau temps par étiquette et par jour",
|
|
350
|
+
metricHelpTagTimeDayTableBody:
|
|
351
|
+
"Une ligne par étiquette et par jour de tâche, avec la somme des minutes pour ce couple. Les lignes sont regroupées par jour calendaire ; plusieurs étiquettes `projet#code` pour un même projet le même jour sont sous une ligne de synthèse @projet — développez pour voir chaque étiquette.",
|
|
352
|
+
metricHelpTagTimeWeekTableAria: "Aide : calendrier hebdomadaire par étiquette",
|
|
353
|
+
metricHelpTagTimeWeekTableBody:
|
|
354
|
+
"Sept cases pour les jours de la semaine plus une colonne total : minutes enregistrées sur les tâches pour chaque date, dans l’ordre imposé par le premier jour de semaine choisi (lundi, dimanche ou samedi). La période rapide « Semaine » des filtres reste lundi–dimanche ; seule cette grille suit votre réglage.",
|
|
355
|
+
metricHelpTagWeekCalendarAria: "Aide : colonnes du calendrier hebdomadaire",
|
|
356
|
+
metricHelpTagWeekCalendarBody:
|
|
357
|
+
"Pour chaque semaine calendaire, la période s’affiche une seule fois au-dessus d’un tableau unique : une ligne par étiquette, les colonnes sont les sept jours locaux (selon le premier jour de semaine) plus le total de la semaine. Chaque en-tête de colonne indique le jour de la semaine et la date calendaire réelle ; survolez un en-tête ou une case jour pour la date exacte (AAAA-MM-JJ). Lorsque plusieurs étiquettes suivent le motif `projet#code` pour un même projet, elles sont regroupées sous une ligne de synthèse @projet ; le chevron permet de développer le détail par étiquette et par minutes.",
|
|
358
|
+
metricHelpTagWeekStartsOnAria: "Aide : premier jour de la semaine",
|
|
359
|
+
metricHelpTagWeekStartsOnBody:
|
|
360
|
+
"Détermine quel jour commence la bande des 7 jours : lundi (habitude ISO), dimanche (habitude nord-américaine) ou samedi. Mémorisé uniquement dans ce navigateur (localStorage).",
|
|
361
|
+
metricHelpWeekNavAria: "Aide : navigation par semaine",
|
|
362
|
+
metricHelpWeekNavBody:
|
|
363
|
+
"Précédente / suivante fait défiler une semaine à la fois parmi les semaines qui ont une durée murale de session ou au moins une session dans la plage filtrée. Sinon, les semaines proviennent du temps enregistré par étiquette ou par @projet. Les graphiques en barres, le tableau par jour et les deux calendriers hebdomadaires (étiquettes et projets) ne montrent que la semaine sélectionnée (sept jours locaux selon le premier jour de semaine).",
|
|
364
|
+
metricHelpTagTimeColTagAria: "Aide : colonne étiquette",
|
|
365
|
+
metricHelpTagTimeColTagBody: "Étiquette Kronosys (#tag) ; peut servir de libellé pour la clé saisie à l’extérieur (ex. élément WBS).",
|
|
366
|
+
metricHelpTagTimeColDayAria: "Aide : colonne jour",
|
|
367
|
+
metricHelpTagTimeColDayBody: "Jour de la tâche (horodatage de fin ou de début), AAAA-MM-JJ.",
|
|
368
|
+
metricHelpTagTimeColWeekAria: "Aide : ligne de période",
|
|
369
|
+
metricHelpTagTimeColWeekBody:
|
|
370
|
+
"Cette ligne nomme la semaine calendaire une seule fois pour le tableau ci-dessous (dates locales). La frontière de semaine suit le réglage « La semaine commence ».",
|
|
371
|
+
metricHelpTagTimeColMinutesAria: "Aide : colonne minutes",
|
|
372
|
+
metricHelpTagTimeColMinutesBody:
|
|
373
|
+
"Somme des minutes de tâche attribuées à cette étiquette sur la période de la ligne. Les minutes ne sont pas réparties entre les étiquettes : une tâche multi-étiquettes compte sa durée entière sur chaque ligne d’étiquette.",
|
|
374
|
+
metricHelpProjectTitleAria: "Aide : temps enregistré par projet",
|
|
375
|
+
metricHelpProjectTitleBody:
|
|
376
|
+
"Durée enregistrée sur les tâches (durationMs) ventilée par @projet, sous forme de calendrier hebdomadaire : une ligne de période par semaine, puis un tableau avec une ligne par projet et sept colonnes jour plus le total de la semaine. Mêmes plage de dates, filtre d’étiquettes, règles d’archivage et navigation par semaine que le calendrier par étiquette.",
|
|
377
|
+
metricHelpProjectCalendarAria: "Aide : calendrier hebdomadaire par projet",
|
|
378
|
+
metricHelpProjectCalendarBody:
|
|
379
|
+
"Même présentation que le calendrier par étiquette : pour chaque semaine, la plage de dates s’affiche une fois ; chaque ligne correspond à un @projet. Les en-têtes de colonnes indiquent le jour de la semaine et la date calendaire ; les cases jour utilisent le jour de la tâche (fin ou début) ; survol d’un en-tête ou d’une case pour AAAA-MM-JJ.",
|
|
380
|
+
metricHelpProjectColProjAria: "Aide : colonne projet",
|
|
381
|
+
metricHelpProjectColProjBody: "Nom du projet sur la tâche, ou « sans projet » si absent.",
|
|
382
|
+
metricHelpProjectColTasksAria: "Aide : colonne tâches",
|
|
383
|
+
metricHelpProjectColTasksBody: "Nombre de lignes de tâches agrégées pour ce projet.",
|
|
384
|
+
metricHelpProjectColTimeAria: "Aide : colonne temps enregistré",
|
|
385
|
+
metricHelpProjectColTimeBody:
|
|
386
|
+
"Total des minutes enregistrées sur les tâches pour ce @projet sur les sept jours de la ligne (durationMs).",
|
|
387
|
+
metricHelpWorkspaceTitleAria: "Aide : instantané du dossier ouvert",
|
|
388
|
+
metricHelpWorkspaceTitleBody:
|
|
389
|
+
"Instantané du premier dossier du workspace : lignes par langage à partir des fichiers suivis par Git ou d’un parcours du dossier. Indépendant des sessions Kronosys ; mis en cache ~5 minutes. Voir le paragraphe descriptif sous le titre.",
|
|
390
|
+
metricHelpWsTotalLinesAria: "Aide : total de lignes (approx.)",
|
|
391
|
+
metricHelpWsTotalLinesBody:
|
|
392
|
+
"Total approximatif de lignes lues dans les fichiers source (extensions reconnues), pour cet instantané.",
|
|
393
|
+
metricHelpWsFileCountAria: "Aide : fichiers parcourus",
|
|
394
|
+
metricHelpWsFileCountBody: "Nombre de fichiers ayant contribué à l’instantané (après filtres de taille et de type).",
|
|
395
|
+
metricHelpWsColLangAria: "Aide : colonne langage",
|
|
396
|
+
metricHelpWsColLangBody: "Identifiant de langage (style TextMate) déduit de l’extension du fichier.",
|
|
397
|
+
metricHelpWsColLinesAria: "Aide : colonne lignes",
|
|
398
|
+
metricHelpWsColLinesBody: "Nombre de lignes pour ce langage dans les fichiers parcourus.",
|
|
399
|
+
metricHelpWsColPercentAria: "Aide : colonne part",
|
|
400
|
+
metricHelpWsColPercentBody:
|
|
401
|
+
"Pourcentage du total de lignes de l’instantané pour ce langage (la somme des arrondis peut différer légèrement de 100 %).",
|
|
402
|
+
metricHelpAggLocColLangAria: "Aide : langage (lignes agrégées)",
|
|
403
|
+
metricHelpAggLocColLangBody:
|
|
404
|
+
"Identifiant de langage (style TextMate) ; les valeurs sont additionnées sur les sessions dans la plage.",
|
|
405
|
+
metricHelpAggLocColLinesAria: "Aide : lignes (agrégé)",
|
|
406
|
+
metricHelpAggLocColLinesBody: "Total des lignes nettes écrites dans ce langage pour les sessions incluses.",
|
|
407
|
+
metricHelpAggSigColLangAria: "Aide : langage (signaux)",
|
|
408
|
+
metricHelpAggSigColLangBody: "Identifiant de langage pour les comptes de signaux agrégés.",
|
|
409
|
+
metricHelpAggSigColCountAria: "Aide : nombre de signaux",
|
|
410
|
+
metricHelpAggSigColCountBody: "Total de signaux de contexte de codage pour ce langage sur les sessions incluses.",
|
|
411
|
+
metricHelpLegendDoneAria: "Aide : légende — tâches terminées",
|
|
412
|
+
metricHelpLegendDoneBody: "Segment vert : tâches marquées terminées pour ce jour (mêmes filtres que le graphique).",
|
|
413
|
+
metricHelpLegendActiveAria: "Aide : légende — en cours",
|
|
414
|
+
metricHelpLegendActiveBody: "Segment ambre : tâches non terminées pour ce jour.",
|
|
415
|
+
metricHelpLegendSessionsAria: "Aide : légende — sessions",
|
|
416
|
+
metricHelpLegendSessionsBody:
|
|
417
|
+
"Hauteur de chaque barre : nombre de sessions dont le jour de session correspond à cette colonne (mêmes règles de plage et d’étiquettes).",
|
|
418
|
+
metricHelpAssiduityRefAria: "Aide : sessions avec heure de début de référence",
|
|
419
|
+
metricHelpAssiduityRefBody:
|
|
420
|
+
"Sessions de la plage pour lesquelles l’hôte a enregistré un instant de début prévu à l’ouverture (`scheduledStartAt` sur l’action `newSession`). Seul l’enchaînement qui lance la session (p. ex. moteur d’horaire) fournit en général ce champ : une nouvelle session lancée depuis le seul tableau de bord n’y a pas, sauf intégration. Mêmes règles de jour de session et d’étiquettes que le comptage des sessions.",
|
|
421
|
+
metricHelpAssiduityLateCountAria: "Aide : sessions en retard (assiduité)",
|
|
422
|
+
metricHelpAssiduityLateCountBody:
|
|
423
|
+
"Parmi les sessions référencées, combien ont démarré après l’instant prévu (écart strictement positif en minutes). Un démarrage à l’heure ou en avance n’augmente pas ce compteur.",
|
|
424
|
+
metricHelpAssiduityLateTotalAria: "Aide : retard cumulé",
|
|
425
|
+
metricHelpAssiduityLateTotalBody:
|
|
426
|
+
"Somme des retards (minutes) session par session dans la plage, en ne comptant que la partie tardive (les démarrages à l’heure ou avant comptent 0).",
|
|
427
|
+
metricHelpAssiduityAvgLateAria: "Aide : retard moyen (lorsqu’en retard)",
|
|
428
|
+
metricHelpAssiduityAvgLateBody:
|
|
429
|
+
"Retard cumulé divisé par le nombre de sessions en retard ; indiqué en « — » s’il n’y en a pas. Pertinent lorsqu’une heure de début a été enregistrée côté hôte.",
|
|
430
|
+
};
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
|
|
3
|
+
import { computeReportingNonFinalFlags } from "./reportingNonFinalIndicators";
|
|
4
|
+
import type { KronosysUpdatePayload } from "./kronosysApi";
|
|
5
|
+
|
|
6
|
+
// ---------------------------------------------------------------------------
|
|
7
|
+
// Helpers
|
|
8
|
+
// ---------------------------------------------------------------------------
|
|
9
|
+
function makePayload(overrides: Partial<KronosysUpdatePayload> = {}): KronosysUpdatePayload {
|
|
10
|
+
return {
|
|
11
|
+
viewType: "dashboard",
|
|
12
|
+
cfg: {},
|
|
13
|
+
history: [],
|
|
14
|
+
historyArchived: [],
|
|
15
|
+
inspectingSessionId: null,
|
|
16
|
+
knownTags: [],
|
|
17
|
+
knownProjects: [],
|
|
18
|
+
userKnownTags: [],
|
|
19
|
+
excludedSuggestionTags: [],
|
|
20
|
+
tagDescriptions: {},
|
|
21
|
+
projectDescriptions: {},
|
|
22
|
+
gitIdentity: {},
|
|
23
|
+
dashboardDataOrigin: "local_next",
|
|
24
|
+
...overrides,
|
|
25
|
+
} as KronosysUpdatePayload;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const ALL_TAGS = new Set<string>();
|
|
29
|
+
const DATE_FROM = "";
|
|
30
|
+
const DATE_TO = "";
|
|
31
|
+
|
|
32
|
+
// ---------------------------------------------------------------------------
|
|
33
|
+
describe("computeReportingNonFinalFlags", () => {
|
|
34
|
+
it("retourne tout false si payload est null", () => {
|
|
35
|
+
const flags = computeReportingNonFinalFlags(null, ALL_TAGS, DATE_FROM, DATE_TO, undefined, "America/Toronto");
|
|
36
|
+
expect(flags).toEqual({
|
|
37
|
+
sessionsNonFinal: false,
|
|
38
|
+
projectsNonFinal: false,
|
|
39
|
+
tagsNonFinal: false,
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it("sessionsNonFinal=true si session live ouverte (sessionId non vide, non archivée)", () => {
|
|
44
|
+
const p = makePayload({ current: { sessionId: "ses-live" } } as Partial<KronosysUpdatePayload>);
|
|
45
|
+
const flags = computeReportingNonFinalFlags(p, ALL_TAGS, DATE_FROM, DATE_TO, undefined, "America/Toronto");
|
|
46
|
+
expect(flags.sessionsNonFinal).toBe(true);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it("sessionsNonFinal=false si session live est archivée", () => {
|
|
50
|
+
const p = makePayload({ current: { sessionId: "ses-archived", archived: true } } as Partial<KronosysUpdatePayload>);
|
|
51
|
+
const flags = computeReportingNonFinalFlags(p, ALL_TAGS, DATE_FROM, DATE_TO, undefined, "America/Toronto");
|
|
52
|
+
expect(flags.sessionsNonFinal).toBe(false);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it("sessionsNonFinal=true si tasksByDayActive contient des valeurs > 0", () => {
|
|
56
|
+
const p = makePayload();
|
|
57
|
+
const flags = computeReportingNonFinalFlags(
|
|
58
|
+
p, ALL_TAGS, DATE_FROM, DATE_TO, { "2026-04-29": 2 }, "America/Toronto"
|
|
59
|
+
);
|
|
60
|
+
expect(flags.sessionsNonFinal).toBe(true);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it("sessionsNonFinal=false si tasksByDayActive est vide", () => {
|
|
64
|
+
const p = makePayload();
|
|
65
|
+
const flags = computeReportingNonFinalFlags(
|
|
66
|
+
p, ALL_TAGS, DATE_FROM, DATE_TO, { "2026-04-29": 0 }, "America/Toronto"
|
|
67
|
+
);
|
|
68
|
+
expect(flags.sessionsNonFinal).toBe(false);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it("projectsNonFinal=true si tâche non terminée avec @projet dans l'historique", () => {
|
|
72
|
+
const p = makePayload({
|
|
73
|
+
history: [
|
|
74
|
+
{
|
|
75
|
+
sessionId: "ses-1",
|
|
76
|
+
tasks: [
|
|
77
|
+
{
|
|
78
|
+
id: "t1",
|
|
79
|
+
isDone: false,
|
|
80
|
+
project: "acme",
|
|
81
|
+
tags: [],
|
|
82
|
+
startTime: "2026-04-29T10:00:00Z",
|
|
83
|
+
},
|
|
84
|
+
],
|
|
85
|
+
},
|
|
86
|
+
],
|
|
87
|
+
} as Partial<KronosysUpdatePayload>);
|
|
88
|
+
const flags = computeReportingNonFinalFlags(p, ALL_TAGS, DATE_FROM, DATE_TO, undefined, "America/Toronto");
|
|
89
|
+
expect(flags.projectsNonFinal).toBe(true);
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it("tagsNonFinal=true si tâche non terminée avec #tag dans l'historique", () => {
|
|
93
|
+
const p = makePayload({
|
|
94
|
+
history: [
|
|
95
|
+
{
|
|
96
|
+
sessionId: "ses-1",
|
|
97
|
+
tasks: [
|
|
98
|
+
{
|
|
99
|
+
id: "t1",
|
|
100
|
+
isDone: false,
|
|
101
|
+
project: "",
|
|
102
|
+
tags: ["dev"],
|
|
103
|
+
startTime: "2026-04-29T10:00:00Z",
|
|
104
|
+
},
|
|
105
|
+
],
|
|
106
|
+
},
|
|
107
|
+
],
|
|
108
|
+
} as Partial<KronosysUpdatePayload>);
|
|
109
|
+
const flags = computeReportingNonFinalFlags(p, ALL_TAGS, DATE_FROM, DATE_TO, undefined, "America/Toronto");
|
|
110
|
+
expect(flags.tagsNonFinal).toBe(true);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it("projectsNonFinal=false si toutes les tâches sont terminées", () => {
|
|
114
|
+
const p = makePayload({
|
|
115
|
+
history: [
|
|
116
|
+
{
|
|
117
|
+
sessionId: "ses-1",
|
|
118
|
+
tasks: [
|
|
119
|
+
{
|
|
120
|
+
id: "t1",
|
|
121
|
+
isDone: true,
|
|
122
|
+
project: "acme",
|
|
123
|
+
tags: ["dev"],
|
|
124
|
+
startTime: "2026-04-29T10:00:00Z",
|
|
125
|
+
},
|
|
126
|
+
],
|
|
127
|
+
},
|
|
128
|
+
],
|
|
129
|
+
} as Partial<KronosysUpdatePayload>);
|
|
130
|
+
const flags = computeReportingNonFinalFlags(p, ALL_TAGS, DATE_FROM, DATE_TO, undefined, "America/Toronto");
|
|
131
|
+
expect(flags.projectsNonFinal).toBe(false);
|
|
132
|
+
expect(flags.tagsNonFinal).toBe(false);
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
it("hors de la plage de dates → non compté", () => {
|
|
136
|
+
const p = makePayload({
|
|
137
|
+
history: [
|
|
138
|
+
{
|
|
139
|
+
sessionId: "ses-1",
|
|
140
|
+
tasks: [
|
|
141
|
+
{
|
|
142
|
+
id: "t1",
|
|
143
|
+
isDone: false,
|
|
144
|
+
project: "acme",
|
|
145
|
+
tags: ["dev"],
|
|
146
|
+
startTime: "2025-01-01T10:00:00Z",
|
|
147
|
+
},
|
|
148
|
+
],
|
|
149
|
+
},
|
|
150
|
+
],
|
|
151
|
+
} as Partial<KronosysUpdatePayload>);
|
|
152
|
+
const flags = computeReportingNonFinalFlags(
|
|
153
|
+
p, ALL_TAGS, "2026-04-01", "2026-04-30", undefined, "America/Toronto"
|
|
154
|
+
);
|
|
155
|
+
expect(flags.projectsNonFinal).toBe(false);
|
|
156
|
+
});
|
|
157
|
+
});
|