Working on participant subscription workflow of school user
This commit is contained in:
parent
4b752f2e50
commit
8f02b2eb5f
12 changed files with 177 additions and 25 deletions
|
@ -1,5 +1,12 @@
|
||||||
package errors
|
package errors
|
||||||
|
|
||||||
import "errors"
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
var RecordExists = errors.New("Record already exists!")
|
"git.andreafazzi.eu/andrea/oef/i18n"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
RecordExists = errors.New("Record already exists!")
|
||||||
|
NotAuthorized = errors.New(i18n.Authorization["notAuthorized"]["it"])
|
||||||
|
)
|
||||||
|
|
|
@ -21,7 +21,7 @@ var (
|
||||||
},
|
},
|
||||||
|
|
||||||
"school": map[string][]int{
|
"school": map[string][]int{
|
||||||
"Participant": []int{PermissionCreate, PermissionRead, PermissionReadAll, PermissionUpdate, PermissionDelete},
|
"Participant": []int{PermissionCreate, PermissionRead, PermissionUpdate, PermissionDelete},
|
||||||
"School": []int{PermissionRead, PermissionUpdate},
|
"School": []int{PermissionRead, PermissionUpdate},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -17,4 +17,9 @@ var (
|
||||||
"it": "il %02d/%02d/%d alle ore %02d:%02d",
|
"it": "il %02d/%02d/%d alle ore %02d:%02d",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
Authorization = map[string]map[string]string{
|
||||||
|
"notAuthorized": map[string]string{
|
||||||
|
"it": "Non si è autorizzati ad accedere a questa pagina",
|
||||||
|
},
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
|
@ -2,11 +2,13 @@ package orm
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"git.andreafazzi.eu/andrea/oef/config"
|
"git.andreafazzi.eu/andrea/oef/config"
|
||||||
|
"git.andreafazzi.eu/andrea/oef/errors"
|
||||||
"git.andreafazzi.eu/andrea/oef/i18n"
|
"git.andreafazzi.eu/andrea/oef/i18n"
|
||||||
"git.andreafazzi.eu/andrea/oef/renderer"
|
"git.andreafazzi.eu/andrea/oef/renderer"
|
||||||
"github.com/jinzhu/gorm"
|
"github.com/jinzhu/gorm"
|
||||||
|
@ -122,8 +124,19 @@ func (model *Participant) Create(args map[string]string, w http.ResponseWriter,
|
||||||
if err := DB().Find(&participant.AllContests).Error; err != nil {
|
if err := DB().Find(&participant.AllContests).Error; err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if err := DB().Find(&participant.AllSchools).Error; err != nil {
|
if isSchool(r) {
|
||||||
return nil, err
|
schoolID, err := strconv.Atoi(getUserIDFromToken(r))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := DB().Find(&participant.AllSchools, schoolID).Error; err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if err := DB().Find(&participant.AllSchools).Error; err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return participant, nil
|
return participant, nil
|
||||||
} else {
|
} else {
|
||||||
|
@ -161,6 +174,18 @@ func (model *Participant) Read(args map[string]string, w http.ResponseWriter, r
|
||||||
|
|
||||||
id := args["id"]
|
id := args["id"]
|
||||||
|
|
||||||
|
// School user can access to its participants only!
|
||||||
|
if isSchool(r) {
|
||||||
|
if err := DB().Preload("School").First(&participant, id).Error; err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if strconv.Itoa(int(participant.SchoolID)) != getUserIDFromToken(r) {
|
||||||
|
setFlashMessage(w, r, "notAuthorized")
|
||||||
|
return nil, errors.NotAuthorized
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if err := DB().Preload("User").Preload("School").Preload("Responses").Preload("Contests").First(&participant, id).Error; err != nil {
|
if err := DB().Preload("User").Preload("School").Preload("Responses").Preload("Contests").First(&participant, id).Error; err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -228,7 +253,7 @@ func (model *Participant) Update(args map[string]string, w http.ResponseWriter,
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
participant.(*School).UserModifierUpdate = NewUserModifierUpdate(r)
|
participant.(*Participant).UserModifierUpdate = NewUserModifierUpdate(r)
|
||||||
|
|
||||||
_, err = SaveParticipant(participant)
|
_, err = SaveParticipant(participant)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -271,7 +296,7 @@ func CreateParticipant(participant *Participant) (*Participant, error) {
|
||||||
func SaveParticipant(participant interface{}) (interface{}, error) {
|
func SaveParticipant(participant interface{}) (interface{}, error) {
|
||||||
participant.(*Participant).FiscalCode = strings.ToUpper(participant.(*Participant).FiscalCode)
|
participant.(*Participant).FiscalCode = strings.ToUpper(participant.(*Participant).FiscalCode)
|
||||||
|
|
||||||
if err := DB(). /*.Omit("Something")*/ Save(participant).Error; err != nil {
|
if err := DB().Omit("School").Save(participant).Error; err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return participant, nil
|
return participant, nil
|
||||||
|
|
38
orm/role.go
Normal file
38
orm/role.go
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
package orm
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/dgrijalva/jwt-go"
|
||||||
|
)
|
||||||
|
|
||||||
|
func getClaims(r *http.Request) jwt.MapClaims {
|
||||||
|
return r.Context().Value("user").(*jwt.Token).Claims.(jwt.MapClaims)
|
||||||
|
}
|
||||||
|
|
||||||
|
func isRole(role string, r *http.Request) bool {
|
||||||
|
if r.Context().Value("user") != nil {
|
||||||
|
return getClaims(r)["role"].(string) == role
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func isAdministrator(r *http.Request) bool {
|
||||||
|
return isRole("administrator", r)
|
||||||
|
}
|
||||||
|
|
||||||
|
func isParticipant(r *http.Request) bool {
|
||||||
|
return isRole("participant", r)
|
||||||
|
}
|
||||||
|
|
||||||
|
func isSchool(r *http.Request) bool {
|
||||||
|
return isRole("school", r)
|
||||||
|
}
|
||||||
|
|
||||||
|
func isSubscriber(r *http.Request) bool {
|
||||||
|
return isRole("subscriber", r)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getUserIDFromToken(r *http.Request) string {
|
||||||
|
return getClaims(r)["user_id"].(string)
|
||||||
|
}
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"git.andreafazzi.eu/andrea/oef/errors"
|
||||||
"git.andreafazzi.eu/andrea/oef/mail"
|
"git.andreafazzi.eu/andrea/oef/mail"
|
||||||
"git.andreafazzi.eu/andrea/oef/renderer"
|
"git.andreafazzi.eu/andrea/oef/renderer"
|
||||||
"github.com/jinzhu/gorm"
|
"github.com/jinzhu/gorm"
|
||||||
|
@ -69,6 +70,10 @@ func (model *School) BeforeSave(tx *gorm.DB) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
model.UserID = user.ID
|
model.UserID = user.ID
|
||||||
|
|
||||||
|
// School code is always uppercase
|
||||||
|
model.Code = strings.ToUpper(model.Code)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,6 +139,11 @@ func (model *School) Read(args map[string]string, w http.ResponseWriter, r *http
|
||||||
|
|
||||||
id := args["id"]
|
id := args["id"]
|
||||||
|
|
||||||
|
if isSchool(r) && id != getUserIDFromToken(r) {
|
||||||
|
setFlashMessage(w, r, "notAuthorized")
|
||||||
|
return nil, errors.NotAuthorized
|
||||||
|
}
|
||||||
|
|
||||||
if err := DB().Preload("User").Preload("Participants").First(&school, id).Error; err != nil {
|
if err := DB().Preload("User").Preload("Participants").First(&school, id).Error; err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -222,7 +232,7 @@ func CreateSchool(school *School) (*School, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func SaveSchool(school interface{}) (interface{}, error) {
|
func SaveSchool(school interface{}) (interface{}, error) {
|
||||||
school.(*School).Code = strings.ToUpper(school.(*School).Code)
|
// school.(*School).Code = strings.ToUpper(school.(*School).Code)
|
||||||
if err := DB(). /*.Omit("Something")*/ Save(school).Error; err != nil {
|
if err := DB(). /*.Omit("Something")*/ Save(school).Error; err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,6 +54,7 @@ var (
|
||||||
"isAdmin": isAdmin,
|
"isAdmin": isAdmin,
|
||||||
"isParticipant": isParticipant,
|
"isParticipant": isParticipant,
|
||||||
"isSubscriber": isSubscriber,
|
"isSubscriber": isSubscriber,
|
||||||
|
"isSchool": isSchool,
|
||||||
"attr": attr,
|
"attr": attr,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -70,6 +71,10 @@ func isParticipant(claims jwt.MapClaims) bool {
|
||||||
return claims["role"].(string) == "participant"
|
return claims["role"].(string) == "participant"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isSchool(claims jwt.MapClaims) bool {
|
||||||
|
return claims["role"].(string) == "school"
|
||||||
|
}
|
||||||
|
|
||||||
func isSubscriber(claims jwt.MapClaims) bool {
|
func isSubscriber(claims jwt.MapClaims) bool {
|
||||||
return claims["role"].(string) == "subscriber"
|
return claims["role"].(string) == "subscriber"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,10 @@
|
||||||
{{define "base"}}
|
{{define "base"}}
|
||||||
|
|
||||||
|
{{$isAdmin := .Claims|isAdmin}}
|
||||||
|
{{$isSubscriber := .Claims|isSubscriber}}
|
||||||
|
{{$isSchool := .Claims|isSchool}}
|
||||||
|
{{$isParticipant := .Claims|isParticipant}}
|
||||||
|
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="it">
|
<html lang="it">
|
||||||
<head>
|
<head>
|
||||||
|
@ -12,7 +18,14 @@
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<nav class="navbar navbar-expand-lg fixed-top navbar-dark bg-primary">
|
<nav class="navbar navbar-expand-lg fixed-top navbar-dark bg-primary">
|
||||||
<a class="navbar-brand" href="{{all "Contest"}}">
|
|
||||||
|
{{$homeURL := ""}}
|
||||||
|
{{if $isAdmin}}{{$homeURL = all "Contest"}}{{end}}
|
||||||
|
{{if $isSubscriber}}{{$homeURL = "#"}}{{end}}
|
||||||
|
{{if $isParticipant}}{{$homeURL = "#"}}{{end}}
|
||||||
|
{{if $isSchool}}{{$homeURL = "#"}}{{end}}
|
||||||
|
|
||||||
|
<a class="navbar-brand" href="{{$homeURL}}">
|
||||||
<span class="fa fa-landmark"></span>
|
<span class="fa fa-landmark"></span>
|
||||||
OEF 2020
|
OEF 2020
|
||||||
</a>
|
</a>
|
||||||
|
|
|
@ -7,7 +7,9 @@
|
||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
<div class="btn-group float-right" role="group">
|
<div class="btn-group float-right" role="group">
|
||||||
{{template "update_button" dict "modelPath" .updatePath}}
|
{{template "update_button" dict "modelPath" .updatePath}}
|
||||||
|
{{if .deletePath}}
|
||||||
{{template "delete_button" dict "modelPath" .deletePath}}
|
{{template "delete_button" dict "modelPath" .deletePath}}
|
||||||
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,8 +1,18 @@
|
||||||
{{ define "content" }}
|
{{ define "content" }}
|
||||||
|
|
||||||
|
{{$isAdmin := .Claims|isAdmin}}
|
||||||
|
{{$isSchool := .Claims|isSchool}}
|
||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
|
|
||||||
|
{{if $isAdmin}}
|
||||||
{{template "breadcrumb" toSlice "Partecipanti" (all "Participant") (.Data|string) "current"}}
|
{{template "breadcrumb" toSlice "Partecipanti" (all "Participant") (.Data|string) "current"}}
|
||||||
|
{{end}}
|
||||||
|
|
||||||
|
{{if $isSchool}}
|
||||||
|
{{template "breadcrumb" toSlice (.Data.School|string) (.Data.SchoolID|show "School") (.Data|string) "current"}}
|
||||||
|
{{end}}
|
||||||
|
|
||||||
{{template "show_header" dict "title" (.Data|string) "updatePath" (.Data.ID|update "Participant") "deletePath" (.Data.ID|delete "Participant")}}
|
{{template "show_header" dict "title" (.Data|string) "updatePath" (.Data.ID|update "Participant") "deletePath" (.Data.ID|delete "Participant")}}
|
||||||
|
|
||||||
<h2 class="karmen-relation-header">Informazioni generali</h2>
|
<h2 class="karmen-relation-header">Informazioni generali</h2>
|
||||||
|
@ -24,7 +34,6 @@
|
||||||
<dd class="col-sm-9">{{.Data.UpdaterIP}}</dd>
|
<dd class="col-sm-9">{{.Data.UpdaterIP}}</dd>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
|
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
|
|
@ -1,14 +1,20 @@
|
||||||
{{ define "content" }}
|
{{ define "content" }}
|
||||||
<div class="container">
|
<div class="container">
|
||||||
|
|
||||||
|
{{$isAdmin := .Claims|isAdmin}}
|
||||||
{{$isSubscriber := .Claims|isSubscriber}}
|
{{$isSubscriber := .Claims|isSubscriber}}
|
||||||
|
{{$isSchool := .Claims|isSchool}}
|
||||||
|
|
||||||
{{$update := .Options.Get "update"}}
|
{{$update := .Options.Get "update"}}
|
||||||
|
|
||||||
{{if not $isSubscriber}}
|
{{if not $isSubscriber}}
|
||||||
|
|
||||||
{{if $update}}
|
{{if $update}}
|
||||||
|
{{if $isSchool}}
|
||||||
|
{{template "breadcrumb" toSlice (.Data|string) (.Data.ID|show "School") "Aggiorna" "current"}}
|
||||||
|
{{else}}
|
||||||
{{template "breadcrumb" toSlice "Scuole" (all "School") (.Data|string) (.Data.ID|show "School") "Aggiorna" "current"}}
|
{{template "breadcrumb" toSlice "Scuole" (all "School") (.Data|string) (.Data.ID|show "School") "Aggiorna" "current"}}
|
||||||
|
{{end}}
|
||||||
{{else}}
|
{{else}}
|
||||||
{{template "breadcrumb" toSlice "Scuole" (all "School") "Aggiungi" "current"}}
|
{{template "breadcrumb" toSlice "Scuole" (all "School") "Aggiungi" "current"}}
|
||||||
{{end}}
|
{{end}}
|
||||||
|
@ -31,7 +37,9 @@
|
||||||
{{$options := ` { name: "Name",id: "school_name",label: "Denominazione dell'istituto",placeholder: "Inserire la denominazione",type: "text",required: "true"} `}}
|
{{$options := ` { name: "Name",id: "school_name",label: "Denominazione dell'istituto",placeholder: "Inserire la denominazione",type: "text",required: "true"} `}}
|
||||||
{{template "input" dict "options" ($options|yaml) "value" (.Data|field "Name") "update" $update}}
|
{{template "input" dict "options" ($options|yaml) "value" (.Data|field "Name") "update" $update}}
|
||||||
|
|
||||||
{{$options := `
|
{{$codeOptions := ""}}
|
||||||
|
{{if or $isAdmin $isSubscriber}}
|
||||||
|
{{$codeOptions = `
|
||||||
name: "Code"
|
name: "Code"
|
||||||
id: "school_code"
|
id: "school_code"
|
||||||
label: "Codice meccanografico"
|
label: "Codice meccanografico"
|
||||||
|
@ -41,7 +49,20 @@
|
||||||
otherAttrs: "maxlength=10 minlength=10"
|
otherAttrs: "maxlength=10 minlength=10"
|
||||||
required: "true"
|
required: "true"
|
||||||
`}}
|
`}}
|
||||||
{{template "input" dict "options" ($options|yaml) "value" (.Data|field "Code") "update" $update}}
|
{{end}}
|
||||||
|
|
||||||
|
{{if $isSchool}}
|
||||||
|
{{$codeOptions = `
|
||||||
|
name: "Code"
|
||||||
|
id: "school_code"
|
||||||
|
label: "Codice meccanografico"
|
||||||
|
type: "text"
|
||||||
|
inputClass: "form-control-plaintext"
|
||||||
|
otherAttrs: "readonly"
|
||||||
|
`}}
|
||||||
|
{{end}}
|
||||||
|
|
||||||
|
{{template "input" dict "options" ($codeOptions|yaml) "value" (.Data|field "Code") "update" $update}}
|
||||||
|
|
||||||
{{$options := ` { name: "Email",id: "school_email",label: "Indirizzo email",placeholder: "Inserire l'indirizzo di posta istituzionale",type: "email",required: "true"} `}}
|
{{$options := ` { name: "Email",id: "school_email",label: "Indirizzo email",placeholder: "Inserire l'indirizzo di posta istituzionale",type: "email",required: "true"} `}}
|
||||||
{{template "input" dict "options" ($options|yaml) "value" (.Data|field "Email") "update" $update}}
|
{{template "input" dict "options" ($options|yaml) "value" (.Data|field "Email") "update" $update}}
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
{{ define "content" }}
|
{{ define "content" }}
|
||||||
|
|
||||||
|
{{$isAdmin := .Claims|isAdmin}}
|
||||||
|
{{$isSchool := .Claims|isSchool}}
|
||||||
|
{{$isSubscriber := .Claims|isSubscriber}}
|
||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
{{if .Claims|isSubscriber}}
|
{{if $isSubscriber}}
|
||||||
{{if .FlashMessages}}
|
{{if .FlashMessages}}
|
||||||
<p>Si è verificato un errore. Clicca <a href="/logout">qui</a> per uscire da questa sessione.</p>
|
<p>Si è verificato un errore. Clicca <a href="/logout">qui</a> per uscire da questa sessione.</p>
|
||||||
{{else}}
|
{{else}}
|
||||||
|
@ -20,8 +24,16 @@
|
||||||
</p>
|
</p>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{else}}
|
{{else}}
|
||||||
|
|
||||||
|
{{$deletePath := ""}}
|
||||||
|
{{if $isAdmin}}
|
||||||
|
{{$deletePath = (.Data.ID|delete "School")}}
|
||||||
|
{{end}}
|
||||||
|
|
||||||
|
{{if $isAdmin}}
|
||||||
{{template "breadcrumb" toSlice "Scuole" (all "School") (.Data|string|trim) "current"}}
|
{{template "breadcrumb" toSlice "Scuole" (all "School") (.Data|string|trim) "current"}}
|
||||||
{{template "show_header" dict "title" (.Data|string|trim) "updatePath" (.Data.ID|update "School") "deletePath" (.Data.ID|delete "School")}}
|
{{end}}
|
||||||
|
{{template "show_header" dict "title" (.Data|string|trim) "updatePath" (.Data.ID|update "School") "deletePath" $deletePath}}
|
||||||
|
|
||||||
<h2 class="karmen-relation-header">Informazioni sulla scuola</h2>
|
<h2 class="karmen-relation-header">Informazioni sulla scuola</h2>
|
||||||
<dl class="row">
|
<dl class="row">
|
||||||
|
@ -41,33 +53,38 @@
|
||||||
<dd class="col-sm-9">{{.Data.User.Password}}</dd>
|
<dd class="col-sm-9">{{.Data.User.Password}}</dd>
|
||||||
{{if $creatorUser:=.Data.CreatedBy}}
|
{{if $creatorUser:=.Data.CreatedBy}}
|
||||||
<dt class="col-sm-3">Creato da</dt>
|
<dt class="col-sm-3">Creato da</dt>
|
||||||
<dd class="col-sm-9">{{$creatorUser.Username}}[{{$creatorUser.Role}}] {{$.Data.CreatedAt|prettyDateTime}}</dd>
|
<dd class="col-sm-9">{{$creatorUser.Username}}[{{$creatorUser.Role}}] {{$.Data.CreatedAt|prettyDateTime}} da {{.Data.CreatorIP}}</dd>
|
||||||
<dt class="col-sm-3">IP di chi ha creato la scuola</dt>
|
|
||||||
<dd class="col-sm-9">{{.Data.CreatorIP}}</dd>
|
|
||||||
{{end}}
|
{{end}}
|
||||||
{{if $updaterUser:=.Data.UpdatedBy}}
|
{{if $updaterUser:=.Data.UpdatedBy}}
|
||||||
<dt class="col-sm-3">Modificato da</dt>
|
<dt class="col-sm-3">Modificato da</dt>
|
||||||
<dd class="col-sm-9">{{$updaterUser.Username}}[{{$updaterUser.Role}}] {{$.Data.UpdatedAt|prettyDateTime}}</dd>
|
<dd class="col-sm-9">{{$updaterUser.Username}}[{{$updaterUser.Role}}] {{$.Data.UpdatedAt|prettyDateTime}} da {{.Data.UpdaterIP}}</dd>
|
||||||
<dt class="col-sm-3">IP di chi ha modificato la scuola</dt>
|
|
||||||
<dd class="col-sm-9">{{.Data.UpdaterIP}}</dd>
|
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
|
|
||||||
{{$options := `
|
{{$options := `
|
||||||
title: "Partecipanti"
|
title: "Partecipanti"
|
||||||
model: "Participant"
|
model: "Participant"
|
||||||
icon: "fa fa-user"
|
icon: "fa fa-user"
|
||||||
`}}
|
`}}
|
||||||
|
|
||||||
{{$noElements := "La scuola non ha iscritto alcun partecipante."}}
|
{{$noElements := (printf "La scuola non ha iscritto alcun partecipante. Clicca %s per iscrivere il primo partecipante." ((create "Participant")|anchor "qui")|html)}}
|
||||||
{{template "relation_list" dict "options" ($options|yaml) "data" .Data.Participants "noElements" $noElements}}
|
{{template "relation_list" dict "options" ($options|yaml) "data" .Data.Participants "noElements" $noElements}}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{{if eq (len .Data.Participants) 1}}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-12">
|
||||||
|
<p class="mt-4">
|
||||||
|
{{(printf "Clicca %s per iscrivere il secondo partecipante." ((create "Participant")|anchor "qui")|html)}}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
|
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue