~humaid/workflow-engine unlisted

5742459f5e4184fddef5d200e0cba0f779f869ff — Humaid AlQassimi 10 months ago aebc1ec
admin: implement adding adding of criteria in steps
M admin.go => admin.go +88 -4
@@ 83,7 83,13 @@ func (e *Engine) RunWebInterface() {
		m.Get("/dash", dashboardHandler)
		m.Get("/s/:service", serviceHandler)
		m.Get("/s/:service/:channel", channelHandler)
		m.Get("/s/:service/:channel/:step", stepHandler)
		m.Group("/s/:service/:channel/:step", func() {
			m.Get("", stepHandler)
			m.Get("/new/criteria/exec", newExecCriteriaHandler)
			m.Post("/new/criteria/exec", binding.BindIgnErr(newCriteriaForm{}), postNewExecCriteriaHandler)
			m.Get("/new/criteria/final", newFinalCriteriaHandler)
			m.Post("/new/criteria/final", binding.BindIgnErr(newCriteriaForm{}), postNewFinalCriteriaHandler)
		})
		m.Group("/new", func() {
			m.Get("/service", newServiceHandler)
			m.Post("/service", binding.BindIgnErr(newServiceForm{}), postNewServiceHandler)


@@ 106,6 112,82 @@ func (e *Engine) RunWebInterface() {
	log.Fatal(http.ListenAndServe(fmt.Sprintf("0.0.0.0:%d", e.Options.AdminPort), m))
}

func postNewExecCriteriaHandler(ctx *macaron.Context, f *session.Flash, errs binding.Errors, form newCriteriaForm) {
	if errs.Len() > 0 {
		f.Error("Make sure to fill required fields")
		ctx.Redirect("/s/" + ctx.Params("service") + "/" + ctx.Params("channel") + "/" + ctx.Params("step") + "/new/criteria/exec")
		return
	}
	e := ctx.Data["Engine"].(*Engine)
	s := e.getStep(ctx.Params("service"), ctx.Params("channel"), ctx.Params("step"))
	if s == nil {
		f.Error("Step not found")
		ctx.Redirect("/dash")
		return
	}
	// TODO check if name exists
	crit := Criteria{
		CriteriaName: form.Name,
		Expression:   form.Expression, //TODO check this first
		FailMessage:  form.FailMessage,
	}

	s.CriteriaExec = append(s.CriteriaExec, crit)
	ctx.Redirect("/s/" + ctx.Params("service") + "/" + ctx.Params("channel") + "/" +
		ctx.Params("step"))
}

func newFinalCriteriaHandler(ctx *macaron.Context, f *session.Flash) {
	e := ctx.Data["Engine"].(*Engine)
	s := e.getStep(ctx.Params("service"), ctx.Params("channel"), ctx.Params("step"))
	if s == nil {
		f.Error("Step not found")
		ctx.Redirect("/dash")
		return
	}
	ctx.Data["Step"] = s
	ctx.Data["Type"] = "final"
	ctx.HTML(http.StatusOK, "new-criteria")
}

func postNewFinalCriteriaHandler(ctx *macaron.Context, f *session.Flash, errs binding.Errors, form newCriteriaForm) {
	if errs.Len() > 0 {
		f.Error("Make sure to fill required fields")
		ctx.Redirect("/s/" + ctx.Params("service") + "/" + ctx.Params("channel") + "/" + ctx.Params("step") + "/new/criteria/final")
		return
	}
	e := ctx.Data["Engine"].(*Engine)
	s := e.getStep(ctx.Params("service"), ctx.Params("channel"), ctx.Params("step"))
	if s == nil {
		f.Error("Step not found")
		ctx.Redirect("/dash")
		return
	}
	// TODO check if name exists
	crit := Criteria{
		CriteriaName: form.Name,
		Expression:   form.Expression, //TODO check this first
		FailMessage:  form.FailMessage,
	}

	s.CriteriaFinal = append(s.CriteriaFinal, crit)
	ctx.Redirect("/s/" + ctx.Params("service") + "/" + ctx.Params("channel") + "/" +
		ctx.Params("step"))
}

func newExecCriteriaHandler(ctx *macaron.Context, f *session.Flash) {
	e := ctx.Data["Engine"].(*Engine)
	s := e.getStep(ctx.Params("service"), ctx.Params("channel"), ctx.Params("step"))
	if s == nil {
		f.Error("Step not found")
		ctx.Redirect("/dash")
		return
	}
	ctx.Data["Step"] = s
	ctx.Data["Type"] = "exec"
	ctx.HTML(http.StatusOK, "new-criteria")
}

func errorsHandler(ctx *macaron.Context) {
	ctx.HTML(http.StatusOK, "errors")
}


@@ 137,6 219,7 @@ func postEditStepHandler(ctx *macaron.Context, f *session.Flash, errs binding.Er
	}
	s.Status = form.Status
	s.Page = form.Page
	s.EndApplication = form.EndApplication
	s.PostTo = strings.Split(form.PostTo, ",")
	s.DataIn = strings.Split(form.DataIn, ",")
	s.DataOut = strings.Split(form.DataOut, ",")


@@ 284,9 367,10 @@ func postNewStepHandler(ctx *macaron.Context, errs binding.Errors, form newStepF
		return
	}
	st := WorkflowStep{
		StepID: form.StepID,
		Status: form.Status,
		Page:   form.Page,
		StepID:         form.StepID,
		Status:         form.Status,
		Page:           form.Page,
		EndApplication: form.EndApplication,
	}
	if len(form.DataIn) > 0 {
		st.DataIn = strings.Split(form.DataIn, ",")

M admin_forms.go => admin_forms.go +13 -6
@@ 13,10 13,17 @@ type newChannelForm struct {
}

type newStepForm struct {
	StepID  string `form:"id" binding:"Required"`
	Status  string `form:"desc"`
	Page    string `form:"page"`
	PostTo  string `form:"post"`
	DataIn  string `form:"data-in"`
	DataOut string `form:"data-out"`
	StepID         string `form:"id" binding:"Required"`
	Status         string `form:"desc"`
	Page           string `form:"page"`
	PostTo         string `form:"post"`
	DataIn         string `form:"data-in"`
	DataOut        string `form:"data-out"`
	EndApplication bool   `form:"end"`
}

type newCriteriaForm struct {
	Name        string `form:"name" binding:"Required"`
	Expression  string `form:"expr" binding:"Required"`
	FailMessage string `form:"fail" binding:"Required"`
}

M templates/edit-step.tmpl => templates/edit-step.tmpl +4 -0
@@ 31,6 31,10 @@
				<input type="text" id="data-out" name="data-out"
				value="{{csv .Step.DataOut}}">
			</div>
			<div class="form-group">
				<p><label for="end">End Application</label><p>
				<input type="checkbox" id="end" name="end"{{if .Step.EndApplication}} checked="1"{{end}}>
			</div>
			<input type="hidden" name="_csrf" value="{{.csrf_token}}">
			<button type="submit" class="btn">Edit step</button>
		</div>

A templates/new-criteria.tmpl => templates/new-criteria.tmpl +24 -0
@@ 0,0 1,24 @@
{{template "base/head" .}}
<div class="content">
	{{template "partials/flash" .}}
	<h2>New {{.Type}} criteria for {{.Step.StepID}}</h2>
	<form method="post">
		<div class="col-5">
			<div class="form-group">
				<p><label for="name">Criteria Name</label><p>
				<input type="text" id="name" name="name" autofocus="1" required="1">
			</div>
			<div class="form-group">
				<p><label for="expr">Expression</label><p>
				<textarea id="expr" name="expr"></textarea>
			</div>
			<div class="form-group">
				<p><label for="fail">Fail Message</label><p>
				<input type="text" id="fail" name="fail">
			</div>
			<button type="submit" class="btn">Add criteria</button>
		</div>
	</form>

</div>
{{template "base/footer" .}}

M templates/new-step.tmpl => templates/new-step.tmpl +4 -0
@@ 28,6 28,10 @@
				<p><label for="data-out">Data Out (comma-separated)</label><p>
				<input type="text" id="data-out" name="data-out">
			</div>
			<div class="form-group">
				<p><label for="end">End Application</label><p>
				<input type="checkbox" id="end" name="end">
			</div>
			<input type="hidden" name="_csrf" value="{{.csrf_token}}">
			<p>You will be able to add pull data, criterias, and commits later.</p>
			<button type="submit" class="btn">Add step</button>

M templates/step.tmpl => templates/step.tmpl +15 -14
@@ 19,35 19,39 @@
	message.</small></p>
	<p><a class="btn"
	href="/edit/step/{{.Rel}}">Edit attributes</a></p>
	<h3>Execution Criteria</h3>
	<h3>Execution Criteria <a class="btn"
	href="/s/{{.Rel}}/new/criteria/exec">+</a></h3>
	
	<p><i>These are criterion required to pass before the step is allowed to
	start.</i></p>
	{{range .Step.CriteriaExec}}
	<div class="entry">
		<a href="/edit/criteria-exec/">{{if .CriteriaName}}{{.CriteriaName}}{{else}}No
		<a href="/s/{{$.Rel}}/edit/criteria/exec/{{.CriteriaName}}">{{if .CriteriaName}}{{.CriteriaName}}{{else}}No
		Name!{{end}}</a>
		<div class="meta">
			<p><a href="#"><code>{{.Expression}}</code></a></p>
			<p><a href="#">Fail message: {{if .FailMessage}}{{.FailMessage}}{{else}}None{{end}}</a></p>
			<p><a><code>{{.Expression}}</code></a></p>
			<p><a>Fail message: {{if .FailMessage}}{{.FailMessage}}{{else}}None{{end}}</a></p>
		</div>
	</div>
	{{end}}
	<h3>Finalisation Criteria</h3>
	<h3>Finalisation Criteria <a class="btn"
	href="/s/{{.Rel}}/new/criteria/final">+</a></h3>
	
	<p><i>These are criterion required to pass before the step is allowed to be
	marked as complete.</i></p>
	{{range .Step.CriteriaFinal}}
	<div class="entry">
		<a href="/s/">{{if .CriteriaName}}{{.CriteriaName}}{{else}}No
		<a href="/s/{{$.Rel}}/edit/criteria/exec/{{.CriteriaName}}">{{if .CriteriaName}}{{.CriteriaName}}{{else}}No
		Name!{{end}}</a>
		<div class="meta">
			<p><a href="#"><code>{{.Expression}}</code></a></p>
			<p><a href="#">Fail message: {{if .FailMessage}}{{.FailMessage}}{{else}}None{{end}}</a></p>
			<p><a><code>{{.Expression}}</code></a></p>
			<p><a>Fail message: {{if .FailMessage}}{{.FailMessage}}{{else}}None{{end}}</a></p>
		</div>
	</div>
	{{end}}
	<h3>Pull Data</h3>
	<h3>Pull Data <a class="btn" href="/s/{{.Rel}}/new/pulldata">+</a></h3>
	<p><i>This is the external services called via HTTP POST.</i></p>
	<h3>Commit Objects</h3>
	<h3>Commit Objects <a class="btn" href="/s/{{.Rel}}/new/commitobject">+</a></h3>
	<p><i>These are objects which are created before committing, and are loaded
	in the commit scripting environment.</i></p>
	{{range .Step.CommitObjects}}


@@ 55,7 59,7 @@
		<a href="/s/"><code>{{.Name}}</code> (type: {{.Type}})</a>
		<div class="meta">
			{{range $key, $value := .Variables}}
			<p><a href="">{{$key}}: <code>{{$value}}</code></a></p>
			<p><a>{{$key}}: <code>{{$value}}</code></a></p>
			{{end}}
		</div>
	</div>


@@ 72,9 76,6 @@
		</div>
	</div>
	{{end}}


	<h3></h3>
</div>
{{template "base/footer" .}}