projecto completo creo, me quedo bonito :3

This commit is contained in:
Daniel Cortés
2019-04-17 12:36:31 -04:00
commit 3c55ad2713
17 changed files with 1356 additions and 0 deletions

141
database.go Normal file
View File

@@ -0,0 +1,141 @@
package main
import (
"database/sql"
_ "github.com/mattn/go-sqlite3"
"todo/models"
)
type DatabaseInterface interface {
GetTodos() ([]models.Todo, error)
GetTodo(int) (models.Todo, error)
CreateTodo(models.Todo) error
DoTodo(int) error
UndoTodo(int) error
DeleteTodo(int) error
}
type DatabaseStore struct {
DB *sql.DB
}
func MustNewDB() *DatabaseStore {
db, err := sql.Open("sqlite3", "./database.sqlite")
if err != nil {
panic(err)
}
err = db.Ping()
if err != nil {
panic(err)
}
return &DatabaseStore{db}
}
func (store *DatabaseStore) GetTodos() ([]models.Todo, error) {
selectAll := `select id, todo, done from todo`
rows, err := store.DB.Query(selectAll)
if err != nil {
return []models.Todo{}, err
}
defer rows.Close()
todos := []models.Todo{}
for rows.Next() {
todo := models.Todo{}
err = rows.Scan(&todo.Id, &todo.Todo, &todo.Done)
if err != nil {
return []models.Todo{}, err
}
todos = append(todos, todo)
}
return todos, nil
}
func (store *DatabaseStore) GetTodo(id int) (models.Todo, error) {
selectOne := `select id, todo, done from todo where id = ?`
var todo models.Todo
err := store.DB.QueryRow(selectOne, id).Scan(&todo.Id, &todo.Todo, &todo.Done)
if err != nil {
return models.Todo{}, err
}
return todo, nil
}
func (store *DatabaseStore) CreateTodo(todo models.Todo) error {
createTodo := `insert into todo (todo, done) values (?, ?)`
statement, err := store.DB.Prepare(createTodo)
if err != nil {
return err
}
defer statement.Close()
_, err = statement.Exec(todo.Todo, false)
if err != nil {
return err
}
return nil
}
func (store *DatabaseStore) ToggleTodo(id int) error {
todo, err := store.GetTodo(id)
if err != nil {
return err
}
setDone := `update todo set done = ? where id = ?`
statement, err := store.DB.Prepare(setDone)
if err != nil {
return err
}
defer statement.Close()
_, err = statement.Exec(!todo.Done, id)
if err != nil {
return err
}
return nil
}
func (store *DatabaseStore) UpdateTodo(todo models.Todo) error {
updateTodo := `update todo set todo = ? where id = ?`
statement, err := store.DB.Prepare(updateTodo)
if err != nil {
return err
}
defer statement.Close()
_, err = statement.Exec(todo.Todo, todo.Id)
if err != nil {
return err
}
return nil
}
func (store *DatabaseStore) DeleteTodo(id int) error {
deleteTodo := `delete from todo where id = ?`
statement, err := store.DB.Prepare(deleteTodo)
if err != nil {
return err
}
defer statement.Close()
_, err = statement.Exec(id)
if err != nil {
return err
}
return nil
}

BIN
database.sqlite Normal file

Binary file not shown.

20
file_server.go Normal file
View File

@@ -0,0 +1,20 @@
package main
import (
"github.com/go-chi/chi"
"net/http"
)
func fileServer(r chi.Router, path string, root http.FileSystem) {
fs := http.StripPrefix(path, http.FileServer(root))
if path != "/" && path[len(path)-1] != '/' {
r.Get(path, http.RedirectHandler(path+"/", 301).ServeHTTP)
path += "/"
}
path += "*"
r.Get(path, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fs.ServeHTTP(w, r)
}))
}

108
handler.go Normal file
View File

