package renderer import ( "bytes" "encoding/json" "fmt" "html/template" "reflect" "strings" "time" filestorage "git.coopgo.io/coopgo-apps/parcoursmob/utils/storage" validatedprofile "git.coopgo.io/coopgo-apps/parcoursmob/utils/validated-profile" groupsstorage "git.coopgo.io/coopgo-platform/groups-management/storage" "github.com/rs/zerolog/log" "github.com/spf13/viper" "gitlab.scity.coop/maas/navitia-golang/types" ) func ModuleAvailable(group groupsstorage.Group, configmodules *viper.Viper) func(string) bool { return func(module string) bool { if module == "dashboard" { return true } groupmodules := group.Data["modules"].(map[string]any) modAvailable, ok := groupmodules[module].(bool) if ok && modAvailable && configmodules.GetBool(fmt.Sprintf("modules.%s.enabled", module)) { return true } return false } } func TimeFrom(d any) *time.Time { paris, err := time.LoadLocation("Europe/Paris") if date, ok := d.(time.Time); ok { if err != nil { return &date } nd := date.In(paris) return &nd } else if date, ok := d.(string); ok { datetime, err := time.Parse("2006-01-02T15:04:05Z", date) if err != nil { datetime, err = time.Parse("2006-01-02", date) if err != nil { log.Error().Err(err).Msg("cannot parse date") } } dt := datetime.In(paris) return &dt } return nil } func TimeFormat(d any, f string) string { date := TimeFrom(d) if date == nil { return "" } if date.Before(time.Now().Add(-24 * 365 * 30 * time.Hour)) { return "" } return date.Format(f) } func GenderISO5218(d any) string { if date, ok := d.(string); ok { switch date { case "0": return "Inconnu" case "1": return "Masculin" case "2": return "Féminin" case "9": return "Sans objet" } } if date, ok := d.(int64); ok { switch date { case 0: return "Inconnu" case 1: return "Masculin" case 2: return "Féminin" case 9: return "Sans objet" } } return "" } func JSON(v any) template.JS { result, _ := json.Marshal(v) return template.JS(result) } func RawJSON(v any) string { buf := new(bytes.Buffer) enc := json.NewEncoder(buf) enc.SetEscapeHTML(false) err := enc.Encode(&v) if err != nil { return "" } return strings.TrimSuffix(buf.String(), "\n") } func UnescapeHTML(s string) template.HTML { return template.HTML(s) } func Dict(v ...interface{}) map[string]interface{} { dict := map[string]interface{}{} lenv := len(v) for i := 0; i < lenv; i += 2 { key := strval(v[i]) if i+1 >= lenv { dict[key] = "" continue } dict[key] = v[i+1] } return dict } func WalkingLength(s types.Section) (l int) { l = 0 if s.Mode == "walking" { for _, p := range s.Path { l = l + int(p.Length) } } return } func strval(v interface{}) string { switch v := v.(type) { case string: return v case []byte: return string(v) case error: return v.Error() case fmt.Stringer: return v.String() default: return fmt.Sprintf("%v", v) } } // GetTemplateFuncMap returns the common template functions for rendering func GetTemplateFuncMap(group groupsstorage.Group, globalConfig *viper.Viper, fileStorage filestorage.FileStorage) template.FuncMap { return template.FuncMap{ "moduleAvailable": ModuleAvailable(group, globalConfig), "timeFrom": TimeFrom, "timeFormat": TimeFormat, "genderISO5218": GenderISO5218, "dict": Dict, "json": JSON, "rawjson": RawJSON, "unescapeHTML": UnescapeHTML, "walkingLength": WalkingLength, "divideFloat64": Divide[float64], "divideInt": Divide[int], "typeOf": reflect.TypeOf, "shortDuration": ShortDuration, "beneficiaryValidatedProfile": validatedprofile.ValidateProfile(globalConfig.Sub("modules.beneficiaries.validated_profile")), "solidarityDriverValidatedProfile": validatedprofile.ValidateProfile(globalConfig.Sub("modules.solidarity_transport.drivers.validated_profile")), "carpoolDriverValidatedProfile": validatedprofile.ValidateProfile(globalConfig.Sub("modules.organized_carpool.drivers.validated_profile")), "beneficiaryDocuments": func(id string) []filestorage.FileInfo { return fileStorage.List(filestorage.PREFIX_BENEFICIARIES + "/" + id) }, "solidarityDocuments": func(id string) []filestorage.FileInfo { return fileStorage.List(filestorage.PREFIX_SOLIDARITY_TRANSPORT_DRIVERS + "/" + id) }, "carpoolDocuments": func(id string) []filestorage.FileInfo { return fileStorage.List(filestorage.PREFIX_ORGANIZED_CARPOOL_DRIVERS + "/" + id) }, } } func Divide[V int | float64](a, b V) V { return a / b } func ShortDuration(d interface{}) string { var duration time.Duration switch v := d.(type) { case time.Duration: duration = v case int: duration = time.Duration(v) * time.Second case int64: duration = time.Duration(v) * time.Second case float64: duration = time.Duration(v) * time.Second default: return "" } s := duration.String() if strings.HasSuffix(s, "m0s") { s = s[:len(s)-2] } if strings.HasSuffix(s, "h0m") { s = s[:len(s)-2] } return s }