6 changed files with 215 additions and 0 deletions
@ -0,0 +1,56 @@
|
||||
package main |
||||
|
||||
import ( |
||||
"bufio" |
||||
"os" |
||||
) |
||||
|
||||
type TxtStore string |
||||
|
||||
func (t *TxtStore) GetGuestbook() (Guestbook, error) { |
||||
var result Guestbook |
||||
|
||||
file, err := os.Open(string(*t)) |
||||
if os.IsNotExist(err) { |
||||
return result, nil |
||||
} else if err != nil { |
||||
return result, err |
||||
} |
||||
defer file.Close() |
||||
|
||||
scanner := bufio.NewScanner(file) |
||||
var comments []string |
||||
|
||||
for scanner.Scan() { |
||||
comments = append([]string{scanner.Text()}, comments...) |
||||
} |
||||
|
||||
err = scanner.Err() |
||||
if err != nil { |
||||
return result, err |
||||
} |
||||
|
||||
result.Comments = comments |
||||
result.Count = len(comments) |
||||
|
||||
return result, nil |
||||
} |
||||
|
||||
func (t *TxtStore) AddComment(comment string) error { |
||||
if comment == "" { |
||||
return nil |
||||
} |
||||
|
||||
options := os.O_WRONLY | os.O_APPEND | os.O_CREATE |
||||
file, err := os.OpenFile(string(*t), options, os.FileMode(0600)) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
|
||||
_, err = file.WriteString(comment + "\n") |
||||
if err != nil { |
||||
return err |
||||
} |
||||
|
||||
return file.Close() |
||||
} |
||||
|
After Width: | Height: | Size: 24 KiB |
@ -0,0 +1,27 @@
|
||||
<!doctype html> |
||||
|
||||
<html lang="ru"> |
||||
<head> |
||||
<meta charset="utf-8"> |
||||
<title>Книга отзывов</title> |
||||
<link rel="icon" type="image/png" sizes="256x256" href="/html/favicon.png"> |
||||
<link rel="stylesheet" type="text/css" href="html/styles.css"> |
||||
</head> |
||||
|
||||
<body> |
||||
<div class="main"> |
||||
<h1>Книга отзывов</h1> |
||||
|
||||
|
||||
<form action="/new" method="POST"> |
||||
<p>Всего записей - {{ .Count }}</p> |
||||
<input type="text" name="comment" placeholder="Ваш отзыв..."> |
||||
<input type="submit" value="Отправить"> |
||||
</form> |
||||
|
||||
<ul> |
||||
{{ range .Comments }}<li>{{ . }}</li>{{ end}} |
||||
</ul> |
||||
</div> |
||||
</body> |
||||
</html> |
||||
@ -0,0 +1,79 @@
|
||||
* { |
||||
margin: 0; |
||||
padding: 0; |
||||
|
||||
font-family: 'Raleway', serif; |
||||
} |
||||
|
||||
body { |
||||
padding: 1%; |
||||
|
||||
color: #2E3E50; |
||||
background: #D8DDDD; |
||||
|
||||
text-align: center; |
||||
letter-spacing: 1px; |
||||
} |
||||
|
||||
.main { |
||||
margin: auto; |
||||
padding: 1% 2%; |
||||
max-width: 800px; |
||||
border-radius: 5px; |
||||
background: #ECF0F1; |
||||
box-shadow: 0 2px 6px 0 rgba(0, 0, 0, .3); |
||||
} |
||||
|
||||
form { |
||||
width: 100%; |
||||
display: flex; |
||||
margin: 2% 0; |
||||
|
||||
} |
||||
|
||||
form p { |
||||
text-align: left; |
||||
padding: 1%; |
||||
font-size: 18px; |
||||
} |
||||
|
||||
input { |
||||
padding: 1%; |
||||
border-radius: 4px; |
||||
border: 1px solid #CCC; |
||||
font-size: 18px; |
||||
} |
||||
|
||||
input[type=text] { |
||||
flex-grow: 1; |
||||
|
||||
margin: 0 .5%; |
||||
} |
||||
|
||||
input[type=submit] { |
||||
cursor: pointer; |
||||
} |
||||
|
||||
input[type=submit]:hover { |
||||
background-color: #D8DDDD; |
||||
} |
||||
|
||||
h1 { |
||||
font-family: 'Baloo Tamma', cursive; |
||||
} |
||||
|
||||
li{ |
||||
list-style-type: none; |
||||
|
||||
font-size: 18px; |
||||
min-width: 24%; |
||||
margin: 2% 0; |
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, .2); |
||||
padding: 1% 2%; |
||||
background: #FFF; |
||||
box-sizing: border-box; |
||||
} |
||||
|
||||
li:hover { |
||||
box-shadow:0 5px 10px rgba(0, 0, 0, .15); |
||||
} |
||||
@ -0,0 +1,50 @@
|
||||
package main |
||||
|
||||
import ( |
||||
"html/template" |
||||
"log" |
||||
"net/http" |
||||
) |
||||
|
||||
type Guestbook struct { |
||||
Comments []string |
||||
Count int |
||||
} |
||||
|
||||
func indexHandler(writer http.ResponseWriter, request *http.Request) { |
||||
html, err := template.ParseFiles("html/index.html") |
||||
check(err) |
||||
|
||||
store := TxtStore("comments.txt") |
||||
guestbook, err := store.GetGuestbook() |
||||
check(err) |
||||
|
||||
err = html.Execute(writer, guestbook) |
||||
check(err) |
||||
} |
||||
|
||||
func newHandler(writer http.ResponseWriter, request *http.Request) { |
||||
comment := request.FormValue("comment") |
||||
store := TxtStore("comments.txt") |
||||
|
||||
err := store.AddComment(comment) |
||||
check(err) |
||||
|
||||
http.Redirect(writer, request, "/", http.StatusFound) |
||||
} |
||||
|
||||
func main() { |
||||
http.HandleFunc("/", indexHandler) |
||||
http.HandleFunc("/new", newHandler) |
||||
|
||||
http.Handle("/html/", http.StripPrefix("/html/", http.FileServer(http.Dir("html")))) |
||||
|
||||
err := http.ListenAndServe("0.0.0.0:80", nil) |
||||
log.Fatal(err) |
||||
} |
||||
|
||||
func check(err error) { |
||||
if err != nil { |
||||
log.Fatal(err) |
||||
} |
||||
} |
||||
Loading…
Reference in new issue