Skip to content

Commit

Permalink
Moved report attr from action to result
Browse files Browse the repository at this point in the history
  • Loading branch information
akclace committed Oct 21, 2024
1 parent 10c628c commit 6b8fe4c
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 70 deletions.
23 changes: 14 additions & 9 deletions internal/app/action/action.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ type Action struct {
name string
description string
path string
report string
run starlark.Callable
suggest starlark.Callable
params []apptype.AppParam
Expand All @@ -49,7 +48,7 @@ type Action struct {
}

// NewAction creates a new action
func NewAction(logger *types.Logger, isDev bool, name, description, apath, report string, run, suggest starlark.Callable,
func NewAction(logger *types.Logger, isDev bool, name, description, apath string, run, suggest starlark.Callable,
params []apptype.AppParam, paramValuesStr map[string]string, paramDict starlark.StringDict,
appPath string) (*Action, error) {

Expand All @@ -76,7 +75,6 @@ func NewAction(logger *types.Logger, isDev bool, name, description, apath, repor
name: name,
description: description,
path: apath,
report: report,
run: run,
suggest: suggest,
params: params,
Expand Down Expand Up @@ -204,6 +202,7 @@ func (a *Action) runAction(w http.ResponseWriter, r *http.Request) {
var valuesStr []string
var status string
var paramErrors map[string]any
report := apptype.AUTO

resultStruct, ok := ret.(*starlarkstruct.Struct)
if ok {
Expand All @@ -227,6 +226,12 @@ func (a *Action) runAction(w http.ResponseWriter, r *http.Request) {
http.Error(w, fmt.Sprintf("error getting result attr paramErrors: %s", err), http.StatusInternalServerError)
return
}

report, err = apptype.GetOptionalStringAttr(resultStruct, "report")
if err != nil {
http.Error(w, fmt.Sprintf("error getting result report: %s", err), http.StatusInternalServerError)
return
}
} else {
// Not a result struct
status = ret.String()
Expand Down Expand Up @@ -279,19 +284,19 @@ func (a *Action) runAction(w http.ResponseWriter, r *http.Request) {
}
}

err = a.renderResults(w, valuesMap, valuesStr)
err = a.renderResults(w, report, valuesMap, valuesStr)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
}

func (a *Action) renderResults(w http.ResponseWriter, valuesMap []map[string]any, valuesStr []string) error {
if a.report == apptype.AUTO {
func (a *Action) renderResults(w http.ResponseWriter, report string, valuesMap []map[string]any, valuesStr []string) error {
if report == apptype.AUTO {
return a.renderResultsAuto(w, valuesMap, valuesStr)
}

switch a.report {
switch report {
case apptype.TABLE:
return a.renderResultsTable(w, valuesMap)
case apptype.TEXT:
Expand All @@ -307,9 +312,9 @@ func (a *Action) renderResults(w http.ResponseWriter, valuesMap []map[string]any
}
var tmplErr error
if len(valuesStr) > 0 {
tmplErr = a.AppTemplate.ExecuteTemplate(w, a.report, valuesStr)
tmplErr = a.AppTemplate.ExecuteTemplate(w, report, valuesStr)
} else {
tmplErr = a.AppTemplate.ExecuteTemplate(w, a.report, valuesMap)
tmplErr = a.AppTemplate.ExecuteTemplate(w, report, valuesMap)
}
_, err = io.WriteString(w, ` </div>`)
if err != nil {
Expand Down
60 changes: 33 additions & 27 deletions internal/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,9 @@ type App struct {
appRouter *chi.Mux // router for the app
actions []*action.Action // actions defined for the app

usesHtmlTemplate bool // Whether the app uses HTML templates, false if only JSON APIs
actionUsesHtmlTemplate bool // Whether the app action uses HTML templates
template *template.Template // unstructured templates, no base_templates defined
templateMap map[string]*template.Template // structured templates, base_templates defined
usesHtmlTemplate bool // Whether the app uses HTML templates, false if only JSON APIs
template *template.Template // unstructured templates, no base_templates defined
templateMap map[string]*template.Template // structured templates, base_templates defined

watcher *fsnotify.Watcher
sseListeners []chan SSEMessage
Expand Down Expand Up @@ -288,41 +287,48 @@ func (a *App) Reload(force, immediate bool, dryRun DryRun) (bool, error) {
}

// Parse HTML templates if there are HTML routes or action uses HTML templates
if a.usesHtmlTemplate || a.actionUsesHtmlTemplate {
baseFiles, err := a.sourceFS.Glob(path.Join(a.codeConfig.Routing.BaseTemplates, "*.go.html"))
baseFiles, err := a.sourceFS.Glob(path.Join(a.codeConfig.Routing.BaseTemplates, "*.go.html"))
if err != nil {
return false, err
}

if len(baseFiles) == 0 {
// No base templates found, use the default unstructured templates
if a.template, err = a.sourceFS.ParseFS(a.funcMap, a.codeConfig.Routing.TemplateLocations...); err != nil {
if strings.Contains(err.Error(), "pattern matches no files") {
if a.usesHtmlTemplate {
// No html templates found, but app has html routes
return false, err
}
// no html templates, ignore error
} else {
// Some other error parsing templates, report
return false, err
}
}
} else {
// Base templates found, using structured templates
base, err := a.sourceFS.ParseFS(a.funcMap, baseFiles...)
if err != nil {
return false, err
}

if len(baseFiles) == 0 {
// No base templates found, use the default unstructured templates
if a.template, err = a.sourceFS.ParseFS(a.funcMap, a.codeConfig.Routing.TemplateLocations...); err != nil {
return false, err
}
} else {
// Base templates found, using structured templates
base, err := a.sourceFS.ParseFS(a.funcMap, baseFiles...)
a.templateMap = make(map[string]*template.Template)
for _, paths := range a.codeConfig.Routing.TemplateLocations {
files, err := a.sourceFS.Glob(paths)
if err != nil {
return false, err
}

a.templateMap = make(map[string]*template.Template)
for _, paths := range a.codeConfig.Routing.TemplateLocations {
files, err := a.sourceFS.Glob(paths)
for _, file := range files {
tmpl, err := base.Clone()
if err != nil {
return false, err
}

for _, file := range files {
tmpl, err := base.Clone()
if err != nil {
return false, err
}

a.templateMap[file], err = tmpl.ParseFS(a.sourceFS.ReadableFS, file)
if err != nil {
return false, err
}
a.templateMap[file], err = tmpl.ParseFS(a.sourceFS.ReadableFS, file)
if err != nil {
return false, err
}
}
}
Expand Down
21 changes: 11 additions & 10 deletions internal/app/apptype/builtins.go
Original file line number Diff line number Diff line change
Expand Up @@ -283,23 +283,18 @@ func createLibraryBuiltin(_ *starlark.Thread, _ *starlark.Builtin, args starlark
}

func createActionBuiltin(_ *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
var name, desc, path, report starlark.String
var name, desc, path starlark.String
var suggest, executor starlark.Callable
if err := starlark.UnpackArgs(LIBRARY, args, kwargs, "name", &name, "path", &path,
"run", &executor, "suggest?", &suggest, "report?", &report, "description?", &desc); err != nil {
if err := starlark.UnpackArgs(ACTION, args, kwargs, "name", &name, "path", &path,
"run", &executor, "suggest?", &suggest, "description?", &desc); err != nil {
return nil, fmt.Errorf("error unpacking action args: %w", err)
}

if report == "" {
report = AUTO
}

fields := starlark.StringDict{
"name": name,
"description": desc,
"path": path,
"run": executor,
"report": report,
}

if suggest != nil {
Expand All @@ -309,13 +304,18 @@ func createActionBuiltin(_ *starlark.Thread, _ *starlark.Builtin, args starlark.
}

func createResultBuiltin(_ *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
var status starlark.String
var status, report starlark.String
var values *starlark.List
var paramErrors *starlark.Dict
if err := starlark.UnpackArgs(RESPONSE, args, kwargs, "status?", &status, "values?", &values, "param_errors?", &paramErrors); err != nil {
if err := starlark.UnpackArgs(RESULT, args, kwargs, "status?", &status, "values?", &values,
"report?", &report, "param_errors?", &paramErrors); err != nil {
return nil, fmt.Errorf("error unpacking result args: %w", err)
}

if report == "" {
report = AUTO
}

if values == nil {
values = starlark.NewList([]starlark.Value{})
}
Expand All @@ -327,6 +327,7 @@ func createResultBuiltin(_ *starlark.Thread, _ *starlark.Builtin, args starlark.
fields := starlark.StringDict{
"status": status,
"values": values,
"report": report,
"param_errors": paramErrors,
}
return starlarkstruct.FromStringDict(starlark.String(RESULT), fields), nil
Expand Down
12 changes: 2 additions & 10 deletions internal/app/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,7 @@ func (a *App) addAction(count int, val starlark.Value, router *chi.Mux) error {
return fmt.Errorf("actions entry %d is not a struct", count)
}

var name, path, description, report string
var name, path, description string
var run, suggest starlark.Callable
var err error
if name, err = apptype.GetStringAttr(actionDef, "name"); err != nil {
Expand All @@ -476,14 +476,6 @@ func (a *App) addAction(count int, val starlark.Value, router *chi.Mux) error {
if run, err = apptype.GetCallableAttr(actionDef, "run"); err != nil {
return err
}
if report, err = apptype.GetStringAttr(actionDef, "report"); err != nil {
return err
}

if report != apptype.AUTO && report != apptype.TEXT && report != apptype.TABLE && report != apptype.JSON {
// action is using a custom report, HTML templates are to be parsed
a.actionUsesHtmlTemplate = true
}

sa, _ := actionDef.Attr("suggest")
if sa != nil {
Expand All @@ -495,7 +487,7 @@ func (a *App) addAction(count int, val starlark.Value, router *chi.Mux) error {
if !strings.HasPrefix(path, "/") {
path = "/" + path
}
action, err := action.NewAction(a.Logger, a.IsDev, name, description, path, report, run, suggest,
action, err := action.NewAction(a.Logger, a.IsDev, name, description, path, run, suggest,
slices.Collect(maps.Values(a.paramInfo)), a.paramValuesStr, a.paramDict, a.Path)
if err != nil {
return fmt.Errorf("error creating action %s: %w", name, err)
Expand Down
28 changes: 14 additions & 14 deletions internal/app/tests/appaction_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ func actionTester(t *testing.T, rootPath bool, actionPath string) {
fileData := map[string]string{
"app.star": `
def handler(dry_run, args):
return ace.result(status="done", values=["a", "b"])
return ace.result(status="done", values=["a", "b"], report=ace.TEXT)
app = ace.app("testApp",
actions=[ace.action("testAction", "` + actionPath + `", handler)])
Expand Down Expand Up @@ -177,7 +177,7 @@ def handler(dry_run, args):
return ace.result(status="done", values=[{"a": 1, "b": "abc"}])
app = ace.app("testApp",
actions=[ace.action("testAction", "/", handler, report=ace.AUTO)])
actions=[ace.action("testAction", "/", handler)])
`,
"params.star": `param("param1", description="param1 description", type=STRING, default="myvalue")`,
Expand Down Expand Up @@ -234,10 +234,10 @@ func TestAutoReportJSON(t *testing.T) {
fileData := map[string]string{
"app.star": `
def handler(dry_run, args):
return ace.result(status="done", values=[{"a": {"c": 1}, "b": "abc"}])
return ace.result(status="done", values=[{"a": {"c": 1}, "b": "abc"}], report=ace.AUTO)
app = ace.app("testApp",
actions=[ace.action("testAction", "/", handler, report=ace.AUTO)])
actions=[ace.action("testAction", "/", handler)])
`,
"params.star": `param("param1", description="param1 description", type=STRING, default="myvalue")`,
Expand Down Expand Up @@ -287,10 +287,10 @@ func TestReportTable(t *testing.T) {
fileData := map[string]string{
"app.star": `
def handler(dry_run, args):
return ace.result(status="done", values=[{"a": {"c": 1}, "b": "abc"}])
return ace.result(status="done", values=[{"a": {"c": 1}, "b": "abc"}], report=ace.TABLE)
app = ace.app("testApp",
actions=[ace.action("testAction", "/", handler, report=ace.TABLE)])
actions=[ace.action("testAction", "/", handler)])
`,
"params.star": `param("param1", description="param1 description", type=STRING, default="myvalue")`,
Expand Down Expand Up @@ -350,10 +350,10 @@ func TestReportTableMissingData(t *testing.T) {
fileData := map[string]string{
"app.star": `
def handler(dry_run, args):
return ace.result(status="done", values=[{"a": 1, "b": "abc"}, {"c": 1, "b": "abc2"}])
return ace.result(status="done", values=[{"a": 1, "b": "abc"}, {"c": 1, "b": "abc2"}], report=ace.TABLE)
app = ace.app("testApp",
actions=[ace.action("testAction", "/", handler, report=ace.TABLE)])
actions=[ace.action("testAction", "/", handler)])
`,
"params.star": `param("param1", description="param1 description", type=STRING, default="myvalue")`,
Expand Down Expand Up @@ -415,10 +415,10 @@ func TestParamPost(t *testing.T) {
fileData := map[string]string{
"app.star": `
def handler(dry_run, args):
return ace.result(status="done", values=[{"c1": args.param1, "c2": args.param2, "c3": args.param3}])
return ace.result(status="done", values=[{"c1": args.param1, "c2": args.param2, "c3": args.param3}], report=ace.TABLE)
app = ace.app("testApp",
actions=[ace.action("testAction", "/", handler, report=ace.TABLE)])
actions=[ace.action("testAction", "/", handler)])
`,
"params.star": `param("param1", description="param1 description", type=STRING, default="myvalue")
Expand Down Expand Up @@ -503,10 +503,10 @@ func TestCustomReport(t *testing.T) {
fileData := map[string]string{
"app.star": `
def handler(dry_run, args):
return ace.result(status="done", values=[{"a": 1, "b": "abc"}])
return ace.result(status="done", values=[{"a": 1, "b": "abc"}], report="custom")
app = ace.app("testApp",
actions=[ace.action("testAction", "/", handler, report="custom")])
actions=[ace.action("testAction", "/", handler)])
`,
"params.star": `param("param1", description="param1 description", type=STRING, default="myvalue")`,
Expand Down Expand Up @@ -610,10 +610,10 @@ def handler(dry_run, args):
if args.param1 == "error":
return "errormessage"
10/args.param3
return ace.result(status="done", values=[{"c1": args.param1, "c2": args.param2, "c3": args.param3}])
return ace.result(status="done", values=[{"c1": args.param1, "c2": args.param2, "c3": args.param3}], report=ace.TABLE)
app = ace.app("testApp",
actions=[ace.action("testAction", "/", handler, report=ace.TABLE)])
actions=[ace.action("testAction", "/", handler)])
`,
"params.star": `param("param1", description="param1 description", type=STRING, default="myvalue")
Expand Down

0 comments on commit 6b8fe4c

Please sign in to comment.