| 174 | } |
| 175 | |
| 176 | export class StatsView extends ItemView { |
| 177 | plugin: TaskNotesPlugin; |
| 178 | |
| 179 | // UI elements |
| 180 | private overviewStatsEl: HTMLElement | null = null; |
| 181 | private todayStatsEl: HTMLElement | null = null; |
| 182 | private weekStatsEl: HTMLElement | null = null; |
| 183 | private monthStatsEl: HTMLElement | null = null; |
| 184 | private projectsStatsEl: HTMLElement | null = null; |
| 185 | private filtersEl: HTMLElement | null = null; |
| 186 | |
| 187 | // State |
| 188 | private currentFilters: StatsFilters = createDefaultStatsFilters(); |
| 189 | private drilldownModal: HTMLElement | null = null; |
| 190 | private currentDrilldownData: ProjectDrilldownData | null = null; |
| 191 | private listeners: EventRef[] = []; |
| 192 | |
| 193 | // Performance optimizations |
| 194 | private statsCache = new Map<string, TaskInfo[]>(); |
| 195 | private lastCacheTime = 0; |
| 196 | private readonly CACHE_DURATION = 60000; // 1 minute |
| 197 | private debounceTimeout: number | null = null; |
| 198 | |
| 199 | constructor(leaf: WorkspaceLeaf, plugin: TaskNotesPlugin) { |
| 200 | super(leaf); |
| 201 | this.plugin = plugin; |
| 202 | } |
| 203 | |
| 204 | getViewType(): string { |
| 205 | return STATS_VIEW_TYPE; |
| 206 | } |
| 207 | |
| 208 | getDisplayText(): string { |
| 209 | return this.plugin.i18n.translate("views.stats.title"); |
| 210 | } |
| 211 | |
| 212 | getIcon(): string { |
| 213 | return "bar-chart-4"; |
| 214 | } |
| 215 | |
| 216 | async onOpen() { |
| 217 | await this.plugin.onReady(); |
| 218 | this.currentFilters = this.loadPersistedFilters(); |
| 219 | |
| 220 | // Listen for task updates to refresh the drill-down modal if it's open |
| 221 | const taskUpdateListener = this.plugin.emitter.on( |
| 222 | EVENT_TASK_UPDATED, |
| 223 | async ({ path, originalTask, updatedTask }) => { |
| 224 | if (!path || !updatedTask || !this.drilldownModal || !this.currentDrilldownData) |
| 225 | return; |
| 226 | |
| 227 | // Check if the updated task is part of the current drill-down data |
| 228 | const taskExists = this.currentDrilldownData.tasks.some( |
| 229 | (task) => |
| 230 | task.path === path || (originalTask && task.path === originalTask.path) |
| 231 | ); |
| 232 | |
| 233 | if (taskExists) { |
nothing calls this directly
no test coverage detected