Added main pages, print and order_pizzas, that interact with the API
This commit is contained in:
parent
d7b35ffffa
commit
e7d62180fe
17
README.md
17
README.md
|
@ -1 +1,18 @@
|
||||||
# Scontrini Web Client
|
# Scontrini Web Client
|
||||||
|
|
||||||
|
Golang simple http server that interfaces with Scontrini-Daemon
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
Compiling
|
||||||
|
|
||||||
|
```sh
|
||||||
|
$ go build
|
||||||
|
$ chmod +x ./Scontrini-Web-Client
|
||||||
|
```
|
||||||
|
|
||||||
|
Executing
|
||||||
|
|
||||||
|
```sh
|
||||||
|
$ ./Scontrini-Web-Client
|
||||||
|
```
|
||||||
|
|
106
api.go
Normal file
106
api.go
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
printer_server_IP = net.ParseIP("127.0.0.1")
|
||||||
|
printer_server_port = 4444
|
||||||
|
)
|
||||||
|
|
||||||
|
// Commands to give to the API
|
||||||
|
type JSONCommand interface {
|
||||||
|
PrintCommand | PizzaCommand | GetPizzasCommand
|
||||||
|
}
|
||||||
|
|
||||||
|
type PrintCommand struct {
|
||||||
|
Command string `json:"command"`
|
||||||
|
Text string `json:"text"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type PizzaCommand struct {
|
||||||
|
Command string `json:"command"`
|
||||||
|
Pizzas []Pizza `json:"pizzas"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetPizzasCommand struct {
|
||||||
|
Command string `json:"command"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// What to receive from the API
|
||||||
|
type JSONReceived interface {
|
||||||
|
ReceivePizzas
|
||||||
|
}
|
||||||
|
|
||||||
|
type ReceivePizzas struct {
|
||||||
|
Pizzas []Pizza `json:"pizzas"`
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All messages from and to the API must have the first 4 bytes set to represent
|
||||||
|
* the length of the message, followed by the message itself
|
||||||
|
*/
|
||||||
|
func sendJSONToServer[T JSONCommand](socket *net.TCPConn, json_command T) (*net.TCPConn, error) {
|
||||||
|
json_data, err := json.Marshal(json_command)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// in case a socket doesn't already exist create a new one
|
||||||
|
if socket == nil {
|
||||||
|
socket, err = net.DialTCP("tcp4", nil, &net.TCPAddr{printer_server_IP, printer_server_port, ""})
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// the first 4 bytes must be the length of the message
|
||||||
|
to_send := make([]byte, 4)
|
||||||
|
binary.LittleEndian.PutUint32(to_send, uint32(len(json_data)))
|
||||||
|
|
||||||
|
to_send = append(to_send, json_data...)
|
||||||
|
socket.Write([]byte(to_send))
|
||||||
|
|
||||||
|
return socket, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func receiveJSONFromServer[T JSONReceived](socket *net.TCPConn, json_received *T) (*net.TCPConn, error) {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
// in case a socket doesn't already exist create a new one
|
||||||
|
if socket == nil {
|
||||||
|
fmt.Println("nil")
|
||||||
|
socket, err = net.DialTCP("tcp4", nil, &net.TCPAddr{printer_server_IP, printer_server_port, ""})
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// the first 4 bytes are the length of the message
|
||||||
|
b := make([]byte, 4)
|
||||||
|
_, err = socket.Read(b[0:])
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
body_length := binary.LittleEndian.Uint32(b)
|
||||||
|
|
||||||
|
body := make([]byte, body_length)
|
||||||
|
_, err = socket.Read(body[0:])
|
||||||
|
|
||||||
|
err = json.Unmarshal(body, json_received)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return socket, nil
|
||||||
|
}
|
126
main.go
Normal file
126
main.go
Normal file
|
@ -0,0 +1,126 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"html/template"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
templates = template.Must(template.ParseFiles("templates/index.html", "templates/pizza.html"))
|
||||||
|
)
|
||||||
|
|
||||||
|
type Pizza struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Price int `json:"price"`
|
||||||
|
Quantity int `json:"quantity"`
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler function for "/"
|
||||||
|
*/
|
||||||
|
func indexHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
templates.ExecuteTemplate(w, "index.html", nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler function for "/print", only accepts POST requests
|
||||||
|
*
|
||||||
|
* Tells the API to print the text specified in its Form
|
||||||
|
*/
|
||||||
|
func printHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if r.Method != http.MethodPost {
|
||||||
|
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
text := r.PostFormValue("text")
|
||||||
|
|
||||||
|
json_command := PrintCommand{Command: "print", Text: text}
|
||||||
|
_, err := sendJSONToServer(nil, json_command)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(w, "Error while connecting to the printer server")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
http.Redirect(w, r, "/", http.StatusSeeOther)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler function for "/pizza", only accepts POST requests
|
||||||
|
*
|
||||||
|
* Tells the API to print the pizza order specified in its Form
|
||||||
|
*/
|
||||||
|
func pizzaHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if r.Method != http.MethodPost {
|
||||||
|
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
pizzas := make([]Pizza, 0)
|
||||||
|
|
||||||
|
r.ParseForm()
|
||||||
|
for key, _ := range r.Form {
|
||||||
|
// only put in the pizzas that have a quantity bigger than 0
|
||||||
|
if key != "submit" && r.Form[key][0] != "0" {
|
||||||
|
quantity, _ := strconv.ParseInt(r.Form[key][0], 10, 0)
|
||||||
|
pizzas = append(pizzas, Pizza{key, 0, int(quantity)})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
json_command := PizzaCommand{Command: "pizza", Pizzas: pizzas}
|
||||||
|
_, err := sendJSONToServer(nil, json_command)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(w, "Error while connecting to the printer server")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
http.Redirect(w, r, "/order_pizzas", http.StatusSeeOther)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler function for "/order_pizzas"
|
||||||
|
*
|
||||||
|
* Asks the API for the list of all pizzas then returns a formatted HTML page
|
||||||
|
*/
|
||||||
|
func orderPizzasHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
json_command := GetPizzasCommand{Command: "get-pizzas"}
|
||||||
|
socket, err := sendJSONToServer(nil, json_command)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(w, "Error while connecting to the printer server")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
pizzas := ReceivePizzas{}
|
||||||
|
_, err = receiveJSONFromServer(socket, &pizzas)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(w, "Error while connecting to the printer server")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
templates.ExecuteTemplate(w, "pizza.html", pizzas.Pizzas)
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
|
||||||
|
mux.HandleFunc("/", indexHandler)
|
||||||
|
mux.HandleFunc("/print", printHandler)
|
||||||
|
mux.HandleFunc("/pizza", pizzaHandler)
|
||||||
|
mux.HandleFunc("/order_pizzas", orderPizzasHandler)
|
||||||
|
|
||||||
|
err := http.ListenAndServe(":8080", mux)
|
||||||
|
if errors.Is(err, http.ErrServerClosed) {
|
||||||
|
fmt.Println("Server closed")
|
||||||
|
} else if err != nil {
|
||||||
|
fmt.Printf("Error starting server: %s\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
21
templates/index.html
Normal file
21
templates/index.html
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<title>Scontrini</title>
|
||||||
|
<link rel="stylesheet" href="">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<h1>SCONTRINI</h1>
|
||||||
|
|
||||||
|
<h2>Cosa stampare:</h2>
|
||||||
|
<form action="/print" method="post">
|
||||||
|
<input name="text" id="text" type="text"></input>
|
||||||
|
<input name="print" id="print" type="submit" value="STAMPA"></input>
|
||||||
|
</form>
|
||||||
|
<button><a href="/order_pizzas">Ordina le pizze</a></button>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
|
|
34
templates/pizza.html
Normal file
34
templates/pizza.html
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<title>Scontrini</title>
|
||||||
|
<link rel="stylesheet" href="">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<h1>PIZZE</h1>
|
||||||
|
|
||||||
|
<form action="/pizza" method="post">
|
||||||
|
<table id="pizzas">
|
||||||
|
{{ range . }}
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
{{ .Name }}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{ .Price }}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input name="{{ .Name }}" type="number" value="0"></input>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{{ end }}
|
||||||
|
</table>
|
||||||
|
<input name="submit" id="submit" type="submit" value="ORDINA LA PIZZA"></input>
|
||||||
|
</form>
|
||||||
|
<button><a href="/">Stampa qualcosa</a></button>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user