feat(onboarding): "Project archive" PLC format + auto-detect from extension
CI / Check (pull_request) Successful in 5m16s
CI / Detect Changes (pull_request) Has been skipped
CI / Deploy Agent (pull_request) Has been skipped
CI / Deploy Dashboard (pull_request) Has been skipped
CI / Deploy Docs (pull_request) Has been skipped
CI / Deploy MCP (pull_request) Has been skipped

A .projectarchive is neither PLCopen XML nor Structured Text, but the wizard's
format dropdown only offered those two — confusing when uploading a CODESYS
archive (found live during the demo).

- add PlcFormat::ProjectArchive (metadata only; processing is content-driven).
- wizard: add the "Project archive (.projectarchive)" option, and auto-select the
  format from the chosen file's extension (.projectarchive/.project → archive,
  .xml → PLCopen XML, .st/.exp/.scl → Structured Text).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Sharang Parnerkar
2026-07-16 21:56:46 +02:00
co-authored by Claude Opus 4.8
parent 98357cae10
commit ac7d09a77e
2 changed files with 27 additions and 2 deletions
+3
View File
@@ -202,6 +202,9 @@ pub enum PlcFormat {
PlcopenXml,
/// IEC 61131-3 Structured Text source.
StructuredText,
/// A CODESYS project archive (`.projectarchive` — a zip bundling the project
/// plus its referenced libraries and runtime; the source of the control-app SBOM).
ProjectArchive,
}
/// PLC-specific configuration for a [`ArtifactKind::PlcProject`] artifact.
+24 -2
View File
@@ -264,6 +264,15 @@ pub fn OnboardingPage() -> Element {
onchange: move |evt| {
let Some(file) = evt.files().into_iter().next() else { return; };
let name = file.name();
// Auto-detect the PLC format from the file extension.
let lname = name.to_ascii_lowercase();
if lname.ends_with(".projectarchive") || lname.ends_with(".project") {
new_plc_format.set("project_archive".to_string());
} else if lname.ends_with(".xml") || lname.ends_with(".plcopen") {
new_plc_format.set("plcopen_xml".to_string());
} else if lname.ends_with(".st") || lname.ends_with(".exp") || lname.ends_with(".scl") {
new_plc_format.set("structured_text".to_string());
}
spawn(async move {
if let Ok(bytes) = file.read_bytes().await {
new_file.set(Some((name, bytes.to_vec())));
@@ -278,8 +287,21 @@ pub fn OnboardingPage() -> Element {
select {
value: "{new_plc_format}",
oninput: move |e| new_plc_format.set(e.value()),
option { value: "plcopen_xml", "PLCopen XML" }
option { value: "structured_text", "Structured Text" }
option {
value: "plcopen_xml",
selected: new_plc_format() == "plcopen_xml",
"PLCopen XML",
}
option {
value: "structured_text",
selected: new_plc_format() == "structured_text",
"Structured Text",
}
option {
value: "project_archive",
selected: new_plc_format() == "project_archive",
"Project archive (.projectarchive)",
}
}
}
}