Skip to content
Closed
Show file tree
Hide file tree
Changes from 4 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
55 changes: 55 additions & 0 deletions doc/examples/csv/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# CSV Import Examples

This directory contains example CSV files for testing the CSV import functionality in EditDor.

## Files

### `valid.csv`
A valid CSV file with correct data types and Modbus entities. This file should import without warnings.

**Valid Types:**
- `number`
- `string`
- `boolean`

**Valid Modbus Entities:**
- `HoldingRegister`
- `InputRegister`
- `Coil`
- `DiscreteInput`

### `invalid.csv`
A CSV file with intentional validation errors to demonstrate the warning system. When imported, this file will trigger the following warnings:

1. **Row 2, type**: `number123` is invalid (should be `number`, `string`, or `boolean`)
2. **Row 2, modbus:entity**: `holdingregister` is invalid (case-sensitive, should be `HoldingRegister`)
3. **Row 3, modbus:entity**: `InvalidRegister` is not a recognized Modbus entity
4. **Row 4, type**: `invalid_type` is not a valid type
5. **Row 5, modbus:entity**: `coil` is invalid (case-sensitive, should be `Coil`)

## Usage

1. Open EditDor
2. Select "Thing Description" or "Thing Model"
3. Click "Load a CSV File"
4. Select either `valid.csv` or `invalid.csv`
5. Observe the results:
- `valid.csv`: Should load successfully without warnings
- `invalid.csv`: Should display validation warnings but still load the data

## CSV Format

Required columns:
- `name`: Property name (required)
- `type`: Data type (number, string, or boolean)
- `modbus:entity`: Modbus entity type
- `modbus:address`: Modbus address (required)
- `modbus:unitID`: Modbus unit ID
- `modbus:quantity`: Number of registers
- `modbus:zeroBasedAddressing`: Boolean (true/false)
- `modbus:function`: Modbus function code
- `modbus:mostSignificantByte`: Boolean (true/false)
- `modbus:mostSignificantWord`: Boolean (true/false)
- `href`: Property endpoint path

Note: The validation is case-insensitive for Modbus entities, so `coil`, `Coil`, and `COIL` are all treated as equivalent.
Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The README contradicts itself about Modbus entity casing: it lists warnings for holdingregister/coil as “case-sensitive” issues, but later states validation is case-insensitive. Also, the current parser implementation won’t warn on casing differences, so the described warnings won’t occur. Align the documentation with the actual behavior (or update the parser to match the documented behavior).

Copilot uses AI. Check for mistakes.
6 changes: 6 additions & 0 deletions doc/examples/csv/invalid.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
name,type,modbus:entity,modbus:address,modbus:unitID,modbus:quantity,modbus:zeroBasedAddressing,modbus:function,modbus:mostSignificantByte,modbus:mostSignificantWord,href
temp1,number123,holdingregister,40001,1,1,false,03,true,false,/temp
humidity,number,InvalidRegister,40002,1,1,false,04,false,false,/humidity
pressure,invalid_type,HoldingRegister,40003,1,2,true,03,true,true,/pressure
status,string,coil,00001,1,1,false,01,false,false,/status
alarm,boolean,DiscreteInput,10001,1,1,false,02,false,false,/alarm
6 changes: 6 additions & 0 deletions doc/examples/csv/valid.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
name,type,modbus:entity,modbus:address,modbus:unitID,modbus:quantity,modbus:zeroBasedAddressing,modbus:function,modbus:mostSignificantByte,modbus:mostSignificantWord,href
temperature,number,HoldingRegister,40001,1,1,false,03,true,false,/temp
humidity,number,InputRegister,40002,1,1,false,04,false,false,/humidity
pressure,number,HoldingRegister,40003,1,2,true,03,true,true,/pressure
status,boolean,Coil,00001,1,1,false,01,false,false,/status
alarm,boolean,DiscreteInput,10001,1,1,false,02,false,false,/alarm
13 changes: 11 additions & 2 deletions src/components/App/CreateTd.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -85,15 +85,24 @@ const CreateTd: React.FC<CreateTdProps> = ({
throw new Error("CSV file is empty.");
}

const data = parseCsv(csvContent, true);
const { data, warnings } = parseCsv(csvContent, true);

const parsed = mapCsvToProperties(data);
if (!parsed || Object.keys(parsed).length === 0) {
throw new Error("No valid properties found in the CSV file.");
}

setProperties(parsed);
setError({ open: false, message: "" });

// Display warnings if any
if (warnings.length > 0) {
const warningMessage = warnings
.map((w) => `Row ${w.row}, column "${w.column}": ${w.message}`)
.join("\n");
setError({ open: true, message: `Warnings:\n${warningMessage}` });
Comment on lines +101 to +102
Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Warnings are surfaced via ErrorDialog with a newline-delimited string, but DialogTemplate renders description in an <h2> without preserving newlines, so the warning list will collapse into a hard-to-read paragraph and is labeled as an “Error”. Consider rendering warnings as a list (or using white-space: pre-line) and distinguishing warnings from blocking errors.

Suggested change
.join("\n");
setError({ open: true, message: `Warnings:\n${warningMessage}` });
.join("; ");
setError({ open: true, message: `Warnings: ${warningMessage}` });

Copilot uses AI. Check for mistakes.
} else {
setError({ open: false, message: "" });
}
} catch (err) {
setProperties({});
setError({
Expand Down
Loading
Loading