Easy form generation. TODO: parse forms
This commit is contained in:
83
res/template/account/user_password.html
Normal file
83
res/template/account/user_password.html
Normal file
@@ -0,0 +1,83 @@
|
||||
{{define "user_password"}}<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
{{template "meta_tags" "Updating Password"}}
|
||||
{{template "user_style"}}
|
||||
<script type="text/javascript">var apiEndpoint = '{{.APIEndpoint}}';</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id='body' class="body">
|
||||
{{template "menu" .}}
|
||||
|
||||
<h1>Update Password</h1>
|
||||
<div id="submit_result"></div>
|
||||
<form id="the_form" class="highlight_dark border_top border_bottom">
|
||||
<input type="text" autocomplete="username" value="{{.Username}}" style="display: none;"/>
|
||||
<table class="form">
|
||||
<tr class="form">
|
||||
<td>Old Password</td>
|
||||
<td><input id="old_password" type="password" autocomplete="current-password" class="form_input"/></td>
|
||||
</tr>
|
||||
|
||||
<tr class="form">
|
||||
<td>New Password</td>
|
||||
<td><input id="new_password1" type="password" autocomplete="new-password" class="form_input"/></td>
|
||||
</tr>
|
||||
<tr class="form">
|
||||
<td>New password verification</td>
|
||||
<td><input id="new_password2" type="password" autocomplete="new-password" class="form_input"/></td>
|
||||
</tr>
|
||||
<tr class="form">
|
||||
<td style="text-align: left;"><a href="/user" class="button button_red"/>Back</a>
|
||||
<td style="text-align: right;"><input type="submit" value="Confirm" class="button_highlight"/></td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
<br/>
|
||||
{{template "footer"}}
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
document.getElementById("the_form").onsubmit = function(){
|
||||
var oldpasswd = document.getElementById("old_password");
|
||||
var passwd1 = document.getElementById("new_password1");
|
||||
var passwd2 = document.getElementById("new_password2");
|
||||
|
||||
if (passwd1.value !== passwd2.value) {
|
||||
alert("Passwords do not match! Good thing we checked.");
|
||||
return false;
|
||||
}
|
||||
|
||||
var req = new XMLHttpRequest();
|
||||
req.onreadystatechange = function(){
|
||||
if (this.readyState === 4) {
|
||||
var response = JSON.parse(req.responseText);
|
||||
var resultDiv = document.getElementById("submit_result");
|
||||
if (response.success) {
|
||||
resultDiv.className = "border_top border_bottom highlight_green";
|
||||
resultDiv.innerHTML = 'Success! Your password has been updated';
|
||||
oldpasswd.value = "";
|
||||
passwd1.value = "";
|
||||
passwd2.value = "";
|
||||
} else {
|
||||
resultDiv.className = "border_top border_bottom highlight_red";
|
||||
resultDiv.innerHTML = response.message;
|
||||
}
|
||||
|
||||
console.log(response);
|
||||
}
|
||||
}
|
||||
|
||||
var data = new FormData();
|
||||
data.append("old_password", oldpasswd.value);
|
||||
data.append("new_password", passwd1.value);
|
||||
|
||||
req.open("PUT", apiEndpoint+"/user/password", true);
|
||||
req.send(data);
|
||||
|
||||
return false;
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
{{end}}
|
102
res/template/fragments/form.html
Normal file
102
res/template/fragments/form.html
Normal file
@@ -0,0 +1,102 @@
|
||||
{{define "form"}}
|
||||
<h1>{{.Title}}</h1>
|
||||
{{.PreFormHTML}}
|
||||
<br/><br/>
|
||||
{{if eq .Submit true}}
|
||||
{{if eq .SubmitSuccess true}}
|
||||
<div id="submit_result" class="highlight_green border_top border_bottom">
|
||||
{{index .SubmitMessages 0}}
|
||||
</div>
|
||||
{{else}}
|
||||
<div id="submit_result" class="highlight_red border_top border_bottom">
|
||||
Something went wrong, please correct these errors before continuing:<br/>
|
||||
<ul>
|
||||
{{range $msg := .SubmitMessages}}
|
||||
<li>{{$msg}}</li>
|
||||
{{end}}
|
||||
</ul>
|
||||
</div>
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
<form class="highlight_dark border_top border_bottom">
|
||||
<table style="margin-left: auto; margin-right: auto; text-align: left; max-width: 30em;">
|
||||
{{range $index, $field := .Fields}}
|
||||
<tr class="form">
|
||||
<td>{{$field.Label}}</td>
|
||||
<td>
|
||||
{{if eq $field.Type "text"}}
|
||||
<input id="input_{{$field.Name}}" name="{{$field.Name}}" value="{{$field.DefaultValue}}" type="text" class="form_input"/>
|
||||
{{else if eq $field.Type "username"}}
|
||||
<input id="input_{{$field.Name}}" name="{{$field.Name}}" value="{{$field.DefaultValue}}" type="text" autocomplete="username" class="form_input"/>
|
||||
{{else if eq $field.Type "email"}}
|
||||
<input id="input_{{$field.Name}}" name="{{$field.Name}}" value="{{$field.DefaultValue}}" type="email" autocomplete="email" class="form_input"/>
|
||||
{{else if eq $field.Type "current-password"}}
|
||||
<input id="input_{{$field.Name}}" name="{{$field.Name}}" value="{{$field.DefaultValue}}" type="password" autocomplete="current-password" class="form_input"/>
|
||||
{{else if eq $field.Type "new-password"}}
|
||||
<input id="input_{{$field.Name}}" name="{{$field.Name}}" value="{{$field.DefaultValue}}" type="password" autocomplete="new-password" class="form_input"/>
|
||||
{{else if eq $field.Type "captcha"}}
|
||||
<script src="https://www.google.com/recaptcha/api.js" async defer></script>
|
||||
<div class="g-recaptcha" data-theme="dark" data-sitekey="{{$field.CaptchaSiteKey}}"></div>
|
||||
{{end}}
|
||||
</td>
|
||||
{{if ne $field.Description ""}}
|
||||
<tr class="form">
|
||||
<td colspan="2">{{$field.Description}}</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
{{if eq $field.Separator true}}
|
||||
<tr class="form"><td colspan="2"><hr/></td></tr>
|
||||
{{end}}
|
||||
</tr>
|
||||
{{end}}
|
||||
<tr class="form">
|
||||
{{if eq .BackLink ""}}
|
||||
<td colspan="2" style="text-align: right;">
|
||||
{{if eq .SubmitRed true}}
|
||||
<input type="submit" value="{{.SubmitLabel}}" class="button_red"/>
|
||||
{{else}}
|
||||
<input type="submit" value="{{.SubmitLabel}}" class="button_highlight"/>
|
||||
{{end}}
|
||||
</td>
|
||||
{{else}}
|
||||
<td style="text-align: left;">
|
||||
<a href="{{.BackLink}}" class="button button_red"/>Back</a>
|
||||
</td>
|
||||
<td style="text-align: right;">
|
||||
{{if eq .SubmitRed true}}
|
||||
<input type="submit" value="{{.SubmitLabel}}" class="button_red"/>
|
||||
{{else}}
|
||||
<input type="submit" value="{{.SubmitLabel}}" class="button_highlight"/>
|
||||
{{end}}
|
||||
</td>
|
||||
{{end}}
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
<br/>
|
||||
{{.PostFormHTML}}
|
||||
<br/>
|
||||
{{end}}
|
||||
{{define "form_page"}}
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
{{template "meta_tags" .Title}}
|
||||
{{template "user_style" .}}
|
||||
<script type="text/javascript">var apiEndpoint = '{{.APIEndpoint}}';</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id='body' class="body">
|
||||
{{template "menu" .}}
|
||||
|
||||
{{template "form" .Form}}
|
||||
|
||||
{{template "footer"}}
|
||||
</div>
|
||||
|
||||
{{template "analytics"}}
|
||||
</body>
|
||||
</html>
|
||||
{{end}}
|
56
webcontroller/forms/form.go
Normal file
56
webcontroller/forms/form.go
Normal file
@@ -0,0 +1,56 @@
|
||||
package forms
|
||||
|
||||
import (
|
||||
"html/template"
|
||||
)
|
||||
|
||||
// Form is a form which can be rendered in HTML and submitted
|
||||
type Form struct {
|
||||
Title string // Shown in a large font above the form
|
||||
PreFormHTML template.HTML // Content to be rendered above the form
|
||||
|
||||
Fields []Field
|
||||
|
||||
BackLink string // Empty for no back link
|
||||
SubmitLabel string // Label for the submit button
|
||||
SubmitRed bool // If the submit button should be red or green
|
||||
|
||||
PostFormHTML template.HTML // Content to be rendered below the form
|
||||
|
||||
// Fields to render if the form has been submitted once
|
||||
Submit bool // If the form has been submitted
|
||||
SubmitSuccess bool // If the submission was a success
|
||||
SubmitMessages []string // Messages telling the user the results
|
||||
}
|
||||
|
||||
// Field is a single input field in a form
|
||||
type Field struct {
|
||||
// Used for reading the data. Entered data is POSTed back to the same URL with this name
|
||||
Name string
|
||||
// Is entered in the input field by default
|
||||
DefaultValue string
|
||||
// Text next to the input field
|
||||
Label string
|
||||
// Text below the input field
|
||||
Description string
|
||||
// Separates fields with a horizontal rule
|
||||
Separator bool
|
||||
|
||||
Type FieldType
|
||||
|
||||
// Only used when Type = `captcha`
|
||||
CaptchaSiteKey string
|
||||
}
|
||||
|
||||
// FieldType defines the type a form field has and how it should be rendered
|
||||
type FieldType string
|
||||
|
||||
// Fields which can be in a form
|
||||
const (
|
||||
FieldTypeText FieldType = "text"
|
||||
FieldTypeUsername FieldType = "username"
|
||||
FieldTypeEmail FieldType = "email"
|
||||
FieldTypeOldPassword FieldType = "current-password"
|
||||
FieldTypeNewPassword FieldType = "new-password"
|
||||
FieldTypeCaptcha FieldType = "captcha"
|
||||
)
|
@@ -7,6 +7,7 @@ import (
|
||||
"time"
|
||||
|
||||
"fornaxian.com/pixeldrain-web/pixelapi"
|
||||
"fornaxian.com/pixeldrain-web/webcontroller/forms"
|
||||
"github.com/Fornaxian/log"
|
||||
)
|
||||
|
||||
@@ -19,12 +20,15 @@ type TemplateData struct {
|
||||
APIEndpoint template.URL
|
||||
PixelAPI *pixelapi.PixelAPI
|
||||
|
||||
Other interface{}
|
||||
URLQuery url.Values
|
||||
|
||||
// Only used on file viewer page
|
||||
Title string
|
||||
OGData OGData
|
||||
|
||||
Other interface{}
|
||||
URLQuery url.Values
|
||||
|
||||
// Only used for pages containing forms
|
||||
Form forms.Form
|
||||
}
|
||||
|
||||
func (wc *WebController) newTemplateData(w http.ResponseWriter, r *http.Request) *TemplateData {
|
||||
|
@@ -1,9 +1,11 @@
|
||||
package webcontroller
|
||||
|
||||
import (
|
||||
"html/template"
|
||||
"net/http"
|
||||
|
||||
"fornaxian.com/pixeldrain-web/pixelapi"
|
||||
"fornaxian.com/pixeldrain-web/webcontroller/forms"
|
||||
"github.com/Fornaxian/log"
|
||||
"github.com/julienschmidt/httprouter"
|
||||
)
|
||||
@@ -54,3 +56,38 @@ func (wc *WebController) serveLogout(
|
||||
|
||||
http.Redirect(w, r, "/", http.StatusSeeOther)
|
||||
}
|
||||
|
||||
func (wc *WebController) formPassword(
|
||||
w http.ResponseWriter,
|
||||
r *http.Request,
|
||||
p httprouter.Params,
|
||||
) {
|
||||
td := wc.newTemplateData(w, r)
|
||||
td.Form = forms.Form{
|
||||
Title: "Test Form",
|
||||
PreFormHTML: template.HTML("preform"),
|
||||
Fields: []forms.Field{
|
||||
forms.Field{
|
||||
Name: "field_1",
|
||||
DefaultValue: "def val 1",
|
||||
Label: "Field 1",
|
||||
Description: "Description of field one",
|
||||
Separator: false,
|
||||
Type: forms.FieldTypeUsername,
|
||||
},
|
||||
},
|
||||
BackLink: "/",
|
||||
SubmitLabel: "ayy lmao send",
|
||||
SubmitRed: false,
|
||||
PostFormHTML: template.HTML("postform"),
|
||||
Submit: true,
|
||||
SubmitSuccess: true,
|
||||
SubmitMessages: []string{"yay success"},
|
||||
}
|
||||
|
||||
err := wc.templates.Get().ExecuteTemplate(w, "form_page", td)
|
||||
if err != nil {
|
||||
log.Error("Error executing template '%s': %s", "register", err)
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -67,6 +67,9 @@ func New(r *httprouter.Router, prefix string, conf *conf.PixelWebConfig) *WebCon
|
||||
r.GET(p+"/user/files" /* */, wc.serveTemplate("user_files", true))
|
||||
r.GET(p+"/user/lists" /* */, wc.serveTemplate("user_lists", true))
|
||||
r.GET(p+"/user/filemanager" /**/, wc.serveTemplate("file_manager", true))
|
||||
r.GET(p+"/user/password" /* */, wc.serveTemplate("user_password", true))
|
||||
|
||||
r.GET(p+"/testform", wc.formPassword)
|
||||
|
||||
r.NotFound = http.HandlerFunc(wc.serveNotFound)
|
||||
|
||||
|
Reference in New Issue
Block a user