@@ -0,0 +1,108 @@
package main
import (
"net/http"
"todo/templates"
"todo/models"
"strconv"
"github.com/go-chi/chi"
)
var store = MustNewDB()
func indexHandler(w http.ResponseWriter, r *http.Request) {
todos, err := store.GetTodos()
if err != nil {
templates.WritePage(w, &templates.Error500Page{"Error al intentar obtener todos los TODO", err.Error()})
return
}
templates.WritePage(w, &templates.IndexPage{todos})
}
func createHandler(w http.ResponseWriter, r *http.Request) {
r.ParseForm()
todo := models.Todo{Id: 0, Todo: r.FormValue("todo"), Done: false}
err := store.CreateTodo(todo)
if err != nil {
templates.WritePage(w, &templates.Error500Page{"Error al intentar crear un nuevo TODO", err.Error()})
return
}
http.Redirect(w, r, "/", http.StatusSeeOther)
}
func toggleHandler(w http.ResponseWriter, r *http.Request) {
id, err := strconv.Atoi(chi.URLParam(r, "id"))
if err != nil {
templates.WritePage(w, &templates.Error500Page{"El id entregado es invalido", err.Error()})
return
}
err = store.ToggleTodo(id)
if err != nil {
templates.WritePage(w, &templates.Error500Page{"Error al actualizar el TODO", err.Error()})
return
}
http.Redirect(w, r, "/", http.StatusSeeOther)
}
func deleteHandler(w http.ResponseWriter, r *http.Request) {
id, err := strconv.Atoi(chi.URLParam(r, "id"))
if err != nil {
templates.WritePage(w, &templates.Error500Page{"El id entregado es invalido", err.Error()})
return
}
err = store.DeleteTodo(id)
if err != nil {
templates.WritePage(w, &templates.Error500Page{"Error al eliminar el TODO", err.Error()})
return
}
http.Redirect(w, r, "/", http.StatusSeeOther)
}
func editHandler(w http.ResponseWriter, r *http.Request) {
id, err := strconv.Atoi(chi.URLParam(r, "id"))
if err != nil {
templates.WritePage(w, &templates.Error500Page{"El id entregado es invalido", err.Error()})
return
}
todos, err := store.GetTodos()
if err != nil {
templates.WritePage(w, &templates.Error500Page{"Error al intentar obtener todos los TODO", err.Error()})
return
}
editingTodo, err := store.GetTodo(id)
if err != nil {
templates.WritePage(w, &templates.Error500Page{"Error al intentar obtener un TODO", err.Error()})
return
}
templates.WritePage(w, &templates.EditPage{todos, editingTodo})
}
func updateHandler(w http.ResponseWriter, r *http.Request) {
r.ParseForm()
id, err := strconv.Atoi(chi.URLParam(r, "id"))
if err != nil {
templates.WritePage(w, &templates.Error500Page{"El id entregado es invalido", err.Error()})
return
}
message := r.FormValue("todo")
todo := models.Todo{Id: id, Todo: message }
err = store.UpdateTodo(todo)
if err != nil {
templates.WritePage(w, &templates.Error500Page{"Error al intentar actualizar un TODO", err.Error()})
return
}
http.Redirect(w, r, "/", http.StatusSeeOther)
}

36
main.go Normal file
View File

@@ -0,0 +1,36 @@
package main
import (
"github.com/go-chi/chi"
"github.com/go-chi/chi/middleware"
_ "github.com/mattn/go-sqlite3"
"log"
"net/http"
"os"
"path/filepath"
)
func main() {
log.Println("Launching TODO App")
log.Println("Generating the routes...")
workDir, _ := os.Getwd()
filesDir := filepath.Join(workDir, "static")
router := chi.NewRouter()
router.Use(middleware.Logger)
router.Get("/", indexHandler)
router.Get("/edit/{id:[0-9]+}", editHandler)
router.Post("/create", createHandler)
router.Post("/toggle/{id:[0-9]+}", toggleHandler)
router.Post("/update/{id:[0-9]+}", updateHandler)
router.Post("/delete/{id:[0-9]+}", deleteHandler)
fileServer(router, "/static", http.Dir(filesDir))
log.Println("Serving the page on port 1337")
http.ListenAndServe(":1337", router)
}

6
makefile Normal file
View File

