reprogl

Форк
0
/
view_models.go 
350 строк · 7.8 Кб
1
package views
2

3
import (
4
	"fmt"
5
	"reflect"
6
	"strings"
7
	"time"
8

9
	"xelbot.com/reprogl/container"
10
	"xelbot.com/reprogl/models"
11
	"xelbot.com/reprogl/security"
12
)
13

14
type Meta struct {
15
	Host         string
16
	HeaderText   string
17
	MetaParts    []MetaName
18
	IsIndexPage  bool
19
	IsAuthorPage bool
20
	titleParts   []string
21
	Ogp          OpenGraph
22
	Canonical    string
23
}
24

25
type MetaName struct {
26
	Name    string
27
	Content string
28
}
29

30
type OpenGraph map[string]string
31

32
type HeaderLineInfo interface {
33
	HeaderLineDescription() string
34
	HeaderLineText() string
35
}
36

37
type DataWithFlashMessage interface {
38
	HasSuccessFlash() bool
39
	FlashSuccess() string
40
	SetSuccessFlash(string)
41
}
42

43
type flashObjectPart struct {
44
	flashSuccess string
45
}
46

47
type identityPart struct {
48
	identity security.Identity
49
}
50

51
type ArticlePageData struct {
52
	Meta
53
	Article      *models.Article
54
	CommentKey   string
55
	AcceptHeader string
56
	flashObjectPart
57
	identityPart
58
}
59

60
type IndexPageData struct {
61
	Meta
62
	HeaderInfo HeaderLineInfo
63
	Paginator  *models.ArticlesPaginator
64
	flashObjectPart
65
}
66

67
type InfoPageData struct {
68
	Meta
69
	HeaderInfo HeaderLineInfo
70
	flashObjectPart
71
	Jobs container.JobHistory
72
}
73

74
type SidebarDummyArticle struct {
75
	IsArticle     bool
76
	RecentPostsID string
77
}
78

79
type StatisticsPageData struct {
80
	Meta
81
	Now          time.Time
82
	Commentators *models.CommentatorList
83
	DummyArticle SidebarDummyArticle
84

85
	MonthArticles   []models.ArticleStatItem
86
	AllTimeArticles []models.ArticleStatItem
87
}
88

89
type LoginPageData struct {
90
	Meta
91
	CsrfToken    string
92
	ErrorMessage string
93
	HasError     bool
94
}
95

96
type UnsubscribePageData struct {
97
	Meta
98
	Settings *models.EmailSubscription
99
	Avatar   string
100
	Success  bool
101
}
102

103
type AuthNavigation struct {
104
	identityPart
105
}
106

107
type MenuAuthData struct {
108
	User *models.User
109
	identityPart
110
}
111

112
type ProfilePageData struct {
113
	Meta
114
	User                  *models.User
115
	SubscriptionsSettings *models.EmailSubscription
116
	DummyArticle          SidebarDummyArticle
117
}
118

119
type OauthPendingPageData struct {
120
	Meta
121
	RequestId string
122
}
123

124
type FragmentCategoriesData struct {
125
	Categories *models.CategoryList
126
}
127

128
type FragmentCommentsData struct {
129
	Comments        models.CommentList
130
	EnabledComments bool
131
	identityPart
132
}
133

134
type FragmentRecentPostsData struct {
135
	RecentPosts *models.RecentPostList
136
}
137

138
func defaultMeta() Meta {
139
	cfg := container.GetConfig()
140

141
	ogp := make(OpenGraph)
142
	// og:title and og:url required for every page
143
	ogp["og:type"] = "website"
144
	ogp["og:image"] = cfg.CDNBaseURL + "/images/kravchik.jpg"
145
	ogp["og:image:width"] = "752"
146
	ogp["og:image:height"] = "376"
147
	ogp["og:locale"] = "ru_RU"
148

149
	return Meta{Host: cfg.Host, HeaderText: cfg.HeaderText, Ogp: ogp}
150
}
151

152
func (m *Meta) AppendTitle(str string) {
153
	m.titleParts = append(m.titleParts, str)
154
	m.SetOpenGraphProperty("og:title", str)
155
}
156

157
func (m *Meta) AppendName(name, content string) {
158
	m.MetaParts = append(m.MetaParts, MetaName{Name: name, Content: content})
159
	if name == "description" {
160
		m.SetOpenGraphProperty("og:description", content)
161
	}
162
}
163

164
func (m *Meta) SetCanonical(link string) {
165
	m.Canonical = link
166
	m.SetOpenGraphProperty("og:url", link)
167
}
168

169
func (m *Meta) SetOpenGraphProperty(property, content string) {
170
	if m.Ogp != nil {
171
		m.Ogp[property] = content
172
	} else {
173
		ogp := make(OpenGraph)
174
		ogp[property] = content
175
		m.Ogp = ogp
176
	}
177
}
178

179
func (m *Meta) BrowserTitle() string {
180
	var title string
181
	if len(m.titleParts) > 0 {
182
		for _, p := range m.titleParts {
183
			title += p + " » "
184
		}
185
	}
186
	title += m.Host
187

188
	return title
189
}
190

191
func (fo *flashObjectPart) HasSuccessFlash() bool {
192
	return len(fo.flashSuccess) > 0
193
}
194

195
func (fo *flashObjectPart) FlashSuccess() string {
196
	return fo.flashSuccess
197
}
198

199
func (fo *flashObjectPart) SetSuccessFlash(msg string) {
200
	fo.flashSuccess = msg
201
}
202

