Allow users to skip the first N data rows when importing CSV files.
This is useful when the CSV contains metadata rows before the actual
task data begins. Adds skip_rows to ImportConfig (backend) and a
number input in the parsing options UI (frontend).
Wrap all <select> elements in Bulma's <div class="select"> wrapper
and remove custom scoped select styles. This fixes readability in
dark mode and ensures consistent styling with the rest of the app.
resetToUpload() cleared state but not the file input's value, so
re-selecting the same file after cancel would not trigger a change
event in the browser.
The error Message was only rendered inside the upload step div, so
preview/import failures during the mapping step were invisible to
users. Move it above the step-conditional sections and remove dead
preview-errors template code.
ErrorCount and Errors fields were never populated by PreviewImport,
making the API contract misleading. Remove them from both the Go
struct and the TypeScript interface.
The migration list linked all migrators to the 'migrate.service' route
by name, which loads MigrationHandler.vue. For the CSV migrator this
would result in a 400 error since it requires the multi-step
MigrationCSV.vue flow with config. Now CSV migrators link to
'migrate.csv' instead.
Remove labels from service structs and move them to the component.
The service now exports simple arrays of values, while the component
handles translation through mapping functions.
Add a new CSV migration module that allows users to import tasks from
any CSV file with custom column mapping and parsing options.
Backend changes:
- New CSV migrator module with detection, preview, and import endpoints
- Auto-detection of delimiter, quote character, and date format
- Suggested column mappings based on column name patterns
- Transactional import using InsertFromStructure
Frontend changes:
- New CSV migration UI with two-step flow (upload -> mapping -> import)
- Column mapping selectors for all task attributes
- Live preview showing first 5 tasks with current mapping
- Parsing option controls for delimiter and date format
The CSV migrator creates a parent "Imported from CSV" project with
child projects based on the project column if provided, or a default
"Tasks" project for tasks without a specified project.
When closing a task modal opened from the Gantt view, the date range
query parameters were lost because closeModal() reconstructed the
route with only projectId and viewId. Now preserves query parameters
from the backdrop view.
Replace static initialDateRange snapshot with reactive filters.value
references inside the computed flatPickerConfig. This ensures the
Flatpickr defaultDate always reflects the current user-selected range
instead of the mount-time values.
Ref #2462
With truncateAll wiping all tables, the test user has no projects,
so ShowTasks never renders and tasksLoaded stays false — meaning
ImportHint (which is gated on tasksLoaded) never appears. Seed a
project with default views so the empty-state hint is visible.
Add isFilteredView parameter to shouldShowTaskInListView() that skips
the parent-hiding logic when viewing tasks through a saved filter.
This ensures all filter-matching tasks are shown.
Ref: #2494
Sets position: relative and z-index: 0 on .gantt-chart-container to
create a new stacking context. This ensures z-index values inside the
Gantt chart (e.g. the sticky timeline header) cannot compete with the
Flatpickr popup that renders at the body level.
Ref #2337
Adds min-inline-size: 100% to .gantt-container so the scrollable area
never appears narrower than the card width, even with short date ranges.
Ref #2337
Moves the drag handle inside the color-bubble-wrapper so both elements
share the same positioned container, eliminating the absolute positioning
mismatch that caused the overlap. Fixes#2493.
Verifies that tasks from read-only shared projects have disabled
checkboxes on the overview page, while tasks from owned projects
remain interactive.
Refs #2399
The Overview's ShowTasks component was not passing the canMarkAsDone prop
to SingleTaskInProject, which defaults to true. This caused read-only tasks
to show an interactive checkbox even though the user doesn't have write
permission.
Use the project's maxPermission from the project store to determine if the
user can mark the task as done. Also fix the disabled condition to use OR
logic so the checkbox is disabled when ANY condition applies: archived,
disabled, or when the user lacks write permission.
Fixes#2399
Add a single retry with a 1-second delay in the 401 interceptor's
doRefresh() before giving up on token renewal. This handles transient
failures like brief network blips or server restarts without immediately
logging the user out.
Also log refresh failures via console.warn so the reason is visible
in browser DevTools for easier diagnosis.
Ref: #2391
When window.API_URL lacks a trailing slash, axios resolves relative URLs
by stripping path segments, causing the refresh request to hit a different
path than the cookie's Path attribute. The browser then omits the HttpOnly
refresh cookie, silently breaking token renewal and logging users out
after the short JWT TTL expires.
Extract a getApiBaseUrl() helper that ensures baseURL always ends with
'/' so relative URL resolution preserves the full path, matching the
cookie scope.
Ref: #2391
Truncate buckets, task_buckets, and task_relations before seeding to
prevent leftover data from previous tests causing false positives
(e.g., bucket selector appearing when it shouldn't).
Add comprehensive end-to-end tests for the WebSocket system:
- Protocol tests: auth (valid/invalid token, timeout, double auth),
subscriptions (valid/invalid event, auth required, unsubscribe),
message delivery (notification on team add, doer exclusion,
multi-connection)
- Frontend integration tests: notification badge update, dropdown
rendering, and logout cleanup via browser-level Playwright tests
- Comment notification test: full flow where user B mentions user A
in a task comment and user A receives real-time WebSocket notification
Includes ws test dependency, shared test helper utilities, and
cascade-truncation of notifications when truncating users to prevent
test pollution.