models.go 5.09 KB
Newer Older
1
2
3
4
package web

import (
	"context"
Lee Brown's avatar
Lee Brown committed
5
	"crypto/md5"
6
	"fmt"
7
	"geeks-accelerator/oss/saas-starter-kit/internal/platform/auth"
8
9
10
11
12
13
14
	"github.com/dustin/go-humanize"
	"strings"
	"time"
)

const DatetimeFormatLocal = "Mon Jan _2 3:04PM"
const DateFormatLocal = "Mon Jan _2"
15
const TimeFormatLocal = time.Kitchen
16
17
18
19
20
21
22
23
24
25
26

// TimeResponse is a response friendly format for displaying the value of a time.
type TimeResponse struct {
	Value      time.Time `json:"value" example:"2019-06-25T03:00:53.284-08:00"`
	ValueUTC   time.Time `json:"value_utc" example:"2019-06-25T11:00:53.284Z"`
	Date       string    `json:"date" example:"2019-06-25"`
	Time       string    `json:"time" example:"03:00:53"`
	Kitchen    string    `json:"kitchen" example:"3:00AM"`
	RFC1123    string    `json:"rfc1123" example:"Tue, 25 Jun 2019 03:00:53 AKDT"`
	Local      string    `json:"local" example:"Tue Jun 25 3:00AM"`
	LocalDate  string    `json:"local_date" example:"Tue Jun 25"`
27
	LocalTime  string    `json:"local_time" example:"3:00AM"`
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
	NowTime    string    `json:"now_time" example:"5 hours ago"`
	NowRelTime string    `json:"now_rel_time" example:"15 hours from now"`
	Timezone   string    `json:"timezone" example:"America/Anchorage"`
}

// NewTimeResponse parses the time to the timezone location set in context and
// returns the display friendly format as TimeResponse.
func NewTimeResponse(ctx context.Context, t time.Time) TimeResponse {

	// If the context has claims, check to see if timezone is set for the current user and
	// then format the input time in that timezone if set.
	claims, ok := ctx.Value(auth.Key).(auth.Claims)
	if ok && claims.TimeLocation() != nil {
		t = t.In(claims.TimeLocation())
	}

44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
	var formatDatetime = DatetimeFormatLocal
	if claims.Preferences.DatetimeFormat != "" {
		formatDatetime = claims.Preferences.DatetimeFormat
	}

	var formatDate = DatetimeFormatLocal
	if claims.Preferences.DateFormat != "" {
		formatDate = claims.Preferences.DateFormat
	}

	var formatTime = DatetimeFormatLocal
	if claims.Preferences.DatetimeFormat != "" {
		formatTime = claims.Preferences.TimeFormat
	}

59
60
61
62
63
64
65
	tr := TimeResponse{
		Value:      t,
		ValueUTC:   t.UTC(),
		Date:       t.Format("2006-01-02"),
		Time:       t.Format("15:04:05"),
		Kitchen:    t.Format(time.Kitchen),
		RFC1123:    t.Format(time.RFC1123),
66
67
68
		Local:      t.Format(formatDatetime),
		LocalDate:  t.Format(formatDate),
		LocalTime:  t.Format(formatTime),
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
		NowTime:    humanize.Time(t.UTC()),
		NowRelTime: humanize.RelTime(time.Now().UTC(), t.UTC(), "ago", "from now"),
	}

	if t.Location() != nil {
		tr.Timezone = t.Location().String()
	}

	return tr
}

// EnumOption represents a single value of an enum option.
type EnumOption struct {
	Value    string `json:"value" example:"active_etc"`
	Title    string `json:"title"  example:"Active Etc"`
	Selected bool   `json:"selected" example:"true"`
}

// EnumResponse is a response friendly format for displaying an enum value that
// includes a list of all possible values.
type EnumResponse struct {
	Value   string       `json:"value" example:"active_etc"`
	Title   string       `json:"title" example:"Active Etc"`
	Options []EnumOption `json:"options,omitempty"`
}

// NewEnumResponse returns a display friendly format for a enum field.
func NewEnumResponse(ctx context.Context, value interface{}, options ...interface{}) EnumResponse {
	er := EnumResponse{
		Value: fmt.Sprintf("%s", value),
		Title: EnumValueTitle(fmt.Sprintf("%s", value)),
	}

	for _, opt := range options {
		optStr := fmt.Sprintf("%s", opt)
Lee Brown's avatar
Lee Brown committed
104
105
106
107
108
109
110
111
112
113
		opt := EnumOption{
			Value: optStr,
			Title: EnumValueTitle(optStr),
		}

		if optStr == er.Value {
			opt.Selected = true
		}

		er.Options = append(er.Options, opt)
114
115
116
117
118
	}

	return er
}

Lee Brown's avatar
Lee Brown committed
119
// EnumResponse is a response friendly format for displaying a multi select enum.
120
121
122
123
type EnumMultiResponse struct {
	Values  []string     `json:"values" example:"active_etc"`
	Options []EnumOption `json:"options,omitempty"`
}
Lee Brown's avatar
Lee Brown committed
124
125
126

// NewEnumMultiResponse returns a display friendly format for a multi enum field.
func NewEnumMultiResponse(ctx context.Context, selected []interface{}, options ...interface{}) EnumMultiResponse {
Lee Brown's avatar
Lee Brown committed
127
	var er EnumMultiResponse
Lee Brown's avatar
Lee Brown committed
128

129
130
131
132
133
	for _, s := range selected {
		selStr := fmt.Sprintf("%s", s)
		er.Values = append(er.Values, selStr)
	}

Lee Brown's avatar
Lee Brown committed
134
135
136
137
138
139
140
141
142
143
144
145
146
147
	for _, opt := range options {
		optStr := fmt.Sprintf("%s", opt)
		opt := EnumOption{
			Value: optStr,
			Title: EnumValueTitle(optStr),
		}

		for _, s := range selected {
			selStr := fmt.Sprintf("%s", s)
			if optStr == selStr {
				opt.Selected = true
			}
		}

148
		er.Options = append(er.Options, opt)
Lee Brown's avatar
Lee Brown committed
149
150
151
152
153
	}

	return er
}

154
155
156
157
158
// EnumValueTitle formats a string value for display.
func EnumValueTitle(v string) string {
	v = strings.Replace(v, "_", " ", -1)
	return strings.Title(v)
}
Lee Brown's avatar
Lee Brown committed
159
160

type GravatarResponse struct {
161
162
	Small  string `json:"small" example:"https://www.gravatar.com/avatar/xy7.jpg?s=30"`
	Medium string `json:"medium" example:"https://www.gravatar.com/avatar/xy7.jpg?s=80"`
Lee Brown's avatar
Lee Brown committed
163
164
165
}

func NewGravatarResponse(ctx context.Context, email string) GravatarResponse {
166
	u := fmt.Sprintf("https://www.gravatar.com/avatar/%x.jpg?s=", md5.Sum([]byte(strings.ToLower(email))))
Lee Brown's avatar
Lee Brown committed
167

168
169
170
171
	return GravatarResponse{
		Small:  u + "30",
		Medium: u + "80",
	}
Lee Brown's avatar
Lee Brown committed
172
}