Merge tag '0.3.0' into production

This commit is contained in:
Andrea Fazzi 2020-02-03 12:53:54 +01:00
commit e92b71e0b1
38 changed files with 1877 additions and 88 deletions

View file

@ -1,14 +1,21 @@
PHONY: all
dockerized:
docker-compose -f compose/docker-compose.yml down
docker-compose -f compose/docker-compose.yml up --build -d
prod:
docker-compose -f docker/oef_prod/docker-compose.yml down
docker-compose -f docker/oef_prod/docker-compose.yml up --build -d
dev:
killall main || echo "Process was not running."
docker-compose -f compose/docker-compose_outside_docker.yml down
docker-compose -f compose/docker-compose_outside_docker.yml up -d db
docker-compose -f compose/docker-compose_outside_docker.yml up -d smtp
go run -race main.go --config=config/config_dev.yaml &
docker-compose -f docker/oef_dev/docker-compose.yaml down
docker-compose -f docker/oef_dev/docker-compose.yaml up -d db
docker-compose -f docker/oef_dev/docker-compose.yaml up -d smtp
go run -race main.go --config=docker/oef_dev/config/config.yaml &
all: dockerized
test:
killall main || echo "Process was not running."
docker-compose -f docker/oef_test/docker-compose.yaml down
docker-compose -f docker/oef_test/docker-compose.yaml up -d db
docker-compose -f docker/oef_test/docker-compose.yaml up -d smtp
go run -race main.go --config=docker/oef_test/config/config.yaml &
all: prod

View file

@ -1 +1,2 @@
0.2.1-10-gac64cee-production
0.2.1-26-g368de33-master

