The Go code for the chart part
The basic of charts in Go is the possibility to add a function into Go HTML template. Similar to Javascript in HTML onclick="myFunction()". The difference is that this custom template function will be reachable from all templates.
1. The chart() function
This is the "func" that is called from the Go template.
func chart(path string) string { rest := strings.Split(path, "/") module := rest[0] mode := rest[1] val := rest[2] sfx := rest[3] //suffix to address separate charts json_data := get_data(module, mode, val) switch mode { case "bar": return get_bar(json_data, sfx) case "pie": return get_pie(json_data, sfx) case "line": return get_line(json_data, sfx) } return "bar" }
2. Add chart() function to all Go templates
I prefer to do this once in an init() function
func init() { tpl = template.Must(template.New("").Funcs(template.FuncMap{ "chart": chart, //add the chart function }).ParseGlob("./public/tmpl/*/*.html")) //two levels deep }
3. The Go chart code
I have separated all chart functions in a separate Go file.
package main import ( "strings" ) func chart(path string) string { rest := strings.Split(path, "/") module := rest[0] mode := rest[1] val := rest[2] sfx := rest[3] //to address separate charts json_data := get_data(module, mode, val) switch mode { case "bar": return get_bar(json_data, sfx) case "pie": return get_pie(json_data, sfx) case "line": return get_line(json_data, sfx) } return "bar" } func get_data(module, mode, val string) string { return `{ "Active":"25", "On hold":"20", "Draft":"30" }` } func get_bar(json_data, sfx string) string { return ` var chartContainer` + sfx + ` = document.getElementById('chrt` + sfx + `'); var myChart` + sfx + ` = echarts.init(chartContainer` + sfx + `); var jsonData` + sfx + ` = ` + json_data + `; var option` + sfx + `; var xAxisData` + sfx + ` = Object.keys(jsonData` + sfx + `); var seriesData` + sfx + ` = Object.values(jsonData` + sfx + `).map(Number); option` + sfx + ` = { xAxis: { data: xAxisData` + sfx + `, }, tooltip: { trigger: 'item' }, yAxis: {}, series: [{ type: 'bar', data: seriesData` + sfx + `, }], }; chartContainer` + sfx + `.style.width = chartContainer` + sfx + `.parentElement.clientWidth + 'px'; chartContainer` + sfx + `.style.height = chartContainer` + sfx + `.parentElement.clientHeight + 'px'; myChart` + sfx + `.getDom().style.width = '100%'; myChart` + sfx + `.getDom().style.height = '100%'; myChart` + sfx + `.resize(); myChart` + sfx + `.setOption(option` + sfx + `); ` } func get_pie(json_data, sfx string) string { return ` var chartContainer` + sfx + ` = document.getElementById('chrt` + sfx + `'); var myChart` + sfx + ` = echarts.init(chartContainer` + sfx + `); let jsonData` + sfx + ` = ` + json_data + `; let option` + sfx + `; var legendData` + sfx + ` = Object.keys(jsonData` + sfx + `); var seriesData` + sfx + ` = legendData` + sfx + `.map(function(name) { return { name: name, value: jsonData` + sfx + `[name] }; }); option` + sfx + ` = { legend: { data: legendData` + sfx + `, }, tooltip: { trigger: 'item' }, series: [{ type: 'pie', radius: '55%', data: seriesData` + sfx + `, }], }; chartContainer` + sfx + `.style.width = '100%'; chartContainer` + sfx + `.style.height = '100%'; myChart` + sfx + `.getDom().style.width = '100%'; myChart` + sfx + `.getDom().style.height = '100%'; myChart` + sfx + `.resize(); myChart` + sfx + `.setOption(option` + sfx + `); ` } func get_line(json_data, sfx string) string { return ` var chartContainer` + sfx + ` = document.getElementById('chrt` + sfx + `'); var myChart` + sfx + ` = echarts.init(chartContainer` + sfx + `); var jsonData` + sfx + ` = ` + json_data + `; var option` + sfx + `; var xAxisData` + sfx + ` = Object.keys(jsonData` + sfx + `); var seriesData` + sfx + ` = Object.values(jsonData` + sfx + `).map(Number); option` + sfx + ` = { xAxis: { data: xAxisData` + sfx + `, }, tooltip: { trigger: 'axis', }, yAxis: {}, series: [{ type: 'line', data: seriesData` + sfx + `, }], }; chartContainer` + sfx + `.style.width = chartContainer` + sfx + `.parentElement.clientWidth + 'px'; chartContainer` + sfx + `.style.height = chartContainer` + sfx + `.parentElement.clientHeight + 'px'; // Set the canvas width and height to 100% to ensure it fits within the container myChart` + sfx + `.getDom().style.width = '100%'; myChart` + sfx + `.getDom().style.height = '100%'; myChart` + sfx + `.resize(); myChart` + sfx + `.setOption(option` + sfx + `); ` }
4. The Go main code
package main import ( "net/http" "strings" "text/template" ) var tpl *template.Template func init() { tpl = template.Must(template.New("").Funcs(template.FuncMap{ "chart": chart, }).ParseGlob("./public/tmpl/*/*.html")) http.Handle("/img/", http.StripPrefix("/img/", http.FileServer(http.Dir("./public/img")))) http.Handle("/css/", http.StripPrefix("/css/", http.FileServer(http.Dir("./public/css")))) http.Handle("/icn/", http.StripPrefix("/icn/", http.FileServer(http.Dir("./public/icn")))) http.Handle("/js/", http.StripPrefix("/js/", http.FileServer(http.Dir("./public/js")))) http.Handle("/misc/", http.StripPrefix("/misc/", http.FileServer(http.Dir("./public/misc")))) } func main() { http.HandleFunc("/", endpoint) http.ListenAndServe(":9098", nil) } func endpoint(w http.ResponseWriter, r *http.Request) { module, mode, _ := getpath(r.URL.Path) var page string switch module { case "robots.txt": http.ServeFile(w, r, "public/misc/robots.txt") case "sitemap.xml": http.ServeFile(w, r, "public/misc/sitemap.xml") case "favicon.ico", "favicon-32x32.png", "favicon-16x16.png": return case "": module = "home" } switch mode { case "edit", "new", "view", "find", "goto", "status", "timer": default: page = module + ".html" set_header(w) // data := json2map(module, mode, val) tpl.ExecuteTemplate(w, page, nil) } } // split url func getpath(path string) (module, mode, val string) { parts := strings.Split(path, "/") switch len(parts) { case 4: val = parts[3] fallthrough case 3: mode = parts[2] fallthrough case 2: module = parts[1] } return // Named return values are used, so just return here } func set_header(w http.ResponseWriter) { w.Header().Set("Access-Control-Allow-Origin", "*") w.Header().Set("Access-Control-Allow-Methods", "*") }