diff --git a/go.mod b/go.mod
index 7335778..1f0f378 100644
--- a/go.mod
+++ b/go.mod
@@ -8,7 +8,10 @@ replace git.coopgo.io/coopgo-platform/groups-management => ../../coopgo-platform
replace git.coopgo.io/coopgo-platform/fleets => ../../coopgo-platform/fleets/
+replace git.coopgo.io/coopgo-platform/agenda => ../../coopgo-platform/agenda/
+
require (
+ git.coopgo.io/coopgo-platform/agenda v0.0.0-00010101000000-000000000000
git.coopgo.io/coopgo-platform/fleets v0.0.0-00010101000000-000000000000
git.coopgo.io/coopgo-platform/groups-management v0.0.0-00010101000000-000000000000
git.coopgo.io/coopgo-platform/mobility-accounts v0.0.0-00010101000000-000000000000
@@ -71,6 +74,7 @@ require (
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20220519153652-3a47de7e79bd // indirect
gopkg.in/ini.v1 v1.66.4 // indirect
+ gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22 // indirect
gopkg.in/square/go-jose.v2 v2.5.2-0.20210529014059-a5c7eec3c614 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
diff --git a/go.sum b/go.sum
index 3671ecc..af717c5 100644
--- a/go.sum
+++ b/go.sum
@@ -667,6 +667,8 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EV
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/ini.v1 v1.66.4 h1:SsAcf+mM7mRZo2nJNGt8mZCjG8ZRaNGMURJw7BsIST4=
gopkg.in/ini.v1 v1.66.4/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
+gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22 h1:VpOs+IwYnYBaFnrNAeB8UUWtL3vEUnzSCL1nVjPhqrw=
+gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
gopkg.in/square/go-jose.v2 v2.5.2-0.20210529014059-a5c7eec3c614 h1:lwJmuuJQGclcankpPJwh8rorzB0bNbVALv8phDGh8TQ=
gopkg.in/square/go-jose.v2 v2.5.2-0.20210529014059-a5c7eec3c614/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
diff --git a/handlers/application/agenda.go b/handlers/application/agenda.go
new file mode 100644
index 0000000..f42fa6f
--- /dev/null
+++ b/handlers/application/agenda.go
@@ -0,0 +1,304 @@
+package application
+
+import (
+ "context"
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "sort"
+ "strconv"
+ "time"
+
+ formvalidators "git.coopgo.io/coopgo-apps/parcoursmob/utils/form-validators"
+ "git.coopgo.io/coopgo-apps/parcoursmob/utils/identification"
+ agenda "git.coopgo.io/coopgo-platform/agenda/grpcapi"
+ agendastorage "git.coopgo.io/coopgo-platform/agenda/storage"
+ groupsmanagement "git.coopgo.io/coopgo-platform/groups-management/grpcapi"
+ "git.coopgo.io/coopgo-platform/groups-management/storage"
+ mobilityaccounts "git.coopgo.io/coopgo-platform/mobility-accounts/grpcapi"
+ "github.com/gorilla/mux"
+ "google.golang.org/protobuf/types/known/structpb"
+ "google.golang.org/protobuf/types/known/timestamppb"
+)
+
+type EventsByStartdate []agendastorage.Event
+
+func (e EventsByStartdate) Len() int { return len(e) }
+func (e EventsByStartdate) Less(i, j int) bool { return e[i].Startdate.Before(e[j].Startdate) }
+func (e EventsByStartdate) Swap(i, j int) { e[i], e[j] = e[j], e[i] }
+
+type EventsForm struct {
+ Name string `json:"name" validate:"required"`
+ Type string `json:"type" validate:"required"`
+ Description string `json:"description"`
+ Address any `json:"address,omitempty"`
+ Allday bool `json:"allday"`
+ Startdate *time.Time `json:"startdate"`
+ Enddate *time.Time `json:"enddate"`
+ Starttime string `json:"starttime"`
+ Endtime string `json:"endtime"`
+ MaxSubscribers int `json:"max_subscribers" validate:"required"`
+}
+
+func (h *ApplicationHandler) AgendaHome(w http.ResponseWriter, r *http.Request) {
+ resp, err := h.services.GRPC.Agenda.GetEvents(context.TODO(), &agenda.GetEventsRequest{
+ Namespaces: []string{"parcoursmob_dispositifs"},
+ Mindate: timestamppb.New(time.Now().Add(-24 * time.Hour)),
+ })
+
+ if err != nil {
+ fmt.Println(err)
+ w.WriteHeader(http.StatusInternalServerError)
+ return
+ }
+
+ responses := []agendastorage.Event{}
+
+ groupids := []string{}
+ for _, e := range resp.Events {
+ groupids = append(groupids, e.Owners...)
+ responses = append(responses, e.ToStorageType())
+ // fmt.Println(e)
+ // fmt.Println(e.ToStorageType())
+ }
+
+ sort.Sort(EventsByStartdate(responses))
+
+ groupsresp, err := h.services.GRPC.GroupsManagement.GetGroupsBatch(context.TODO(), &groupsmanagement.GetGroupsBatchRequest{
+ Groupids: groupids,
+ })
+ groups := map[string]any{}
+
+ if err == nil {
+ for _, g := range groupsresp.Groups {
+ groups[g.Id] = g.ToStorageType()
+ }
+ }
+
+ h.Renderer.AgendaHome(w, r, responses, groups)
+}
+
+func (h *ApplicationHandler) AgendaCreateEvent(w http.ResponseWriter, r *http.Request) {
+ if r.Method == "POST" {
+ // Get current group
+ g := r.Context().Value(identification.GroupKey)
+ if g == nil {
+ w.WriteHeader(http.StatusBadRequest)
+ return
+ }
+
+ group := g.(storage.Group)
+
+ eventForm, err := parseEventsForm(r)
+ if err != nil {
+ fmt.Println(err)
+ w.WriteHeader(http.StatusBadRequest)
+ return
+ }
+
+ fmt.Println(eventForm)
+
+ data, _ := structpb.NewStruct(map[string]any{
+ "address": eventForm.Address,
+ })
+
+ request := &agenda.CreateEventRequest{
+ Event: &agenda.Event{
+ Namespace: "parcoursmob_dispositifs",
+ Owners: []string{group.ID},
+ Type: eventForm.Type,
+ Name: eventForm.Name,
+ Description: eventForm.Description,
+ Startdate: timestamppb.New(*eventForm.Startdate),
+ Enddate: timestamppb.New(*eventForm.Enddate),
+ Starttime: eventForm.Starttime,
+ Endtime: eventForm.Endtime,
+ Allday: eventForm.Allday,
+ MaxSubscribers: int64(eventForm.MaxSubscribers),
+ Data: data,
+ },
+ }
+
+ resp, err := h.services.GRPC.Agenda.CreateEvent(context.TODO(), request)
+
+ if err != nil {
+ fmt.Println(err)
+ w.WriteHeader(http.StatusInternalServerError)
+ return
+ }
+
+ http.Redirect(w, r, fmt.Sprintf("/app/agenda/%s", resp.Event.Id), http.StatusFound)
+
+ }
+ h.Renderer.AgendaCreateEvent(w, r)
+}
+
+func (h *ApplicationHandler) AgendaDisplayEvent(w http.ResponseWriter, r *http.Request) {
+ vars := mux.Vars(r)
+ eventid := vars["eventid"]
+
+ request := &agenda.GetEventRequest{
+ Id: eventid,
+ }
+
+ resp, err := h.services.GRPC.Agenda.GetEvent(context.TODO(), request)
+ if err != nil {
+ fmt.Println(err)
+ w.WriteHeader(http.StatusInternalServerError)
+ return
+ }
+
+ grouprequest := &groupsmanagement.GetGroupRequest{
+ Id: resp.Event.Owners[0],
+ }
+
+ groupresp, err := h.services.GRPC.GroupsManagement.GetGroup(context.TODO(), grouprequest)
+ if err != nil {
+ fmt.Println(err)
+ w.WriteHeader(http.StatusInternalServerError)
+ return
+ }
+
+ subscribers := map[string]any{}
+
+ subscriberresp, err := h.services.GRPC.MobilityAccounts.GetAccountsBatch(
+ context.TODO(),
+ &mobilityaccounts.GetAccountsBatchRequest{
+ Accountids: resp.Event.Subscribers,
+ },
+ )
+
+ if err == nil {
+ for _, sub := range subscriberresp.Accounts {
+ subscribers[sub.Id] = sub.ToStorageType()
+ }
+ }
+
+ g := r.Context().Value(identification.GroupKey)
+ if g == nil {
+ fmt.Println(err)
+ w.WriteHeader(http.StatusInternalServerError)
+ return
+ }
+
+ group := g.(storage.Group)
+
+ accountids := []string{}
+ for _, m := range group.Members {
+ if !contains(resp.Event.Subscribers, m) {
+ accountids = append(accountids, m)
+ }
+ }
+
+ accountresp, err := h.services.GRPC.MobilityAccounts.GetAccountsBatch(
+ context.TODO(),
+ &mobilityaccounts.GetAccountsBatchRequest{
+ Accountids: accountids,
+ },
+ )
+
+ accounts := []any{}
+
+ if err == nil {
+ for _, acc := range accountresp.Accounts {
+ accounts = append(accounts, acc)
+ }
+ }
+
+ h.Renderer.AgendaDisplayEvent(w, r, resp.Event.ToStorageType(), groupresp.Group.ToStorageType(), subscribers, accounts)
+}
+
+func (h *ApplicationHandler) AgendaSubscribeEvent(w http.ResponseWriter, r *http.Request) {
+ vars := mux.Vars(r)
+ eventid := vars["eventid"]
+
+ if err := r.ParseForm(); err != nil {
+ fmt.Println(err)
+ w.WriteHeader(http.StatusBadRequest)
+ return
+ }
+
+ subscriber := r.FormValue("subscriber")
+
+ request := &agenda.SubscribeEventRequest{
+ Eventid: eventid,
+ Subscriber: subscriber,
+ }
+
+ _, err := h.services.GRPC.Agenda.SubscribeEvent(context.TODO(), request)
+ if err != nil {
+ fmt.Println(err)
+ w.WriteHeader(http.StatusInternalServerError)
+ return
+ }
+
+ http.Redirect(w, r, fmt.Sprintf("/app/agenda/%s", eventid), http.StatusFound)
+}
+
+func parseEventsForm(r *http.Request) (*EventsForm, error) {
+ if err := r.ParseForm(); err != nil {
+ return nil, err
+ }
+
+ var startdate *time.Time
+ var enddate *time.Time
+
+ if r.PostFormValue("startdate") != "" {
+ d, err := time.Parse("2006-01-02", r.PostFormValue("startdate"))
+ if err != nil {
+ return nil, err
+ }
+ startdate = &d
+ }
+
+ if r.PostFormValue("enddate") != "" {
+ d, err := time.Parse("2006-01-02", r.PostFormValue("enddate"))
+ if err != nil {
+ return nil, err
+ }
+ enddate = &d
+ }
+
+ max_subscribers, err := strconv.Atoi(r.PostFormValue("max_subscribers"))
+ if err != nil {
+ return nil, err
+ }
+
+ formData := &EventsForm{
+ Name: r.PostFormValue("name"),
+ Type: r.PostFormValue("type"),
+ Description: r.PostFormValue("description"),
+ Startdate: startdate,
+ Enddate: enddate,
+ Starttime: r.PostFormValue("starttime"),
+ Endtime: r.PostFormValue("endtime"),
+ MaxSubscribers: max_subscribers,
+ }
+
+ if r.PostFormValue("allday") == "true" {
+ formData.Allday = true
+ }
+
+ if r.PostFormValue("address") != "" {
+ var a any
+ json.Unmarshal([]byte(r.PostFormValue("address")), &a)
+
+ formData.Address = a
+ }
+
+ validate := formvalidators.New()
+ if err := validate.Struct(formData); err != nil {
+ return nil, err
+ }
+
+ return formData, nil
+}
+
+func contains(s []string, e string) bool {
+ for _, a := range s {
+ if a == e {
+ return true
+ }
+ }
+ return false
+}
diff --git a/handlers/application/beneficiaries.go b/handlers/application/beneficiaries.go
index 422a619..a0f9231 100644
--- a/handlers/application/beneficiaries.go
+++ b/handlers/application/beneficiaries.go
@@ -16,6 +16,7 @@ import (
formvalidators "git.coopgo.io/coopgo-apps/parcoursmob/utils/form-validators"
"git.coopgo.io/coopgo-apps/parcoursmob/utils/identification"
profilepictures "git.coopgo.io/coopgo-apps/parcoursmob/utils/profile-pictures"
+ fleets "git.coopgo.io/coopgo-platform/fleets/grpcapi"
groupsmanagement "git.coopgo.io/coopgo-platform/groups-management/grpcapi"
"git.coopgo.io/coopgo-platform/groups-management/storage"
mobilityaccounts "git.coopgo.io/coopgo-platform/mobility-accounts/grpcapi"
@@ -61,7 +62,7 @@ func (h *ApplicationHandler) BeneficiaryCreate(w http.ResponseWriter, r *http.Re
if r.Method == "POST" {
- dataMap, err := parseForm(r)
+ dataMap, err := parseBeneficiariesForm(r)
if err != nil {
fmt.Println(err)
w.WriteHeader(http.StatusBadRequest)
@@ -128,7 +129,23 @@ func (h *ApplicationHandler) BeneficiaryDisplay(w http.ResponseWriter, r *http.R
//TODO filter namespaces
//TODO filter groups
- h.Renderer.BeneficiaryDisplay(w, r, resp.Account.ToStorageType())
+ bookingsrequest := &fleets.GetDriverBookingsRequest{
+ Driver: beneficiaryID,
+ }
+ bookingsresp, err := h.services.GRPC.Fleets.GetDriverBookings(context.TODO(), bookingsrequest)
+ if err != nil {
+ fmt.Println(err)
+ w.WriteHeader(http.StatusInternalServerError)
+ return
+ }
+
+ bookings := []any{}
+
+ for _, b := range bookingsresp.Bookings {
+ bookings = append(bookings, b.ToStorageType())
+ }
+
+ h.Renderer.BeneficiaryDisplay(w, r, resp.Account.ToStorageType(), bookings)
}
func (h *ApplicationHandler) BeneficiaryUpdate(w http.ResponseWriter, r *http.Request) {
@@ -137,7 +154,7 @@ func (h *ApplicationHandler) BeneficiaryUpdate(w http.ResponseWriter, r *http.Re
if r.Method == "POST" {
- dataMap, err := parseForm(r)
+ dataMap, err := parseBeneficiariesForm(r)
if err != nil {
fmt.Println(err)
w.WriteHeader(http.StatusBadRequest)
@@ -189,56 +206,6 @@ func (h *ApplicationHandler) BeneficiaryUpdate(w http.ResponseWriter, r *http.Re
h.Renderer.BeneficiaryUpdate(w, r, resp.Account.ToStorageType())
}
-func parseForm(r *http.Request) (map[string]any, error) {
- if err := r.ParseForm(); err != nil {
- return nil, err
- }
-
- var date *time.Time
-
- if r.PostFormValue("birthdate") != "" {
- d, err := time.Parse("2006-01-02", r.PostFormValue("birthdate"))
- if err != nil {
- return nil, err
- }
- date = &d
- }
-
- formData := BeneficiariesForm{
- FirstName: r.PostFormValue("first_name"),
- LastName: r.PostFormValue("last_name"),
- Email: r.PostFormValue("email"),
- Birthdate: date,
- PhoneNumber: r.PostFormValue("phone_number"),
- Gender: r.PostFormValue("gender"),
- }
-
- if r.PostFormValue("address") != "" {
- var a any
- json.Unmarshal([]byte(r.PostFormValue("address")), &a)
-
- formData.Address = a
- }
-
- validate := formvalidators.New()
- if err := validate.Struct(formData); err != nil {
- return nil, err
- }
-
- d, err := json.Marshal(formData)
- if err != nil {
- return nil, err
- }
-
- var dataMap map[string]any
- err = json.Unmarshal(d, &dataMap)
- if err != nil {
- return nil, err
- }
-
- return dataMap, nil
-}
-
func (h *ApplicationHandler) BeneficiaryPicture(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
beneficiaryID := vars["beneficiaryid"]
@@ -312,3 +279,53 @@ func (h *ApplicationHandler) beneficiaries(r *http.Request) ([]any, error) {
return accounts, err
}
+
+func parseBeneficiariesForm(r *http.Request) (map[string]any, error) {
+ if err := r.ParseForm(); err != nil {
+ return nil, err
+ }
+
+ var date *time.Time
+
+ if r.PostFormValue("birthdate") != "" {
+ d, err := time.Parse("2006-01-02", r.PostFormValue("birthdate"))
+ if err != nil {
+ return nil, err
+ }
+ date = &d
+ }
+
+ formData := BeneficiariesForm{
+ FirstName: r.PostFormValue("first_name"),
+ LastName: r.PostFormValue("last_name"),
+ Email: r.PostFormValue("email"),
+ Birthdate: date,
+ PhoneNumber: r.PostFormValue("phone_number"),
+ Gender: r.PostFormValue("gender"),
+ }
+
+ if r.PostFormValue("address") != "" {
+ var a any
+ json.Unmarshal([]byte(r.PostFormValue("address")), &a)
+
+ formData.Address = a
+ }
+
+ validate := formvalidators.New()
+ if err := validate.Struct(formData); err != nil {
+ return nil, err
+ }
+
+ d, err := json.Marshal(formData)
+ if err != nil {
+ return nil, err
+ }
+
+ var dataMap map[string]any
+ err = json.Unmarshal(d, &dataMap)
+ if err != nil {
+ return nil, err
+ }
+
+ return dataMap, nil
+}
diff --git a/handlers/application/vehicles-management.go b/handlers/application/vehicles-management.go
index f5e9e5d..cc504ad 100644
--- a/handlers/application/vehicles-management.go
+++ b/handlers/application/vehicles-management.go
@@ -5,6 +5,7 @@ import (
"encoding/json"
"fmt"
"net/http"
+ "time"
"git.coopgo.io/coopgo-apps/parcoursmob/utils/identification"
fleets "git.coopgo.io/coopgo-platform/fleets/grpcapi"
@@ -14,6 +15,7 @@ import (
"github.com/google/uuid"
"github.com/gorilla/mux"
"google.golang.org/protobuf/types/known/structpb"
+ "google.golang.org/protobuf/types/known/timestamppb"
)
func (h *ApplicationHandler) VehiclesManagementOverview(w http.ResponseWriter, r *http.Request) {
@@ -182,6 +184,57 @@ func (h ApplicationHandler) VehicleManagementBookingDisplay(w http.ResponseWrite
booking := resp.Booking.ToStorageType()
+ if r.Method == "POST" {
+ r.ParseForm()
+
+ newbooking := resp.Booking
+
+ startdate := r.FormValue("startdate")
+ if startdate != "" {
+ newstartdate, _ := time.Parse("2006-01-02", startdate)
+ newbooking.Startdate = timestamppb.New(newstartdate)
+
+ if newstartdate.Before(newbooking.Unavailablefrom.AsTime()) {
+ newbooking.Unavailablefrom = timestamppb.New(newstartdate)
+ }
+ }
+
+ enddate := r.FormValue("enddate")
+ if enddate != "" {
+ newenddate, _ := time.Parse("2006-01-02", enddate)
+ newbooking.Enddate = timestamppb.New(newenddate)
+
+ if newenddate.After(newbooking.Unavailableto.AsTime()) || newenddate.Equal(newbooking.Unavailableto.AsTime()) {
+ newbooking.Unavailableto = timestamppb.New(newenddate.Add(24 * time.Hour))
+ }
+ }
+
+ unavailablefrom := r.FormValue("unavailablefrom")
+ if unavailablefrom != "" {
+ newunavailablefrom, _ := time.Parse("2006-01-02", unavailablefrom)
+ newbooking.Unavailablefrom = timestamppb.New(newunavailablefrom)
+ }
+
+ unavailableto := r.FormValue("unavailableto")
+ if unavailableto != "" {
+ newunavailableto, _ := time.Parse("2006-01-02", unavailableto)
+ newbooking.Unavailableto = timestamppb.New(newunavailableto)
+ }
+
+ request := &fleets.UpdateBookingRequest{
+ Booking: newbooking,
+ }
+
+ _, err := h.services.GRPC.Fleets.UpdateBooking(context.TODO(), request)
+ if err != nil {
+ fmt.Println(err)
+ w.WriteHeader(http.StatusInternalServerError)
+ return
+ }
+
+ booking = newbooking.ToStorageType()
+ }
+
beneficiaryrequest := &mobilityaccounts.GetAccountRequest{
Id: booking.Driver,
}
diff --git a/handlers/application/vehicles.go b/handlers/application/vehicles.go
index 5d26ddc..92f0a3f 100644
--- a/handlers/application/vehicles.go
+++ b/handlers/application/vehicles.go
@@ -6,10 +6,15 @@ import (
"net/http"
"time"
+ "git.coopgo.io/coopgo-apps/parcoursmob/utils/identification"
fleets "git.coopgo.io/coopgo-platform/fleets/grpcapi"
+ groupsmanagement "git.coopgo.io/coopgo-platform/groups-management/grpcapi"
+ "git.coopgo.io/coopgo-platform/groups-management/storage"
mobilityaccounts "git.coopgo.io/coopgo-platform/mobility-accounts/grpcapi"
+ "github.com/coreos/go-oidc"
"github.com/google/uuid"
"github.com/gorilla/mux"
+ "google.golang.org/protobuf/types/known/structpb"
"google.golang.org/protobuf/types/known/timestamppb"
)
@@ -71,6 +76,32 @@ func (h ApplicationHandler) VehiclesSearch(w http.ResponseWriter, r *http.Reques
}
func (h ApplicationHandler) Book(w http.ResponseWriter, r *http.Request) {
+ // Get Group
+ g := r.Context().Value(identification.GroupKey)
+ if g == nil {
+ fmt.Println("no current group")
+ w.WriteHeader(http.StatusInternalServerError)
+ return
+ }
+ current_group := g.(storage.Group)
+
+ // Get current user ID
+ u := r.Context().Value(identification.IdtokenKey)
+ if u == nil {
+ fmt.Println("no current user")
+ w.WriteHeader(http.StatusInternalServerError)
+ return
+ }
+ current_user_token := u.(*oidc.IDToken)
+
+ // Get current user claims
+ c := r.Context().Value(identification.ClaimsKey)
+ if c == nil {
+ fmt.Println("no current user claims")
+ w.WriteHeader(http.StatusInternalServerError)
+ return
+ }
+ current_user_claims := c.(map[string]any)
vars := mux.Vars(r)
vehicleid := vars["vehicleid"]
@@ -84,6 +115,25 @@ func (h ApplicationHandler) Book(w http.ResponseWriter, r *http.Request) {
startdate, _ := time.Parse("2006-01-02", start)
enddate, _ := time.Parse("2006-01-02", end)
+ data := map[string]any{
+ "booked_by": map[string]any{
+ "user": map[string]any{
+ "id": current_user_token.Subject,
+ "display_name": current_user_claims["display_name"],
+ },
+ "group": map[string]any{
+ "id": current_group.ID,
+ "name": current_group.Data["name"],
+ },
+ },
+ }
+ datapb, err := structpb.NewStruct(data)
+ if err != nil {
+ fmt.Println(err)
+ w.WriteHeader(http.StatusInternalServerError)
+ return
+ }
+
booking := &fleets.Booking{
Id: uuid.NewString(),
Vehicleid: vehicleid,
@@ -92,13 +142,14 @@ func (h ApplicationHandler) Book(w http.ResponseWriter, r *http.Request) {
Enddate: timestamppb.New(enddate),
Unavailablefrom: timestamppb.New(startdate),
Unavailableto: timestamppb.New(enddate.Add(72 * time.Hour)),
+ Data: datapb,
}
request := &fleets.CreateBookingRequest{
Booking: booking,
}
- _, err := h.services.GRPC.Fleets.CreateBooking(context.TODO(), request)
+ _, err = h.services.GRPC.Fleets.CreateBooking(context.TODO(), request)
if err != nil {
fmt.Println(err)
w.WriteHeader(http.StatusBadRequest)
@@ -136,16 +187,34 @@ func (h ApplicationHandler) VehicleBookingDisplay(w http.ResponseWriter, r *http
return
}
- // grouprequest := &groupsmanagement.GetGroupRequest{
- // Id: booking.Vehicle.Administrators[0],
- // }
+ grouprequest := &groupsmanagement.GetGroupRequest{
+ Id: booking.Vehicle.Administrators[0],
+ }
- // groupresp, err := h.services.GRPC.GroupsManagement.GetGroup(context.TODO(), grouprequest)
- // if err != nil {
- // fmt.Println(err)
- // w.WriteHeader(http.StatusInternalServerError)
- // return
- // }
+ groupresp, err := h.services.GRPC.GroupsManagement.GetGroup(context.TODO(), grouprequest)
+ if err != nil {
+ fmt.Println(err)
+ w.WriteHeader(http.StatusInternalServerError)
+ return
+ }
- h.Renderer.VehicleBookingDisplay(w, r, booking, booking.Vehicle, beneficiaryresp.Account.ToStorageType(), "")
+ h.Renderer.VehicleBookingDisplay(w, r, booking, booking.Vehicle, beneficiaryresp.Account.ToStorageType(), groupresp.Group.ToStorageType())
+}
+
+func (h ApplicationHandler) VehiclesBookingsList(w http.ResponseWriter, r *http.Request) {
+ request := &fleets.GetBookingsRequest{}
+ resp, err := h.services.GRPC.Fleets.GetBookings(context.TODO(), request)
+ if err != nil {
+ fmt.Println(err)
+ w.WriteHeader(http.StatusNotFound)
+ return
+ }
+
+ bookings := []any{}
+
+ for _, b := range resp.Bookings {
+ bookings = append(bookings, b.ToStorageType())
+ }
+
+ h.Renderer.VehicleBookingsList(w, r, bookings)
}
diff --git a/main.go b/main.go
index 859959e..94bba2f 100644
--- a/main.go
+++ b/main.go
@@ -54,6 +54,7 @@ func main() {
r.HandleFunc("/auth/groups/", authHandler.Groups)
r.HandleFunc("/auth/groups/switch", authHandler.GroupSwitch)
+ r.HandleFunc("/", redirectApp)
api_router := r.PathPrefix("/api").Subrouter()
api_router.HandleFunc("/", apiHandler.NotFound)
@@ -68,7 +69,9 @@ func main() {
application.HandleFunc("/beneficiaries/{beneficiaryid}", applicationHandler.BeneficiaryDisplay)
application.HandleFunc("/beneficiaries/{beneficiaryid}/update", applicationHandler.BeneficiaryUpdate)
application.HandleFunc("/beneficiaries/{beneficiaryid}/picture", applicationHandler.BeneficiaryPicture)
+ application.HandleFunc("/members/{beneficiaryid}/picture", applicationHandler.BeneficiaryPicture)
application.HandleFunc("/vehicles/", applicationHandler.VehiclesSearch)
+ application.HandleFunc("/vehicles/bookings/", applicationHandler.VehiclesBookingsList)
application.HandleFunc("/vehicles/bookings/{bookingid}", applicationHandler.VehicleBookingDisplay)
application.HandleFunc("/vehicles/v/{vehicleid}/b/{beneficiaryid}", applicationHandler.Book)
application.HandleFunc("/vehicles-management/", applicationHandler.VehiclesManagementOverview)
@@ -76,6 +79,10 @@ func main() {
application.HandleFunc("/vehicles-management/fleet/{vehicleid}", applicationHandler.VehiclesFleetDisplay)
application.HandleFunc("/vehicles-management/fleet/{vehicleid}/update", applicationHandler.VehiclesFleetUpdate)
application.HandleFunc("/vehicles-management/bookings/{bookingid}", applicationHandler.VehicleManagementBookingDisplay)
+ application.HandleFunc("/agenda/", applicationHandler.AgendaHome)
+ application.HandleFunc("/agenda/create-event", applicationHandler.AgendaCreateEvent)
+ application.HandleFunc("/agenda/{eventid}", applicationHandler.AgendaDisplayEvent)
+ application.HandleFunc("/agenda/{eventid}/subscribe", applicationHandler.AgendaSubscribeEvent)
//TODO Subrouters with middlewares checking security for each module ?
application.Use(idp.Middleware)
application.Use(idp.GroupsMiddleware)
@@ -98,3 +105,7 @@ func main() {
log.Fatal(srv.ListenAndServe())
}
+
+func redirectApp(w http.ResponseWriter, r *http.Request) {
+ http.Redirect(w, r, "/app/", http.StatusFound)
+}
diff --git a/renderer/agenda.go b/renderer/agenda.go
new file mode 100644
index 0000000..d96c837
--- /dev/null
+++ b/renderer/agenda.go
@@ -0,0 +1,40 @@
+package renderer
+
+import (
+ "net/http"
+
+ agendastorage "git.coopgo.io/coopgo-platform/agenda/storage"
+)
+
+const agendaMenu = "events"
+
+func (renderer *Renderer) AgendaHome(w http.ResponseWriter, r *http.Request, events []agendastorage.Event, groups map[string]any) {
+ files := renderer.ThemeConfig.GetStringSlice("views.agenda.list.files")
+ state := NewState(r, renderer.ThemeConfig, agendaMenu)
+ state.ViewState = map[string]any{
+ "events": events,
+ "groups": groups,
+ }
+
+ renderer.Render("agenda home", w, r, files, state)
+}
+
+func (renderer *Renderer) AgendaCreateEvent(w http.ResponseWriter, r *http.Request) {
+ files := renderer.ThemeConfig.GetStringSlice("views.agenda.create_event.files")
+ state := NewState(r, renderer.ThemeConfig, agendaMenu)
+
+ renderer.Render("agenda create event", w, r, files, state)
+}
+
+func (renderer *Renderer) AgendaDisplayEvent(w http.ResponseWriter, r *http.Request, event any, group any, subscribers map[string]any, beneficiaries any) {
+ files := renderer.ThemeConfig.GetStringSlice("views.agenda.display_event.files")
+ state := NewState(r, renderer.ThemeConfig, agendaMenu)
+ state.ViewState = map[string]any{
+ "event": event,
+ "group": group,
+ "subscribers": subscribers,
+ "beneficiaries": beneficiaries,
+ }
+
+ renderer.Render("agenda create event", w, r, files, state)
+}
diff --git a/renderer/beneficiaries.go b/renderer/beneficiaries.go
index 20d5fe0..614cee8 100644
--- a/renderer/beneficiaries.go
+++ b/renderer/beneficiaries.go
@@ -50,10 +50,13 @@ type BeneficiariesDisplayState struct {
Beneficiary any
}
-func (renderer *Renderer) BeneficiaryDisplay(w http.ResponseWriter, r *http.Request, beneficiary any) {
+func (renderer *Renderer) BeneficiaryDisplay(w http.ResponseWriter, r *http.Request, beneficiary any, bookings []any) {
files := renderer.ThemeConfig.GetStringSlice("views.beneficiaries.display.files")
state := NewState(r, renderer.ThemeConfig, beneficiariesMenu)
- state.ViewState = beneficiary
+ state.ViewState = map[string]any{
+ "beneficiary": beneficiary,
+ "bookings": bookings,
+ }
renderer.Render("beneficiaries_display", w, r, files, state)
}
diff --git a/renderer/renderer.go b/renderer/renderer.go
index e4f9f66..43900db 100644
--- a/renderer/renderer.go
+++ b/renderer/renderer.go
@@ -122,6 +122,8 @@ func NewState(r *http.Request, themeConfig *viper.Viper, menuState string) Rende
Display: modules["administration"].(bool),
Active: menuState == administrationMenu,
},
+
+ //TODO from configuration for icons at least
MenuItems: []MenuItem{
{
Title: "Tableau de bord",
@@ -155,7 +157,7 @@ func NewState(r *http.Request, themeConfig *viper.Viper, menuState string) Rende
Title: "Véhicules partagés",
Link: "/app/vehicles/",
Active: menuState == "vehicles",
- Icon: "hero:outline/user-group",
+ Icon: "tabler-icons:car",
})
}
@@ -168,11 +170,11 @@ func NewState(r *http.Request, themeConfig *viper.Viper, menuState string) Rende
})
}
- if modules["events"].(bool) {
+ if modules["agenda"].(bool) {
ls.MenuItems = append(ls.MenuItems, MenuItem{
- Title: "Dispositifs",
- Link: "/app/events/",
- Active: menuState == "events",
+ Title: "Agenda dispositifs",
+ Link: "/app/agenda/",
+ Active: menuState == "agenda",
Icon: "hero:outline/calendar",
})
}
diff --git a/renderer/vehicles.go b/renderer/vehicles.go
index 50982df..0dd88d8 100644
--- a/renderer/vehicles.go
+++ b/renderer/vehicles.go
@@ -38,3 +38,13 @@ func (renderer *Renderer) VehicleBookingDisplay(w http.ResponseWriter, r *http.R
renderer.Render("vehicles search", w, r, files, state)
}
+
+func (renderer *Renderer) VehicleBookingsList(w http.ResponseWriter, r *http.Request, bookings []any) {
+ files := renderer.ThemeConfig.GetStringSlice("views.vehicles.bookings_list.files")
+ state := NewState(r, renderer.ThemeConfig, vehiclesMenu)
+ state.ViewState = map[string]any{
+ "bookings": bookings,
+ }
+
+ renderer.Render("vehicles search", w, r, files, state)
+}
diff --git a/services/agenda.go b/services/agenda.go
new file mode 100644
index 0000000..b27e30f
--- /dev/null
+++ b/services/agenda.go
@@ -0,0 +1,23 @@
+package services
+
+import (
+ agenda "git.coopgo.io/coopgo-platform/agenda/grpcapi"
+ "google.golang.org/grpc"
+)
+
+type AgendaService struct {
+ agenda.AgendaClient
+}
+
+func NewAgendaService(dial string) (*AgendaService, error) {
+ conn, err := grpc.Dial(dial, grpc.WithInsecure())
+
+ client := agenda.NewAgendaClient(conn)
+ if err != nil {
+ return nil, err
+ }
+
+ return &AgendaService{
+ AgendaClient: client,
+ }, nil
+}
diff --git a/services/services.go b/services/services.go
index bc17da5..14b4890 100644
--- a/services/services.go
+++ b/services/services.go
@@ -1,6 +1,7 @@
package services
import (
+ agenda "git.coopgo.io/coopgo-platform/agenda/grpcapi"
fleets "git.coopgo.io/coopgo-platform/fleets/grpcapi"
groupsmanagement "git.coopgo.io/coopgo-platform/groups-management/grpcapi"
mobilityaccounts "git.coopgo.io/coopgo-platform/mobility-accounts/grpcapi"
@@ -15,6 +16,7 @@ type GRPCServices struct {
MobilityAccounts mobilityaccounts.MobilityAccountsClient
GroupsManagement groupsmanagement.GroupsManagementClient
Fleets fleets.FleetsClient
+ Agenda agenda.AgendaClient
}
func NewServicesHandler(cfg *viper.Viper) (*ServicesHandler, error) {
@@ -22,6 +24,7 @@ func NewServicesHandler(cfg *viper.Viper) (*ServicesHandler, error) {
mobilityAccountsDial = cfg.GetString("services.grpc.mobilityaccounts.dial")
groupsManagementDial = cfg.GetString("services.grpc.groupsmanagement.dial")
fleetsDial = cfg.GetString("services.grpc.fleets.dial")
+ agendaDial = cfg.GetString("services.grpc.agenda.dial")
)
mobilityAccounts, err := NewMobilityAccountService(mobilityAccountsDial)
if err != nil {
@@ -38,11 +41,17 @@ func NewServicesHandler(cfg *viper.Viper) (*ServicesHandler, error) {
return nil, err
}
+ agendaSvc, err := NewAgendaService(agendaDial)
+ if err != nil {
+ return nil, err
+ }
+
return &ServicesHandler{
GRPC: GRPCServices{
MobilityAccounts: mobilityAccounts,
GroupsManagement: groupsManagement,
Fleets: fleetsSvc,
+ Agenda: agendaSvc,
},
}, nil
}
diff --git a/themes/default/config.yaml b/themes/default/config.yaml
index 13f42f5..5c6fbf0 100644
--- a/themes/default/config.yaml
+++ b/themes/default/config.yaml
@@ -39,6 +39,10 @@ views:
booking_display:
files:
- layouts/vehicles/booking-display.html
+ bookings_list:
+ files:
+ - layouts/vehicles_management/_partials/bookings-list.html
+ - layouts/vehicles/bookings-list.html
vehicles_management:
overview:
files:
@@ -62,6 +66,17 @@ views:
booking_display:
files:
- layouts/vehicles_management/booking-display.html
+ agenda:
+ list:
+ files:
+ - layouts/agenda/home.html
+ display_event:
+ files:
+ - layouts/agenda/display-event.html
+ create_event:
+ files:
+ - layouts/_partials/address_autocomplete.html
+ - layouts/agenda/create-event.html
administration:
home:
files:
@@ -96,4 +111,4 @@ icons:
hero:solid/search:
hero:solid/selector:
img:profile-picture-placeholder:
-
+ tabler-icons:car:
diff --git a/themes/default/layouts/administration/create_group.html b/themes/default/layouts/administration/create_group.html
index eedf35f..c5485ab 100644
--- a/themes/default/layouts/administration/create_group.html
+++ b/themes/default/layouts/administration/create_group.html
@@ -117,8 +117,8 @@
class="focus:ring-co-blue h-4 w-4 text-co-blue border-gray-300 rounded">
-
Dispositifs
-
Gestion des dispositifs pour les bénéficiaires (auto-écoles sociales, événements, ...)
+ Agenda dispositifs
+
Agenda des dispositifs pour les bénéficiaires (sessions permis, événements, ...)
diff --git a/themes/default/layouts/administration/display_group.html b/themes/default/layouts/administration/display_group.html
index c669351..c321fc6 100644
--- a/themes/default/layouts/administration/display_group.html
+++ b/themes/default/layouts/administration/display_group.html
@@ -88,8 +88,8 @@
class="focus:ring-co-blue h-4 w-4 text-co-blue border-gray-300 rounded">
-
Dispositifs
-
Gestion des dispositifs pour les bénéficiaires (auto-écoles sociales, événements, ...)
+ Agenda dispositifs
+
Agenda des dispositifs pour les bénéficiaires (sessions permis, événements, ...)
diff --git a/themes/default/layouts/agenda/create-event.html b/themes/default/layouts/agenda/create-event.html
new file mode 100644
index 0000000..115fba6
--- /dev/null
+++ b/themes/default/layouts/agenda/create-event.html
@@ -0,0 +1,212 @@
+{{ define "content" }}
+
+
+
Ajouter à l'agenda
+
+
+
+
+{{end}}
\ No newline at end of file
diff --git a/themes/default/layouts/agenda/display-event.html b/themes/default/layouts/agenda/display-event.html
new file mode 100644
index 0000000..fcc31a7
--- /dev/null
+++ b/themes/default/layouts/agenda/display-event.html
@@ -0,0 +1,140 @@
+{{ define "content" }}
+
+
+
+
+
{{.ViewState.event.Name}}
+
+ {{if eq .ViewState.event.Startdate .ViewState.event.Enddate}}
+ Le {{(timeFrom .ViewState.event.Startdate).Format "02/01/2006"}}
+ {{else}}
+ Du {{(timeFrom .ViewState.event.Startdate).Format "02/01/2006"}} au {{(timeFrom .ViewState.event.Enddate).Format "02/01/2006"}}
+ {{end}}
+
+
+
+
+
+
+
+
+
+
+
Informations
+
Informations sur le dispositif.
+
+
+
+ {{if .ViewState.event.Type}}
+
+
Type
+ {{.ViewState.event.Type}}
+
+ {{end}}
+ {{if .ViewState.group}}
+
+
Structure gestionnaire
+ {{.ViewState.group.Data.name}}
+
+ {{end}}
+ {{if .ViewState.event.MaxSubscribers}}
+
+
Total places
+ {{.ViewState.event.MaxSubscribers}}
+
+ {{end}}
+ {{if ne .ViewState.event.MaxSubscribers 0}}
+
+
Places restantes
+ {{.ViewState.event.RemainingSubscriptions}}
+
+ {{end}}
+ {{if .ViewState.event.Data.address}}
+
+
Adresse
+ {{.ViewState.event.Data.address.properties.label}}
+
+ {{end}}
+ {{if .ViewState.event.Description}}
+
+
Description
+ {{.ViewState.event.Description}}
+
+ {{end}}
+
+
+
+
+
+
+
+
Inscrire un bénéficiaire
+ {{if gt .ViewState.event.RemainingSubscriptions 0}}
+
+
+
+ Inscrire le bénéficiaire
+
+
+ {{else}}
+
Il n'y a plus de place disponible
+ {{end}}
+ {{if .ViewState.subscribers}}
+
Inscrits
+
+ {{range .ViewState.subscribers}}
+
+ {{end}}
+
+ {{end}}
+
+
+
+
+{{ end }}
\ No newline at end of file
diff --git a/themes/default/layouts/agenda/home.html b/themes/default/layouts/agenda/home.html
new file mode 100644
index 0000000..49c9aef
--- /dev/null
+++ b/themes/default/layouts/agenda/home.html
@@ -0,0 +1,110 @@
+{{define "content"}}
+
+
Agenda dispositifs
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Type de dispositif
+
+
+ Structure
+
+
+ Nom
+
+
+ Lieu
+
+
+ Dates
+
+
+ Places disponibles
+
+
+ Bénéficiaires positionnés
+
+
+ Actions
+
+
+
+ {{range .ViewState.events}}
+
+
+ {{.Type}}
+
+
+
+
+ {{range .Owners}}
+ {{if (index $.ViewState.groups .)}}
+ {{(index $.ViewState.groups .).Data.name}}
+ {{end}}
+ {{end}}
+
+
+
+ {{.Name}}
+
+
+ {{if .Data.address}}{{.Data.address.properties.label}}{{end}}
+
+
+
+ {{if eq .Startdate .Enddate}}
+ Le {{(timeFrom .Startdate).Format "02/01/2006"}}
+ {{else}}
+ Du {{(timeFrom .Startdate).Format "02/01/2006"}} Au {{(timeFrom .Enddate).Format "02/01/2006"}}
+ {{end}}
+
+
+
+ {{.RemainingSubscriptions}}
+
+
+
+ {{range .Subscribers}}
+
+ {{end}}
+
+
+
+
+
+ Voir
+
+
+ {{end}}
+
+
+
+
+
+
+
+
+{{end}}
\ No newline at end of file
diff --git a/themes/default/layouts/beneficiaries/_partials/beneficiary-vehicles.html b/themes/default/layouts/beneficiaries/_partials/beneficiary-vehicles.html
index b5d4a77..897ade0 100644
--- a/themes/default/layouts/beneficiaries/_partials/beneficiary-vehicles.html
+++ b/themes/default/layouts/beneficiaries/_partials/beneficiary-vehicles.html
@@ -1,8 +1,16 @@
{{define "beneficiary_vehicles"}}
+ {{if .ViewState.bookings}}
+
Mises à disposition réalisées
+
+ {{range .ViewState.bookings}}
+ Du {{(timeFrom .Startdate).Format "02/01/2006"}} au {{(timeFrom .Enddate).Format "02/01/2006"}}
+ {{end}}
+
+ {{end}}
Réserver un véhicule
-
+
Du
diff --git a/themes/default/layouts/beneficiaries/display.html b/themes/default/layouts/beneficiaries/display.html
index 2f42ebc..4db8599 100644
--- a/themes/default/layouts/beneficiaries/display.html
+++ b/themes/default/layouts/beneficiaries/display.html
@@ -5,24 +5,24 @@
-
+
-
{{.ViewState.Data.first_name}}
- {{.ViewState.Data.last_name}}
-
{{if .ViewState.Metadata.created}}Ajouté le {{.ViewState.Metadata.created}} par
+
{{.ViewState.beneficiary.Data.first_name}}
+ {{.ViewState.beneficiary.Data.last_name}}
+
{{if .ViewState.beneficiary.Metadata.created}}Ajouté le {{.ViewState.beneficiary.Metadata.created}} par
Conseiller 1 {{end}}
@@ -38,44 +38,44 @@
- {{if .ViewState.Data.email}}
+ {{if .ViewState.beneficiary.Data.email}}
Email
- {{.ViewState.Data.email}}
+ {{.ViewState.beneficiary.Data.email}}
{{end}}
- {{if .ViewState.Data.phone_number}}
+ {{if .ViewState.beneficiary.Data.phone_number}}
Téléphone
- {{.ViewState.Data.phone_number}}
+ {{.ViewState.beneficiary.Data.phone_number}}
{{end}}
- {{if .ViewState.Data.birthdate}}
+ {{if .ViewState.beneficiary.Data.birthdate}}
Date de naissance
- {{(timeFrom .ViewState.Data.birthdate).Format
+ {{(timeFrom .ViewState.beneficiary.Data.birthdate).Format
"02/01/2006"}}
{{end}}
- {{if and .ViewState.Data.gender (ne .ViewState.Data.gender "0")}}
+ {{if and .ViewState.beneficiary.Data.gender (ne .ViewState.beneficiary.Data.gender "0")}}
Genre
- {{genderISO5218 .ViewState.Data.gender}}
+ {{genderISO5218 .ViewState.beneficiary.Data.gender}}
{{end}}
- {{if .ViewState.Data.address}}
+ {{if .ViewState.beneficiary.Data.address}}
Adresse
- {{.ViewState.Data.address.properties.label}}
+ {{.ViewState.beneficiary.Data.address.properties.label}}
{{end}}
-
+
Select a tab
- Notes
+
Déplacements
@@ -100,10 +100,10 @@
- {{template "beneficiary_notes" .}}
{{template "beneficiary_journeys" .}}
{{template "beneficiary_vehicles" .}}
{{template "beneficiary_events" .}}
{{template "beneficiary_files" .}}
+ {{template "beneficiary_notes" .}}
diff --git a/themes/default/layouts/vehicles/booking-display.html b/themes/default/layouts/vehicles/booking-display.html
index afc7eb4..b30f8f3 100644
--- a/themes/default/layouts/vehicles/booking-display.html
+++ b/themes/default/layouts/vehicles/booking-display.html
@@ -92,9 +92,24 @@
Gestionnaire
- COOPGO
+ {{.ViewState.group.Data.name}}
+ {{if .ViewState.booking.Data.booked_by}}
+
+ {{end}}
Véhicule
@@ -122,7 +137,7 @@
"02/01/2006"}}
-
Date de fin
+ Date de retour
{{(timeFrom .ViewState.booking.Enddate).Format
"02/01/2006"}}
diff --git a/themes/default/layouts/vehicles/bookings-list.html b/themes/default/layouts/vehicles/bookings-list.html
new file mode 100644
index 0000000..5cc979c
--- /dev/null
+++ b/themes/default/layouts/vehicles/bookings-list.html
@@ -0,0 +1,68 @@
+{{define "content"}}
+
+
Réservations
+
+
+
+
+
+
+
+
+
+
+
+
+ Type
+
+
+ Beneficiaire
+
+
+ Dates
+
+
+ Actions
+
+
+
+
+
+ {{range .ViewState.bookings}}
+
+
+
+ Voiture
+
+
+
+
+
+
+ Du {{(timeFrom .Startdate).Format "02/01/2006"}} au {{(timeFrom .Enddate).Format "02/01/2006"}}
+
+
+ Voir
+
+
+ {{end}}
+
+
+
+
+
+
+
+
+
+
+{{end}}
\ No newline at end of file
diff --git a/themes/default/layouts/vehicles/search.html b/themes/default/layouts/vehicles/search.html
index 518aefb..073d824 100644
--- a/themes/default/layouts/vehicles/search.html
+++ b/themes/default/layouts/vehicles/search.html
@@ -7,7 +7,7 @@
-
+
Voir les prêts de véhicules
@@ -33,7 +33,7 @@
return this.beneficiaries.filter(b => b['data']['first_name'].includes(text) || b['data']['last_name'].includes(text))
},
fields: {
- beneficiaryid: null,
+ beneficiaryid: {{if .ViewState.search}}'{{.ViewState.search.beneficiary.ID}}'{{else}}null{{end}},
},
selectbeneficiary(beneficiary) {
console.log(beneficiary)
diff --git a/themes/default/layouts/vehicles_management/_partials/bookings-list.html b/themes/default/layouts/vehicles_management/_partials/bookings-list.html
index a646f4a..4f7f232 100644
--- a/themes/default/layouts/vehicles_management/_partials/bookings-list.html
+++ b/themes/default/layouts/vehicles_management/_partials/bookings-list.html
@@ -46,7 +46,8 @@
{{$vehicle.Data.licence_plate}}
-
+
+ {{if .ViewState.booking.Data.booked_by}}
+
+
+ {{end}}
Véhicule
@@ -118,23 +139,82 @@
{{end}}
Date de récupération
-
{{(timeFrom .ViewState.booking.Startdate).Format
- "02/01/2006"}}
+
+
+
{{(timeFrom .ViewState.booking.Startdate).Format "02/01/2006"}}
+
Modifier
+
+
+
+
+
+
+ OK
+
+
+
-
Date de fin
-
{{(timeFrom .ViewState.booking.Enddate).Format
- "02/01/2006"}}
+
Date de retour
+
+
+
{{(timeFrom .ViewState.booking.Enddate).Format "02/01/2006"}}
+
Modifier
+
+
+
+
+
+
+ OK
+
+
+
Indisponible à partir du
-
{{(timeFrom .ViewState.booking.Unavailablefrom).Format
- "02/01/2006"}}
+
+
+
{{(timeFrom .ViewState.booking.Unavailablefrom).Format "02/01/2006"}}
+
Modifier
+
+
+
+
+
+
+ OK
+
+
+
Sera à nouveau disponible le
-
{{(timeFrom .ViewState.booking.Unavailableto).Format
- "02/01/2006"}}
+
+
+
{{(timeFrom .ViewState.booking.Unavailableto).Format "02/01/2006"}}
+
Modifier
+
+
+
+
+
+
+ OK
+
+
diff --git a/themes/default/layouts/vehicles_management/fleet-display.html b/themes/default/layouts/vehicles_management/fleet-display.html
index 387f392..d786100 100644
--- a/themes/default/layouts/vehicles_management/fleet-display.html
+++ b/themes/default/layouts/vehicles_management/fleet-display.html
@@ -74,7 +74,7 @@
{{range .ViewState.vehicle.Bookings}}
-
+
Du {{(timeFrom .Startdate).Format "02/01/2006"}} au {{(timeFrom .Enddate).Format "02/01/2006"}}
diff --git a/themes/default/public/css/main.css b/themes/default/public/css/main.css
index 5d43147..d445bc0 100644
--- a/themes/default/public/css/main.css
+++ b/themes/default/public/css/main.css
@@ -798,14 +798,6 @@ html {
left: 0px;
}
-.top-4 {
- top: 1rem;
-}
-
-.left-4 {
- left: 1rem;
-}
-
.z-40 {
z-index: 40;
}
@@ -830,22 +822,10 @@ html {
grid-column: span 3 / span 3;
}
-.col-span-2 {
- grid-column: span 2 / span 2;
-}
-
-.col-span-4 {
- grid-column: span 4 / span 4;
-}
-
.col-span-5 {
grid-column: span 5 / span 5;
}
-.m-auto {
- margin: auto;
-}
-
.mx-auto {
margin-left: auto;
margin-right: auto;
@@ -861,6 +841,11 @@ html {
margin-right: -1rem;
}
+.my-4 {
+ margin-top: 1rem;
+ margin-bottom: 1rem;
+}
+
.-my-1\.5 {
margin-top: -0.375rem;
margin-bottom: -0.375rem;
@@ -871,9 +856,9 @@ html {
margin-bottom: -0.25rem;
}
-.my-4 {
- margin-top: 1rem;
- margin-bottom: 1rem;
+.my-8 {
+ margin-top: 2rem;
+ margin-bottom: 2rem;
}
.-mr-12 {
@@ -952,18 +937,18 @@ html {
margin-bottom: -1px;
}
-.-mb-8 {
- margin-bottom: -2rem;
-}
-
-.-ml-px {
- margin-left: -1px;
-}
-
.-ml-4 {
margin-left: -1rem;
}
+.-mt-4 {
+ margin-top: -1rem;
+}
+
+.mb-4 {
+ margin-bottom: 1rem;
+}
+
.-mt-2 {
margin-top: -0.5rem;
}
@@ -980,12 +965,20 @@ html {
margin-right: -0.25rem;
}
-.mb-4 {
- margin-bottom: 1rem;
+.mr-2 {
+ margin-right: 0.5rem;
}
-.-mt-4 {
- margin-top: -1rem;
+.mr-0 {
+ margin-right: 0px;
+}
+
+.mt-16 {
+ margin-top: 4rem;
+}
+
+.mt-12 {
+ margin-top: 3rem;
}
.block {
@@ -1012,10 +1005,6 @@ html {
display: table;
}
-.flow-root {
- display: flow-root;
-}
-
.grid {
display: grid;
}
@@ -1060,10 +1049,6 @@ html {
height: 3rem;
}
-.h-96 {
- height: 24rem;
-}
-
.max-h-60 {
max-height: 15rem;
}
@@ -1116,12 +1101,8 @@ html {
width: 3rem;
}
-.w-0\.5 {
- width: 0.125rem;
-}
-
-.w-0 {
- width: 0px;
+.w-11 {
+ width: 2.75rem;
}
.min-w-0 {
@@ -1190,6 +1171,11 @@ html {
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
+.translate-x-5 {
+ --tw-translate-x: 1.25rem;
+ transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
+}
+
.scale-95 {
--tw-scale-x: .95;
--tw-scale-y: .95;
@@ -1221,10 +1207,6 @@ html {
user-select: none;
}
-.grid-flow-row {
- grid-auto-flow: row;
-}
-
.grid-cols-6 {
grid-template-columns: repeat(6, minmax(0, 1fr));
}
@@ -1233,6 +1215,10 @@ html {
grid-template-columns: repeat(1, minmax(0, 1fr));
}
+.grid-cols-2 {
+ grid-template-columns: repeat(2, minmax(0, 1fr));
+}
+
.grid-cols-3 {
grid-template-columns: repeat(3, minmax(0, 1fr));
}
@@ -1241,10 +1227,6 @@ html {
grid-template-columns: repeat(7, minmax(0, 1fr));
}
-.grid-cols-2 {
- grid-template-columns: repeat(2, minmax(0, 1fr));
-}
-
.flex-row {
flex-direction: row;
}
@@ -1344,24 +1326,18 @@ html {
margin-left: calc(2rem * calc(1 - var(--tw-space-x-reverse)));
}
-.space-x-3 > :not([hidden]) ~ :not([hidden]) {
- --tw-space-x-reverse: 0;
- margin-right: calc(0.75rem * var(--tw-space-x-reverse));
- margin-left: calc(0.75rem * calc(1 - var(--tw-space-x-reverse)));
-}
-
-.space-x-4 > :not([hidden]) ~ :not([hidden]) {
- --tw-space-x-reverse: 0;
- margin-right: calc(1rem * var(--tw-space-x-reverse));
- margin-left: calc(1rem * calc(1 - var(--tw-space-x-reverse)));
-}
-
.-space-x-px > :not([hidden]) ~ :not([hidden]) {
--tw-space-x-reverse: 0;
margin-right: calc(-1px * var(--tw-space-x-reverse));
margin-left: calc(-1px * calc(1 - var(--tw-space-x-reverse)));
}
+.space-x-3 > :not([hidden]) ~ :not([hidden]) {
+ --tw-space-x-reverse: 0;
+ margin-right: calc(0.75rem * var(--tw-space-x-reverse));
+ margin-left: calc(0.75rem * calc(1 - var(--tw-space-x-reverse)));
+}
+
.space-y-8 > :not([hidden]) ~ :not([hidden]) {
--tw-space-y-reverse: 0;
margin-top: calc(2rem * calc(1 - var(--tw-space-y-reverse)));
@@ -1374,12 +1350,6 @@ html {
margin-left: calc(0.5rem * calc(1 - var(--tw-space-x-reverse)));
}
-.space-x-6 > :not([hidden]) ~ :not([hidden]) {
- --tw-space-x-reverse: 0;
- margin-right: calc(1.5rem * var(--tw-space-x-reverse));
- margin-left: calc(1.5rem * calc(1 - var(--tw-space-x-reverse)));
-}
-
.space-y-reverse > :not([hidden]) ~ :not([hidden]) {
--tw-space-y-reverse: 1;
}
@@ -1478,9 +1448,9 @@ html {
border-bottom-right-radius: 0.375rem;
}
-.rounded-b-2xl {
+.rounded-r-2xl {
+ border-top-right-radius: 1rem;
border-bottom-right-radius: 1rem;
- border-bottom-left-radius: 1rem;
}
.rounded-l-2xl {
@@ -1488,9 +1458,9 @@ html {
border-bottom-left-radius: 1rem;
}
-.rounded-r-2xl {
- border-top-right-radius: 1rem;
+.rounded-b-2xl {
border-bottom-right-radius: 1rem;
+ border-bottom-left-radius: 1rem;
}
.border {
@@ -1501,10 +1471,6 @@ html {
border-width: 2px;
}
-.border-4 {
- border-width: 4px;
-}
-
.border-r {
border-right-width: 1px;
}
@@ -1521,18 +1487,10 @@ html {
border-bottom-width: 2px;
}
-.border-r-0 {
- border-right-width: 0px;
-}
-
.border-l-0 {
border-left-width: 0px;
}
-.border-dashed {
- border-style: dashed;
-}
-
.border-gray-200 {
--tw-border-opacity: 1;
border-color: rgb(229 231 235 / var(--tw-border-opacity));
@@ -1602,31 +1560,6 @@ html {
background-color: rgb(249 250 251 / var(--tw-bg-opacity));
}
-.bg-gray-200 {
- --tw-bg-opacity: 1;
- background-color: rgb(229 231 235 / var(--tw-bg-opacity));
-}
-
-.bg-gray-400 {
- --tw-bg-opacity: 1;
- background-color: rgb(156 163 175 / var(--tw-bg-opacity));
-}
-
-.bg-blue-500 {
- --tw-bg-opacity: 1;
- background-color: rgb(59 130 246 / var(--tw-bg-opacity));
-}
-
-.bg-green-500 {
- --tw-bg-opacity: 1;
- background-color: rgb(34 197 94 / var(--tw-bg-opacity));
-}
-
-.bg-blue-600 {
- --tw-bg-opacity: 1;
- background-color: rgb(37 99 235 / var(--tw-bg-opacity));
-}
-
.bg-green-100 {
--tw-bg-opacity: 1;
background-color: rgb(220 252 231 / var(--tw-bg-opacity));
@@ -1637,11 +1570,6 @@ html {
background-color: rgb(238 242 255 / var(--tw-bg-opacity));
}
-.bg-gray-300 {
- --tw-bg-opacity: 1;
- background-color: rgb(209 213 219 / var(--tw-bg-opacity));
-}
-
.bg-indigo-600 {
--tw-bg-opacity: 1;
background-color: rgb(79 70 229 / var(--tw-bg-opacity));
@@ -1652,6 +1580,11 @@ html {
background-color: rgb(17 24 39 / var(--tw-bg-opacity));
}
+.bg-gray-200 {
+ --tw-bg-opacity: 1;
+ background-color: rgb(229 231 235 / var(--tw-bg-opacity));
+}
+
.bg-opacity-75 {
--tw-bg-opacity: 0.75;
}
@@ -1660,8 +1593,8 @@ html {
padding: 1rem;
}
-.p-6 {
- padding: 1.5rem;
+.p-12 {
+ padding: 3rem;
}
.p-2 {
@@ -1676,14 +1609,6 @@ html {
padding: 0.25rem;
}
-.p-8 {
- padding: 2rem;
-}
-
-.p-12 {
- padding: 3rem;
-}
-
.px-4 {
padding-left: 1rem;
padding-right: 1rem;
@@ -1749,26 +1674,16 @@ html {
padding-bottom: 0.75rem;
}
-.px-6 {
- padding-left: 1.5rem;
- padding-right: 1.5rem;
-}
-
-.py-0\.5 {
- padding-top: 0.125rem;
- padding-bottom: 0.125rem;
-}
-
-.py-0 {
- padding-top: 0px;
- padding-bottom: 0px;
-}
-
.py-8 {
padding-top: 2rem;
padding-bottom: 2rem;
}
+.px-6 {
+ padding-left: 1.5rem;
+ padding-right: 1.5rem;
+}
+
.pt-5 {
padding-top: 1.25rem;
}
@@ -1809,40 +1724,28 @@ html {
padding-left: 1rem;
}
-.pb-8 {
- padding-bottom: 2rem;
-}
-
-.pt-1\.5 {
- padding-top: 0.375rem;
-}
-
-.pt-1 {
- padding-top: 0.25rem;
-}
-
.pr-4 {
padding-right: 1rem;
}
-.pr-2 {
- padding-right: 0.5rem;
+.pr-12 {
+ padding-right: 3rem;
}
.pt-8 {
padding-top: 2rem;
}
+.pr-2 {
+ padding-right: 0.5rem;
+}
+
.pl-1\.5 {
padding-left: 0.375rem;
}
-.pl-3\.5 {
- padding-left: 0.875rem;
-}
-
-.pr-12 {
- padding-right: 3rem;
+.pb-1 {
+ padding-bottom: 0.25rem;
}
.text-left {
@@ -1857,6 +1760,10 @@ html {
text-align: right;
}
+.text-justify {
+ text-align: justify;
+}
+
.align-middle {
vertical-align: middle;
}
@@ -1916,10 +1823,6 @@ html {
font-weight: 800;
}
-.font-black {
- font-weight: 900;
-}
-
.uppercase {
text-transform: uppercase;
}
@@ -1989,16 +1892,16 @@ html {
color: rgb(22 101 52 / var(--tw-text-opacity));
}
-.text-gray-600 {
- --tw-text-opacity: 1;
- color: rgb(75 85 99 / var(--tw-text-opacity));
-}
-
.text-co-green {
--tw-text-opacity: 1;
color: rgb(108 193 31 / var(--tw-text-opacity));
}
+.text-gray-600 {
+ --tw-text-opacity: 1;
+ color: rgb(75 85 99 / var(--tw-text-opacity));
+}
+
.placeholder-gray-500::-moz-placeholder {
--tw-placeholder-opacity: 1;
color: rgb(107 114 128 / var(--tw-placeholder-opacity));
@@ -2058,9 +1961,9 @@ html {
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
}
-.ring-8 {
+.ring-0 {
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
- --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(8px + var(--tw-ring-offset-width)) var(--tw-ring-color);
+ --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(0px + var(--tw-ring-offset-width)) var(--tw-ring-color);
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
}
@@ -2101,6 +2004,14 @@ html {
transition-duration: 150ms;
}
+.transition-colors {
+ transition-property: color, background-color, border-color, fill, stroke, -webkit-text-decoration-color;
+ transition-property: color, background-color, border-color, text-decoration-color, fill, stroke;
+ transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, -webkit-text-decoration-color;
+ transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
+ transition-duration: 150ms;
+}
+
.duration-300 {
transition-duration: 300ms;
}
@@ -2113,6 +2024,10 @@ html {
transition-duration: 75ms;
}
+.duration-200 {
+ transition-duration: 200ms;
+}
+
.ease-linear {
transition-timing-function: linear;
}
@@ -2188,21 +2103,16 @@ html {
background-color: rgb(36 56 135 / var(--tw-bg-opacity));
}
-.hover\:bg-blue-700:hover {
- --tw-bg-opacity: 1;
- background-color: rgb(29 78 216 / var(--tw-bg-opacity));
-}
-
-.hover\:bg-indigo-700:hover {
- --tw-bg-opacity: 1;
- background-color: rgb(67 56 202 / var(--tw-bg-opacity));
-}
-
.hover\:bg-gray-100:hover {
--tw-bg-opacity: 1;
background-color: rgb(243 244 246 / var(--tw-bg-opacity));
}
+.hover\:bg-blue-700:hover {
+ --tw-bg-opacity: 1;
+ background-color: rgb(29 78 216 / var(--tw-bg-opacity));
+}
+
.hover\:bg-opacity-5:hover {
--tw-bg-opacity: 0.05;
}
@@ -2222,9 +2132,9 @@ html {
color: rgb(55 65 81 / var(--tw-text-opacity));
}
-.hover\:text-indigo-900:hover {
+.hover\:text-co-blue:hover {
--tw-text-opacity: 1;
- color: rgb(49 46 129 / var(--tw-text-opacity));
+ color: rgb(36 56 135 / var(--tw-text-opacity));
}
.hover\:text-gray-900:hover {
@@ -2232,23 +2142,13 @@ html {
color: rgb(17 24 39 / var(--tw-text-opacity));
}
-.hover\:text-co-blue:hover {
- --tw-text-opacity: 1;
- color: rgb(36 56 135 / var(--tw-text-opacity));
-}
-
-.hover\:text-inherit:hover {
- color: inherit;
-}
-
.hover\:text-gray-500:hover {
--tw-text-opacity: 1;
color: rgb(107 114 128 / var(--tw-text-opacity));
}
-.hover\:text-indigo-500:hover {
- --tw-text-opacity: 1;
- color: rgb(99 102 241 / var(--tw-text-opacity));
+.hover\:text-inherit:hover {
+ color: inherit;
}
.focus\:border-transparent:focus {
@@ -2327,16 +2227,16 @@ html {
--tw-ring-color: rgb(99 102 241 / var(--tw-ring-opacity));
}
-.focus\:ring-blue-500:focus {
- --tw-ring-opacity: 1;
- --tw-ring-color: rgb(59 130 246 / var(--tw-ring-opacity));
-}
-
.focus\:ring-co-red:focus {
--tw-ring-opacity: 1;
--tw-ring-color: rgb(255 19 0 / var(--tw-ring-opacity));
}
+.focus\:ring-blue-500:focus {
+ --tw-ring-opacity: 1;
+ --tw-ring-color: rgb(59 130 246 / var(--tw-ring-opacity));
+}
+
.focus\:ring-offset-2:focus {
--tw-ring-offset-width: 2px;
}
@@ -2367,6 +2267,10 @@ html {
grid-column: span 1 / span 1;
}
+ .sm\:col-span-6 {
+ grid-column: span 6 / span 6;
+ }
+
.sm\:mx-auto {
margin-left: auto;
margin-right: auto;
@@ -2437,10 +2341,6 @@ html {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
- .sm\:grid-cols-6 {
- grid-template-columns: repeat(6, minmax(0, 1fr));
- }
-
.sm\:grid-cols-3 {
grid-template-columns: repeat(3, minmax(0, 1fr));
}
diff --git a/utils/identification/oidc.go b/utils/identification/oidc.go
index 7931121..5e60c9a 100644
--- a/utils/identification/oidc.go
+++ b/utils/identification/oidc.go
@@ -51,7 +51,7 @@ func NewIdentificationProvider(cfg *viper.Viper, services *services.ServicesHand
Endpoint: provider.Endpoint(),
// "openid" is a required scope for OpenID Connect flows.
- Scopes: []string{oidc.ScopeOpenID, "groups", "profile"},
+ Scopes: []string{oidc.ScopeOpenID, "groups", "first_name", "last_name", "display_name"},
}
var store = sessions.NewCookieStore([]byte(sessionsSecret))