mirror of
https://github.com/go-vikunja/vikunja.git
synced 2026-05-03 10:27:01 +00:00
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.
103 lines
3.5 KiB
Go
103 lines
3.5 KiB
Go
// Vikunja is a to-do list application to facilitate your life.
|
|
// Copyright 2018-present Vikunja and contributors. All rights reserved.
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU Affero General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU Affero General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU Affero General Public License
|
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
package migration
|
|
|
|
import (
|
|
"net/http"
|
|
|
|
"code.vikunja.io/api/pkg/web"
|
|
)
|
|
|
|
// ErrNotAZipFile represents a "ErrNotAZipFile" kind of error.
|
|
type ErrNotAZipFile struct{}
|
|
|
|
func (err *ErrNotAZipFile) Error() string {
|
|
return "The provided file is not a valid zip file"
|
|
}
|
|
|
|
// ErrCodeNotAZipFile holds the unique world-error code of this error
|
|
const ErrCodeNotAZipFile = 14001
|
|
|
|
// HTTPError holds the http error description
|
|
func (err *ErrNotAZipFile) HTTPError() web.HTTPError {
|
|
return web.HTTPError{
|
|
HTTPCode: http.StatusBadRequest,
|
|
Code: ErrCodeNotAZipFile,
|
|
Message: "The provided file is not a valid zip file.",
|
|
}
|
|
}
|
|
|
|
// ErrFileIsEmpty represents a "ErrFileIsEmpty" kind of error.
|
|
type ErrFileIsEmpty struct{}
|
|
|
|
func (err *ErrFileIsEmpty) Error() string {
|
|
return "The provided file does not contain any data"
|
|
}
|
|
|
|
// ErrCodeFileIsEmpty holds the unique world-error code of this error
|
|
const ErrCodeFileIsEmpty = 14002
|
|
|
|
// HTTPError holds the http error description
|
|
func (err *ErrFileIsEmpty) HTTPError() web.HTTPError {
|
|
return web.HTTPError{
|
|
HTTPCode: http.StatusBadRequest,
|
|
Code: ErrCodeFileIsEmpty,
|
|
Message: "The provided file does not contain any data.",
|
|
}
|
|
}
|
|
|
|
// ErrCSVConfigRequired represents an error when the CSV migration endpoint
|
|
// is called without the required configuration. The CSV migrator requires
|
|
// a mapping configuration and must be used via /migration/csv/migrate with
|
|
// a config form field.
|
|
type ErrCSVConfigRequired struct{}
|
|
|
|
func (err *ErrCSVConfigRequired) Error() string {
|
|
return "CSV import requires a configuration with column mappings. Use the /migration/csv/detect endpoint to get suggested mappings, then call /migration/csv/migrate with a config form field."
|
|
}
|
|
|
|
// ErrCodeCSVConfigRequired holds the unique world-error code of this error
|
|
const ErrCodeCSVConfigRequired = 14004
|
|
|
|
// HTTPError holds the http error description
|
|
func (err *ErrCSVConfigRequired) HTTPError() web.HTTPError {
|
|
return web.HTTPError{
|
|
HTTPCode: http.StatusBadRequest,
|
|
Code: ErrCodeCSVConfigRequired,
|
|
Message: "CSV import requires a configuration with column mappings. Use the /migration/csv/detect endpoint to get suggested mappings, then call /migration/csv/migrate with a config form field.",
|
|
}
|
|
}
|
|
|
|
// ErrNotACSVFile represents a "ErrNotACSVFile" kind of error.
|
|
type ErrNotACSVFile struct{}
|
|
|
|
func (err *ErrNotACSVFile) Error() string {
|
|
return "The provided file is not a valid CSV file"
|
|
}
|
|
|
|
// ErrCodeNotACSVFile holds the unique world-error code of this error
|
|
const ErrCodeNotACSVFile = 14003
|
|
|
|
// HTTPError holds the http error description
|
|
func (err *ErrNotACSVFile) HTTPError() web.HTTPError {
|
|
return web.HTTPError{
|
|
HTTPCode: http.StatusBadRequest,
|
|
Code: ErrCodeNotACSVFile,
|
|
Message: "The provided file is not a valid CSV file.",
|
|
}
|
|
}
|