Replace the misleading ErrNotACSVFile with a new ErrCSVConfigRequired
error in the Migrate method. The new error explains that the CSV
migrator requires a column mapping configuration and points to the
correct /migration/csv/detect endpoint.
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).
The CSV handler imported echo/v4 instead of echo/v5 (which the project
uses), used value receiver echo.Context instead of pointer
*echo.Context, and called a non-existent handler.HandleHTTPError
function. Update to match existing handler patterns.
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.
Previously all parseCSV errors were mapped to ErrNotACSVFile, hiding
the actual cause. Now ErrFileIsEmpty is propagated correctly instead
of being misreported as an invalid CSV file.
parseCSV previously ignored the quoteChar parameter (named _). Since
Go's csv.Reader only supports double-quote, we now pre-process the
data to replace alternative quote characters before parsing.
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.