Conversation
Greptile SummaryThis PR introduces a new Task Tracker view (
Confidence Score: 3/5Not safe to merge — two P1 defects (broken task-template filtering, dev proxy overrides all API traffic) and the entire UI is in Russian. The taskTemplates computed bug produces incorrect data for any user with templates across multiple tasks, the proxy change breaks standard dev-mode API calls for all existing features, and the Russian-only UI makes the feature inaccessible to the app's English-speaking user base. src/views/TaskTracker.vue (logic bug + localization) and vue.config.js (proxy misconfiguration) need attention before this is ready to merge. Important Files Changed
Sequence DiagramsequenceDiagram
participant User
participant TaskTracker.vue
participant taskTrackerClient.ts
participant API as /api/0/task-tracker
User->>TaskTracker.vue: created()
TaskTracker.vue->>taskTrackerClient.ts: getTasks()
taskTrackerClient.ts->>API: GET /tasks
API-->>taskTrackerClient.ts: tasks[]
taskTrackerClient.ts-->>TaskTracker.vue: tasks (with active task)
TaskTracker.vue->>taskTrackerClient.ts: getTemplates()
taskTrackerClient.ts->>API: GET /templates
API-->>TaskTracker.vue: templates[]
User->>TaskTracker.vue: selectTask(taskId)
TaskTracker.vue->>taskTrackerClient.ts: deselectTask(prevId)
taskTrackerClient.ts->>API: POST /tasks/{prevId}/deselect
TaskTracker.vue->>taskTrackerClient.ts: selectTask(taskId)
taskTrackerClient.ts->>API: POST /tasks/{taskId}/select
TaskTracker.vue->>taskTrackerClient.ts: syncActivityWatch(taskId)
taskTrackerClient.ts->>API: GET /activity-watch?taskId={taskId}
API-->>TaskTracker.vue: appUsages[]
User->>TaskTracker.vue: onCategoryChange(au, idx)
TaskTracker.vue->>taskTrackerClient.ts: updateAppCategory(taskId, auId, cat)
taskTrackerClient.ts->>API: PUT /tasks/{taskId}/app-usages
API-->>TaskTracker.vue: updated usage
Reviews (1): Last reviewed commit: "feat: add task tracker view" | Re-trigger Greptile |
| taskTemplates(): any[] { | ||
| return this.templates.filter((t: any) => t.taskId !== null); | ||
| }, |
There was a problem hiding this comment.
taskTemplates shows templates for all tasks, not the selected task
The taskTemplates computed property filters where t.taskId !== null, which returns templates linked to any task, not just the currently active one. A user with templates for multiple tasks would see them all merged together in this section.
| taskTemplates(): any[] { | |
| return this.templates.filter((t: any) => t.taskId !== null); | |
| }, | |
| taskTemplates(): any[] { | |
| return this.templates.filter((t: any) => t.taskId === this.selectedTaskId); | |
| }, |
| proxy: { | ||
| '/api': { | ||
| target: 'http://127.0.0.1:5666', | ||
| changeOrigin: true | ||
| }, | ||
| } |
There was a problem hiding this comment.
Dev proxy routes all
/api to port 5666, breaking existing AW server calls
The proxy catch-all /api rule forwards every API request (including /api/0/buckets, /api/0/events, etc.) to port 5666 (the task-tracker service). The standard ActivityWatch server runs on port 5600, so all existing API calls in dev mode will fail. The proxy should either use a more specific prefix (e.g. /api/0/task-tracker) or keep the standard AW server on 5600 for the general /api path and add an additional entry just for the task-tracker prefix.
proxy: {
'/api/0/task-tracker': {
target: 'http://127.0.0.1:5666',
changeOrigin: true
},
'/api': {
target: 'http://127.0.0.1:5600',
changeOrigin: true
},
},| h1.tt-title Трекер времени | ||
|
|
||
| // Task & Template Creation | ||
| section.tt-section | ||
| div.tt-section-header | ||
| b-button(@click="showCreateForm = !showCreateForm", variant="primary") | ||
| | + Добавить задачу |
There was a problem hiding this comment.
All UI strings are hardcoded in Russian
The entire view — title, button labels, placeholders, empty-state messages, modal titles — is in Russian ("Трекер времени", "Добавить задачу", etc.), while the rest of the application is in English. This is inconsistent with the existing UI and will confuse non-Russian-speaking users who navigate to the Task Tracker.
| async fetchTemplates() { | ||
| try { | ||
| const taskId = this.selectedTaskId; | ||
| const templates = await taskTrackerApi.getTemplates(); | ||
| this.templates = templates; | ||
| } catch (e) { | ||
| console.error('Error fetching templates:', e); | ||
| } | ||
| }, |
There was a problem hiding this comment.
Unused variable
taskId in fetchTemplates
taskId is assigned this.selectedTaskId but never used in the function body. It looks like this was meant to be passed to a filtered getTemplates call but was left behind.
| async fetchTemplates() { | |
| try { | |
| const taskId = this.selectedTaskId; | |
| const templates = await taskTrackerApi.getTemplates(); | |
| this.templates = templates; | |
| } catch (e) { | |
| console.error('Error fetching templates:', e); | |
| } | |
| }, | |
| async fetchTemplates() { | |
| try { | |
| const templates = await taskTrackerApi.getTemplates(); | |
| this.templates = templates; | |
| } catch (e) { | |
| console.error('Error fetching templates:', e); | |
| } | |
| }, |
| async handleTemplateSubmit() { | ||
| if (!this.newTemplateName.trim()) return; | ||
| try { | ||
| const taskId = this.newTemplateScope === 'task' ? this.selectedTaskId : null; | ||
| if (this.editTemplateId) { | ||
| const updated = await taskTrackerApi.updateTemplate( | ||
| this.editTemplateId, | ||
| this.newTemplateName.trim(), | ||
| this.newTemplateCategory, | ||
| taskId | ||
| ); | ||
| const idx = this.templates.findIndex((t: any) => t.id === this.editTemplateId); | ||
| if (idx >= 0) Object.assign(this.templates[idx], updated); | ||
| } else { | ||
| const tmpl = await taskTrackerApi.createTemplate( | ||
| this.newTemplateName.trim(), | ||
| this.newTemplateCategory, | ||
| taskId | ||
| ); | ||
| this.templates.unshift(tmpl); | ||
| } | ||
| this.showTemplateModal = false; | ||
| this.editTemplateId = null; | ||
| this.newTemplateName = ''; | ||
| this.newTemplateCategory = 'PRODUCTIVE'; | ||
| this.newTemplateScope = 'general'; | ||
| } catch (e) { | ||
| console.error('Error saving template:', e); | ||
| } | ||
| }, |
There was a problem hiding this comment.
Async
@ok handler doesn't prevent modal close on failure
handleTemplateSubmit is async, but b-modal's @ok event fires and closes the modal before the promise resolves. If the API call throws, the modal has already been dismissed and the error is only surfaced via console.error. Use bvModalEvt.preventDefault() and manually close the modal on success to keep it open when the request fails.
async handleTemplateSubmit(bvModalEvt: any) {
bvModalEvt.preventDefault();
if (!this.newTemplateName.trim()) return;
try {
// ... existing logic ...
this.$nextTick(() => { this.showTemplateModal = false; });
} catch (e) {
console.error('Error saving template:', e);
}
},
No description provided.