app-manager: convert input back to the renderable format

Change-Id: Ibd426a37f153549bcde8c22117390b6f76771286
diff --git a/core/installer/repoio.go b/core/installer/repoio.go
index 59d614b..1d0bf7f 100644
--- a/core/installer/repoio.go
+++ b/core/installer/repoio.go
@@ -252,6 +252,14 @@
 	Derived Derived        `json:"derived"`
 }
 
+func (a AppConfig) Input(schema Schema) map[string]any {
+	ret, err := derivedToConfig(a.Derived.Values, schema)
+	if err != nil {
+		panic(err) // TODO(gio): handle
+	}
+	return ret
+}
+
 type allocatePortReq struct {
 	Protocol      string `json:"protocol"`
 	SourcePort    int    `json:"sourcePort"`
@@ -491,6 +499,68 @@
 	return ret, nil
 }
 
+func derivedToConfig(derived map[string]any, schema Schema) (map[string]any, error) {
+	ret := make(map[string]any)
+	for k, def := range schema.Fields() {
+		v, ok := derived[k]
+		// TODO(gio): if missing use default value
+		if !ok {
+			continue
+		}
+		switch def.Kind() {
+		case KindBoolean:
+			ret[k] = v
+		case KindString:
+			ret[k] = v
+		case KindInt:
+			ret[k] = v
+		case KindNetwork:
+			vm, ok := v.(map[string]any)
+			if !ok {
+				return nil, fmt.Errorf("expected map")
+			}
+			name, ok := vm["name"]
+			if !ok {
+				return nil, fmt.Errorf("expected network name")
+			}
+			ret[k] = name
+		case KindAuth:
+			vm, ok := v.(map[string]any)
+			if !ok {
+				return nil, fmt.Errorf("expected map")
+			}
+			r, err := derivedToConfig(vm, AuthSchema)
+			if err != nil {
+				return nil, err
+			}
+			ret[k] = r
+		case KindSSHKey:
+			vm, ok := v.(map[string]any)
+			if !ok {
+				return nil, fmt.Errorf("expected map")
+			}
+			r, err := derivedToConfig(vm, SSHKeySchema)
+			if err != nil {
+				return nil, err
+			}
+			ret[k] = r
+		case KindStruct:
+			vm, ok := v.(map[string]any)
+			if !ok {
+				return nil, fmt.Errorf("expected map")
+			}
+			r, err := derivedToConfig(vm, def)
+			if err != nil {
+				return nil, err
+			}
+			ret[k] = r
+		default:
+			return nil, fmt.Errorf("Should not reach!")
+		}
+	}
+	return ret, nil
+}
+
 func findNetwork(networks []Network, name string) (Network, error) {
 	for _, n := range networks {
 		if n.Name == name {
diff --git a/core/installer/welcome/appmanager-tmpl/app.html b/core/installer/welcome/appmanager-tmpl/app.html
index 6f956f3..c1ae84a 100644
--- a/core/installer/welcome/appmanager-tmpl/app.html
+++ b/core/installer/welcome/appmanager-tmpl/app.html
@@ -12,7 +12,7 @@
       <label for="{{ $name }}">
         <span>{{ $name }}</span>
       </label>
-	  <input type="text" name="{{ $name }}" oninput="valueChanged({{ $name }}, parseInt(this.value))" {{ if $readonly }}disabled{{ end }} {{ if index $data $name }}checked{{ end }} />
+	  <input type="text" name="{{ $name }}" oninput="valueChanged({{ $name }}, parseInt(this.value))" {{ if $readonly }}disabled{{ end }} value="{{ index $data $name }}" />
     {{ else if eq $schema.Kind 1 }}
       <label for="{{ $name }}">
         <span>{{ $name }}</span>
@@ -28,7 +28,7 @@
         <span>{{ $name }}</span>
       </label>
 	  <select name="{{ $name }}" oninput="valueChanged({{ $name }}, this.value)" {{ if $readonly }}disabled{{ end }} >
-		{{ if not $readonly }}<option disabled selected value> -- select an option -- </option>{{ end }}
+		{{ if not $readonly }}<option disabled selected value>Available networks</option>{{ end }}
 		{{ range $networks }}
 		  <option {{if eq .Name (index $data $name) }}selected{{ end }}>{{ .Name }}</option>
 		{{ end }}
@@ -75,7 +75,7 @@
 
 <form id="config-form">
     {{ if $instance }}
-      {{ template "schema-form" (dict "Schema" $schema "AvailableNetworks" $networks "ReadOnly" false "Data" $instance.Config) }}
+      {{ template "schema-form" (dict "Schema" $schema "AvailableNetworks" $networks "ReadOnly" false "Data" ($instance.Input $schema)) }}
     {{ else }}
       {{ template "schema-form" (dict "Schema" $schema "AvailableNetworks" $networks "ReadOnly" false "Data" (dict)) }}
     {{ end }}
@@ -93,7 +93,7 @@
   {{ if or (not $instance) (ne $instance.Id .Id)}}
     <details>
       <summary>{{ .Id }}</summary>
-      {{ template "schema-form" (dict "Schema" $schema "AvailableNetworks" $networks "ReadOnly" true "Data" .Config ) }}
+      {{ template "schema-form" (dict "Schema" $schema "AvailableNetworks" $networks "ReadOnly" true "Data" (.Input $schema) ) }}
       <a href="/instance/{{ .Id }}" role="button" class="secondary">View</a>
     </details>
   {{ end }}
@@ -139,7 +139,7 @@
 
 <script>
  let readme = "";
- let config = {{ if $instance }}JSON.parse({{ toJson $instance.Config }}){{ else }}{}{{ end }};
+ let config = {{ if $instance }}JSON.parse({{ toJson ($instance.Input $schema) }}){{ else }}{}{{ end }};
 
  function setValue(name, value, config) {
   let items = name.split(".")