diff --git a/go.mod b/go.mod index dd80b97..d453e3c 100644 --- a/go.mod +++ b/go.mod @@ -42,6 +42,7 @@ require ( github.com/coreos/go-systemd/v22 v22.3.2 // indirect github.com/dustin/go-humanize v1.0.0 // indirect github.com/fsnotify/fsnotify v1.5.4 // indirect + github.com/go-mail/mail v2.3.1+incompatible // indirect github.com/go-playground/locales v0.14.0 // indirect github.com/go-playground/universal-translator v0.18.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect diff --git a/go.sum b/go.sum index dd98fc9..59dc913 100644 --- a/go.sum +++ b/go.sum @@ -121,6 +121,8 @@ github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vb github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-mail/mail v2.3.1+incompatible h1:UzNOn0k5lpfVtO31cK3hn6I4VEVGhe3lX8AJBAxXExM= +github.com/go-mail/mail v2.3.1+incompatible/go.mod h1:VPWjmmNyRsWXQZHVHT3g0YbIINUkSmuKOiLIDkWbL6M= github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU= diff --git a/handlers/application/support.go b/handlers/application/support.go new file mode 100644 index 0000000..1721500 --- /dev/null +++ b/handlers/application/support.go @@ -0,0 +1,40 @@ +package application + +import ( + "fmt" + "net/http" + + "git.coopgo.io/coopgo-apps/parcoursmob/utils/identification" +) + +type Message struct { + Content string +} + +func (h *ApplicationHandler) SupportSend(w http.ResponseWriter, r *http.Request) { + + 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) + + comment := r.PostFormValue(("comment")) + + if r.Method == "POST" { + data := map[string]any{ + "key": comment, + "user": current_user_claims["email"], + } + + if err := h.emailing.Send("support.request", "support@parcoursmob.fr", data); err != nil { + fmt.Println(err) + w.WriteHeader(http.StatusInternalServerError) + } + http.Redirect(w, r, "/app/", http.StatusFound) + return + } + h.Renderer.SupportSend(w, r, comment, current_user_claims) +} diff --git a/main.go b/main.go index 285e393..d158e04 100644 --- a/main.go +++ b/main.go @@ -103,6 +103,11 @@ func main() { application.HandleFunc("/group/settings", applicationHandler.GroupSettingsDisplay) application.HandleFunc("/group/settings/invite-member", applicationHandler.GroupSettingsInviteMember) + + /********************Code Supprt Emailing************************/ + application.HandleFunc("/support/", applicationHandler.SupportSend) + /****************************************************************/ + //TODO Subrouters with middlewares checking security for each module ? application.Use(idp.Middleware) application.Use(idp.GroupsMiddleware) diff --git a/renderer/renderer.go b/renderer/renderer.go index b1c06e3..f0d44b1 100644 --- a/renderer/renderer.go +++ b/renderer/renderer.go @@ -58,6 +58,7 @@ func (renderer *Renderer) Render(name string, w http.ResponseWriter, r *http.Req }, ) t = template.Must(t.ParseFiles(prefixed_files...)) + err := t.ExecuteTemplate(w, "main", state) if err != nil { fmt.Println(err) @@ -186,6 +187,18 @@ func NewState(r *http.Request, themeConfig *viper.Viper, menuState string) Rende }) } + /*************************** my code ******************************/ + if modules["support"] != nil && modules["support"].(bool) { + ls.MenuItems = append(ls.MenuItems, MenuItem{ + Title: "Support", + Link: "/app/support/", + Active: menuState == commentMenu, + Icon: "hero:outline/support", + }) + + } + /*************************** my code ******************************/ + if modules["directory"] != nil && modules["directory"].(bool) { ls.MenuItems = append(ls.MenuItems, MenuItem{ Title: "Répertoire solutions", diff --git a/renderer/support.go b/renderer/support.go new file mode 100644 index 0000000..feeca42 --- /dev/null +++ b/renderer/support.go @@ -0,0 +1,20 @@ +package renderer + +import ( + "net/http" +) + +const commentMenu = "comment" + +//const commentsend = "sendComment" + +func (renderer *Renderer) SupportSend(w http.ResponseWriter, r *http.Request, comment any, admins any) { + + files := renderer.ThemeConfig.GetStringSlice("views.support.request.files") + state := NewState(r, renderer.ThemeConfig, commentMenu) + state.ViewState = map[string]any{ + "comment": comment, + "admins": admins, + } + renderer.Render("comment", w, r, files, state) +} diff --git a/themes/default/config.yaml b/themes/default/config.yaml index aff77ec..4481431 100644 --- a/themes/default/config.yaml +++ b/themes/default/config.yaml @@ -32,6 +32,7 @@ views: files: - web/layouts/_partials/address_autocomplete.html - web/layouts/beneficiaries/update.html + vehicles: search: files: @@ -96,6 +97,10 @@ views: - web/layouts/journeys/_partials/journeys-carpool.html - web/layouts/journeys/_partials/journeys-public-transit.html - web/layouts/journeys/search.html + support: + request: + files: + - web/layouts/support/support.html administration: home: files: @@ -141,6 +146,7 @@ icons: svg: coopgo:parcoursmob/monogram: hero:outline/briefcase: + hero:outline/support: hero:outline/calendar: hero:outline/chevron-right: hero:outline/cog: @@ -192,4 +198,11 @@ emails: subject: PAROURSMOB - Réinitialisez votre mot de passe files: - emails/layout.html - - emails/auth/retrieve-password.html \ No newline at end of file + - emails/auth/retrieve-password.html + support: + request: + subject: PARCOURMOB - Demande de support + files: + - emails/layout.html + - emails/onboarding/support_emailing.html + diff --git a/themes/default/emails/onboarding/support_emailing.html b/themes/default/emails/onboarding/support_emailing.html new file mode 100644 index 0000000..40ea8c7 --- /dev/null +++ b/themes/default/emails/onboarding/support_emailing.html @@ -0,0 +1,4 @@ +{{define "content"}} +

Vous avez reçu un commentaire sur PARCOURSMOB de la part de {{.user}}

+

{{.key}}

+{{end}} \ No newline at end of file diff --git a/themes/default/web/layouts/support/support.html b/themes/default/web/layouts/support/support.html new file mode 100644 index 0000000..d54ece2 --- /dev/null +++ b/themes/default/web/layouts/support/support.html @@ -0,0 +1,27 @@ +{{define "content"}} + +
+

Demande de support

+
+

+ Le support PARCOURSMOB est ouvert les jours ouvrés de 9h à 18h. Vous pouvez également nous joindre par email à support@parcoursmob.fr, par exemple pour nous envoyez des copies d'écran du problème que vous rencontrez. +

+
+ +
+
+ + + +
+
+ +
+
+ +
+
+
+ {{end}} diff --git a/themes/default/web/public/css/main.css b/themes/default/web/public/css/main.css index 4bb5b88..cb99184 100644 --- a/themes/default/web/public/css/main.css +++ b/themes/default/web/public/css/main.css @@ -1259,6 +1259,10 @@ html { user-select: none; } +.resize-none { + resize: none; +} + .appearance-none { -webkit-appearance: none; -moz-appearance: none; @@ -1527,6 +1531,11 @@ html { border-bottom-left-radius: 1rem; } +.rounded-t-lg { + border-top-left-radius: 0.5rem; + border-top-right-radius: 0.5rem; +} + .border { border-width: 1px; } @@ -1535,6 +1544,10 @@ html { border-width: 2px; } +.border-0 { + border-width: 0px; +} + .border-r { border-right-width: 1px; } @@ -1689,6 +1702,14 @@ html { padding: 0.375rem; } +.p-8 { + padding: 2rem; +} + +.p-0 { + padding: 0px; +} + .px-4 { padding-left: 1rem; padding-right: 1rem; @@ -1820,10 +1841,6 @@ html { padding-top: 2rem; } -.pb-6 { - padding-bottom: 1.5rem; -} - .pt-4 { padding-top: 1rem; } @@ -1848,6 +1865,14 @@ html { padding-left: 0.375rem; } +.pb-6 { + padding-bottom: 1.5rem; +} + +.pb-2 { + padding-bottom: 0.5rem; +} + .text-left { text-align: left; } @@ -2278,11 +2303,6 @@ html { color: rgb(55 65 81 / var(--tw-text-opacity)); } -.hover\:text-indigo-500:hover { - --tw-text-opacity: 1; - color: rgb(99 102 241 / var(--tw-text-opacity)); -} - .hover\:text-gray-900:hover { --tw-text-opacity: 1; color: rgb(17 24 39 / var(--tw-text-opacity)); @@ -2297,6 +2317,11 @@ html { color: inherit; } +.hover\:text-indigo-500:hover { + --tw-text-opacity: 1; + color: rgb(99 102 241 / var(--tw-text-opacity)); +} + .focus\:border-transparent:focus { border-color: transparent; } @@ -2316,6 +2341,11 @@ html { border-color: rgb(59 130 246 / var(--tw-border-opacity)); } +.focus\:border-indigo-600:focus { + --tw-border-opacity: 1; + border-color: rgb(79 70 229 / var(--tw-border-opacity)); +} + .focus\:placeholder-gray-400:focus::-moz-placeholder { --tw-placeholder-opacity: 1; color: rgb(156 163 175 / var(--tw-placeholder-opacity)); @@ -2404,6 +2434,23 @@ html { color: rgb(107 114 128 / var(--tw-text-opacity)); } +@media (prefers-color-scheme: dark) { + .dark\:border-gray-600 { + --tw-border-opacity: 1; + border-color: rgb(75 85 99 / var(--tw-border-opacity)); + } + + .dark\:bg-gray-700 { + --tw-bg-opacity: 1; + background-color: rgb(55 65 81 / var(--tw-bg-opacity)); + } + + .dark\:bg-gray-800 { + --tw-bg-opacity: 1; + background-color: rgb(31 41 55 / var(--tw-bg-opacity)); + } +} + @media (min-width: 640px) { .sm\:col-span-3 { grid-column: span 3 / span 3; @@ -2629,6 +2676,14 @@ html { grid-column: span 2 / span 2; } + .md\:col-span-3 { + grid-column: span 3 / span 3; + } + + .md\:col-span-6 { + grid-column: span 6 / span 6; + } + .md\:mx-0 { margin-left: 0px; margin-right: 0px; diff --git a/utils/identification/oidc.go b/utils/identification/oidc.go index 9adf208..f11f5cf 100644 --- a/utils/identification/oidc.go +++ b/utils/identification/oidc.go @@ -52,7 +52,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", "first_name", "last_name", "display_name"}, + Scopes: []string{oidc.ScopeOpenID, "groups", "first_name", "last_name", "display_name", "email"}, } store := storage.NewSessionStore(kv, []byte(sessionsSecret))