203
func (ip *identityPart) SetIdentity(identity security.Identity) {
204
	ip.identity = identity
205
}
206

207
func (ip *identityPart) HasIdentity() bool {
208
	return !ip.identity.IsZero()
209
}
210

211
func (ip *identityPart) IsAdmin() bool {
212
	return ip.identity.IsAdmin()
213
}
214

215
func NewArticlePageData(article *models.Article, commentKey, accept string) *ArticlePageData {
216
	meta := defaultMeta()
217
	if article.Description.Valid {
218
		meta.AppendName("description", article.Description.String)
219
	}
220

221
	return &ArticlePageData{
222
		Article:      article,
223
		Meta:         meta,
224
		CommentKey:   commentKey,
225
		AcceptHeader: accept,
226
	}
227
}
228

229
func NewIndexPageData(paginator *models.ArticlesPaginator) *IndexPageData {
230
	meta := defaultMeta()
231
	meta.IsIndexPage = true
232

233
	return &IndexPageData{
234
		Paginator: paginator,
235
		Meta:      meta,
236
	}
237
}
238

239
func NewCategoryPageData(paginator *models.ArticlesPaginator, headerInfo HeaderLineInfo) *IndexPageData {
240
	var browserTitle, metaDescription string
241
	meta := defaultMeta()
242
	meta.IsIndexPage = true
243

244
	switch reflect.TypeOf(headerInfo).String() {
245
	case "*models.Category":
246
		browserTitle = fmt.Sprintf("Категория \"%s\"", headerInfo.HeaderLineText())
247
		metaDescription = fmt.Sprintf("Записи из категории \"%s\"", headerInfo.HeaderLineText())
248
	case "*models.Tag":
249
		browserTitle = fmt.Sprintf("Тег \"%s\"", headerInfo.HeaderLineText())
250
		metaDescription = fmt.Sprintf("Записи по тегу \"%s\"", headerInfo.HeaderLineText())
251
	}
252

253
	if paginator.CurrentPage > 1 {
254
		browserTitle += fmt.Sprintf(". Страница %d", paginator.CurrentPage)
255
		metaDescription += fmt.Sprintf(". Страница %d", paginator.CurrentPage)
256
	}
257
	meta.AppendTitle(browserTitle)
258
	meta.AppendName("description", metaDescription)
259
	meta.AppendName("robots", "noindex, follow")
260

261
	return &IndexPageData{Paginator: paginator, HeaderInfo: headerInfo, Meta: meta}
262
}
263

264
func NewInfoPageData() *InfoPageData {
265
	meta := defaultMeta()
266
	meta.IsAuthorPage = true
267
	meta.AppendName("description", "Персональный блог Харченко Александра. Общая информация.")
268
	meta.AppendTitle("Обо мне")
269

270
	return &InfoPageData{
271
		Meta: meta,
272
		Jobs: container.GetConfig().Jobs.Sort(),
273
	}
274
}
275

276
func NewStatisticsPageData() *StatisticsPageData {
277
	meta := defaultMeta()
278
	meta.AppendName("description", "Статистика посещений и комментариев.")
279
	meta.AppendTitle("Статистика")
280

281
	return &StatisticsPageData{
282
		Meta:         meta,
283
		Now:          time.Now(),
284
		DummyArticle: SidebarDummyArticle{RecentPostsID: "0"},
285
	}
286
}
287

288
func NewLoginPageData(token, errorMessage string, hasError bool) *LoginPageData {
289
	meta := defaultMeta()
290
	meta.AppendTitle("Вход")
291
	meta.AppendName("description", "Страница логина. Описание тут не особо-то и нужно, но Yandex Webmaster настаивает")
292

293
	return &LoginPageData{
294
		Meta:         meta,
295
		CsrfToken:    token,
296
		ErrorMessage: errorMessage,
297
		HasError:     hasError,
298
	}
299
}
300

301
func NewUnsubscribePageData(settings *models.EmailSubscription, avatarLink string, success bool) *UnsubscribePageData {
302
	meta := defaultMeta()
303
	meta.AppendTitle("Отписка от email-уведомлений")
304

305
	return &UnsubscribePageData{
306
		Meta:     meta,
307
		Settings: settings,
308
		Avatar:   avatarLink,
309
		Success:  success,
310
	}
311
}
312

313
func NewAuthNavigationData() *AuthNavigation {
314
	return &AuthNavigation{}
315
}
316

317
func NewMenuAuthData(user *models.User) *MenuAuthData {
318
	return &MenuAuthData{User: user}
319
}
320

321
func NewProfilePageData(user *models.User, settings *models.EmailSubscription) *ProfilePageData {
322
	meta := defaultMeta()
323
	meta.AppendTitle("Профиль")
324

325
	return &ProfilePageData{
326
		Meta:         meta,
327
		User:         user,
328
		DummyArticle: SidebarDummyArticle{RecentPostsID: "0"},
329

330
		SubscriptionsSettings: settings,
331
	}
332
}
333

334
func NewOauthPendingPageData(requsetId string) *OauthPendingPageData {
335
	meta := defaultMeta()
336
	meta.AppendTitle("Ожидайте...")
337

338
	return &OauthPendingPageData{
339
		Meta:      meta,
340
		RequestId: requsetId,
341
	}
342
}
343

344
func (apd *ArticlePageData) AcceptWebp() bool {
345
	return strings.Contains(apd.AcceptHeader, "image/webp")
346
}
347

348
func (apd *ArticlePageData) AcceptAvif() bool {
349
	return strings.Contains(apd.AcceptHeader, "image/avif")
350
}
351

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.