X-Git-Url: https://gerrit.akraino.org/r/gitweb?a=blobdiff_plain;f=src%2Ffoundation%2Fapi%2Frevel%2Ftemplate_functions.go;fp=src%2Ffoundation%2Fapi%2Frevel%2Ftemplate_functions.go;h=98bb988de4a2246124176b3e9895d36f0186dd12;hb=1d1ee6961c93781e1187d8c7faa868da6b2f01f4;hp=0000000000000000000000000000000000000000;hpb=56dd5e0f2164b37b40ac1daa188ccc618b4cbd19;p=iec.git diff --git a/src/foundation/api/revel/template_functions.go b/src/foundation/api/revel/template_functions.go new file mode 100644 index 0000000..98bb988 --- /dev/null +++ b/src/foundation/api/revel/template_functions.go @@ -0,0 +1,341 @@ +package revel + +import ( + "bytes" + "errors" + "fmt" + "github.com/xeonx/timeago" + "html" + "html/template" + "reflect" + "strings" + "time" +) + +var ( + // The functions available for use in the templates. + TemplateFuncs = map[string]interface{}{ + "url": ReverseURL, + "set": func(viewArgs map[string]interface{}, key string, value interface{}) template.JS { + viewArgs[key] = value + return template.JS("") + }, + "append": func(viewArgs map[string]interface{}, key string, value interface{}) template.JS { + if viewArgs[key] == nil { + viewArgs[key] = []interface{}{value} + } else { + viewArgs[key] = append(viewArgs[key].([]interface{}), value) + } + return template.JS("") + }, + "field": NewField, + "firstof": func(args ...interface{}) interface{} { + for _, val := range args { + switch val.(type) { + case nil: + continue + case string: + if val == "" { + continue + } + return val + default: + return val + } + } + return nil + }, + "option": func(f *Field, val interface{}, label string) template.HTML { + selected := "" + if f.Flash() == val || (f.Flash() == "" && f.Value() == val) { + selected = " selected" + } + + return template.HTML(fmt.Sprintf(``, + html.EscapeString(fmt.Sprintf("%v", val)), selected, html.EscapeString(label))) + }, + "radio": func(f *Field, val string) template.HTML { + checked := "" + if f.Flash() == val { + checked = " checked" + } + return template.HTML(fmt.Sprintf(``, + html.EscapeString(f.Name), html.EscapeString(val), checked)) + }, + "checkbox": func(f *Field, val string) template.HTML { + checked := "" + if f.Flash() == val { + checked = " checked" + } + return template.HTML(fmt.Sprintf(``, + html.EscapeString(f.Name), html.EscapeString(val), checked)) + }, + // Pads the given string with  's up to the given width. + "pad": func(str string, width int) template.HTML { + if len(str) >= width { + return template.HTML(html.EscapeString(str)) + } + return template.HTML(html.EscapeString(str) + strings.Repeat(" ", width-len(str))) + }, + + "errorClass": func(name string, viewArgs map[string]interface{}) template.HTML { + errorMap, ok := viewArgs["errors"].(map[string]*ValidationError) + if !ok || errorMap == nil { + templateLog.Warn("errorClass: Called 'errorClass' without 'errors' in the view args.") + return template.HTML("") + } + valError, ok := errorMap[name] + if !ok || valError == nil { + return template.HTML("") + } + return template.HTML(ErrorCSSClass) + }, + + "msg": func(viewArgs map[string]interface{}, message string, args ...interface{}) template.HTML { + str, ok := viewArgs[CurrentLocaleViewArg].(string) + if !ok { + return "" + } + return template.HTML(MessageFunc(str, message, args...)) + }, + + // Replaces newlines with
+ "nl2br": func(text string) template.HTML { + return template.HTML(strings.Replace(template.HTMLEscapeString(text), "\n", "
", -1)) + }, + + // Skips sanitation on the parameter. Do not use with dynamic data. + "raw": func(text string) template.HTML { + return template.HTML(text) + }, + + // Pluralize, a helper for pluralizing words to correspond to data of dynamic length. + // items - a slice of items, or an integer indicating how many items there are. + // pluralOverrides - optional arguments specifying the output in the + // singular and plural cases. by default "" and "s" + "pluralize": func(items interface{}, pluralOverrides ...string) string { + singular, plural := "", "s" + if len(pluralOverrides) >= 1 { + singular = pluralOverrides[0] + if len(pluralOverrides) == 2 { + plural = pluralOverrides[1] + } + } + + switch v := reflect.ValueOf(items); v.Kind() { + case reflect.Int: + if items.(int) != 1 { + return plural + } + case reflect.Slice: + if v.Len() != 1 { + return plural + } + default: + templateLog.Error("pluralize: unexpected type: ", "value", v) + } + return singular + }, + + // Format a date according to the application's default date(time) format. + "date": func(date time.Time) string { + return date.Format(DateFormat) + }, + "datetime": func(date time.Time) string { + return date.Format(DateTimeFormat) + }, + // Fetch an object from the session. + "session": func(key string, viewArgs map[string]interface{}) interface{} { + if viewArgs != nil { + if c, found := viewArgs["_controller"]; found { + if v, err := c.(*Controller).Session.Get(key); err == nil { + return v + } else { + templateLog.Errorf("template.session, key %s error %v", key, err) + } + } else { + templateLog.Warnf("template.session, key %s requested without controller", key) + } + } else { + templateLog.Warnf("template.session, key %s requested passing in view args", key) + } + return "" + }, + + "slug": Slug, + "even": func(a int) bool { return (a % 2) == 0 }, + + // Using https://github.com/xeonx/timeago + "timeago": TimeAgo, + "i18ntemplate": func(args ...interface{}) (template.HTML, error) { + templateName, lang := "", "" + var viewArgs interface{} + switch len(args) { + case 0: + templateLog.Error("i18ntemplate: No arguments passed to template call") + case 1: + // Assume only the template name is passed in + templateName = args[0].(string) + case 2: + // Assume template name and viewArgs is passed in + templateName = args[0].(string) + viewArgs = args[1] + // Try to extract language from the view args + if viewargsmap, ok := viewArgs.(map[string]interface{}); ok { + lang, _ = viewargsmap[CurrentLocaleViewArg].(string) + } + default: + // Assume third argument is the region + templateName = args[0].(string) + viewArgs = args[1] + lang, _ = args[2].(string) + if len(args) > 3 { + templateLog.Error("i18ntemplate: Received more parameters then needed for", "template", templateName) + } + } + + var buf bytes.Buffer + // Get template + tmpl, err := MainTemplateLoader.TemplateLang(templateName, lang) + if err == nil { + err = tmpl.Render(&buf, viewArgs) + } else { + templateLog.Error("i18ntemplate: Failed to render i18ntemplate ", "name", templateName, "error", err) + } + return template.HTML(buf.String()), err + }, + } +) + +///////////////////// +// Template functions +///////////////////// + +// ReverseURL returns a url capable of invoking a given controller method: +// "Application.ShowApp 123" => "/app/123" +func ReverseURL(args ...interface{}) (template.URL, error) { + if len(args) == 0 { + return "", errors.New("no arguments provided to reverse route") + } + + action := args[0].(string) + if action == "Root" { + return template.URL(AppRoot), nil + } + + pathData, found := splitActionPath(nil, action, true) + + if !found { + return "", fmt.Errorf("reversing '%s', expected 'Controller.Action'", action) + } + + // Look up the types. + + if pathData.TypeOfController == nil { + return "", fmt.Errorf("Failed reversing %s: controller not found %#v", action, pathData) + } + + // Note method name is case insensitive search + methodType := pathData.TypeOfController.Method(pathData.MethodName) + if methodType == nil { + return "", errors.New("revel/controller: In " + action + " failed to find function " + pathData.MethodName) + } + + if len(methodType.Args) < len(args)-1 { + return "", fmt.Errorf("reversing %s: route defines %d args, but received %d", + action, len(methodType.Args), len(args)-1) + } + // Unbind the arguments. + argsByName := make(map[string]string) + // Bind any static args first + fixedParams := len(pathData.FixedParamsByName) + + for i, argValue := range args[1:] { + Unbind(argsByName, methodType.Args[i+fixedParams].Name, argValue) + } + + return template.URL(MainRouter.Reverse(args[0].(string), argsByName).URL), nil +} + +func Slug(text string) string { + separator := "-" + text = strings.ToLower(text) + text = invalidSlugPattern.ReplaceAllString(text, "") + text = whiteSpacePattern.ReplaceAllString(text, separator) + text = strings.Trim(text, separator) + return text +} + +var timeAgoLangs = map[string]timeago.Config{} + +func TimeAgo(args ...interface{}) string { + + datetime := time.Now() + lang := "" + var viewArgs interface{} + switch len(args) { + case 0: + templateLog.Error("TimeAgo: No arguments passed to timeago") + case 1: + // only the time is passed in + datetime = args[0].(time.Time) + case 2: + // time and region is passed in + datetime = args[0].(time.Time) + switch v := reflect.ValueOf(args[1]); v.Kind() { + case reflect.String: + // second params type string equals region + lang, _ = args[1].(string) + case reflect.Map: + // second params type map equals viewArgs + viewArgs = args[1] + if viewargsmap, ok := viewArgs.(map[string]interface{}); ok { + lang, _ = viewargsmap[CurrentLocaleViewArg].(string) + } + default: + templateLog.Error("TimeAgo: unexpected type: ", "value", v) + } + default: + // Assume third argument is the region + datetime = args[0].(time.Time) + if reflect.ValueOf(args[1]).Kind() != reflect.Map { + templateLog.Error("TimeAgo: unexpected type", "value", args[1]) + } + if reflect.ValueOf(args[2]).Kind() != reflect.String { + templateLog.Error("TimeAgo: unexpected type: ", "value", args[2]) + } + viewArgs = args[1] + lang, _ = args[2].(string) + if len(args) > 3 { + templateLog.Error("TimeAgo: Received more parameters then needed for timeago") + } + } + if lang == "" { + lang, _ = Config.String(defaultLanguageOption) + if lang == "en" { + timeAgoLangs[lang] = timeago.English + } + } + _, ok := timeAgoLangs[lang] + if !ok { + timeAgoLangs[lang] = timeago.Config{ + PastPrefix: "", + PastSuffix: " " + MessageFunc(lang, "ago"), + FuturePrefix: MessageFunc(lang, "in") + " ", + FutureSuffix: "", + Periods: []timeago.FormatPeriod{ + {time.Second, MessageFunc(lang, "about a second"), MessageFunc(lang, "%d seconds")}, + {time.Minute, MessageFunc(lang, "about a minute"), MessageFunc(lang, "%d minutes")}, + {time.Hour, MessageFunc(lang, "about an hour"), MessageFunc(lang, "%d hours")}, + {timeago.Day, MessageFunc(lang, "one day"), MessageFunc(lang, "%d days")}, + {timeago.Month, MessageFunc(lang, "one month"), MessageFunc(lang, "%d months")}, + {timeago.Year, MessageFunc(lang, "one year"), MessageFunc(lang, "%d years")}, + }, + Zero: MessageFunc(lang, "about a second"), + Max: 73 * time.Hour, + DefaultLayout: "2006-01-02", + } + + } + return timeAgoLangs[lang].Format(datetime) +}