CatalyzeUpDocs
impact pulse / product

CSV Option Upload

CSV Option Upload for Survey Questions

Overview

When creating MULTIPLE_CHOICE questions with many options (e.g., a list of 195 countries, job titles, languages), manually typing each option is tedious and error-prone. This feature allows survey creators to upload a CSV file to bulk-populate the options list for a question.

Related Specs: WeHappers Migration | Structured Assessments

Use Cases

  1. Country dropdown: WeHappers needs a "What country are you in?" question with 195+ countries
  2. Organization lists: Large NGOs with many partner organizations
  3. Skill inventories: Competency assessments with predefined skill lists
  4. Location lists: Cities, regions, or districts within a country

User Flow

  1. User is in the Survey Builder editing a MULTIPLE_CHOICE question
  2. User clicks "Import from CSV" button (next to the manual "Add Option" button)
  3. File picker opens, accepts .csv and .txt files
  4. File is parsed client-side (no server upload needed)
  5. Options are extracted and displayed in the options list
  6. User can review, reorder, add, or remove individual options before saving
  7. User saves the question normally

CSV Format

Simple format (one column, no header)

Canada
France
Germany
United States

With header (auto-detected and skipped)

Country
Canada
France
Germany
United States

With weights (two columns)

For MULTIPLE_CHOICE questions that use weighted_options scoring, a second column provides the weight:

Option,Weight
Strongly Agree,5
Agree,4
Neutral,3
Disagree,2
Strongly Disagree,1

Parsing Rules

  1. Accept .csv and .txt files
  2. If the file has one column, treat each row as an option label
  3. If the file has two columns, treat column 1 as the label and column 2 as the weight (for option_weights in scoring_config)
  4. Auto-detect and skip header row if it matches common patterns ("Option", "Label", "Name", "Country", "Value")
  5. Trim whitespace from each value
  6. Remove empty rows
  7. Remove duplicate values (case-insensitive comparison, keep first occurrence)
  8. Maximum 500 options per question

Frontend Implementation

Component: CsvOptionImport.tsx

Location: frontend/src/components/CsvOptionImport.tsx

interface CsvOptionImportProps {
  onImport: (options: string[], weights?: Record<string, number>) => void;
}

Behavior:

  • Renders a secondary button "Import from CSV" in the question builder
  • Opens native file picker on click
  • Parses CSV client-side using basic string splitting (no library needed for this simple format)
  • Calls onImport with the parsed options array
  • Shows a toast with count: "Imported 195 options"
  • If duplicates were removed, shows: "Imported 195 options (3 duplicates removed)"

Integration with QuestionBuilder

In the existing QuestionBuilder.tsx, add the import button when question.type === "MULTIPLE_CHOICE":

[Add Option] [Import from CSV]

The imported options replace the current options list (with a confirmation dialog if options already exist).

Backend Changes

None. The CSV parsing happens entirely on the frontend. The backend receives the same options: string[] array it always does when saving a question. The weights (if provided) populate the existing scoring_config.option_weights field.

Validation

  • File size limit: 100KB (prevents accidental large file uploads)
  • Option length limit: 200 characters per option
  • Option count limit: 500 per question
  • Show clear error messages for malformed files

Edge Cases

  1. File with mixed encodings: Parse as UTF-8, show error if parsing fails
  2. Options with commas: Support quoted values ("New York, NY")
  3. Existing options: Prompt "Replace existing options?" or "Append to existing options?"
  4. Empty file: Show error "No options found in file"

Example: Country List

A ready-made CSV file with all countries could be provided as a downloadable template in the Survey Builder UI:

[Import from CSV] [Download country template]

This template file would contain the standard ISO country list (195 countries) for immediate use.