lot of new functionalities
This commit is contained in:
469
servers/web/application/agenda.go
Normal file
469
servers/web/application/agenda.go
Normal file
@@ -0,0 +1,469 @@
|
||||
package application
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
formvalidators "git.coopgo.io/coopgo-apps/parcoursmob/core/utils/form-validators"
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
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"`
|
||||
}
|
||||
|
||||
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 (h *Handler) AgendaHomeHTTPHandler() http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
today := time.Now().Truncate(24 * time.Hour)
|
||||
result, err := h.applicationHandler.GetAgendaEvents(r.Context(), &today, nil)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("error retrieving agenda events")
|
||||
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
h.renderer.AgendaHome(w, r, result.Events, result.Groups)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Handler) AgendaHistoryHTTPHandler() http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
result, err := h.applicationHandler.GetAgendaEvents(r.Context(), nil, nil)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("error retrieving agenda events")
|
||||
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
h.renderer.AgendaHistory(w, r, result.Events, result.Groups)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Handler) AgendaCreateEventHTTPHandler() http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method == "POST" {
|
||||
// Parse form data
|
||||
eventForm, err := parseEventsForm(r)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("error parsing event form")
|
||||
http.Error(w, "Bad Request", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
// Handle file upload if present
|
||||
var file io.Reader
|
||||
var filename string
|
||||
var fileSize int64
|
||||
var documentType, documentName string
|
||||
|
||||
contentType := r.Header.Get("Content-Type")
|
||||
if strings.HasPrefix(contentType, "multipart/form-data") {
|
||||
err = r.ParseMultipartForm(100 * 1024 * 1024) // 100 MB limit
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("error parsing multipart form")
|
||||
http.Error(w, "Bad Request", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
uploadedFile, header, err := r.FormFile("file-upload")
|
||||
if err == nil {
|
||||
defer uploadedFile.Close()
|
||||
file = uploadedFile
|
||||
filename = header.Filename
|
||||
fileSize = header.Size
|
||||
documentType = r.FormValue("file_type")
|
||||
documentName = r.FormValue("file_name")
|
||||
} else if err != http.ErrMissingFile {
|
||||
log.Error().Err(err).Msg("error retrieving file")
|
||||
http.Error(w, "Bad Request", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
eventID, err := h.applicationHandler.CreateAgendaEvent(
|
||||
r.Context(),
|
||||
eventForm.Name,
|
||||
eventForm.Type,
|
||||
eventForm.Description,
|
||||
eventForm.Address,
|
||||
eventForm.Allday,
|
||||
eventForm.Startdate,
|
||||
eventForm.Enddate,
|
||||
eventForm.Starttime,
|
||||
eventForm.Endtime,
|
||||
eventForm.MaxSubscribers,
|
||||
file,
|
||||
filename,
|
||||
fileSize,
|
||||
documentType,
|
||||
documentName,
|
||||
)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("error creating agenda event")
|
||||
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
http.Redirect(w, r, fmt.Sprintf("/app/agenda/%s", eventID), http.StatusFound)
|
||||
return
|
||||
}
|
||||
|
||||
// For GET requests, render the create event form with config data
|
||||
documentTypes := h.cfg.GetStringSlice("modules.agenda.documents_types")
|
||||
fileTypes := h.cfg.GetStringMapString("storage.files.file_types")
|
||||
h.renderer.AgendaCreateEvent(w, r, documentTypes, fileTypes, nil)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Handler) AgendaDisplayEventHTTPHandler() http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
eventID := vars["eventid"]
|
||||
|
||||
result, err := h.applicationHandler.GetAgendaEvent(r.Context(), eventID)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("error retrieving agenda event")
|
||||
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
documentTypes := h.cfg.GetStringSlice("modules.agenda.documents_types")
|
||||
fileTypes := h.cfg.GetStringMapString("storage.files.file_types")
|
||||
h.renderer.AgendaDisplayEvent(w, r, result.Event, result.Group, documentTypes, fileTypes, result.Documents, result.Subscribers, result.Accounts)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Handler) AgendaUpdateEventHTTPHandler() http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
eventID := vars["eventid"]
|
||||
|
||||
if r.Method == "POST" {
|
||||
// Parse form data
|
||||
eventForm, err := parseEventsForm(r)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("error parsing event form")
|
||||
http.Error(w, "Bad Request", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
updatedEventID, err := h.applicationHandler.UpdateAgendaEvent(
|
||||
r.Context(),
|
||||
eventID,
|
||||
eventForm.Name,
|
||||
eventForm.Type,
|
||||
eventForm.Description,
|
||||
eventForm.Address,
|
||||
eventForm.Allday,
|
||||
eventForm.Startdate,
|
||||
eventForm.Enddate,
|
||||
eventForm.Starttime,
|
||||
eventForm.Endtime,
|
||||
eventForm.MaxSubscribers,
|
||||
)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("error updating agenda event")
|
||||
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
http.Redirect(w, r, fmt.Sprintf("/app/agenda/%s", updatedEventID), http.StatusFound)
|
||||
return
|
||||
}
|
||||
|
||||
// For GET requests, render the update event form
|
||||
result, err := h.applicationHandler.GetAgendaEvent(r.Context(), eventID)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("error retrieving agenda event")
|
||||
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
h.renderer.AgendaUpdateEvent(w, r, result.Event)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Handler) AgendaDeleteEventHTTPHandler() http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
eventID := vars["eventid"]
|
||||
|
||||
if r.Method == "POST" {
|
||||
if err := h.applicationHandler.DeleteAgendaEvent(r.Context(), eventID); err != nil {
|
||||
log.Error().Err(err).Msg("error deleting agenda event")
|
||||
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
http.Redirect(w, r, "/app/agenda/", http.StatusFound)
|
||||
return
|
||||
}
|
||||
|
||||
// For GET requests, render the delete confirmation form
|
||||
result, err := h.applicationHandler.GetAgendaEvent(r.Context(), eventID)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("error retrieving agenda event")
|
||||
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
h.renderer.AgendaDeleteEvent(w, r, result.Event)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Handler) AgendaSubscribeEventHTTPHandler() http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
eventID := vars["eventid"]
|
||||
|
||||
if r.Method == "POST" {
|
||||
if err := r.ParseForm(); err != nil {
|
||||
log.Error().Err(err).Msg("error parsing form")
|
||||
http.Error(w, "Bad Request", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
subscriber := r.FormValue("subscriber")
|
||||
|
||||
// Get current user and group information
|
||||
current_group, err := h.currentGroup(r)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("error getting current group")
|
||||
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
current_user_token, current_user_claims, err := h.currentUser(r)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("error getting current user")
|
||||
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
subscriptionData := map[string]any{
|
||||
"subscribed_by": map[string]any{
|
||||
"user": map[string]any{
|
||||
"id": current_user_token.Subject,
|
||||
"display_name": current_user_claims["first_name"].(string) + " " + current_user_claims["last_name"].(string),
|
||||
"email": current_user_claims["email"].(string),
|
||||
},
|
||||
"group": map[string]any{
|
||||
"id": current_group.ID,
|
||||
"name": current_group.Data["name"],
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
if err := h.applicationHandler.SubscribeToAgendaEvent(r.Context(), eventID, subscriber, subscriptionData); err != nil {
|
||||
log.Error().Err(err).Msg("error subscribing to agenda event")
|
||||
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
http.Redirect(w, r, fmt.Sprintf("/app/agenda/%s", eventID), http.StatusFound)
|
||||
return
|
||||
}
|
||||
|
||||
// For GET requests, redirect to event display
|
||||
http.Redirect(w, r, fmt.Sprintf("/app/agenda/%s", eventID), http.StatusFound)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Handler) AgendaDeleteSubscribeEventHTTPHandler() http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
eventID := vars["eventid"]
|
||||
subscribeID := vars["subscribeid"]
|
||||
|
||||
if r.Method == "POST" {
|
||||
if err := r.ParseForm(); err != nil {
|
||||
log.Error().Err(err).Msg("error parsing form")
|
||||
http.Error(w, "Bad Request", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
motif := r.FormValue("motif")
|
||||
|
||||
// Get current user and group information
|
||||
current_group, err := h.currentGroup(r)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("error getting current group")
|
||||
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
current_user_token, current_user_claims, err := h.currentUser(r)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("error getting current user")
|
||||
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.applicationHandler.UnsubscribeFromAgendaEvent(
|
||||
r.Context(),
|
||||
eventID,
|
||||
subscribeID,
|
||||
motif,
|
||||
current_user_token.Subject,
|
||||
current_user_claims["first_name"].(string)+" "+current_user_claims["last_name"].(string),
|
||||
current_user_claims["email"].(string),
|
||||
current_group.ID,
|
||||
current_group.Data["name"].(string),
|
||||
); err != nil {
|
||||
log.Error().Err(err).Msg("error unsubscribing from agenda event")
|
||||
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
http.Redirect(w, r, fmt.Sprintf("/app/agenda/%s", eventID), http.StatusFound)
|
||||
return
|
||||
}
|
||||
|
||||
// For GET requests, render the delete subscription form
|
||||
h.renderer.AgendaDeleteSubscribeEvent(w, r, eventID)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Handler) AgendaHistoryEventHTTPHandler() http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
eventID := vars["eventid"]
|
||||
|
||||
result, err := h.applicationHandler.GetAgendaEventHistory(r.Context(), eventID)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("error retrieving agenda event history")
|
||||
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
h.renderer.AgendaHistoryEvent(w, r, result.Event, result.Group, result.Subscribers, result.Accounts)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Handler) EventDocumentsHTTPHandler() http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
eventID := vars["eventid"]
|
||||
|
||||
if err := r.ParseMultipartForm(100 * 1024 * 1024); err != nil { // 100 MB limit
|
||||
log.Error().Err(err).Msg("error parsing multipart form")
|
||||
http.Error(w, "Bad Request", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
documentType := r.FormValue("type")
|
||||
documentName := r.FormValue("name")
|
||||
|
||||
file, header, err := r.FormFile("file-upload")
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("error retrieving file")
|
||||
http.Error(w, "Bad Request", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
if err := h.applicationHandler.AddEventDocument(r.Context(), eventID, file, header.Filename, header.Size, documentType, documentName); err != nil {
|
||||
log.Error().Err(err).Msg("error adding event document")
|
||||
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
http.Redirect(w, r, fmt.Sprintf("/app/agenda/%s", eventID), http.StatusFound)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Handler) EventDocumentDownloadHTTPHandler() http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
eventID := vars["eventid"]
|
||||
document := vars["document"]
|
||||
|
||||
file, info, err := h.applicationHandler.GetEventDocument(r.Context(), eventID, document)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("error retrieving event document")
|
||||
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", info.ContentType)
|
||||
if _, err = io.Copy(w, file); err != nil {
|
||||
log.Error().Err(err).Msg("error copying file content")
|
||||
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
http.Redirect(w, r, fmt.Sprintf("/app/agenda/%s", eventID), http.StatusFound)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user