@@ -0,0 +1,6 @@
templates/%.qtpl.go: templates/%.qtpl
cd templates; qtc
todo: *.go templates/*.go
go build
clean:
rm todo templates/*.qtpl.go

7
models/todo.go Normal file
View File

@@ -0,0 +1,7 @@
package models
type Todo struct {
Id int
Todo string
Done bool
}

33
static/custom.css Normal file
View File

@@ -0,0 +1,33 @@
input[type=submit].button-green {
color:#FFF;
background-color:#30dd8d;
border-color:#30dd8d;
}
input[type=submit].button-green:focus,
input[type=submit].button-green:hover {
color:#FFF;
background-color:#2ab775;
border-color:#2ab775;
}
input[type=submit].button-red {
color:#FFF;
background-color:#f7474a;
border-color:#f7474a;
}
input[type=submit].button-red:focus,
input[type=submit].button-red:hover {
color:#FFF;
background-color:#d33d3f;
border-color:#d33d3f;
}
.title {
text-decoration: none;
}
form {
margin-bottom: 0px;
}

25
templates/500.qtpl Normal file
View File

@@ -0,0 +1,25 @@
{% code
type Error500Page struct {
Message string
Error string
}
%}
{% func (p *Error500Page ) Title() %}
500
{% endfunc %}
{% func (p *Error500Page ) Stylesheets() %}
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/skeleton/2.0.4/skeleton.min.css">
{% endfunc %}
{% func (p *Error500Page ) Scripts() %}
{% endfunc %}
{% func (p *Error500Page ) Body() %}
<div class="container">
<h1>Error: 500</h1>
<p>{%s p.Message %}</p>
<p>{%s p.Error %}</p>
</div>
{% endfunc %}

175
templates/500.qtpl.go Normal file
View File

@@ -0,0 +1,175 @@
// This file is automatically generated by qtc from "500.qtpl".
// See https://github.com/valyala/quicktemplate for details.
//line 500.qtpl:1
package templates
//line 500.qtpl:1
import (
qtio422016 "io"
qt422016 "github.com/valyala/quicktemplate"
)
//line 500.qtpl:1
var (
_ = qtio422016.Copy
_ = qt422016.AcquireByteBuffer
)
//line 500.qtpl:2
type Error500Page struct {
Message string
Error string
}
//line 500.qtpl:8
func (p *Error500Page) StreamTitle(qw422016 *qt422016.Writer) {
//line 500.qtpl:8
qw422016.N().S(`
500
`)
//line 500.qtpl:10
}
//line 500.qtpl:10
func (p *Error500Page) WriteTitle(qq422016 qtio422016.Writer) {
//line 500.qtpl:10
qw422016 := qt422016.AcquireWriter(qq422016)
//line 500.qtpl:10
p.StreamTitle(qw422016)
//line 500.qtpl:10
qt422016.ReleaseWriter(qw422016)
//line 500.qtpl:10
}
//line 500.qtpl:10
func (p *Error500Page) Title() string {
//line 500.qtpl:10
qb422016 := qt422016.AcquireByteBuffer()
//line 500.qtpl:10
p.WriteTitle(qb422016)
//line 500.qtpl:10
qs422016 := string(qb422016.B)
//line 500.qtpl:10
qt422016.ReleaseByteBuffer(qb422016)
//line 500.qtpl:10
return qs422016
//line 500.qtpl:10
}
//line 500.qtpl:12
func (p *Error500Page) StreamStylesheets(qw422016 *qt422016.Writer) {
//line 500.qtpl:12
qw422016.N().S(`
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/skeleton/2.0.4/skeleton.min.css">
`)
//line 500.qtpl:14
}
//line 500.qtpl:14
func (p *Error500Page) WriteStylesheets(qq422016 qtio422016.Writer) {
//line 500.qtpl:14
qw422016 := qt422016.AcquireWriter(qq422016)
//line 500.qtpl:14
p.StreamStylesheets(qw422016)
//line 500.qtpl:14
qt422016.ReleaseWriter(qw422016)
//line 500.qtpl:14
}
//line 500.qtpl:14
func (p *Error500Page) Stylesheets() string {
//line 500.qtpl:14
qb422016 := qt422016.AcquireByteBuffer()
//line 500.qtpl:14
p.WriteStylesheets(qb422016)
//line 500.qtpl:14
qs422016 := string(qb422016.B)
//line 500.qtpl:14
qt422016.ReleaseByteBuffer(qb422016)
//line 500.qtpl:14
return qs422016
//line 500.qtpl:14
}
//line 500.qtpl:16
func (p *Error500Page) StreamScripts(qw422016 *qt422016.Writer) {
//line 500.qtpl:16
qw422016.N().S(`
`)
//line 500.qtpl:17
}
//line 500.qtpl:17
func (p *Error500Page) WriteScripts(qq422016 qtio422016.Writer) {
//line 500.qtpl:17
qw422016 := qt422016.AcquireWriter(qq422016)
//line 500.qtpl:17
p.StreamScripts(qw422016)
//line 500.qtpl:17
qt422016.ReleaseWriter(qw422016)
//line 500.qtpl:17
}
//line 500.qtpl:17
func (p *Error500Page) Scripts() string {
//line 500.qtpl:17
qb422016 := qt422016.AcquireByteBuffer()
//line 500.qtpl:17
p.WriteScripts(qb422016)
//line 500.qtpl:17
qs422016 := string(qb422016.B)
//line 500.qtpl:17
qt422016.ReleaseByteBuffer(qb422016)
//line 500.qtpl:17
return qs422016
//line 500.qtpl:17
}
//line 500.qtpl:19
func (p *Error500Page) StreamBody(qw422016 *qt422016.Writer) {
//line 500.qtpl:19
qw422016.N().S(`
<div class="container">
<h1>Error: 500</h1>
<p>`)
//line 500.qtpl:22
qw422016.E().S(p.Message)
//line 500.qtpl:22
qw422016.N().S(`</p>
<p>`)
//line 500.qtpl:23
qw422016.E().S(p.Error)
//line 500.qtpl:23
qw422016.N().S(`</p>
</div>
`)
//line 500.qtpl:25
}
//line 500.qtpl:25
func (p *Error500Page) WriteBody(qq422016 qtio422016.Writer) {
//line 500.qtpl:25
qw422016 := qt422016.AcquireWriter(qq422016)
//line 500.qtpl:25
p.StreamBody(qw422016)
//line 500.qtpl:25
qt422016.ReleaseWriter(qw422016)
//line 500.qtpl:25
}
//line 500.qtpl:25
func (p *Error500Page) Body() string {
//line 500.qtpl:25
qb422016 := qt422016.AcquireByteBuffer()
//line 500.qtpl:25
p.WriteBody(qb422016)
//line 500.qtpl:25
qs422016 := string(qb422016.B)
//line 500.qtpl:25
qt422016.ReleaseByteBuffer(qb422016)
//line 500.qtpl:25
return qs422016
//line 500.qtpl:25
}

31
templates/base.qtpl Normal file
View File

@@ -0,0 +1,31 @@
{% interface PageImpl {
Title()
Stylesheets()
Scripts()
Body()
}
%}
{% func Page(p PageImpl) %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
<title>{%= p.Title() %}</title>
{%= p.Stylesheets() %}
{%= p.Scripts() %}
</head>
<body>
{%= p.Body() %}
</body>
</html>
{% endfunc %}
{% func GetDoneButton(done bool) %}
{% if done %}
<input type="submit" class="button-primary button-green u-full-width" value="">
{% else %}
<input type="submit" class="button-primary button-red u-full-width" value="">
{% endif %}
{% endfunc %}

161
templates/base.qtpl.go Normal file
View File

@@ -0,0 +1,161 @@
// This file is automatically generated by qtc from "base.qtpl".
// See https://github.com/valyala/quicktemplate for details.
//line base.qtpl:1
package templates
//line base.qtpl:1
import (
qtio422016 "io"
qt422016 "github.com/valyala/quicktemplate"
)
//line base.qtpl:1
var (
_ = qtio422016.Copy
_ = qt422016.AcquireByteBuffer
)
//line base.qtpl:1
type PageImpl interface {
//line base.qtpl:1
Title() string
//line base.qtpl:1
StreamTitle(qw422016 *qt422016.Writer)
//line base.qtpl:1
WriteTitle(qq422016 qtio422016.Writer)
//line base.qtpl:1
Stylesheets() string
//line base.qtpl:1
StreamStylesheets(qw422016 *qt422016.Writer)
//line base.qtpl:1
WriteStylesheets(qq422016 qtio422016.Writer)
//line base.qtpl:1
Scripts() string
//line base.qtpl:1
StreamScripts(qw422016 *qt422016.Writer)
//line base.qtpl:1
WriteScripts(qq422016 qtio422016.Writer)
//line base.qtpl:1
Body() string
//line base.qtpl:1
StreamBody(qw422016 *qt422016.Writer)
//line base.qtpl:1
WriteBody(qq422016 qtio422016.Writer)
//line base.qtpl:1
}
//line base.qtpl:9
func StreamPage(qw422016 *qt422016.Writer, p PageImpl) {
//line base.qtpl:9
qw422016.N().S(`
<!DOCTYPE html>
<html lang="en">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
<title>`)
//line base.qtpl:14
p.StreamTitle(qw422016)
//line base.qtpl:14
qw422016.N().S(`</title>
`)
//line base.qtpl:15
p.StreamStylesheets(qw422016)
//line base.qtpl:15
qw422016.N().S(`
`)
//line base.qtpl:16
p.StreamScripts(qw422016)
//line base.qtpl:16
qw422016.N().S(`
</head>
<body>
`)
//line base.qtpl:20
p.StreamBody(qw422016)
//line base.qtpl:20
qw422016.N().S(`
</body>
</html>
`)
//line base.qtpl:23
}
//line base.qtpl:23
func WritePage(qq422016 qtio422016.Writer, p PageImpl) {
//line base.qtpl:23
qw422016 := qt422016.AcquireWriter(qq422016)
//line base.qtpl:23
StreamPage(qw422016, p)
//line base.qtpl:23
qt422016.ReleaseWriter(qw422016)
//line base.qtpl:23
}
//line base.qtpl:23
func Page(p PageImpl) string {
//line base.qtpl:23
qb422016 := qt422016.AcquireByteBuffer()
//line base.qtpl:23
WritePage(qb422016, p)
//line base.qtpl:23
qs422016 := string(qb422016.B)
//line base.qtpl:23
qt422016.ReleaseByteBuffer(qb422016)
//line base.qtpl:23
return qs422016
//line base.qtpl:23
}
//line base.qtpl:25
func StreamGetDoneButton(qw422016 *qt422016.Writer, done bool) {
//line base.qtpl:25
qw422016.N().S(`
`)
//line base.qtpl:26
if done {
//line base.qtpl:26
qw422016.N().S(`
<input type="submit" class="button-primary button-green u-full-width" value="">
`)
//line base.qtpl:28
} else {
//line base.qtpl:28
qw422016.N().S(`
<input type="submit" class="button-primary button-red u-full-width" value="">
`)
//line base.qtpl:30
}
//line base.qtpl:30
qw422016.N().S(`
`)
//line base.qtpl:31
}
//line base.qtpl:31
func WriteGetDoneButton(qq422016 qtio422016.Writer, done bool) {
//line base.qtpl:31
qw422016 := qt422016.AcquireWriter(qq422016)
//line base.qtpl:31
StreamGetDoneButton(qw422016, done)
//line base.qtpl:31
qt422016.ReleaseWriter(qw422016)
//line base.qtpl:31
}
//line base.qtpl:31
func GetDoneButton(done bool) string {
//line base.qtpl:31
qb422016 := qt422016.AcquireByteBuffer()
//line base.qtpl:31
WriteGetDoneButton(qb422016, done)
//line base.qtpl:31
qs422016 := string(qb422016.B)
//line base.qtpl:31
qt422016.ReleaseByteBuffer(qb422016)
//line base.qtpl:31
return qs422016
//line base.qtpl:31
}

67
templates/edit.qtpl Normal file
View File

@@ -0,0 +1,67 @@
{% import "todo/models" %}
{% code
type EditPage struct {
Todos []models.Todo
EditingTodo models.Todo
}
%}
{% func (p *EditPage ) Title() %}
Todo
{% endfunc %}
{% func (p *EditPage ) Stylesheets() %}
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/skeleton/2.0.4/skeleton.min.css">
<link rel="stylesheet" type="text/css" href="/static/custom.css">
{% endfunc %}
{% func (p *EditPage ) Scripts() %}
{% endfunc %}
{% func (p *EditPage ) Body() %}
<div class="container">
<a href="/" class="title"><h1>TODO in Golang</h1></a>
<form action="/update/{%d p.EditingTodo.Id %}" method="post">
<div class="row">
<div class="nine columns">
<input type="text" class="u-full-width" name="todo" id="todo" value="{%s p.EditingTodo.Todo %}">
</div>
<div class="three columns">
<input type="submit" class="button-primary u-full-width" value="Update">
</div>
</div>
</form>
{% for _, todo := range p.Todos %}
<div class="row">
<div class="one column">
<form action="/undo/{%d todo.Id %}" method="post">
{%= GetDoneButton(todo.Done) %}
</form>
</div>
<div class="seven columns">
<p>{%s todo.Todo %}</p>
</div>
{% if todo.Id == p.EditingTodo.Id %}
<div class="two columns">
<input type="submit" disabled="disabled" class="u-full-width" value="Editing">
</div>
{% else %}
<div class="two columns">
<form action="/edit/{%d todo.Id %}">
<input type="submit" class="button-primary u-full-width" value="Edit">
</form>
</div>
{% endif %}
<div class="two columns">
<form action="/undo/{%d todo.Id %}" method="post">
<input type="submit" class="button-red u-full-width" value="Delete">
</form>
</div>
</div>
{% endfor %}
</div>
{% endfunc %}

257
templates/edit.qtpl.go Normal file
View File

@@ -0,0 +1,257 @@
// This file is automatically generated by qtc from "edit.qtpl".
// See https://github.com/valyala/quicktemplate for details.
//line edit.qtpl:1
package templates
//line edit.qtpl:1
import "todo/models"
//line edit.qtpl:3
import (
qtio422016 "io"
qt422016 "github.com/valyala/quicktemplate"
)
//line edit.qtpl:3
var (
_ = qtio422016.Copy
_ = qt422016.AcquireByteBuffer
)
//line edit.qtpl:4
type EditPage struct {
Todos []models.Todo
EditingTodo models.Todo
}
//line edit.qtpl:10
func (p *EditPage) StreamTitle(qw422016 *qt422016.Writer) {
//line edit.qtpl:10
qw422016.N().S(`
Todo
`)
//line edit.qtpl:12
}
//line edit.qtpl:12
func (p *EditPage) WriteTitle(qq422016 qtio422016.Writer) {
//line edit.qtpl:12
qw422016 := qt422016.AcquireWriter(qq422016)
//line edit.qtpl:12
p.StreamTitle(qw422016)
//line edit.qtpl:12
qt422016.ReleaseWriter(qw422016)
//line edit.qtpl:12
}
//line edit.qtpl:12
func (p *EditPage) Title() string {
//line edit.qtpl:12
qb422016 := qt422016.AcquireByteBuffer()
//line edit.qtpl:12
p.WriteTitle(qb422016)
//line edit.qtpl:12
qs422016 := string(qb422016.B)
//line edit.qtpl:12
qt422016.ReleaseByteBuffer(qb422016)
//line edit.qtpl:12
return qs422016
//line edit.qtpl:12
}
//line edit.qtpl:14
func (p *EditPage) StreamStylesheets(qw422016 *qt422016.Writer) {
//line edit.qtpl:14
qw422016.N().S(`
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/skeleton/2.0.4/skeleton.min.css">
<link rel="stylesheet" type="text/css" href="/static/custom.css">
`)
//line edit.qtpl:17
}
//line edit.qtpl:17
func (p *EditPage) WriteStylesheets(qq422016 qtio422016.Writer) {
//line edit.qtpl:17
qw422016 := qt422016.AcquireWriter(qq422016)
//line edit.qtpl:17
p.StreamStylesheets(qw422016)
//line edit.qtpl:17
qt422016.ReleaseWriter(qw422016)
//line edit.qtpl:17
}
//line edit.qtpl:17
func (p *EditPage) Stylesheets() string {
//line edit.qtpl:17
qb422016 := qt422016.AcquireByteBuffer()
//line edit.qtpl:17
p.WriteStylesheets(qb422016)
//line edit.qtpl:17
qs422016 := string(qb422016.B)
//line edit.qtpl:17
qt422016.ReleaseByteBuffer(qb422016)
//line edit.qtpl:17
return qs422016
//line edit.qtpl:17
}
//line edit.qtpl:19
func (p *EditPage) StreamScripts(qw422016 *qt422016.Writer) {
//line edit.qtpl:19
qw422016.N().S(`
`)
//line edit.qtpl:20
}
//line edit.qtpl:20
func (p *EditPage) WriteScripts(qq422016 qtio422016.Writer) {
//line edit.qtpl:20
qw422016 := qt422016.AcquireWriter(qq422016)
//line edit.qtpl:20
p.StreamScripts(qw422016)
//line edit.qtpl:20
qt422016.ReleaseWriter(qw422016)
//line edit.qtpl:20
}
//line edit.qtpl:20
func (p *EditPage) Scripts() string {
//line edit.qtpl:20
qb422016 := qt422016.AcquireByteBuffer()
//line edit.qtpl:20
p.WriteScripts(qb422016)
//line edit.qtpl:20
qs422016 := string(qb422016.B)
//line edit.qtpl:20
qt422016.ReleaseByteBuffer(qb422016)
//line edit.qtpl:20
return qs422016
//line edit.qtpl:20
}
//line edit.qtpl:22
func (p *EditPage) StreamBody(qw422016 *qt422016.Writer) {
//line edit.qtpl:22
qw422016.N().S(`
<div class="container">
<a href="/" class="title"><h1>TODO in Golang</h1></a>
<form action="/update/`)
//line edit.qtpl:25
qw422016.N().D(p.EditingTodo.Id)
//line edit.qtpl:25
qw422016.N().S(`" method="post">
<div class="row">
<div class="nine columns">
<input type="text" class="u-full-width" name="todo" id="todo" value="`)
//line edit.qtpl:28
qw422016.E().S(p.EditingTodo.Todo)
//line edit.qtpl:28
qw422016.N().S(`">
</div>
<div class="three columns">
<input type="submit" class="button-primary u-full-width" value="Update">
</div>
</div>
</form>
`)
//line edit.qtpl:36
for _, todo := range p.Todos {
//line edit.qtpl:36
qw422016.N().S(`
<div class="row">
<div class="one column">
<form action="/undo/`)
//line edit.qtpl:39
qw422016.N().D(todo.Id)
//line edit.qtpl:39
qw422016.N().S(`" method="post">
`)
//line edit.qtpl:40
StreamGetDoneButton(qw422016, todo.Done)
//line edit.qtpl:40
qw422016.N().S(`
</form>
</div>
<div class="seven columns">
<p>`)
//line edit.qtpl:44
qw422016.E().S(todo.Todo)
//line edit.qtpl:44
qw422016.N().S(`</p>
</div>
`)
//line edit.qtpl:46
if todo.Id == p.EditingTodo.Id {
//line edit.qtpl:46
qw422016.N().S(`
<div class="two columns">
<input type="submit" disabled="disabled" class="u-full-width" value="Editing">
</div>
`)
//line edit.qtpl:50
} else {
//line edit.qtpl:50
qw422016.N().S(`
<div class="two columns">
<form action="/edit/`)
//line edit.qtpl:52
qw422016.N().D(todo.Id)
//line edit.qtpl:52
qw422016.N().S(`">
<input type="submit" class="button-primary u-full-width" value="Edit">
</form>
</div>
`)
//line edit.qtpl:56
}
//line edit.qtpl:56
qw422016.N().S(`
<div class="two columns">
<form action="/undo/`)
//line edit.qtpl:58
qw422016.N().D(todo.Id)
//line edit.qtpl:58
qw422016.N().S(`" method="post">
<input type="submit" class="button-red u-full-width" value="Delete">
</form>
</div>
</div>
`)
//line edit.qtpl:63
}
//line edit.qtpl:63
qw422016.N().S(`
</div>
`)
//line edit.qtpl:66
}
//line edit.qtpl:66
func (p *EditPage) WriteBody(qq422016 qtio422016.Writer) {
//line edit.qtpl:66
qw422016 := qt422016.AcquireWriter(qq422016)
//line edit.qtpl:66
p.StreamBody(qw422016)
//line edit.qtpl:66
qt422016.ReleaseWriter(qw422016)
//line edit.qtpl:66
}
//line edit.qtpl:66
func (p *EditPage) Body() string {
//line edit.qtpl:66
qb422016 := qt422016.AcquireByteBuffer()
//line edit.qtpl:66
p.WriteBody(qb422016)
//line edit.qtpl:66
qs422016 := string(qb422016.B)
//line edit.qtpl:66
qt422016.ReleaseByteBuffer(qb422016)
//line edit.qtpl:66
return qs422016
//line edit.qtpl:66
}

59
templates/index.qtpl Normal file
View File

@@ -0,0 +1,59 @@
{% import "todo/models" %}
{% code
type IndexPage struct {
Todos []models.Todo
}
%}
{% func (p *IndexPage ) Title() %}
Todo
{% endfunc %}
{% func (p *IndexPage ) Stylesheets() %}
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/skeleton/2.0.4/skeleton.min.css">
<link rel="stylesheet" type="text/css" href="/static/custom.css">
{% endfunc %}
{% func (p *IndexPage ) Scripts() %}
{% endfunc %}
{% func (p *IndexPage ) Body() %}
<div class="container">
<a href="/" class="title"><h1>TODO in Golang</h1></a>
<form action="/create" method="post">
<div class="row">
<div class="nine columns">
<input type="text" class="u-full-width" name="todo" id="todo">
</div>
<div class="three columns">
<input type="submit" class="button-primary u-full-width" value="add">
</div>
</div>
</form>
{% for _, todo := range p.Todos %}
<div class="row">
<div class="one column">
<form action="/toggle/{%d todo.Id %}" method="post">
{%= GetDoneButton(todo.Done) %}
</form>
</div>
<div class="seven columns">
<p>{%s todo.Todo %}</p>
</div>
<div class="two columns">
<form action="/edit/{%d todo.Id %}">
<input type="submit" class="button-primary u-full-width" value="Edit">
</form>
</div>
<div class="two columns">
<form action="/delete/{%d todo.Id %}" method="post">
<input type="submit" class="button-primary button-red u-full-width" value="Delete">
</form>
</div>
</div>
{% endfor %}
</div>
{% endfunc %}

230
templates/index.qtpl.go Normal file
View File

@@ -0,0 +1,230 @@
// This file is automatically generated by qtc from "index.qtpl".
// See https://github.com/valyala/quicktemplate for details.
//line index.qtpl:1
package templates
//line index.qtpl:1
import "todo/models"
//line index.qtpl:3
import (
qtio422016 "io"
qt422016 "github.com/valyala/quicktemplate"
)
//line index.qtpl:3
var (
_ = qtio422016.Copy
_ = qt422016.AcquireByteBuffer
)
//line index.qtpl:4
type IndexPage struct {
Todos []models.Todo
}
//line index.qtpl:9
func (p *IndexPage) StreamTitle(qw422016 *qt422016.Writer) {
//line index.qtpl:9
qw422016.N().S(`
Todo
`)
//line index.qtpl:11
}
//line index.qtpl:11
func (p *IndexPage) WriteTitle(qq422016 qtio422016.Writer) {
//line index.qtpl:11
qw422016 := qt422016.AcquireWriter(qq422016)
//line index.qtpl:11
p.StreamTitle(qw422016)
//line index.qtpl:11
qt422016.ReleaseWriter(qw422016)
//line index.qtpl:11
}
//line index.qtpl:11
func (p *IndexPage) Title() string {
//line index.qtpl:11
qb422016 := qt422016.AcquireByteBuffer()
//line index.qtpl:11
p.WriteTitle(qb422016)
//line index.qtpl:11
qs422016 := string(qb422016.B)
//line index.qtpl:11
qt422016.ReleaseByteBuffer(qb422016)
//line index.qtpl:11
return qs422016
//line index.qtpl:11
}
//line index.qtpl:13
func (p *IndexPage) StreamStylesheets(qw422016 *qt422016.Writer) {
//line index.qtpl:13
qw422016.N().S(`
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/skeleton/2.0.4/skeleton.min.css">
<link rel="stylesheet" type="text/css" href="/static/custom.css">
`)
//line index.qtpl:16
}
//line index.qtpl:16
func (p *IndexPage) WriteStylesheets(qq422016 qtio422016.Writer) {
//line index.qtpl:16
qw422016 := qt422016.AcquireWriter(qq422016)
//line index.qtpl:16
p.StreamStylesheets(qw422016)
//line index.qtpl:16
qt422016.ReleaseWriter(qw422016)
//line index.qtpl:16
}
//line index.qtpl:16
func (p *IndexPage) Stylesheets() string {
//line index.qtpl:16
qb422016 := qt422016.AcquireByteBuffer()
//line index.qtpl:16
p.WriteStylesheets(qb422016)
//line index.qtpl:16
qs422016 := string(qb422016.B)
//line index.qtpl:16
qt422016.ReleaseByteBuffer(qb422016)
//line index.qtpl:16
return qs422016
//line index.qtpl:16
}
//line index.qtpl:18
func (p *IndexPage) StreamScripts(qw422016 *qt422016.Writer) {
//line index.qtpl:18
qw422016.N().S(`
`)
//line index.qtpl:19
}
//line index.qtpl:19
func (p *IndexPage) WriteScripts(qq422016 qtio422016.Writer) {
//line index.qtpl:19
qw422016 := qt422016.AcquireWriter(qq422016)
//line index.qtpl:19
p.StreamScripts(qw422016)
//line index.qtpl:19
qt422016.ReleaseWriter(qw422016)
//line index.qtpl:19
}
//line index.qtpl:19
func (p *IndexPage) Scripts() string {
//line index.qtpl:19
qb422016 := qt422016.AcquireByteBuffer()
//line index.qtpl:19
p.WriteScripts(qb422016)
//line index.qtpl:19
qs422016 := string(qb422016.B)
//line index.qtpl:19
qt422016.ReleaseByteBuffer(qb422016)
//line index.qtpl:19
return qs422016
//line index.qtpl:19
}
//line index.qtpl:21
func (p *IndexPage) StreamBody(qw422016 *qt422016.Writer) {
//line index.qtpl:21
qw422016.N().S(`
<div class="container">
<a href="/" class="title"><h1>TODO in Golang</h1></a>
<form action="/create" method="post">
<div class="row">
<div class="nine columns">
<input type="text" class="u-full-width" name="todo" id="todo">
</div>
<div class="three columns">
<input type="submit" class="button-primary u-full-width" value="add">
</div>
</div>
</form>
`)
//line index.qtpl:35
for _, todo := range p.Todos {
//line index.qtpl:35
qw422016.N().S(`
<div class="row">
<div class="one column">
<form action="/toggle/`)
//line index.qtpl:38
qw422016.N().D(todo.Id)
//line index.qtpl:38
qw422016.N().S(`" method="post">
`)
//line index.qtpl:39
StreamGetDoneButton(qw422016, todo.Done)
//line index.qtpl:39
qw422016.N().S(`
</form>
</div>
<div class="seven columns">
<p>`)
//line index.qtpl:43
qw422016.E().S(todo.Todo)
//line index.qtpl:43
qw422016.N().S(`</p>
</div>
<div class="two columns">
<form action="/edit/`)
//line index.qtpl:46
qw422016.N().D(todo.Id)
//line index.qtpl:46
qw422016.N().S(`">
<input type="submit" class="button-primary u-full-width" value="Edit">
</form>
</div>
<div class="two columns">
<form action="/delete/`)
//line index.qtpl:51
qw422016.N().D(todo.Id)
//line index.qtpl:51
qw422016.N().S(`" method="post">
<input type="submit" class="button-primary button-red u-full-width" value="Delete">
</form>
</div>
</div>
`)
//line index.qtpl:56
}
//line index.qtpl:56
qw422016.N().S(`
</div>
`)
//line index.qtpl:59
}
//line index.qtpl:59
func (p *IndexPage) WriteBody(qq422016 qtio422016.Writer) {
//line index.qtpl:59
qw422016 := qt422016.AcquireWriter(qq422016)
//line index.qtpl:59
p.StreamBody(qw422016)
//line index.qtpl:59
qt422016.ReleaseWriter(qw422016)
//line index.qtpl:59
}
//line index.qtpl:59
func (p *IndexPage) Body() string {
//line index.qtpl:59
qb422016 := qt422016.AcquireByteBuffer()
//line index.qtpl:59
p.WriteBody(qb422016)
//line index.qtpl:59
qs422016 := string(qb422016.B)
//line index.qtpl:59
qt422016.ReleaseByteBuffer(qb422016)
//line index.qtpl:59
return qs422016
//line index.qtpl:59
}

BIN
todo Executable file

Binary file not shown.