100 lines
3.5 KiB
Go
100 lines
3.5 KiB
Go
package run
|
|
|
|
import (
|
|
"encoding/json"
|
|
|
|
"git.iwork-ai.com/xdc/iqudo-top1/internal/model"
|
|
"git.iwork-ai.com/xdc/iqudo-top1/internal/scriptkit"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
// NodeView is the public view of the current SOP node.
|
|
type NodeView struct {
|
|
NodeKey string `json:"node_key"`
|
|
Type string `json:"type"`
|
|
Title string `json:"title"`
|
|
Content string `json:"content"`
|
|
Config json.RawMessage `json:"config,omitempty"`
|
|
Fields []PublicFieldView `json:"fields,omitempty"`
|
|
Presentation *NodePresentation `json:"presentation,omitempty"`
|
|
Stage *scriptkit.StageView `json:"stage,omitempty"`
|
|
}
|
|
|
|
// PublicFieldView mirrors a scenario field for the client.
|
|
type PublicFieldView struct {
|
|
Key string `json:"key"`
|
|
Name string `json:"name"`
|
|
Type string `json:"type"`
|
|
Required bool `json:"required"`
|
|
Options json.RawMessage `json:"options"`
|
|
Validation json.RawMessage `json:"validation"`
|
|
}
|
|
|
|
func nodeView(db *gorm.DB, run model.SOPRun, node model.SOPNode) (NodeView, error) {
|
|
view := NodeView{NodeKey: node.NodeKey, Type: node.Type, Title: node.Title, Content: node.Content, Config: json.RawMessage(node.Config)}
|
|
switch node.Type {
|
|
case "start":
|
|
input, derived, answers := mapsFromRun(run)
|
|
presentation, err := loadStartPresentation(db, node, run.TenantID, scriptkit.RenderContext{Input: input, Derived: derived, Form: answers})
|
|
if err != nil {
|
|
return view, err
|
|
}
|
|
view.Presentation = presentation
|
|
case "question", "choice", "form":
|
|
fields, err := loadPublicNodeFields(db, node, run.TenantID)
|
|
if err != nil {
|
|
return view, err
|
|
}
|
|
view.Fields = fields
|
|
case "stage":
|
|
stage, err := buildStageView(db, run, node)
|
|
if err != nil {
|
|
return view, err
|
|
}
|
|
view.Stage = stage
|
|
}
|
|
return view, nil
|
|
}
|
|
|
|
// mapsFromRun returns input, derived and form maps for legacy views.
|
|
func mapsFromRun(run model.SOPRun) (map[string]interface{}, map[string]interface{}, map[string]interface{}) {
|
|
input := map[string]interface{}{}
|
|
_ = json.Unmarshal(run.Input, &input)
|
|
derived := map[string]interface{}{}
|
|
_ = json.Unmarshal(run.Derived, &derived)
|
|
answers := map[string]interface{}{}
|
|
_ = json.Unmarshal(run.Answers, &answers)
|
|
return input, derived, answers
|
|
}
|
|
|
|
func loadPublicNodeFields(db *gorm.DB, node model.SOPNode, tenantID uint64) ([]PublicFieldView, error) {
|
|
var config answerNodeConfig
|
|
if err := json.Unmarshal(node.Config, &config); err != nil {
|
|
return nil, err
|
|
}
|
|
keys := config.FieldKeys
|
|
if config.FieldKey != "" {
|
|
keys = []string{config.FieldKey}
|
|
}
|
|
if len(keys) == 0 {
|
|
return nil, nil
|
|
}
|
|
var fields []model.ScenarioField
|
|
if err := db.Table("scenario_fields sf").Select("sf.*").Joins("JOIN sops s ON s.scenario_id = sf.scenario_id").Where("s.id = ? AND sf.tenant_id = ? AND sf.field_key IN ?", node.SOPID, tenantID, keys).Find(&fields).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
byKey := make(map[string]model.ScenarioField, len(fields))
|
|
for _, field := range fields {
|
|
byKey[field.FieldKey] = field
|
|
}
|
|
views := make([]PublicFieldView, 0, len(keys))
|
|
for _, key := range keys {
|
|
field, ok := byKey[key]
|
|
if !ok {
|
|
continue
|
|
}
|
|
views = append(views, PublicFieldView{Key: field.FieldKey, Name: field.FieldName, Type: field.FieldType, Required: field.Required || config.Required || containsString(config.RequiredFieldKeys, key), Options: json.RawMessage(field.Options), Validation: json.RawMessage(field.Validation)})
|
|
}
|
|
return views, nil
|
|
}
|