Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,43 @@ Calendar sync with Google and Microsoft (OAuth) or any ICS feed. Time tracking w

## Integrations

### Vikunja Sync

Sync tasks bidirectionally with a [Vikunja](https://vikunja.io/) instance. Changes in TaskNotes push to Vikunja, and changes in Vikunja pull back to TaskNotes.

**Setup:**
1. Go to **Settings → TaskNotes → Integrations**
2. Find the **Vikunja Task Sync** card
3. Enter your **API URL** (e.g., `https://vikunja.example.com/api/v1`)
4. Enter your **API Token** (get it from Vikunja Settings → API Tokens)
5. Enter the **Default List ID** (found in the URL when viewing a project: `/projects/123/list`)
6. Click **Test Connection** to verify
7. Toggle **Enable Vikunja Sync**

**Sync options:**
- **Sync on create/update/complete**: Push changes when tasks are created, modified, or completed
- **Two-way sync**: Pull changes from Vikunja on a configurable interval
- **Sync Now**: Manually trigger a sync from the settings

**Field mapping:**
| TaskNotes | Vikunja |
|-----------|---------|
| title | title |
| status (done/open) | done |
| due | due_date |
| scheduled | start_date |
| priority | priority |
| tags | labels |
| recurrence | repeat_after |
| reminders | reminders |
| projects | parent task (via relations) |
| body content | description (HTML) |

### Other Integrations

TaskNotes has an optional HTTP API. There's a [browser extension](https://github.com/callumalpass/tasknotes-browser-extension) and a [CLI](https://github.com/callumalpass/tasknotes-cli). Webhooks can notify external services on task changes. See [HTTP API docs](./docs/HTTP_API.md) and [Webhooks docs](./docs/webhooks.md).


## Language support

UI: English, German, Spanish, French, Japanese, Russian, Chinese.
Expand Down
68 changes: 62 additions & 6 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -74,12 +74,16 @@
"@fullcalendar/list": "^6.1.17",
"@fullcalendar/multimonth": "^6.1.17",
"@fullcalendar/timegrid": "^6.1.17",
"@types/showdown": "^2.0.6",
"@types/turndown": "^5.0.6",
"chrono-node": "^2.7.5",
"date-fns": "^4.1.0",
"ical.js": "^2.2.1",
"obsidian-daily-notes-interface": "^0.9.4",
"reflect-metadata": "^0.2.2",
"rrule": "^2.8.1",
"showdown": "^2.1.0",
"turndown": "^7.2.2",
"yaml": "^2.3.1"
}
}
28 changes: 26 additions & 2 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ import { MicrosoftCalendarService } from "./services/MicrosoftCalendarService";
import { LicenseService } from "./services/LicenseService";
import { CalendarProviderRegistry } from "./services/CalendarProvider";
import { TaskCalendarSyncService } from "./services/TaskCalendarSyncService";
import { VikunjaService } from "./services/VikunjaService";
import { VikunjaSyncService } from "./services/VikunjaSyncService";

interface TranslatedCommandDefinition {
id: string;
Expand Down Expand Up @@ -218,6 +220,10 @@ export default class TaskNotesPlugin extends Plugin {
// Task-to-Google Calendar sync service
taskCalendarSyncService: TaskCalendarSyncService;

// Vikunja Integration
vikunjaService: VikunjaService;
vikunjaSyncService: VikunjaSyncService;

// Bases filter converter for exporting saved views
basesFilterConverter: import("./services/BasesFilterConverter").BasesFilterConverter;

Expand Down Expand Up @@ -624,6 +630,24 @@ export default class TaskNotesPlugin extends Plugin {
this.googleCalendarService
);

// Initialize Vikunja services
this.vikunjaService = new VikunjaService(this, this.settings.vikunja);
this.vikunjaSyncService = new VikunjaSyncService(this, this.vikunjaService);
this.vikunjaSyncService.initialize();

// Add Vikunja Sync Command
this.addCommand({
id: "vikunja-sync-now",
name: "Vikunja: Sync Now",
callback: async () => {
if (this.vikunjaSyncService) {
new Notice("Vikunja sync started.");
await this.vikunjaSyncService.syncFromVikunja();
new Notice("Vikunja sync completed.");
}
},
});

// Microsoft Calendar
this.microsoftCalendarService.on("data-changed", () => {
// Trigger calendar view refreshes when Microsoft Calendar events change
Expand Down Expand Up @@ -1324,7 +1348,7 @@ export default class TaskNotesPlugin extends Plugin {
const hasNewCalendarSettings = Object.keys(DEFAULT_SETTINGS.calendarViewSettings).some(
(key) =>
!loadedData?.calendarViewSettings?.[
key as keyof typeof DEFAULT_SETTINGS.calendarViewSettings
key as keyof typeof DEFAULT_SETTINGS.calendarViewSettings
]
);
const hasNewCommandMappings = Object.keys(DEFAULT_SETTINGS.commandFileMapping).some(
Expand Down Expand Up @@ -2993,7 +3017,7 @@ export default class TaskNotesPlugin extends Plugin {
current.disableNoteIndexing !== this.previousCacheSettings.disableNoteIndexing ||
current.storeTitleInFilename !== this.previousCacheSettings.storeTitleInFilename ||
JSON.stringify(current.fieldMapping) !==
JSON.stringify(this.previousCacheSettings.fieldMapping)
JSON.stringify(this.previousCacheSettings.fieldMapping)
);
}

Expand Down
Loading