Compare commits
8 commits
main
...
developmen
| Author | SHA1 | Date | |
|---|---|---|---|
| 2a47aa90a3 | |||
|
|
ff0f06c0b9 | ||
|
|
6db6d78ad9 | ||
|
|
88cfe035e0 | ||
|
|
32a37eea32 | ||
|
|
f84ee2a466 | ||
|
|
aba6e13663 | ||
|
|
a0d6ff1cff |
20 changed files with 630 additions and 499 deletions
12
README.md
12
README.md
|
|
@ -1,12 +0,0 @@
|
||||||
# ddServer
|
|
||||||
|
|
||||||
This is a simple Webserver, which helps zou creating monsters for a dungeons & dragons game
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
Either clone the repo and build it your self.
|
|
||||||
- You need to have go installed for that
|
|
||||||
|
|
||||||
Or download the latest release and start your server with
|
|
||||||
```bash
|
|
||||||
./ddServer
|
|
||||||
```
|
|
||||||
5
go.mod
5
go.mod
|
|
@ -2,7 +2,10 @@ module ddServer
|
||||||
|
|
||||||
go 1.21.4
|
go 1.21.4
|
||||||
|
|
||||||
require github.com/stretchr/testify v1.8.4
|
require (
|
||||||
|
github.com/stretchr/testify v1.8.4
|
||||||
|
golang.org/x/text v0.14.0
|
||||||
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
|
|
|
||||||
2
go.sum
2
go.sum
|
|
@ -4,6 +4,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||||
|
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||||
|
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ func AboutHandler(content embed.FS) http.HandlerFunc {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute the template with the provided data
|
// Execute the template with the provided data
|
||||||
data := map[string]any{
|
data := map[string]interface{}{
|
||||||
"Title": "Dungeons & Dragons Monster Generator",
|
"Title": "Dungeons & Dragons Monster Generator",
|
||||||
}
|
}
|
||||||
err = tmpl.ExecuteTemplate(w, "about", data)
|
err = tmpl.ExecuteTemplate(w, "about", data)
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,14 @@ package handlers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"ddServer/model"
|
"ddServer/model"
|
||||||
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"golang.org/x/text/cases"
|
||||||
|
"golang.org/x/text/language"
|
||||||
)
|
)
|
||||||
|
|
||||||
// AddMonster is a http.HandlerFunc that adds a new monster to the Monsters slice.
|
// AddMonster is a http.HandlerFunc that adds a new monster to the Monsters slice.
|
||||||
|
|
@ -94,32 +98,32 @@ func parseMonster(r *http.Request) model.Monster {
|
||||||
Wis: parseInt(r.FormValue("wis")),
|
Wis: parseInt(r.FormValue("wis")),
|
||||||
Cha: parseInt(r.FormValue("cha")),
|
Cha: parseInt(r.FormValue("cha")),
|
||||||
Save: model.Save{
|
Save: model.Save{
|
||||||
Dex: r.FormValue("saveDex"),
|
Dex: checkCheckbox("savedex", r),
|
||||||
Con: r.FormValue("saveCon"),
|
Con: checkCheckbox("savecon", r),
|
||||||
Wis: r.FormValue("saveWis"),
|
Wis: checkCheckbox("savewis", r),
|
||||||
Str: r.FormValue("saveStr"),
|
Str: checkCheckbox("savestr", r),
|
||||||
Cha: r.FormValue("saveCha"),
|
Cha: checkCheckbox("savecha", r),
|
||||||
Int: r.FormValue("saveInt"),
|
Int: checkCheckbox("saveint", r),
|
||||||
},
|
},
|
||||||
Skill: model.Skill{
|
Skill: model.Skill{
|
||||||
Perception: r.FormValue("perception"),
|
Perception: checkCheckbox("perception", r),
|
||||||
Stealth: r.FormValue("stealth"),
|
Stealth: checkCheckbox("stealth", r),
|
||||||
Acrobatics: r.FormValue("acrobatics"),
|
Acrobatics: checkCheckbox("acrobatics", r),
|
||||||
AnimalHandling: r.FormValue("animalHandling"),
|
AnimalHandling: checkCheckbox("animalhandling", r),
|
||||||
Arcana: r.FormValue("arcana"),
|
Arcana: checkCheckbox("arcana", r),
|
||||||
Athletics: r.FormValue("athletics"),
|
Athletics: checkCheckbox("athletics", r),
|
||||||
Deception: r.FormValue("deception"),
|
Deception: checkCheckbox("deception", r),
|
||||||
History: r.FormValue("history"),
|
History: checkCheckbox("history", r),
|
||||||
Insight: r.FormValue("insight"),
|
Insight: checkCheckbox("insight", r),
|
||||||
Intimidation: r.FormValue("intimidation"),
|
Intimidation: checkCheckbox("intimidation", r),
|
||||||
Investigation: r.FormValue("investigation"),
|
Investigation: checkCheckbox("investigation", r),
|
||||||
Medicine: r.FormValue("medicine"),
|
Medicine: checkCheckbox("medicine", r),
|
||||||
Nature: r.FormValue("nature"),
|
Nature: checkCheckbox("nature", r),
|
||||||
Performance: r.FormValue("performance"),
|
Performance: checkCheckbox("performance", r),
|
||||||
Persuasion: r.FormValue("persuasion"),
|
Persuasion: checkCheckbox("persuasion", r),
|
||||||
SleightOfHand: r.FormValue("sleightOfHand"),
|
SleightOfHand: checkCheckbox("sleightofhand", r),
|
||||||
Survival: r.FormValue("survival"),
|
Survival: checkCheckbox("survival", r),
|
||||||
Religion: r.FormValue("religion"),
|
Religion: checkCheckbox("religion", r),
|
||||||
},
|
},
|
||||||
Resist: []string{r.FormValue("resist")},
|
Resist: []string{r.FormValue("resist")},
|
||||||
ConditionImmune: []string{r.FormValue("conditionImmune")},
|
ConditionImmune: []string{r.FormValue("conditionImmune")},
|
||||||
|
|
@ -142,3 +146,10 @@ func parseMonster(r *http.Request) model.Monster {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func checkCheckbox(field string, r *http.Request) string {
|
||||||
|
if r.FormValue(fmt.Sprintf("check%v", cases.Caser(cases.Title(language.Und)).String(field))) == "on" {
|
||||||
|
return r.FormValue(field)
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ func ContactHandler(content embed.FS) http.HandlerFunc {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute the contact template
|
// Execute the contact template
|
||||||
err = tmpl.ExecuteTemplate(w, "contact", map[string]any{
|
err = tmpl.ExecuteTemplate(w, "contact", map[string]interface{}{
|
||||||
"Title": "Dungeons & Dragons Monster Generator",
|
"Title": "Dungeons & Dragons Monster Generator",
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ func FormHandler(content embed.FS, monsters *[]model.Monster) http.HandlerFunc {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute the template and render the response.
|
// Execute the template and render the response.
|
||||||
data := map[string]any{
|
data := map[string]interface{}{
|
||||||
"Title": "Dungeons & Dragons Monster Generator",
|
"Title": "Dungeons & Dragons Monster Generator",
|
||||||
"Monsters": *monsters,
|
"Monsters": *monsters,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
46
handlers/load_file_handler.go
Normal file
46
handlers/load_file_handler.go
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
package handlers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"ddServer/model"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
func LoadFileHandler(monsters *[]model.Monster) http.HandlerFunc {
|
||||||
|
log.Print("LoadFileHandler called")
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
r.ParseMultipartForm(10 << 20) // 10 MB limit
|
||||||
|
|
||||||
|
// Get the file from the request
|
||||||
|
file, _, err := r.FormFile("uploadFile")
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, "Error retrieving file", http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
// Parse the file content
|
||||||
|
decoder := json.NewDecoder(file)
|
||||||
|
var loadedChars model.Character
|
||||||
|
err = decoder.Decode(&loadedChars)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, "Error decoding file content", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lock the Monsters slice and append the loaded monsters, then unlock the slice
|
||||||
|
mu.Lock()
|
||||||
|
defer mu.Unlock()
|
||||||
|
|
||||||
|
// Assuming 'loadedChars' contains an array of Monster objects
|
||||||
|
for _, monster := range loadedChars.Monster {
|
||||||
|
*monsters = append(*monsters, monster)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("%v\n", monsters)
|
||||||
|
// Send a success response
|
||||||
|
http.Redirect(w, r, "/monsterTable", http.StatusTemporaryRedirect)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -16,7 +16,7 @@ func MainHandler(content embed.FS, monsters *[]model.Monster) http.HandlerFunc {
|
||||||
log.Print("MainHandler called")
|
log.Print("MainHandler called")
|
||||||
|
|
||||||
// Parse the templates from the embedded file system
|
// Parse the templates from the embedded file system
|
||||||
tmpl, err := template.ParseFS(content, "templates/main.html", "templates/monsterForm.html", "templates/monster.html", "templates/monsterTable.html", "templates/base.html")
|
tmpl, err := template.ParseFS(content, "templates/main.html", "templates/monsterForm.html", "templates/monster.html", "templates/monsterTable.html", "templates/base.html", "templates/skills.html")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Template parsing error: %v\n", err)
|
log.Printf("Template parsing error: %v\n", err)
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
|
@ -28,7 +28,7 @@ func MainHandler(content embed.FS, monsters *[]model.Monster) http.HandlerFunc {
|
||||||
defer mu.Unlock()
|
defer mu.Unlock()
|
||||||
|
|
||||||
// Execute the main template with the provided data
|
// Execute the main template with the provided data
|
||||||
err = tmpl.ExecuteTemplate(w, "main", map[string]any{
|
err = tmpl.ExecuteTemplate(w, "main", map[string]interface{}{
|
||||||
"Title": "Dungeons & Dragons Monster Generator",
|
"Title": "Dungeons & Dragons Monster Generator",
|
||||||
"Monsters": *monsters,
|
"Monsters": *monsters,
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ func MonsterTableHandler(content embed.FS, monsters *[]model.Monster) http.Handl
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute the template and pass the necessary data
|
// Execute the template and pass the necessary data
|
||||||
err = tmpl.ExecuteTemplate(w, "monsterTable", map[string]any{
|
err = tmpl.ExecuteTemplate(w, "monsterTable", map[string]interface{}{
|
||||||
"Title": "Dungeons & Dragons Monster Generator",
|
"Title": "Dungeons & Dragons Monster Generator",
|
||||||
"Monsters": *monsters,
|
"Monsters": *monsters,
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -8,40 +8,44 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SkillCalculationHandler ist ein http.HandlerFunc, der von htmx getriggert wird,
|
// SkillCalculationHandler is an http.HandlerFunc triggered by htmx when the user makes entries in certain fields and then populates the skill fields.
|
||||||
// wenn der Benutzer Einträge in bestimmten Feldern macht, und dann die Skill-Felder befüllt.
|
|
||||||
func SkillCalculationHandler(content embed.FS) http.HandlerFunc {
|
func SkillCalculationHandler(content embed.FS) http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
log.Print("SkillCalculationHandler called")
|
// Check if the request is a POST request.
|
||||||
|
|
||||||
// Überprüfen Sie, ob die Anfrage eine POST-Anfrage ist.
|
|
||||||
if r.Method != http.MethodPost {
|
if r.Method != http.MethodPost {
|
||||||
log.Print("Method not allowed")
|
|
||||||
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse Formulardaten.
|
// Parse form data.
|
||||||
err := r.ParseForm()
|
err := r.ParseForm()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Error parsing form data: %v", err)
|
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
tmplFiles := []string{"templates/base.html", "templates/header.html", "templates/skills.html", "templates/main.html", "templates/footer.html", "templates/about.html"}
|
// Parse template files.
|
||||||
|
tmplFiles := []string{
|
||||||
|
"templates/base.html",
|
||||||
|
"templates/header.html",
|
||||||
|
"templates/skills.html",
|
||||||
|
"templates/main.html",
|
||||||
|
"templates/footer.html",
|
||||||
|
"templates/about.html",
|
||||||
|
}
|
||||||
tmpl, err := template.ParseFS(content, tmplFiles...)
|
tmpl, err := template.ParseFS(content, tmplFiles...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Template parsing error: %v\n", err)
|
|
||||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Parse form field values and calculate skill values.
|
||||||
str := parseFieldValue(r.FormValue("str"))
|
str := parseFieldValue(r.FormValue("str"))
|
||||||
dex := parseFieldValue(r.FormValue("dex"))
|
dex := parseFieldValue(r.FormValue("dex"))
|
||||||
int := parseFieldValue(r.FormValue("int"))
|
int := parseFieldValue(r.FormValue("int"))
|
||||||
cha := parseFieldValue(r.FormValue("cha"))
|
cha := parseFieldValue(r.FormValue("cha"))
|
||||||
wis := parseFieldValue(r.FormValue("wis"))
|
wis := parseFieldValue(r.FormValue("wis"))
|
||||||
|
con := parseFieldValue(r.FormValue("con"))
|
||||||
cr := parseFieldValue(r.FormValue("cr"))
|
cr := parseFieldValue(r.FormValue("cr"))
|
||||||
crBonus := calcBonus(cr)
|
crBonus := calcBonus(cr)
|
||||||
|
|
||||||
|
|
@ -64,79 +68,124 @@ func SkillCalculationHandler(content embed.FS) http.HandlerFunc {
|
||||||
"sleightOfHand": strconv.Itoa(calcAbilityScore(dex) + crBonus),
|
"sleightOfHand": strconv.Itoa(calcAbilityScore(dex) + crBonus),
|
||||||
"stealth": strconv.Itoa(calcAbilityScore(dex) + crBonus),
|
"stealth": strconv.Itoa(calcAbilityScore(dex) + crBonus),
|
||||||
"survival": strconv.Itoa(calcAbilityScore(wis) + crBonus),
|
"survival": strconv.Itoa(calcAbilityScore(wis) + crBonus),
|
||||||
|
"saveStr": strconv.Itoa(calcAbilityScore(str) + crBonus),
|
||||||
|
"saveWis": strconv.Itoa(calcAbilityScore(wis) + crBonus),
|
||||||
|
"saveCon": strconv.Itoa(calcAbilityScore(con) + crBonus),
|
||||||
|
"saveInt": strconv.Itoa(calcAbilityScore(int) + crBonus),
|
||||||
|
"saveCha": strconv.Itoa(calcAbilityScore(cha) + crBonus),
|
||||||
|
"saveDex": strconv.Itoa(calcAbilityScore(dex) + crBonus),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Execute template with skill values.
|
||||||
err = tmpl.ExecuteTemplate(w, "skills", skillValues)
|
err = tmpl.ExecuteTemplate(w, "skills", skillValues)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Template execution error: %v\n", err)
|
|
||||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// calcBonus calculates the bonus based on the given credit rating.
|
||||||
|
// It returns the bonus value as an integer.
|
||||||
func calcBonus(cr int) int {
|
func calcBonus(cr int) int {
|
||||||
if cr >= 0 && cr < 5 {
|
switch {
|
||||||
|
case cr >= 0 && cr < 5:
|
||||||
|
log.Println("Bonus calculated for credit rating:", cr)
|
||||||
return 2
|
return 2
|
||||||
} else if cr >= 5 && cr < 9 {
|
case cr >= 5 && cr < 9:
|
||||||
|
log.Println("Bonus calculated for credit rating:", cr)
|
||||||
return 3
|
return 3
|
||||||
} else if cr >= 9 && cr < 14 {
|
case cr >= 9 && cr < 14:
|
||||||
|
log.Println("Bonus calculated for credit rating:", cr)
|
||||||
return 4
|
return 4
|
||||||
} else if cr >= 14 && cr < 18 {
|
case cr >= 14 && cr < 18:
|
||||||
|
log.Println("Bonus calculated for credit rating:", cr)
|
||||||
return 5
|
return 5
|
||||||
} else if cr >= 18 && cr < 21 {
|
case cr >= 18 && cr < 21:
|
||||||
|
log.Println("Bonus calculated for credit rating:", cr)
|
||||||
return 6
|
return 6
|
||||||
} else if cr >= 21 && cr < 25 {
|
case cr >= 21 && cr < 25:
|
||||||
|
log.Println("Bonus calculated for credit rating:", cr)
|
||||||
return 7
|
return 7
|
||||||
} else if cr >= 25 && cr < 28 {
|
case cr >= 25 && cr < 28:
|
||||||
|
log.Println("Bonus calculated for credit rating:", cr)
|
||||||
return 8
|
return 8
|
||||||
} else if cr >= 28 && cr < 31 {
|
case cr >= 28 && cr < 31:
|
||||||
|
log.Println("Bonus calculated for credit rating:", cr)
|
||||||
return 9
|
return 9
|
||||||
} else {
|
default:
|
||||||
|
log.Println("Invalid credit rating:", cr)
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// calcAbilityScore calculates the ability score based on the given value.
|
||||||
func calcAbilityScore(val int) int {
|
func calcAbilityScore(val int) int {
|
||||||
if val < 2 {
|
switch {
|
||||||
|
case val < 2:
|
||||||
|
log.Println("Ability Score: -5")
|
||||||
return -5
|
return -5
|
||||||
} else if val >= 2 && val < 4 {
|
case val < 4:
|
||||||
|
log.Println("Ability Score: -4")
|
||||||
return -4
|
return -4
|
||||||
} else if val >= 4 && val < 6 {
|
case val < 6:
|
||||||
|
log.Println("Ability Score: -3")
|
||||||
return -3
|
return -3
|
||||||
} else if val >= 6 && val < 8 {
|
case val < 8:
|
||||||
|
log.Println("Ability Score: -2")
|
||||||
return -2
|
return -2
|
||||||
} else if val >= 8 && val < 10 {
|
case val < 10:
|
||||||
|
log.Println("Ability Score: -1")
|
||||||
return -1
|
return -1
|
||||||
} else if val >= 10 && val < 12 {
|
case val < 12:
|
||||||
|
log.Println("Ability Score: 0")
|
||||||
return 0
|
return 0
|
||||||
} else if val >= 12 && val < 14 {
|
case val < 14:
|
||||||
|
log.Println("Ability Score: 1")
|
||||||
return 1
|
return 1
|
||||||
} else if val >= 14 && val < 16 {
|
case val < 16:
|
||||||
|
log.Println("Ability Score: 2")
|
||||||
return 2
|
return 2
|
||||||
} else if val >= 16 && val < 18 {
|
case val < 18:
|
||||||
|
log.Println("Ability Score: 3")
|
||||||
return 3
|
return 3
|
||||||
} else if val >= 18 && val < 20 {
|
case val < 20:
|
||||||
|
log.Println("Ability Score: 4")
|
||||||
return 4
|
return 4
|
||||||
} else if val >= 20 && val < 22 {
|
case val < 22:
|
||||||
|
log.Println("Ability Score: 5")
|
||||||
return 5
|
return 5
|
||||||
} else if val >= 22 && val < 24 {
|
case val < 24:
|
||||||
|
log.Println("Ability Score: 6")
|
||||||
return 6
|
return 6
|
||||||
} else if val >= 24 && val < 26 {
|
case val < 26:
|
||||||
|
log.Println("Ability Score: 7")
|
||||||
return 7
|
return 7
|
||||||
} else if val >= 26 && val < 28 {
|
case val < 28:
|
||||||
|
log.Println("Ability Score: 8")
|
||||||
return 8
|
return 8
|
||||||
} else if val >= 28 && val < 30 {
|
case val < 30:
|
||||||
|
log.Println("Ability Score: 9")
|
||||||
return 9
|
return 9
|
||||||
} else {
|
default:
|
||||||
|
log.Println("Ability Score: 10")
|
||||||
return 10
|
return 10
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// parseFieldValue takes a string value and returns an integer.
|
||||||
|
// If the string value cannot be converted to an integer, it logs an error and returns 0.
|
||||||
|
// The function follows these rules:
|
||||||
|
// - No line is over 66 characters.
|
||||||
func parseFieldValue(value string) int {
|
func parseFieldValue(value string) int {
|
||||||
|
// Convert the string value to an integer using strconv.Atoi.
|
||||||
|
// If an error occurs during the conversion, log the error and return 0.
|
||||||
val, err := strconv.Atoi(value)
|
val, err := strconv.Atoi(value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Error converting field value to integer: %v", err)
|
log.Printf("Error converting field value to integer: %v", err)
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
// Log the converted integer value for debugging purposes.
|
||||||
|
log.Printf("Converted field value to integer: %d", val)
|
||||||
|
// Return the converted integer value.
|
||||||
return val
|
return val
|
||||||
}
|
}
|
||||||
|
|
|
||||||
1
main.go
1
main.go
|
|
@ -37,6 +37,7 @@ func main() {
|
||||||
routes.HandleFunc("/contact", handlers.ContactHandler(content))
|
routes.HandleFunc("/contact", handlers.ContactHandler(content))
|
||||||
routes.HandleFunc("/monsterTable", handlers.MonsterTableHandler(content, &Monsters))
|
routes.HandleFunc("/monsterTable", handlers.MonsterTableHandler(content, &Monsters))
|
||||||
routes.HandleFunc("/calculate-skills", handlers.SkillCalculationHandler(content))
|
routes.HandleFunc("/calculate-skills", handlers.SkillCalculationHandler(content))
|
||||||
|
routes.HandleFunc("/loadFile", handlers.LoadFileHandler(&Monsters))
|
||||||
// Print the message indicating that 'static' has been included.
|
// Print the message indicating that 'static' has been included.
|
||||||
log.Printf("Eingebunden is %v\n", static)
|
log.Printf("Eingebunden is %v\n", static)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,57 +1,58 @@
|
||||||
{{ define "contact" }}
|
{{ define "contact" }}
|
||||||
<div class="tile is-parent">
|
<div class="tile is-parent">
|
||||||
<div class="tile is-child card ">
|
<div class="tile is-child card ">
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
<div class="media-content">
|
<div class="media-content">
|
||||||
<p class="title is-4">Contact Us</p>
|
<p class="title is-4">Contact Us</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
|
|
||||||
<div class="contact-info">
|
<div class="contact-info">
|
||||||
<h2>Our Contact Information</h2>
|
<h2>Our Contact Information</h2>
|
||||||
<p>You can reach us through the following channels:</p>
|
<p>You can reach us through the following channels:</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li>Email: example@example.com</li>
|
<li>Email: example@example.com</li>
|
||||||
<li>Phone: +123456789</li>
|
<li>Phone: +123456789</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="contact-form">
|
||||||
|
<h2>Contact Form</h2>
|
||||||
|
<form action="/submitContact" method="post">
|
||||||
|
<div class="field">
|
||||||
|
<label for="name">Your Name:</label>
|
||||||
|
<div class="control">
|
||||||
|
<input type="text" name="name" required placeholder="Your name"
|
||||||
|
class="input input-bordered w-full max-w-xs">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="field">
|
||||||
|
<label for="email">Your Email:</label>
|
||||||
|
<div class="control">
|
||||||
|
<input type="email" name="email" required placeholder="Your email"
|
||||||
|
class="input input-bordered w-full max-w-xs">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="field">
|
||||||
|
<label for="message">Your Message:</label>
|
||||||
|
<div class="control">
|
||||||
|
<textarea name="message" required placeholder="Type your message here"
|
||||||
|
class="textarea"></textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="field">
|
||||||
|
<div class="control">
|
||||||
|
<button type="submit" class="button is-primary">Send Message</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="contact-form">
|
|
||||||
<h2>Contact Form</h2>
|
|
||||||
<form action="/submitContact" method="post">
|
|
||||||
<div class="field">
|
|
||||||
<label for="name">Your Name:</label>
|
|
||||||
<div class="control">
|
|
||||||
<input type="text" name="name" required placeholder="Your name"
|
|
||||||
class="input input-bordered w-full max-w-xs">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="field">
|
|
||||||
<label for="email">Your Email:</label>
|
|
||||||
<div class="control">
|
|
||||||
<input type="email" name="email" required placeholder="Your email"
|
|
||||||
class="input input-bordered w-full max-w-xs">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="field">
|
|
||||||
<label for="message">Your Message:</label>
|
|
||||||
<div class="control">
|
|
||||||
<textarea name="message" required placeholder="Type your message here" class="textarea"></textarea>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="field">
|
|
||||||
<div class="control">
|
|
||||||
<button type="submit" class="button is-primary">Send Message</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
|
||||||
|
|
@ -6,4 +6,4 @@
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
@ -78,4 +78,4 @@
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
</header>
|
</header>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
@ -1,109 +1,131 @@
|
||||||
{{ define "main" }}
|
{{ define "main" }}
|
||||||
<div class="tile is-parent">
|
<div class="tile is-parent">
|
||||||
<div class="tile is-child card ">
|
<div class="tile is-child card ">
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
<div class="media-content">
|
<div class="media-content">
|
||||||
<p class="title is-4">Monster Form</p>
|
<p class="title is-4">Monster Form</p>
|
||||||
|
</div>
|
||||||
|
<div class="content">
|
||||||
|
<form hx-post="/loadFile" hx-encoding="multipart/form-data"
|
||||||
|
_='on htmx:xhr:progress(loaded, total) set #progress.value to (loaded/total)*100'>
|
||||||
|
<div class="file">
|
||||||
|
<label class="file-label">
|
||||||
|
<input class="file-input" type="file" name="uploadFile">
|
||||||
|
<span class="file-cta">
|
||||||
|
<span class="file-icon">
|
||||||
|
<i class="fas fa-upload"></i>
|
||||||
|
</span>
|
||||||
|
<span class="file-label">
|
||||||
|
Choose a file…
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="field">
|
||||||
|
<div class="control">
|
||||||
|
<button class="button" type="button" hx-post="/loadFile" hx-trigger="click" hx-target="#monster-table"
|
||||||
|
hx-swap="outerHTML">Press Me</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="content">
|
</div>
|
||||||
<form action="/submit" method="post" class="">
|
</form>
|
||||||
<div class="field">
|
<form action="/submit" method="post" class="">
|
||||||
<td><label for="filename">Filename:</label></td>
|
<div class="field">
|
||||||
<div class="control"><input type="text" name="filename" required placeholder="Dateiname"
|
<td><label for="filename">Filename:</label></td>
|
||||||
class="input input-bordered w-full max-w-xs">
|
<div class="control"><input type="text" name="filename" required placeholder="Dateiname"
|
||||||
</div>
|
class="input input-bordered w-full max-w-xs">
|
||||||
</div>
|
|
||||||
<div class="field">
|
|
||||||
<div class="control">
|
|
||||||
<button type="button" hx-post="/addMonster" hx-trigger="click" hx-target="#monster-table"
|
|
||||||
hx-swap="outerHTML" class="button is-info" hx-boost="true">Add
|
|
||||||
Monster</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{{ template "monsterform" . }}
|
|
||||||
<input type="hidden" name="filename" value="{{.Filename}}">
|
|
||||||
<input type="submit" value="Submit" class="button is-primary">
|
|
||||||
</form>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{{ template "monsterform" . }}
|
||||||
|
<div class="field">
|
||||||
|
<div class="control">
|
||||||
|
<button type="button" hx-post="/addMonster" hx-trigger="click" hx-target="#monster-table"
|
||||||
|
hx-swap="outerHTML" class="button is-info" hx-boost="true">Add
|
||||||
|
Monster</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<input type="hidden" name="filename" value="{{.Filename}}">
|
||||||
|
<input type="submit" value="Submit" class="button is-primary">
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="tile is-parent">
|
<div class="tile is-parent">
|
||||||
<div class="tile is-child card">
|
<div class="tile is-child card">
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
<div class="media-content">
|
<div class="media-content">
|
||||||
<p class="title is-4 is-centered">Existing Monsters</p>
|
<p class="title is-4 is-centered">Existing Monsters</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="table-container">
|
<div class="table-container">
|
||||||
<table class="table">
|
<table class="table">
|
||||||
<colgroup>
|
<colgroup>
|
||||||
<col style="width: 100px;">
|
<col style="width: 100px;">
|
||||||
<col style="width: 100px;">
|
<col style="width: 100px;">
|
||||||
</colgroup>
|
</colgroup>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Name</th>
|
<th>Name</th>
|
||||||
<th>Source</th>
|
<th>Source</th>
|
||||||
<th>Size</th>
|
<th>Size</th>
|
||||||
<th>Type</th>
|
<th>Type</th>
|
||||||
<th>Alignment</th>
|
<th>Alignment</th>
|
||||||
<th>AC</th>
|
<th>AC</th>
|
||||||
<th>AC Form</th>
|
<th>AC Form</th>
|
||||||
<th>HP Average</th>
|
<th>HP Average</th>
|
||||||
<th>HP Formula</th>
|
<th>HP Formula</th>
|
||||||
<th>Walk</th>
|
<th>Walk</th>
|
||||||
<th>Swim</th>
|
<th>Swim</th>
|
||||||
<th>Burrow</th>
|
<th>Burrow</th>
|
||||||
<th>Climb</th>
|
<th>Climb</th>
|
||||||
<th>Fly</th>
|
<th>Fly</th>
|
||||||
<th>Str</th>
|
<th>Str</th>
|
||||||
<th>Dex</th>
|
<th>Dex</th>
|
||||||
<th>Con</th>
|
<th>Con</th>
|
||||||
<th>Int</th>
|
<th>Int</th>
|
||||||
<th>Wis</th>
|
<th>Wis</th>
|
||||||
<th>Cha</th>
|
<th>Cha</th>
|
||||||
<th>Save Dex</th>
|
<th>Save Dex</th>
|
||||||
<th>Save Con</th>
|
<th>Save Con</th>
|
||||||
<th>Save Wis</th>
|
<th>Save Wis</th>
|
||||||
<th>Save Str</th>
|
<th>Save Str</th>
|
||||||
<th>Save Con</th>
|
<th>Save Int</th>
|
||||||
<th>Save Cha</th>
|
<th>Save Cha</th>
|
||||||
<th>Perception</th>
|
<th>Perception</th>
|
||||||
<th>Stealth</th>
|
<th>Stealth</th>
|
||||||
<th>Acrobatics</th>
|
<th>Acrobatics</th>
|
||||||
<th>AnimalHandling</th>
|
<th>AnimalHandling</th>
|
||||||
<th>Arcana</th>
|
<th>Arcana</th>
|
||||||
<th>Athletics</th>
|
<th>Athletics</th>
|
||||||
<th>Deception</th>
|
<th>Deception</th>
|
||||||
<th>History</th>
|
<th>History</th>
|
||||||
<th>Insight</th>
|
<th>Insight</th>
|
||||||
<th>Intimidation</th>
|
<th>Intimidation</th>
|
||||||
<th>Investigation</th>
|
<th>Investigation</th>
|
||||||
<th>Medicine</th>
|
<th>Medicine</th>
|
||||||
<th>Nature</th>
|
<th>Nature</th>
|
||||||
<th>Performance</th>
|
<th>Performance</th>
|
||||||
<th>Persuasion</th>
|
<th>Persuasion</th>
|
||||||
<th>SleightOfHand</th>
|
<th>SleightOfHand</th>
|
||||||
<th>Survival</th>
|
<th>Survival</th>
|
||||||
<th>Religion</th>
|
<th>Religion</th>
|
||||||
<th>Damage Resistance</th>
|
<th>Damage Resistance</th>
|
||||||
<th>Damage Immune</th>
|
<th>Damage Immune</th>
|
||||||
<th>Vulnerable</th>
|
<th>Vulnerable</th>
|
||||||
<th>Condition Immune</th>
|
<th>Condition Immune</th>
|
||||||
<th>Senses</th>
|
<th>Senses</th>
|
||||||
<th>Languages</th>
|
<th>Languages</th>
|
||||||
<th>CR</th>
|
<th>CR</th>
|
||||||
<th>Trait Name</th>
|
<th>Trait Name</th>
|
||||||
<th>Trait Entry</th>
|
<th>Trait Entry</th>
|
||||||
<th>Action Name</th>
|
<th>Action Name</th>
|
||||||
<th>Action Entry</th>
|
<th>Action Entry</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
{{ template "monsterTable" }}
|
{{ template "monsterTable" }}
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
@ -24,7 +24,7 @@
|
||||||
<td>{{.Save.Con}}</td>
|
<td>{{.Save.Con}}</td>
|
||||||
<td>{{.Save.Wis}}</td>
|
<td>{{.Save.Wis}}</td>
|
||||||
<td>{{.Save.Str}}</td>
|
<td>{{.Save.Str}}</td>
|
||||||
<td>{{.Save.Con}}</td>
|
<td>{{.Save.Int}}</td>
|
||||||
<td>{{.Save.Cha}}</td>
|
<td>{{.Save.Cha}}</td>
|
||||||
<td>{{.Skill.Perception}}</td>
|
<td>{{.Skill.Perception}}</td>
|
||||||
<td>{{.Skill.Stealth}}</td>
|
<td>{{.Skill.Stealth}}</td>
|
||||||
|
|
@ -56,4 +56,4 @@
|
||||||
<td>{{range .Actions}}{{.Name}}{{end}}</td>
|
<td>{{range .Actions}}{{.Name}}{{end}}</td>
|
||||||
<td>{{range .Actions}}{{range .Entries}}{{.}}{{end}}{{end}}</td>
|
<td>{{range .Actions}}{{range .Entries}}{{.}}{{end}}{{end}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
@ -87,61 +87,6 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card tile is-ancestor is-vertical">
|
|
||||||
<header class="card-header">
|
|
||||||
<p class="card-header-title">
|
|
||||||
Speed
|
|
||||||
</p>
|
|
||||||
</header>
|
|
||||||
<div class="card-content">
|
|
||||||
<div class="content">
|
|
||||||
<div class="tile is-ancestor">
|
|
||||||
<div class="tile is-parent">
|
|
||||||
<div class="tile is-child field">
|
|
||||||
<label for="walk">Walk:</label>
|
|
||||||
<div class="control">
|
|
||||||
<input type="number" name="walk" required class="input input-bordered w-full max-w-xs">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="tile is-parent">
|
|
||||||
<div class="tile is-child field">
|
|
||||||
<label for="burrow">Burrow:</label>
|
|
||||||
<div class="control">
|
|
||||||
<input type="number" name="burrow" required class="input input-bordered w-full max-w-xs">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="tile is-parent">
|
|
||||||
<div class="tile is-child field">
|
|
||||||
<label for="climb">Climb:</label>
|
|
||||||
<div class="control">
|
|
||||||
<input type="number" name="climb" required class="input input-bordered w-full max-w-xs">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="tile is-ancestor">
|
|
||||||
<div class="tile is-parent">
|
|
||||||
<div class="tile is-child field">
|
|
||||||
<label for="fly">Fly:</label>
|
|
||||||
<div class="control">
|
|
||||||
<input type="number" name="fly" required class="input input-bordered w-full max-w-xs">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="tile is-parent">
|
|
||||||
<div class="tile is-child field">
|
|
||||||
<label for="swim">Swim:</label>
|
|
||||||
<div class="control">
|
|
||||||
<input type="number" name="swim" required class="input input-bordered w-full max-w-xs">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="tile is-ancestor">
|
<div class="tile is-ancestor">
|
||||||
<div class="tile is-parent">
|
<div class="tile is-parent">
|
||||||
<div class="tile is-child field">
|
<div class="tile is-child field">
|
||||||
|
|
@ -209,20 +154,14 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="tile is-parent">
|
</div>
|
||||||
<div class="tile is-child field">
|
<div id="skills" class="tile is-ancestor is-vertical">
|
||||||
<label for="passive">Passive:</label>
|
{{ template "skills" }}
|
||||||
<div class="control">
|
|
||||||
<input type="number" name="passive" required class="input input-bordered w-full max-w-xs"
|
|
||||||
hx-post="/calculate-skills" hx-trigger="keyup changed delay:100ms" hx-target="#skills" hx-swap="innerHTML">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="card tile is-ancestor is-vertical">
|
<div class="card tile is-ancestor is-vertical">
|
||||||
<header class="card-header">
|
<header class="card-header">
|
||||||
<p class="card-header-title">
|
<p class="card-header-title">
|
||||||
Save
|
Speed
|
||||||
</p>
|
</p>
|
||||||
</header>
|
</header>
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
|
|
@ -230,61 +169,50 @@
|
||||||
<div class="tile is-ancestor">
|
<div class="tile is-ancestor">
|
||||||
<div class="tile is-parent gap">
|
<div class="tile is-parent gap">
|
||||||
<div class="tile is-child field">
|
<div class="tile is-child field">
|
||||||
<label for="saveDex">Dex:</label>
|
<label for="walk">Walk:</label>
|
||||||
<div class="control">
|
<div class="control">
|
||||||
<input type="text" name="saveDex" required class="input input-bordered w-full max-w-xs">
|
<input type="number" name="walk" required class="input input-bordered w-full max-w-xs">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="tile is-parent gap">
|
<div class="tile is-parent gap">
|
||||||
<div class="tile is-child field">
|
<div class="tile is-child field">
|
||||||
<label for="saveCon">Con:</label>
|
<label for="burrow">Burrow:</label>
|
||||||
<div class="control">
|
<div class="control">
|
||||||
<input type="text" name="saveCon" required class="input input-bordered w-full max-w-xs">
|
<input type="number" name="burrow" required class="input input-bordered w-full max-w-xs">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="tile is-parent gap">
|
<div class="tile is-parent gap">
|
||||||
<div class="tile is-child field">
|
<div class="tile is-child field">
|
||||||
<label for="saveWis">Wis:</label>
|
<label for="climb">Climb:</label>
|
||||||
<div class="control">
|
<div class="control">
|
||||||
<input type="text" name="saveWis" required class="input input-bordered w-full max-w-xs">
|
<input type="number" name="climb" required class="input input-bordered w-full max-w-xs">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="tile is-ancestor">
|
||||||
<div class="tile is-ancestor">
|
<div class="tile is-parent gap">
|
||||||
<div class="tile is-parent gap">
|
<div class="tile is-child field">
|
||||||
<div class="tile is-child field">
|
<label for="fly">Fly:</label>
|
||||||
<label for="saveCha">Cha:</label>
|
<div class="control">
|
||||||
<div class="control">
|
<input type="number" name="fly" required class="input input-bordered w-full max-w-xs">
|
||||||
<input type="text" name="saveCha" required class="input input-bordered w-full max-w-xs">
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="tile is-parent gap">
|
||||||
<div class="tile is-parent gap">
|
<div class="tile is-child field">
|
||||||
<div class="tile is-child field">
|
<label for="swim">Swim:</label>
|
||||||
<label for="saveInt">Int:</label>
|
<div class="control">
|
||||||
<div class="control">
|
<input type="number" name="swim" required class="input input-bordered w-full max-w-xs">
|
||||||
<input type="text" name="saveInt" required class="input input-bordered w-full max-w-xs">
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="tile is-parent gap">
|
|
||||||
<div class="tile is-child field">
|
|
||||||
<label for="saveStr">Str:</label>
|
|
||||||
<div class="control">
|
|
||||||
<input type="text" name="saveStr" required class="input input-bordered w-full max-w-xs">
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="skills" class="card tile is-ancestor is-vertical">
|
|
||||||
{{ template "skills" }}
|
|
||||||
</div>
|
|
||||||
<div class="tile is-ancestor">
|
<div class="tile is-ancestor">
|
||||||
<div class="tile is-parent">
|
<div class="tile is-parent">
|
||||||
<div class="tile is-child field">
|
<div class="tile is-child field">
|
||||||
|
|
@ -375,4 +303,4 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
@ -4,4 +4,4 @@
|
||||||
{{ template "monster" . }}
|
{{ template "monster" . }}
|
||||||
</tbody>
|
</tbody>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
@ -1,185 +1,265 @@
|
||||||
{{ define "skills" }}
|
{{ define "skills" }}
|
||||||
<header class="card-header">
|
<div class="tile is-parent">
|
||||||
<p class="card-header-title">
|
<div class="card tile is-child is-ancestor is-vertical">
|
||||||
Skill
|
<header class="card-header">
|
||||||
</p>
|
<p class="card-header-title">
|
||||||
</header>
|
Save
|
||||||
<div class="card-content">
|
</p>
|
||||||
<div class="content">
|
</header>
|
||||||
<div class="tile is-ancestor">
|
<div class="card-content">
|
||||||
<div class="tile is-parent">
|
<div class="content">
|
||||||
<div class="tile is-child field">
|
<div class="tile is-ancestor">
|
||||||
<label for="acrobatics">Acrobatics:</label>
|
<div class="tile is-parent gap">
|
||||||
<div class="control">
|
<div class="tile is-child field">
|
||||||
<input type="text" name="acrobatics" required class="input input-bordered w-full max-w-xs" value="{{
|
<label class="checkbox" for="savedex"><input type="checkbox" name="checkSavedex">Dex:</label>
|
||||||
.acrobatics }}" readonly>
|
<div class="control">
|
||||||
|
<input type="text" name="savedex" required class="input input-bordered w-full max-w-xs"
|
||||||
|
value="{{.saveDex}}" readonly>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="tile is-parent gap">
|
||||||
|
<div class="tile is-child field">
|
||||||
|
<label class="checkbox" for="savecon"><input type="checkbox" name="checkSavecon">Con:</label>
|
||||||
|
<div class="control">
|
||||||
|
<input type="text" name="savecon" required class="input input-bordered w-full max-w-xs"
|
||||||
|
value="{{.saveCon}}" readonly>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="tile is-parent gap">
|
||||||
|
<div class="tile is-child field">
|
||||||
|
<label class="checkbox" for="savewis"><input type="checkbox" name="checkSavewis">Wis:</label>
|
||||||
|
<div class="control">
|
||||||
|
<input type="text" name="savewis" required class="input input-bordered w-full max-w-xs"
|
||||||
|
value="{{.saveWis}}" readonly>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="tile is-parent">
|
<div class="tile is-ancestor">
|
||||||
<div class="tile is-child field">
|
<div class="tile is-parent gap">
|
||||||
<label for="animalHandling">Animal Handling:</label>
|
<div class="tile is-child field">
|
||||||
<div class="control">
|
<label class="checkbox" for="savecha"><input type="checkbox" name="checkSavecha">Cha:</label>
|
||||||
<input type="text" name="animalHandling" required class="input input-bordered w-full max-w-xs"
|
<div class="control">
|
||||||
value="{{ .animalHandling }}" readonly>
|
<input type="text" name="savecha" required class="input input-bordered w-full max-w-xs"
|
||||||
|
value="{{.saveCha}}" readonly>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="tile is-parent gap">
|
||||||
<div class="tile is-parent">
|
<div class="tile is-child field">
|
||||||
<div class="tile is-child field">
|
<label class="checkbox" for="saveint"><input type="checkbox" name="checkSaveint">Int:</label>
|
||||||
<label for="arcana">Arcana:</label>
|
<div class="control">
|
||||||
<div class="control">
|
<input type="text" name="saveint" required class="input input-bordered w-full max-w-xs"
|
||||||
<input type="text" name="arcana" required class="input input-bordered w-full max-w-xs" value="{{ .arcana }}"
|
value="{{.saveInt}}" readonly>
|
||||||
readonly>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="tile is-parent gap">
|
||||||
</div>
|
<div class="tile is-child field">
|
||||||
<div class="tile is-ancestor">
|
<label class="checkbox" for="savestr"><input type="checkbox" name="checkSavestr">Str:</label>
|
||||||
<div class="tile is-parent">
|
<div class="control">
|
||||||
<div class="tile is-child field">
|
<input type="text" name="savestr" required class="input input-bordered w-full max-w-xs"
|
||||||
<label for="athletics">Athletics:</label>
|
value="{{.saveStr}}" readonly>
|
||||||
<div class="control">
|
</div>
|
||||||
<input type="text" name="athletics" required class="input input-bordered w-full max-w-xs"
|
|
||||||
value="{{ .athletics }}" readonly>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="tile is-parent">
|
|
||||||
<div class="tile is-child field">
|
|
||||||
<label for="deception">Deception:</label>
|
|
||||||
<div class="control">
|
|
||||||
<input type="text" name="deception" required class="input input-bordered w-full max-w-xs"
|
|
||||||
value="{{ .deception }}" readonly>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="tile is-parent">
|
|
||||||
<div class="tile is-child field">
|
|
||||||
<label for="history">History:</label>
|
|
||||||
<div class="control">
|
|
||||||
<input type="text" name="history" required class="input input-bordered w-full max-w-xs"
|
|
||||||
value="{{ .history }}" readonly>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="tile is-ancestor">
|
|
||||||
<div class="tile is-parent">
|
|
||||||
<div class="tile is-child field">
|
|
||||||
<label for="insight">Insight:</label>
|
|
||||||
<div class="control">
|
|
||||||
<input type="text" name="insight" required class="input input-bordered w-full max-w-xs"
|
|
||||||
value="{{ .insight }}" readonly>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="tile is-parent">
|
|
||||||
<div class="tile is-child field">
|
|
||||||
<label for="intimidation">Intimidation:</label>
|
|
||||||
<div class="control">
|
|
||||||
<input type="text" name="intimidation" required class="input input-bordered w-full max-w-xs"
|
|
||||||
value="{{ .intimidation }}" readonly>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="tile is-parent">
|
|
||||||
<div class="tile is-child field">
|
|
||||||
<label for="investigation">Investigation:</label>
|
|
||||||
<div class="control">
|
|
||||||
<input type="text" name="investigation" required class="input input-bordered w-full max-w-xs"
|
|
||||||
value="{{ .investigation }}" readonly>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="tile is-ancestor">
|
|
||||||
<div class="tile is-parent">
|
|
||||||
<div class="tile is-child field">
|
|
||||||
<label for="medicine">Medicine:</label>
|
|
||||||
<div class="control">
|
|
||||||
<input type="text" name="medicine" required class="input input-bordered w-full max-w-xs"
|
|
||||||
value="{{ .medicine }}" readonly>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="tile is-parent">
|
|
||||||
<div class="tile is-child field">
|
|
||||||
<label for="nature">Nature:</label>
|
|
||||||
<div class="control">
|
|
||||||
<input type="text" name="nature" required class="input input-bordered w-full max-w-xs" value="{{ .nature }}"
|
|
||||||
readonly>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="tile is-parent">
|
|
||||||
<div class="tile is-child field">
|
|
||||||
<label for="performance">Performance:</label>
|
|
||||||
<div class="control">
|
|
||||||
<input type="text" name="performance" required class="input input-bordered w-full max-w-xs"
|
|
||||||
value="{{ .performance }}" readonly>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="tile is-ancestor">
|
|
||||||
<div class="tile is-parent">
|
|
||||||
<div class="tile is-child field">
|
|
||||||
<label for="perception">Perception:</label>
|
|
||||||
<div class="control">
|
|
||||||
<input type="text" name="perception" required class="input input-bordered w-full max-w-xs"
|
|
||||||
value="{{ .perception }}" readonly>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="tile is-parent">
|
|
||||||
<div class="tile is-child field">
|
|
||||||
<label for="stealth">Stealth:</label>
|
|
||||||
<div class="control">
|
|
||||||
<input type="text" name="stealth" required class="input input-bordered w-full max-w-xs"
|
|
||||||
value="{{ .stealth }}" readonly>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="tile is-parent">
|
|
||||||
<div class="tile is-child field">
|
|
||||||
<label for="persuasion">Persuasion:</label>
|
|
||||||
<div class="control">
|
|
||||||
<input type="text" name="persuasion" required class="input input-bordered w-full max-w-xs"
|
|
||||||
value="{{ .persuasion }}" readonly>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="tile is-ancestor">
|
|
||||||
<div class="tile is-parent">
|
|
||||||
<div class="tile is-child field">
|
|
||||||
<label for="sleightOfHand">Sleight of Hand:</label>
|
|
||||||
<div class="control">
|
|
||||||
<input type="text" name="sleightOfHand" required class="input input-bordered w-full max-w-xs"
|
|
||||||
value="{{.sleightOfHand }}" readonly>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="tile is-parent">
|
|
||||||
<div class="tile is-child field">
|
|
||||||
<label for="religion">Religion:</label>
|
|
||||||
<div class="control">
|
|
||||||
<input type="text" name="religion" required class="input input-bordered w-full max-w-xs"
|
|
||||||
value="{{ .religion }}" readonly>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="tile is-parent">
|
|
||||||
<div class="tile is-child field">
|
|
||||||
<label for="survival">Survival:</label>
|
|
||||||
<div class="control">
|
|
||||||
<input type="text" name="survival" required class="input input-bordered w-full max-w-xs"
|
|
||||||
value="{{ .survival }}" readonly>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{ end }}
|
<div class="tile is-parent">
|
||||||
|
<div class="card tile is-child is-ancestor is-vertical">
|
||||||
|
<header class="card-header">
|
||||||
|
<p class="card-header-title">
|
||||||
|
Skill
|
||||||
|
</p>
|
||||||
|
</header>
|
||||||
|
<div class="card-content">
|
||||||
|
<div class="content">
|
||||||
|
<div class="tile is-ancestor">
|
||||||
|
<div class="tile is-parent">
|
||||||
|
<div class="tile is-child field">
|
||||||
|
<label class="checkbox" for="acrobatics"><input type="checkbox" name="checkAcrobatics">Acrobatics:</label>
|
||||||
|
<div class="control">
|
||||||
|
<input type="text" name="acrobatics" required class="input input-bordered w-full max-w-xs" value="{{
|
||||||
|
.acrobatics }}" readonly>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="tile is-parent">
|
||||||
|
<div class="tile is-child field">
|
||||||
|
<label for="animalhandling" class="checkbox"><input type="checkbox" name="checkAnimalhandling">Animal
|
||||||
|
Handling:</label>
|
||||||
|
<div class="control">
|
||||||
|
<input type="text" name="animalhandling" required class="input input-bordered w-full max-w-xs"
|
||||||
|
value="{{ .animalHandling }}" readonly>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="tile is-parent">
|
||||||
|
<div class="tile is-child field">
|
||||||
|
<label for="arcana" class="ceckbox"><input type="checkbox" name="checkArcana">Arcana:</label>
|
||||||
|
<div class="control">
|
||||||
|
<input type="text" name="arcana" required class="input input-bordered w-full max-w-xs"
|
||||||
|
value="{{ .arcana }}" readonly>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="tile is-ancestor">
|
||||||
|
<div class="tile is-parent">
|
||||||
|
<div class="tile is-child field">
|
||||||
|
<label for="athletics" class="checkbox"><input type="checkbox" name="checkAthletics">Athletics:</label>
|
||||||
|
<div class="control">
|
||||||
|
<input type="text" name="athletics" required class="input input-bordered w-full max-w-xs"
|
||||||
|
value="{{ .athletics }}" readonly>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="tile is-parent">
|
||||||
|
<div class="tile is-child field">
|
||||||
|
<label for="deception" class="checkbox"><input type="checkbox" name="checkDeception">Deception:</label>
|
||||||
|
<div class="control">
|
||||||
|
<input type="text" name="deception" required class="input input-bordered w-full max-w-xs"
|
||||||
|
value="{{ .deception }}" readonly>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="tile is-parent">
|
||||||
|
<div class="tile is-child field">
|
||||||
|
<label for="history" class="checkbox"><input type="checkbox" name="checkHistory">History:</label>
|
||||||
|
<div class="control">
|
||||||
|
<input type="text" name="history" required class="input input-bordered w-full max-w-xs"
|
||||||
|
value="{{ .history }}" readonly>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="tile is-ancestor">
|
||||||
|
<div class="tile is-parent">
|
||||||
|
<div class="tile is-child field">
|
||||||
|
<label for="insight" class="checkbox"><input type="checkbox" name="checkInsight">Insight:</label>
|
||||||
|
<div class="control">
|
||||||
|
<input type="text" name="insight" required class="input input-bordered w-full max-w-xs"
|
||||||
|
value="{{ .insight }}" readonly>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="tile is-parent">
|
||||||
|
<div class="tile is-child field">
|
||||||
|
<label for="intimidation" class="checkbox"><input type="checkbox"
|
||||||
|
name="checkIntimidation">Intimidation:</label>
|
||||||
|
<div class="control">
|
||||||
|
<input type="text" name="intimidation" required class="input input-bordered w-full max-w-xs"
|
||||||
|
value="{{ .intimidation }}" readonly>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="tile is-parent">
|
||||||
|
<div class="tile is-child field">
|
||||||
|
<label for="investigation" class="checkbox"><input type="checkbox"
|
||||||
|
name="checkInvestigation">Investigation:</label>
|
||||||
|
<div class="control">
|
||||||
|
<input type="text" name="investigation" required class="input input-bordered w-full max-w-xs"
|
||||||
|
value="{{ .investigation }}" readonly>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="tile is-ancestor">
|
||||||
|
<div class="tile is-parent">
|
||||||
|
<div class="tile is-child field">
|
||||||
|
<label for="medicine" class="checkbox"><input type="checkbox" name="checkMedicine">Medicine:</label>
|
||||||
|
<div class="control">
|
||||||
|
<input type="text" name="medicine" required class="input input-bordered w-full max-w-xs"
|
||||||
|
value="{{ .medicine }}" readonly>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="tile is-parent">
|
||||||
|
<div class="tile is-child field">
|
||||||
|
<label for="nature" class="checkbox"><input type="checkbox" name="checkNature">Nature:</label>
|
||||||
|
<div class="control">
|
||||||
|
<input type="text" name="nature" required class="input input-bordered w-full max-w-xs"
|
||||||
|
value="{{ .nature }}" readonly>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="tile is-parent">
|
||||||
|
<div class="tile is-child field">
|
||||||
|
<label for="performance" class="checkbox"><input type="checkbox"
|
||||||
|
name="checkPerformance">Performance:</label>
|
||||||
|
<div class="control">
|
||||||
|
<input type="text" name="performance" required class="input input-bordered w-full max-w-xs"
|
||||||
|
value="{{ .performance }}" readonly>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="tile is-ancestor">
|
||||||
|
<div class="tile is-parent">
|
||||||
|
<div class="tile is-child field">
|
||||||
|
<label for="perception" class="checkbox"><input type="checkbox" name="checkPerception">Perception:</label>
|
||||||
|
<div class="control">
|
||||||
|
<input type="text" name="perception" required class="input input-bordered w-full max-w-xs"
|
||||||
|
value="{{ .perception }}" readonly>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="tile is-parent">
|
||||||
|
<div class="tile is-child field">
|
||||||
|
<label for="stealth" class="checkbox"><input type="checkbox" name="checkStealth">Stealth:</label>
|
||||||
|
<div class="control">
|
||||||
|
<input type="text" name="stealth" required class="input input-bordered w-full max-w-xs"
|
||||||
|
value="{{ .stealth }}" readonly>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="tile is-parent">
|
||||||
|
<div class="tile is-child field">
|
||||||
|
<label for="persuasion" class="checkbox"><input type="checkbox" name="checkPersuasion">Persuasion:</label>
|
||||||
|
<div class="control">
|
||||||
|
<input type="text" name="persuasion" required class="input input-bordered w-full max-w-xs"
|
||||||
|
value="{{ .persuasion }}" readonly>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="tile is-ancestor">
|
||||||
|
<div class="tile is-parent">
|
||||||
|
<div class="tile is-child field">
|
||||||
|
<label for="sleightofhand" class="checkbox"><input type="checkbox" name="checkSleightofhand">Sleight of
|
||||||
|
Hand:</label>
|
||||||
|
<div class="control">
|
||||||
|
<input type="text" name="sleightofhand" required class="input input-bordered w-full max-w-xs"
|
||||||
|
value="{{.sleightOfHand }}" readonly>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="tile is-parent">
|
||||||
|
<div class="tile is-child field">
|
||||||
|
<label for="religion" class="checkbox"><input type="checkbox" name="checkReligion">Religion:</label>
|
||||||
|
<div class="control">
|
||||||
|
<input type="text" name="religion" required class="input input-bordered w-full max-w-xs"
|
||||||
|
value="{{ .religion }}" readonly>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="tile is-parent">
|
||||||
|
<div class="tile is-child field">
|
||||||
|
<label for="survival" class="checkbox"><input type="checkbox" name="checkSurvival">Survival:</label>
|
||||||
|
<div class="control">
|
||||||
|
<input type="text" name="survival" required class="input input-bordered w-full max-w-xs"
|
||||||
|
value="{{ .survival }}" readonly>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue