mirror of
https://github.com/oarkflow/mq.git
synced 2025-10-06 00:16:49 +08:00
127 lines
4.1 KiB
Go
127 lines
4.1 KiB
Go
package handlers
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"html/template"
|
|
"os"
|
|
|
|
"github.com/oarkflow/jet"
|
|
"github.com/oarkflow/jsonschema"
|
|
"github.com/oarkflow/mq"
|
|
"github.com/oarkflow/mq/consts"
|
|
"github.com/oarkflow/mq/dag"
|
|
"github.com/oarkflow/mq/renderer"
|
|
)
|
|
|
|
type RenderHTMLNode struct {
|
|
dag.Operation
|
|
renderer *renderer.JSONSchemaRenderer
|
|
}
|
|
|
|
func (c *RenderHTMLNode) prepareRenderer(schemaFile string, data, templateData map[string]any, template string, templateFiles ...string) (string, error) {
|
|
if c.renderer == nil {
|
|
var templateFile string
|
|
if len(templateFiles) > 0 {
|
|
templateFile = templateFiles[0]
|
|
}
|
|
schema, ok := data["__schema"].(*jsonschema.Schema)
|
|
if !ok {
|
|
return "", fmt.Errorf("schema file %s not found in context", schemaFile)
|
|
}
|
|
if schema == nil {
|
|
return "", fmt.Errorf("schema file %s not found", schemaFile)
|
|
}
|
|
renderer, err := renderer.GetFromSchema(schema, template, templateFile)
|
|
if err != nil {
|
|
return "", fmt.Errorf("failed to get renderer from file %s: %v", schemaFile, err)
|
|
}
|
|
c.renderer = renderer.Renderer
|
|
}
|
|
return c.renderer.RenderFields(templateData)
|
|
}
|
|
|
|
func (c *RenderHTMLNode) ProcessTask(ctx context.Context, task *mq.Task) mq.Result {
|
|
data := c.Payload.Data
|
|
var (
|
|
schemaFile, _ = data["schema_file"].(string)
|
|
templateStr, _ = data["template"].(string)
|
|
templateFile, _ = data["template_file"].(string)
|
|
)
|
|
templateData, err := dag.UnmarshalPayload[map[string]any](ctx, task.Payload)
|
|
if err != nil {
|
|
return mq.Result{Error: err, Ctx: ctx}
|
|
}
|
|
if templateData == nil {
|
|
templateData = make(map[string]any)
|
|
}
|
|
delete(templateData, "html_content")
|
|
if c.Payload.Mapping != nil {
|
|
for k, v := range c.Payload.Mapping {
|
|
_, val := dag.GetVal(ctx, v, templateData)
|
|
templateData[k] = val
|
|
}
|
|
}
|
|
templateData["task_id"] = ctx.Value("task_id")
|
|
var renderedHTML string
|
|
parser := jet.NewWithMemory(jet.WithDelims("{{", "}}"))
|
|
switch {
|
|
// 1. JSONSchema + HTML Template
|
|
case schemaFile != "" && templateStr != "" && templateFile == "":
|
|
fmt.Println("Using JSONSchema and inline HTML template", c.ID)
|
|
renderedHTML, err = c.prepareRenderer(schemaFile, data, templateData, templateStr)
|
|
// 2. JSONSchema + HTML File
|
|
case schemaFile != "" && templateFile != "" && templateStr == "":
|
|
fmt.Println("Using JSONSchema and HTML file", c.ID)
|
|
renderedHTML, err = c.prepareRenderer(schemaFile, data, templateData, "", templateFile)
|
|
// 3. Only JSONSchema
|
|
case (schemaFile != "" || c.renderer != nil) && templateStr == "" && templateFile == "":
|
|
fmt.Println("Using only JSONSchema", c.ID)
|
|
renderedHTML, err = c.prepareRenderer(schemaFile, data, templateData, "")
|
|
// 4. Only HTML Template
|
|
case templateStr != "" && templateFile == "" && schemaFile == "":
|
|
fmt.Println("Using inline HTML template", c.ID)
|
|
tmpl, err := template.New("inline").Parse(templateStr)
|
|
if err != nil {
|
|
return mq.Result{Error: fmt.Errorf("failed to parse template: %v", err), Ctx: ctx}
|
|
}
|
|
var buf bytes.Buffer
|
|
err = tmpl.Execute(&buf, templateData)
|
|
if err != nil {
|
|
return mq.Result{Error: fmt.Errorf("failed to execute template: %v", err), Ctx: ctx}
|
|
}
|
|
renderedHTML = buf.String()
|
|
// 5. Only HTML File
|
|
case templateFile != "" && templateStr == "" && schemaFile == "":
|
|
fmt.Println("Using HTML file", c.ID)
|
|
fileContent, err := os.ReadFile(templateFile)
|
|
if err != nil {
|
|
return mq.Result{Error: fmt.Errorf("failed to read template file: %v", err), Ctx: ctx}
|
|
}
|
|
renderedHTML, err = parser.ParseTemplate(string(fileContent), templateData)
|
|
if err != nil {
|
|
return mq.Result{Error: err, Ctx: ctx}
|
|
}
|
|
default:
|
|
return mq.Result{Error: fmt.Errorf("no valid rendering approach found"), Ctx: ctx}
|
|
}
|
|
|
|
if err != nil {
|
|
return mq.Result{Payload: task.Payload, Error: err, Ctx: ctx, ConditionStatus: "invalid"}
|
|
}
|
|
|
|
ctx = context.WithValue(ctx, consts.ContentType, consts.TypeHtml)
|
|
resultData := map[string]any{
|
|
"html_content": renderedHTML,
|
|
"step": "form",
|
|
}
|
|
bt, _ := json.Marshal(resultData)
|
|
return mq.Result{Payload: bt, Ctx: ctx}
|
|
}
|
|
|
|
func NewRenderHTMLNode(id string) *RenderHTMLNode {
|
|
return &RenderHTMLNode{Operation: dag.Operation{Key: "render-html", ID: id, Type: dag.Page, Tags: []string{"built-in"}}}
|
|
}
|