3
benchmarks/.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
benchmarks
targets/*
results/*

187
benchmarks/gen_targets.go Normal file
View file

@ -0,0 +1,187 @@
package main
import (
"bytes"
"encoding/json"
"errors"
"flag"
"fmt"
"io/ioutil"
"log"
"net/http"
"net/url"
"os"
"path"
"path/filepath"
"strings"
"text/template"
"git.andreafazzi.eu/andrea/oef/client"
"git.andreafazzi.eu/andrea/oef/orm"
"github.com/gocarina/gocsv"
vegeta "github.com/tsenart/vegeta/lib"
)
type config struct {
Url string
}
type genFunc func(string, *config) error
var (
generators map[string]genFunc
templateDir string = "./templates"
)
func incr(value int) int {
return value + 1
}
func genPOSTResponseTargets(targetName string, conf *config) error {
var (
participants []*orm.Participant
tokens map[string]string
)
log.Println("Read participants.csv...")
input, err := ioutil.ReadFile("./testdata/participants.csv")
if err != nil {
return err
}
if err := gocsv.Unmarshal(strings.NewReader(string(input)), &participants); err != nil {
panic(err)
}
log.Println("Obtaining tokens for each participants...")
tokens = make(map[string]string, 0)
for _, participant := range participants {
token, err := client.GetToken(conf.Url, participant.FiscalCode, participant.Password)
if err != nil {
return err
}
tokens[participant.FiscalCode] = token
}
targets := make([]*vegeta.Target, 0)
form := url.Values{}
form.Set("Singleresponses.0", "32")
for i, participant := range participants {
targets = append(targets, &vegeta.Target{
Method: "POST",
URL: fmt.Sprintf("%s/responses/%d/update?format=html&tpl_content=responses_add_update&tpl_layout=base&update=true&login_session=%s", conf.Url, i+1, tokens[participant.FiscalCode]),
Body: []byte(form.Encode()),
Header: http.Header{"Content-Type": []string{"application/x-www-form-urlencoded"}},
})
}
err = os.Mkdir("targets", 0777)
if errors.Is(err, &os.PathError{}) {
return err
}
output, err := os.Create("./targets/post_response_targets.txt")
if err != nil {
return err
}
defer output.Close()
for _, t := range targets {
var line string
buf := bytes.NewBufferString(line)
encoder := json.NewEncoder(buf)
encoder.SetEscapeHTML(false)
err := encoder.Encode(t)
// jsonData, err := json.Marshal(t)
if err != nil {
return err
}
_, err = output.WriteString(buf.String() + "\n\n")
if err != nil {
return err
}
}
return nil
}
func genGETResponseTargets(targetName string, conf *config) error {
var data struct {
Participants []*orm.Participant
Tokens map[string]string
Config *config
}
data.Config = conf
log.Println("Read participants.csv...")
input, err := ioutil.ReadFile("./testdata/participants.csv")
if err != nil {
return err
}
if err := gocsv.Unmarshal(strings.NewReader(string(input)), &data.Participants); err != nil {
panic(err)
}
log.Println("Obtaining tokens for each participants...")
data.Tokens = make(map[string]string, 0)
for _, participant := range data.Participants {
token, err := client.GetToken(data.Config.Url, participant.FiscalCode, participant.Password)
if err != nil {
return err
}
data.Tokens[participant.FiscalCode] = token
}
tmplPath := path.Join(templateDir, targetName+".tpl")
log.Printf("Parse %s template", tmplPath)
tmpl, err := template.New(filepath.Base(tmplPath)).Funcs(template.FuncMap{"incr": incr}).ParseFiles(tmplPath)
if err != nil {
return err
}
err = os.Mkdir("targets", 0777)
if errors.Is(err, &os.PathError{}) {
return err
}
output, err := os.Create("./targets/response_targets.txt")
if err != nil {
return err
}
defer output.Close()
log.Printf("Execute %s template and generate targets...", targetName)
err = tmpl.Execute(output, data)
if err != nil {
return err
}
return nil
}
func init() {
generators = map[string]genFunc{
"responses": genGETResponseTargets,
"post_responses": genPOSTResponseTargets,
}
}
func main() {
target := flag.String("targets", "responses", "Generate targets for participants responses.")
url := flag.String("url", "http://localhost:3000", "The URL of the host.")
flag.Parse()
fn, ok := generators[*target]
if !ok {
log.Fatal(errors.New("Unknown target"))
}
err := fn(*target, &config{Url: *url})
if err != nil {
panic(err)
}
}

View file

@ -1,6 +0,0 @@
#!/bin/bash
token=`curl -u admin:aolieVooju https://test.olimpiadi-economiaefinanza.it/get_token | jq -r '.Token'`
url="https://test.olimpiadi-economiaefinanza.it/responses/1/update?format=html&tpl_content=responses_add_update&tpl_layout=base&update=true&login_session=${token}"
ab -n 100 -c 10 $url

View file

@ -0,0 +1,4 @@
{{range $id, $participant := .Participants -}}
{{- $username := $participant.FiscalCode -}}
GET {{$.Config.Url}}/responses/{{$id|incr}}/update?format=html&tpl_content=responses_add_update&tpl_layout=base&update=true&login_session={{index $.Tokens $username}}
{{end}}

1001
benchmarks/testdata/participants.csv vendored Normal file

File diff suppressed because it is too large Load diff

View file

@ -60,6 +60,13 @@ func Dial(host, username, password string) (*Client, error) {
return client, nil
}
// GetToken get the token associated with the user.
func GetToken(host, username, password string) (string, error) {
client, err := Dial(host, username, password)
return client.token, err
}
func (c *Client) SendRequest(method string, path string, data []byte) ([]byte, error) {
// Create the https request
@ -228,27 +235,3 @@ func (c *Client) Exists(model orm.IDer) bool {
_, err := c.Read(model)
return err != gorm.ErrRecordNotFound
}
// // FIXME: refactor this (it's duplicated across the code)
// func pluralizedModelName(value interface{}) string {
// return inflection.Plural(strings.ToLower(reflect.ModelName(value)))
// }
// // FIXME: refactor this (it's duplicated across the code)
// func callString(value interface{}) string {
// if value != nil {
// switch reflect.ValueOf(value).Kind() {
// case reflect.String:
// return value.(string)
// case reflect.Bool:
// if value.(bool) {
// return i18n.Text["answerCorrect"]["it"]
// }
// return "false"
// default:
// return reflect.ValueOf(value).MethodByName("String").Interface().(func() string)()
// }
// } else {
// return ""
// }
// }

View file

@ -45,6 +45,9 @@ type ConfigT struct {
LogLevel int `yaml:"log_level"`
// Enable profiling
Profiling bool
// Secret keys
Keys struct {
@ -68,9 +71,9 @@ type ConfigT struct {
// Handlers
Handlers struct {
PathPatterns map[string]PathPattern
APIPathPatterns map[string]PathPattern
Permissions map[string]map[string][]int
PathPatterns map[string]PathPattern
APIPathPatterns map[string]PathPattern
Permissions map[string]map[string][]int
AllowSessionURLQuery bool `yaml:"allow_session_url_query"`
}

10
dist/main.bundle.js vendored

File diff suppressed because one or more lines are too long

5
dist/styles.css vendored
View file

@ -4,6 +4,7 @@ html {
body {
padding-top: 60px;
position: relative;
}
div.login {
@ -103,7 +104,7 @@ ul.karmen-related-elements {
}
.sticky-offset {
top: 56px;
top: 60px;
}
.oef-anchor-selection:target {
@ -121,7 +122,7 @@ ul.karmen-related-elements {
div.oef-anchor {
display: block;
position: relative;
top: -56px;
top: -60px;
visibility: hidden;
}

View file

@ -0,0 +1,31 @@
url: "http://localhost:3000"
log_level: 2
language: "it"
keys:
cookie_store_key: "something-very-secret"
jwt_signing_key: "secret"
handlers:
allow_session_url_query: true
orm:
connection: "oef:oef@tcp(localhost:3307)/oef_dev"
options: "charset=utf8&parseTime=True&loc=Local"
automigrate: true
regenerate: false
admin:
username: "admin"
password: "admin"
subscriber:
password: "subscribe"
smtp:
host: "localhost"
port: 1025
username: ""
password: ""
from: "no-reply@olimpiadi-economiaefinanza.it"
bcc: "bcc@fake.org"

View file

@ -3,7 +3,7 @@ version: "3.3"
services:
app:
build: ../
build: ../../
ports:
- 3000:3000
environment:
@ -19,7 +19,6 @@ services:
restart: always
volumes:
- db:/var/lib/mysql
# - ./sql:/docker-entrypoint-initdb.d
env_file:
- db.env
ports:

View file

@ -0,0 +1,17 @@
url: "http://localhost:3000"
log_level: 2
language: "it"
keys:
cookie_store_key: "something-very-secret"
jwt_signing_key: "secret"
orm:
connection: "oef:oef@tcp(db:3306)/oef_dev"
options: "charset=utf8&parseTime=True&loc=Local"
automigrate: true
regenerate: false
admin:
username: "admin"
password: "admin"

10
docker/oef_prod/db.env Normal file
View file

@ -0,0 +1,10 @@
MYSQL_ROOT_PASSWORD=oef
MYSQL_PASSWORD=oef
MYSQL_DATABASE=oef_prod
MYSQL_USER=oef

View file

@ -3,7 +3,7 @@ version: "3.3"
services:
app:
build: ../
build: ../../
ports:
- 3000:3000
environment:
@ -11,7 +11,7 @@ services:
- DB_PORT=3306
volumes:
- /etc/localtime:/etc/localtime:ro
- ../config/config.yaml:/src/oef/config/config.yaml
- ./config/config.yaml:/src/oef/config/config.yaml
db:
image: mariadb

View file

@ -0,0 +1,32 @@
url: "http://localhost:3000"
log_level: 2
language: "it"
profiling: true
keys:
cookie_store_key: "something-very-secret"
jwt_signing_key: "secret"
handlers:
allow_session_url_query: true
orm:
connection: "oef:oef@tcp(localhost:3307)/oef_test"
options: "charset=utf8&parseTime=True&loc=Local"
automigrate: true
regenerate: false
admin:
username: "admin"
password: "admin"
subscriber:
password: "subscribe"
smtp:
host: "localhost"
port: 1025
username: ""
password: ""
from: "no-reply@olimpiadi-economiaefinanza.it"
bcc: "bcc@fake.org"

10
docker/oef_test/db.env Normal file
View file

@ -0,0 +1,10 @@
MYSQL_ROOT_PASSWORD=oef
MYSQL_PASSWORD=oef
MYSQL_DATABASE=oef_test
MYSQL_USER=oef

View file

@ -0,0 +1,37 @@
version: "3.3"
services:
app:
build: ../../
ports:
- 3000:3000
environment:
- DB_HOST=db
- DB_PORT=3306
volumes:
- /etc/localtime:/etc/localtime:ro
- ./config/config.yaml:/src/oef/config/config.yaml
db:
image: mariadb
command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW
restart: always
volumes:
- db:/var/lib/mysql
- ./sql:/docker-entrypoint-initdb.d
env_file:
- db.env
ports:
- 3307:3306
smtp:
image: digiplant/fake-smtp
ports:
- "1025:25"
volumes:
db:

File diff suppressed because one or more lines are too long

21
go.mod
View file

@ -6,21 +6,42 @@ require (
github.com/BurntSushi/toml v0.3.1
github.com/PuerkitoBio/goquery v1.5.0
github.com/auth0/go-jwt-middleware v0.0.0-20190805220309-36081240882b
github.com/bmizerany/perks v0.0.0-20141205001514-d9a9656a3a4b // indirect
github.com/c2h5oh/datasize v0.0.0-20200112174442-28bbd4740fee // indirect
github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/dgryski/go-gk v0.0.0-20140819190930-201884a44051 // indirect
github.com/dustin/go-humanize v1.0.0 // indirect
github.com/elgs/gojq v0.0.0-20160421194050-81fa9a608a13 // indirect
github.com/elgs/gosplitargs v0.0.0-20161028071935-a491c5eeb3c8 // indirect
github.com/gobwas/glob v0.2.3
github.com/gocarina/gocsv v0.0.0-20190927101021-3ecffd272576
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
github.com/gorilla/handlers v1.4.2
github.com/gorilla/mux v1.7.3
github.com/gorilla/schema v1.1.0
github.com/gorilla/sessions v1.2.0
github.com/influxdata/tdigest v0.0.1 // indirect
github.com/jinzhu/gorm v1.9.11
github.com/jinzhu/inflection v1.0.0
github.com/kr/pretty v0.1.0 // indirect
github.com/mailru/easyjson v0.7.0 // indirect
github.com/monochromegane/terminal v0.0.0-20161222050454-9bc47e2707d9 // indirect
github.com/pkg/profile v1.4.0
github.com/remogatto/prettytest v0.0.0-20191105125618-8fe70ed7a3e1
github.com/robfig/cron v1.2.0
github.com/rs/jplot v0.0.0-20180624024257-9b69b4534805 // indirect
github.com/sethvargo/go-password v0.1.3
github.com/smartystreets/goconvey v1.6.4 // indirect
github.com/streadway/quantile v0.0.0-20150917103942-b0c588724d25 // indirect
github.com/tsenart/go-tsz v0.0.0-20180814235614-0bd30b3df1c3 // indirect
github.com/tsenart/vegeta v12.7.0+incompatible
github.com/urfave/negroni v1.0.0 // indirect
github.com/wcharczuk/go-chart v2.0.1+incompatible // indirect
golang.org/x/crypto v0.0.0-20200128174031-69ecbb4d6d5d // indirect
golang.org/x/image v0.0.0-20200119044424-58c23975cae1 // indirect
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa // indirect
golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9 // indirect
golang.org/x/text v0.3.2 // indirect
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
gopkg.in/yaml.v2 v2.2.4
)

51
go.sum
View file

@ -16,15 +16,27 @@ github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb
github.com/auth0/go-jwt-middleware v0.0.0-20190805220309-36081240882b h1:CvoEHGmxWl5kONC5icxwqV899dkf4VjOScbxLpllEnw=
github.com/auth0/go-jwt-middleware v0.0.0-20190805220309-36081240882b/go.mod h1:LWMyo4iOLWXHGdBki7NIht1kHru/0wM179h+d3g8ATM=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/bmizerany/perks v0.0.0-20141205001514-d9a9656a3a4b h1:AP/Y7sqYicnjGDfD5VcY4CIfh1hRXBUavxrvELjTiOE=
github.com/bmizerany/perks v0.0.0-20141205001514-d9a9656a3a4b/go.mod h1:ac9efd0D1fsDb3EJvhqgXRbFx7bs2wqZ10HQPeU8U/Q=
github.com/c2h5oh/datasize v0.0.0-20200112174442-28bbd4740fee h1:BnPxIde0gjtTnc9Er7cxvBk8DHLWhEux0SxayC8dP6I=
github.com/c2h5oh/datasize v0.0.0-20200112174442-28bbd4740fee/go.mod h1:S/7n9copUssQ56c7aAgHqftWO4LTf4xY6CGWt8Bc+3M=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/denisenkom/go-mssqldb v0.0.0-20190515213511-eb9f6a1743f3 h1:tkum0XDgfR0jcVVXuTsYv/erY2NnEDqwRojbxR1rBYA=
github.com/denisenkom/go-mssqldb v0.0.0-20190515213511-eb9f6a1743f3/go.mod h1:zAg7JM8CkOJ43xKXIj7eRO9kmWm/TW578qo+oDO6tuM=
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgryski/go-gk v0.0.0-20140819190930-201884a44051 h1:ByJUvQYyTtNNCVfYNM48q6uYUT4fAlN0wNmd3th4BSo=
github.com/dgryski/go-gk v0.0.0-20140819190930-201884a44051/go.mod h1:qm+vckxRlDt0aOla0RYJJVeqHZlWfOm2UIxHaqPB46E=
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
github.com/elgs/gojq v0.0.0-20160421194050-81fa9a608a13 h1:/voSflvo4UvPT0XZy+YQMuUk04topJ2swxyOOyXefMM=
github.com/elgs/gojq v0.0.0-20160421194050-81fa9a608a13/go.mod h1:rQELVIqRXpraeUryHOBadz99ePvEVQmTVpGr8M9QQ4Q=
github.com/elgs/gosplitargs v0.0.0-20161028071935-a491c5eeb3c8 h1:bD2/rCXwgXJm2vgoSSSCM9IPjVFfEoQFFblzg7HHABI=
github.com/elgs/gosplitargs v0.0.0-20161028071935-a491c5eeb3c8/go.mod h1:o4DgpccPNAQAlPSxo7I4L/LWNh2oyr/BBGSynrLTmZM=
github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 h1:Yzb9+7DPaBjB8zlTR87/ElzFsnQfuHnVUVqpZZIcV5Y=
github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
@ -39,6 +51,8 @@ github.com/gocarina/gocsv v0.0.0-20190927101021-3ecffd272576 h1:nDMaZgjBNKhsVJEW
github.com/gocarina/gocsv v0.0.0-20190927101021-3ecffd272576/go.mod h1:/oj50ZdPq/cUjA02lMZhijk5kR31SEydKyqah1OgBuo=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
@ -64,6 +78,8 @@ github.com/gorilla/sessions v1.2.0 h1:S7P+1Hm5V/AT9cjEcUD5uDaQSX0OE577aCXgoaKpYb
github.com/gorilla/sessions v1.2.0/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/influxdata/tdigest v0.0.1 h1:XpFptwYmnEKUqmkcDjrzffswZ3nvNeevbUSLPP/ZzIY=
github.com/influxdata/tdigest v0.0.1/go.mod h1:Z0kXnxzbTC2qrx4NaIzYkE1k66+6oEDQTvL95hQFh5Y=
github.com/jinzhu/gorm v1.9.11 h1:gaHGvE+UnWGlbWG4Y3FUwY1EcZ5n6S9WtqBA/uySMLE=
github.com/jinzhu/gorm v1.9.11/go.mod h1:bu/pK8szGZ2puuErfU0RwyeNdsf3e6nCX/noXaVxkfw=
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
@ -84,9 +100,13 @@ github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/lib/pq v1.1.1 h1:sJZmqHoEaY7f+NPP8pgLB/WxulyR3fewgCM2qaSlBb4=
github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/mailru/easyjson v0.7.0 h1:aizVhC/NAAcKWb+5QsU1iNOZb4Yws5UO2I+aIprQITM=
github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
github.com/mattn/go-sqlite3 v1.11.0 h1:LDdKkqtYlom37fkvqs8rMPFKAMe8+SgjbwZ6ex1/A/Q=
github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/monochromegane/terminal v0.0.0-20161222050454-9bc47e2707d9 h1:YhsMshmD0JlqM4ss3JBY6Ul4QLigGvBtShFYHkb3JGg=
github.com/monochromegane/terminal v0.0.0-20161222050454-9bc47e2707d9/go.mod h1:9N3QHEQ4Ov/dAnHmOIJ8ffm8O1iQfCPfso+PpakXPsY=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
@ -94,6 +114,8 @@ github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1Cpa
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/profile v1.4.0 h1:uCmaf4vVbWAOZz36k1hrQD7ijGRzLwaME8Am/7a4jZI=
github.com/pkg/profile v1.4.0/go.mod h1:NWz/XGvpEW1FyYQ7fCx4dqYBLlfTcE+A9FLAkNKqjFE=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
@ -109,6 +131,8 @@ github.com/remogatto/prettytest v0.0.0-20191105125618-8fe70ed7a3e1 h1:qU1a7/zsCi
github.com/remogatto/prettytest v0.0.0-20191105125618-8fe70ed7a3e1/go.mod h1:jOEnp79oIHy5cvQSHeLcgVJk1GHOOHJHQWps/d1N5Yo=
github.com/robfig/cron v1.2.0 h1:ZjScXvvxeQ63Dbyxy76Fj3AT3Ut0aKsyd2/tl3DTMuQ=
github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k=
github.com/rs/jplot v0.0.0-20180624024257-9b69b4534805 h1:Y9XRz+J6fBX74oHZX9KwMzVRnq7AJNxfJSilUpZBrvU=
github.com/rs/jplot v0.0.0-20180624024257-9b69b4534805/go.mod h1:1GjGIxIXi6t9QbWYLwl8E7knyiIbtoGShze7zXmj2Nw=
github.com/sethvargo/go-password v0.1.3 h1:18KkbGDkw8SuzeohAbWqBLNSfRQblVwEHOLbPa0PvWM=
github.com/sethvargo/go-password v0.1.3/go.mod h1:2tyaaoHK/AlXwh5WWQDYjqQbHcq4cjPj5qb/ciYvu/Q=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
@ -116,16 +140,29 @@ github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykE
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/streadway/quantile v0.0.0-20150917103942-b0c588724d25 h1:7z3LSn867ex6VSaahyKadf4WtSsJIgne6A1WLOAGM8A=
github.com/streadway/quantile v0.0.0-20150917103942-b0c588724d25/go.mod h1:lbP8tGiBjZ5YWIc2fzuRpTaz0b/53vT6PEs3QuAWzuU=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/tsenart/go-tsz v0.0.0-20180814235614-0bd30b3df1c3 h1:pcQGQzTwCg//7FgVywqge1sW9Yf8VMsMdG58MI5kd8s=
github.com/tsenart/go-tsz v0.0.0-20180814235614-0bd30b3df1c3/go.mod h1:SWZznP1z5Ki7hDT2ioqiFKEse8K9tU2OUvaRI0NeGQo=
github.com/tsenart/vegeta v12.7.0+incompatible h1:sGlrv11EMxQoKOlDuMWR23UdL90LE5VlhKw/6PWkZmU=
github.com/tsenart/vegeta v12.7.0+incompatible/go.mod h1:Smz/ZWfhKRcyDDChZkG3CyTHdj87lHzio/HOCkbndXM=
github.com/urfave/negroni v1.0.0 h1:kIimOitoypq34K7TG7DUaJ9kq/N4Ofuwi1sjz0KipXc=
github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4=
github.com/wcharczuk/go-chart v2.0.1+incompatible h1:0pz39ZAycJFF7ju/1mepnk26RLVLBCWz1STcD3doU0A=
github.com/wcharczuk/go-chart v2.0.1+incompatible/go.mod h1:PF5tmL4EIx/7Wf+hEkpCqYi5He4u90sw+0+6FhrryuE=
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c h1:Vj5n4GlwjmQteupaxJ9+0FNOmBrHfq7vN4btdGoDZgI=
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200128174031-69ecbb4d6d5d h1:9FCpayM9Egr1baVnV1SX0H87m+XB0B8S0hAMi99X/3U=
golang.org/x/crypto v0.0.0-20200128174031-69ecbb4d6d5d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/image v0.0.0-20200119044424-58c23975cae1 h1:5h3ngYt7+vXCDZCup/HkCQgW5XwmSvR/nA2JmJ0RErg=
golang.org/x/image v0.0.0-20200119044424-58c23975cae1/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@ -139,6 +176,9 @@ golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73r
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa h1:F+8P+gmewFQYRk6JoLQLwjBCTu3mcIURZfNkVweuRKA=
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -150,15 +190,26 @@ golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9 h1:1/DFK4b7JH8DmkqhUk48onnSfrPzImPoVxuomtbT2nk=
golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2 h1:z99zHgr7hKfrUcX/KsoJk5FJfjTceCKIp96+biqP4To=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
gonum.org/v1/gonum v0.0.0-20181121035319-3f7ecaa7e8ca/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo=
gonum.org/v1/netlib v0.0.0-20181029234149-ec6d1f5cefe6/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw=
google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=

View file

@ -374,6 +374,9 @@ func respondWithError(h *Handlers, w http.ResponseWriter, r *http.Request, err e
if format == "" {
format = renderer.GetContentFormat(r)
}
if h.Config.LogLevel > config.LOG_LEVEL_OFF {
log.Println(err)
}
w.WriteHeader(http.StatusInternalServerError)
h.Renderer[format].Render(w, r, h.CookieStore, err)
}

View file

@ -8,6 +8,7 @@ import (
"time"
"github.com/gorilla/handlers"
"github.com/pkg/profile"
"git.andreafazzi.eu/andrea/oef/config"
oef_handlers "git.andreafazzi.eu/andrea/oef/handlers"
@ -65,6 +66,11 @@ func main() {
log.Println("Eventually write regions on DB...")
orm.CreateRegions(db)
if conf.Profiling {
log.Println("Start profiling...")
defer profile.Start().Stop()
}
log.Println("OEF is listening to port 3000...")
htmlRenderer, err := renderer.NewHTMLRenderer("templates")

View file

@ -132,7 +132,12 @@ func (model *Response) Read(db *Database, args map[string]string, w http.Respons
id := args["id"]
if err := db._db.Preload("Contest").Preload("Participant").First(&response, id).Error; err != nil {
if err := db._db.
Preload("Contest").
Preload("Participant").
Preload("Creator").
Preload("Updater").
First(&response, id).Error; err != nil {
return nil, err
}
@ -232,7 +237,6 @@ func (model *Response) Update(db *Database, args map[string]string, w http.Respo
if !response.(*Response).IsActive() {
return nil, errors.OutOfTime
}
err = renderer.Decode(response, r)
if err != nil {
return nil, err

View file

@ -33,7 +33,7 @@ var (
"prettyTime": prettyTime,
"prettyDateTime": prettyDateTime,
"zeroTime": zeroTime,
"minutes": minutes,
"seconds": seconds,
"modelPath": modelPath,
"dict": dict,
"yaml": yaml,
@ -50,7 +50,7 @@ var (
"mod2": mod2,
"toLower": toLower,
"anchor": anchor,
"alertLink": alertLink,
"alertLink": alertLink,
"html": html,
"field": field,
"modelName": modelName,
@ -329,8 +329,8 @@ func zeroTime(t *time.Time) bool {
return *t == time.Time{}
}
func minutes(d time.Duration) int {
return int(d.Minutes())
func seconds(d time.Duration) int {
return int(d.Seconds())
}
func modelPath(model string, action string, id uint) string {

View file

@ -4,9 +4,13 @@ $(function () {
setInterval(function() {
var timeleft = parseInt($("#timeleft").html());
timeleft--;
if (timeleft > 0) {
timeleft--;
} else {
timeleft = 0;
}
$("#timeleft").html(timeleft)
}, 1000*60);
}, 1000);
$("#myInput").on("keyup", function(eventObject) {

View file

@ -4,6 +4,7 @@ html {
body {
padding-top: 60px;
position: relative;
}
div.login {
@ -103,7 +104,7 @@ ul.karmen-related-elements {
}
.sticky-offset {
top: 56px;
top: 60px;
}
.oef-anchor-selection:target {
@ -121,6 +122,6 @@ ul.karmen-related-elements {
div.oef-anchor {
display: block;
position: relative;
top: -56px;
top: -60px;
visibility: hidden;
}

View file

@ -23,7 +23,7 @@
<link rel="stylesheet" href="/styles.css" />
<title>Olimpiadi di Economia e Finanza - Piattaforma di gara</title>
</head>
<body>
<body data-spy="scroll">
<nav class="navbar navbar-expand-lg fixed-top navbar-dark bg-primary">
{{- $homeURL := "" -}}
{{- if $isAdmin}}{{$homeURL = all "Contest"}}{{end}}
@ -94,8 +94,8 @@
</div>
</div>
<script
src="https://code.jquery.com/jquery-3.4.1.slim.min.js"
integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n"
src="https://code.jquery.com/jquery-3.4.1.min.js"
integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo="
crossorigin="anonymous">
</script>
<script

View file

@ -43,7 +43,7 @@
</div>
</footer>
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://code.jquery.com/jquery-3.4.1.min.js" integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>

View file

@ -5,7 +5,7 @@
<a href="{{.id|show .options.model}}" class="btn btn-default">Annulla</a>
{{else}}
{{if .options.cancelTitle}}
<a href="{{all .options.model}}" class="btn btn-default">Annulla</a>
<a href="{{if .referer}}{{.referer|html}}{{else}}{{all .options.model}}{{end}}" class="btn btn-default">Annulla</a>
{{end}}
{{end}}
</div>

View file

@ -97,7 +97,7 @@
icon: "fa fa-hourglass-start"
`}}
{{$noElements := "Al partecipante non è associata alcuna risposta."}}
{{$noElements := "Al partecipante non è associata alcuna prova."}}
{{template "relation_list" dict "options" ($options|yaml) "data" .Data.Responses "noElements" $noElements}}
</div>

View file

@ -12,21 +12,19 @@
{{- end -}}
{{- if $isAdmin -}}
{{template "add_update_header" dict "update" $update "addTitle" "Rispondi al questionario" "updateTitle" (printf "Aggiorna %s" (.Data|string))}}
{{- else -}}
{{template "add_update_header" dict "update" $update "addTitle" "Rispondi al questionario" "updateTitle" (.Data|string)}}
{{- end -}}
{{- $form := "form_add_update" -}}
<div class="row">
<div class="col-2 border-right">
<div class="col-2">
<div class="sticky-top sticky-offset">
<nav class="nav flex-column">
{{- if and $isParticipant .Data.TimeLeft}}
<h5 class="mt-1 badge badge-info sticky-top sticky-offset">Tempo rimanente <span id="timeleft">{{.Data.TimeLeft.Minutes|toInt}}</span> min</h5>
{{- end -}}
{{range $n, $question := .Data.Questions -}}
<a class="nav-link" href="#question_{{$n}}">Domanda {{$n|incr}}</a>
{{end -}}
</nav>
<div class="card">
<div class="card-header">Explorer delle domande</div>
<div id="navbar_questions" class="list-group">
{{range $n, $question := .Data.Questions -}}
<a class="list-group-item list-group-item-action" href="#question_{{$n}}">Domanda {{$n|incr}}</a>
{{end -}}
</div>
</div>
</div>
</div>
<div class="col">
@ -36,6 +34,7 @@
method="POST"
role="form"
id={{$form}}>
<div data-spy="scroll" data-target="#navbar_questions" data-offset="0">
{{range $id,$question := .Data.Questions -}}
<div class="oef-anchor" id="question_{{$id}}"></div>
<div class="oef-anchor-selection">
@ -57,15 +56,30 @@
</div>
<hr>
{{end}}
{{- if $isAdmin -}}
{{- $options := ` { cancelTitle: "Annulla", saveTitle: "Salva", model: "Response" } ` -}}
{{- template "submit_cancel_buttons" dict "options" ($options|yaml) "id" (.Data|field "ID") "update" $update -}}
{{- else -}}
{{- $options := ` { saveTitle: "Invia le risposte", model: "Response" } ` -}}
{{template "submit_cancel_buttons" dict "options" ($options|yaml) "id" (.Data|field "ID") "update" $update}}
{{end -}}
</div>
</form>
</div>
<div class="col-2">
<div class="sticky-top sticky-offset">
<div class="card">
<div class="card-header">
Informazioni sulla prova
</div>
<div class="card-body">
<dl>
<dt>Gara</dt><dd>{{.Data.Contest}}</dd>
<dt>Partecipante</dt><dd>{{.Data.Participant}}</dd>
{{- if $isParticipant -}}
<dt>Tempo rimanente</dt>{{if .Data.TimeLeft}}<dd><span id="timeleft">{{.Data.TimeLeft.Seconds|toInt}}</span> secondi rimanenti</dd>{{else}}<dd>La gara è sempre attiva</dd>{{end}}
{{- end -}}
</dl>
<button type="submit" class="btn btn-primary" form="{{$form}}">Salva</button>
</div>
</div>
</div>
</div>
</div>
</div>
{{ end -}}

View file

@ -23,7 +23,7 @@
<dd class="col-sm-9">
{{if not (.Data.Contest.Date|zeroTime)}}
Giorno {{.Data.Contest.Date|prettyDate}} dalle ore {{.Data.Contest.StartTime|convertTime}} alle ore {{.Data.Contest.EndTime|convertTime}}
{{- if not .Data.IsActive -}}<strong> [Scaduta]</strong>{{- end -}}
{{- if not .Data.IsActive -}}<strong> [Scaduta o non ancora attiva]</strong>{{- end -}}
{{else}}
La gara è sempre attiva.
{{end}}

View file

@ -106,7 +106,11 @@
{{template "submit_cancel_buttons" dict "options" ($options|yaml) "id" (.Data|field "ID") "update" $update}}
{{else}}
{{$options := ` { cancelTitle: "Annulla", saveTitle: "Salva", model: "School" } `}}
{{if $isAdmin}}
{{template "submit_cancel_buttons" dict "options" ($options|yaml) "id" (.Data|field "ID") "update" $update}}
{{else}}
{{template "submit_cancel_buttons" dict "options" ($options|yaml) "id" (.Data|field "ID") "update" $update "referer" (.Data.ID|show "School")}}
{{end}}
{{end}}
</form>

View file

@ -56,6 +56,9 @@
<dt class="col-sm-3">Password</dt>
<dd class="col-sm-9"><span class="text-monospace">{{.Data.User.Password}}</span></dd>
<dt class="col-sm-3">Referente di sede</dt><dd class="col-sm-9">{{.Data.SchoolContactPersonLastname}} {{.Data.SchoolContactPersonFirstname}}</dd>
<dt class="col-sm-3">Responsabile di gara</dt><dd class="col-sm-9">{{.Data.ContestDirectorLastname}} {{.Data.ContestDirectorFirstname}}</dd>
{{if $isAdmin}}
{{if $creatorUser:=.Data.CreatedBy}}
<dt class="col-sm-3">Creato da</dt>

View file

@ -1,6 +1,5 @@
#!/bin/bash
echo "Executing Makefile... $1"
make -k $1