Skip to content

feat: add task tracker view#807

Open
SumNic wants to merge 1 commit intoActivityWatch:masterfrom
SumNic:sumnic/task-tracker
Open

feat: add task tracker view#807
SumNic wants to merge 1 commit intoActivityWatch:masterfrom
SumNic:sumnic/task-tracker

Conversation

@SumNic
Copy link
Copy Markdown

@SumNic SumNic commented Apr 19, 2026

No description provided.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Apr 19, 2026

Greptile Summary

This PR introduces a new Task Tracker view (/task-tracker) with a dedicated API client, nav header entry, and route — allowing users to create tasks, track app usage time, and manage templates. There are two P1 issues that should be addressed before merging:

  • taskTemplates logic bug: the computed property returns templates for every task (t.taskId !== null) instead of filtering to only the currently selected task.
  • Dev proxy misconfiguration: the new /api proxy in vue.config.js routes all API traffic to port 5666, breaking all existing ActivityWatch server calls (port 5600) in development mode.
  • Russian-only UI: all strings are hardcoded in Russian, inconsistent with the English-language rest of the app.

Confidence Score: 3/5

Not 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

Filename Overview
src/views/TaskTracker.vue New task tracker view; has a logic bug in taskTemplates (shows all tasks' templates instead of only the selected task's), all UI strings are hardcoded in Russian, and the async modal submit handler doesn't prevent close on failure.
vue.config.js Adds dev server proxy for /api pointing to port 5666 (task-tracker service), which breaks all existing ActivityWatch API calls (port 5600) in dev mode.
src/util/taskTrackerClient.ts New API client wrapping the task-tracker REST endpoints using relative URLs; clean structure with good error handling.
src/components/Header.vue Adds a "Task Tracker" nav item with tasks icon; the icon import is correctly included in the script block.
src/route.js Registers the /task-tracker route with lazy-loaded TaskTracker component — straightforward and correct.

Sequence Diagram

sequenceDiagram
    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
Loading

Reviews (1): Last reviewed commit: "feat: add task tracker view" | Re-trigger Greptile

Comment thread src/views/TaskTracker.vue
Comment on lines +454 to +456
taskTemplates(): any[] {
return this.templates.filter((t: any) => t.taskId !== null);
},
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 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.

Suggested change
taskTemplates(): any[] {
return this.templates.filter((t: any) => t.taskId !== null);
},
taskTemplates(): any[] {
return this.templates.filter((t: any) => t.taskId === this.selectedTaskId);
},

Comment thread vue.config.js
Comment on lines +61 to +66
proxy: {
'/api': {
target: 'http://127.0.0.1:5666',
changeOrigin: true
},
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 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
    },
},

Comment thread src/views/TaskTracker.vue
Comment on lines +3 to +9
h1.tt-title Трекер времени

// Task & Template Creation
section.tt-section
div.tt-section-header
b-button(@click="showCreateForm = !showCreateForm", variant="primary")
| + Добавить задачу
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 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.

Comment thread src/views/TaskTracker.vue
Comment on lines +615 to +623
async fetchTemplates() {
try {
const taskId = this.selectedTaskId;
const templates = await taskTrackerApi.getTemplates();
this.templates = templates;
} catch (e) {
console.error('Error fetching templates:', e);
}
},
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 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.

Suggested change
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);
}
},

Comment thread src/views/TaskTracker.vue
Comment on lines +649 to +678
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);
}
},
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 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);
  }
},

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant