github.com/kotovmak/go-admin@v1.1.1/template/types/page.go (about) 1 // Copyright 2019 GoAdmin Core Team. All rights reserved. 2 // Use of this source code is governed by a Apache-2.0 style 3 // license that can be found in the LICENSE file. 4 5 package types 6 7 import ( 8 "bytes" 9 "fmt" 10 "html/template" 11 "strconv" 12 textTmpl "text/template" 13 14 "github.com/kotovmak/go-admin/context" 15 "github.com/kotovmak/go-admin/modules/config" 16 "github.com/kotovmak/go-admin/modules/menu" 17 "github.com/kotovmak/go-admin/modules/system" 18 "github.com/kotovmak/go-admin/modules/utils" 19 "github.com/kotovmak/go-admin/plugins/admin/models" 20 ) 21 22 // Attribute is the component interface of template. Every component of 23 // template should implement it. 24 type Attribute struct { 25 TemplateList map[string]string 26 Separation bool 27 } 28 29 // Page used in the template as a top variable. 30 type Page struct { 31 // User is the login user. 32 User models.UserModel 33 34 // Menu is the left side menu of the template. 35 Menu menu.Menu 36 37 // Panel is the main content of template. 38 Panel Panel 39 40 // System contains some system info. 41 System SystemInfo 42 43 // UrlPrefix is the prefix of url. 44 UrlPrefix string 45 46 // Title is the title of the web page. 47 Title string 48 49 // Logo is the logo of the template. 50 Logo template.HTML 51 52 // MiniLogo is the downsizing logo of the template. 53 MiniLogo template.HTML 54 55 // ColorScheme is the color scheme of the template. 56 ColorScheme string 57 58 // IndexUrl is the home page url of the site. 59 IndexUrl string 60 61 // AssetUrl is the cdn link of assets 62 CdnUrl string 63 64 // Custom html in the tag head. 65 CustomHeadHtml template.HTML 66 67 // Custom html after body. 68 CustomFootHtml template.HTML 69 70 TmplHeadHTML template.HTML 71 TmplFootJS template.HTML 72 73 // Components assets 74 AssetsList template.HTML 75 76 // Footer info 77 FooterInfo template.HTML 78 79 // Load as Iframe or not 80 Iframe bool 81 82 // Whether update menu or not 83 UpdateMenu bool 84 85 // Top Nav Buttons 86 navButtons Buttons 87 NavButtonsHTML template.HTML 88 } 89 90 type NewPageParam struct { 91 User models.UserModel 92 Menu *menu.Menu 93 UpdateMenu bool 94 Panel Panel 95 Logo template.HTML 96 Assets template.HTML 97 Buttons Buttons 98 Iframe bool 99 TmplHeadHTML template.HTML 100 TmplFootJS template.HTML 101 NavButtonsHTML template.HTML 102 NavButtonsJS template.HTML 103 } 104 105 func (param *NewPageParam) NavButtonsAndJS() (template.HTML, template.HTML) { 106 navBtnFooter := template.HTML("") 107 navBtn := template.HTML("") 108 btnJS := template.JS("") 109 110 for _, btn := range param.Buttons { 111 if btn.IsType(ButtonTypeNavDropDown) { 112 content, js := btn.Content() 113 navBtn += content 114 btnJS += js 115 for _, item := range btn.(*NavDropDownButton).Items { 116 navBtnFooter += item.GetAction().FooterContent() 117 _, js := item.Content() 118 btnJS += js 119 } 120 } else { 121 navBtnFooter += btn.GetAction().FooterContent() 122 content, js := btn.Content() 123 navBtn += content 124 btnJS += js 125 } 126 } 127 128 return template.HTML(ParseTableDataTmpl(navBtn)), 129 navBtnFooter + template.HTML(ParseTableDataTmpl(`<script>`+btnJS+`</script>`)) 130 } 131 132 func NewPage(param *NewPageParam) *Page { 133 134 if param.NavButtonsHTML == template.HTML("") { 135 param.NavButtonsHTML, param.NavButtonsJS = param.NavButtonsAndJS() 136 } 137 138 logo := param.Logo 139 if logo == template.HTML("") { 140 logo = config.GetLogo() 141 } 142 143 return &Page{ 144 User: param.User, 145 Menu: *param.Menu, 146 Panel: param.Panel, 147 UpdateMenu: param.UpdateMenu, 148 System: SystemInfo{ 149 Version: system.Version(), 150 Theme: config.GetTheme(), 151 }, 152 UrlPrefix: config.AssertPrefix(), 153 Title: config.GetTitle(), 154 Logo: logo, 155 MiniLogo: config.GetMiniLogo(), 156 ColorScheme: config.GetColorScheme(), 157 IndexUrl: config.GetIndexURL(), 158 CdnUrl: config.GetAssetUrl(), 159 CustomHeadHtml: config.GetCustomHeadHtml(), 160 CustomFootHtml: config.GetCustomFootHtml() + param.NavButtonsJS, 161 FooterInfo: config.GetFooterInfo(), 162 AssetsList: param.Assets, 163 navButtons: param.Buttons, 164 Iframe: param.Iframe, 165 NavButtonsHTML: param.NavButtonsHTML, 166 TmplHeadHTML: param.TmplHeadHTML, 167 TmplFootJS: param.TmplFootJS, 168 } 169 } 170 171 func (page *Page) AddButton(title template.HTML, icon string, action Action) *Page { 172 page.navButtons = append(page.navButtons, GetNavButton(title, icon, action)) 173 page.CustomFootHtml += action.FooterContent() 174 return page 175 } 176 177 func NewPagePanel(panel Panel) *Page { 178 return &Page{ 179 Panel: panel, 180 System: SystemInfo{ 181 Version: system.Version(), 182 }, 183 } 184 } 185 186 // SystemInfo contains basic info of system. 187 type SystemInfo struct { 188 Version string 189 Theme string 190 } 191 192 type TableRowData struct { 193 Id template.HTML 194 Ids template.HTML 195 Value map[string]InfoItem 196 } 197 198 func ParseTableDataTmpl(content interface{}) string { 199 var ( 200 c string 201 ok bool 202 ) 203 if c, ok = content.(string); !ok { 204 if cc, ok := content.(template.HTML); ok { 205 c = string(cc) 206 } else { 207 c = string(content.(template.JS)) 208 } 209 } 210 t := template.New("row_data_tmpl") 211 t, _ = t.Parse(c) 212 buf := new(bytes.Buffer) 213 _ = t.Execute(buf, TableRowData{Ids: `typeof(selectedRows)==="function" ? selectedRows().join() : ""`}) 214 return buf.String() 215 } 216 217 func ParseTableDataTmplWithID(id template.HTML, content string, value ...map[string]InfoItem) string { 218 t := textTmpl.New("row_data_tmpl") 219 t, _ = t.Parse(content) 220 buf := new(bytes.Buffer) 221 v := make(map[string]InfoItem) 222 if len(value) > 0 { 223 v = value[0] 224 } 225 _ = t.Execute(buf, TableRowData{ 226 Id: id, 227 Ids: `typeof(selectedRows)==="function" ? selectedRows().join() : ""`, 228 Value: v, 229 }) 230 return buf.String() 231 } 232 233 // Panel contains the main content of the template which used as pjax. 234 type Panel struct { 235 Title template.HTML 236 Description template.HTML 237 Content template.HTML 238 239 CSS template.CSS 240 JS template.JS 241 Url string 242 243 // Whether to toggle the sidebar 244 MiniSidebar bool 245 246 // Auto refresh page switch. 247 AutoRefresh bool 248 // Refresh page intervals, the unit is second. 249 RefreshInterval []int 250 251 Callbacks Callbacks 252 } 253 254 type Component interface { 255 GetContent() template.HTML 256 GetJS() template.JS 257 GetCSS() template.CSS 258 GetCallbacks() Callbacks 259 } 260 261 func (p Panel) AddComponent(comp Component) Panel { 262 p.JS += comp.GetJS() 263 p.CSS += comp.GetCSS() 264 p.Content += comp.GetContent() 265 p.Callbacks = append(p.Callbacks, comp.GetCallbacks()...) 266 return p 267 } 268 269 func (p Panel) AddJS(js template.JS) Panel { 270 p.JS += js 271 return p 272 } 273 274 func (p Panel) GetContent(params ...bool) Panel { 275 276 compress := false 277 278 if len(params) > 0 { 279 compress = params[0] 280 } 281 282 var ( 283 animation, style, remove = template.HTML(""), template.HTML(""), template.HTML("") 284 ani = config.GetAnimation() 285 ) 286 287 if ani.Type != "" && (len(params) < 2 || params[1]) { 288 animation = template.HTML(` class='pjax-container-content animated ` + ani.Type + `'`) 289 if ani.Delay != 0 { 290 style = template.HTML(fmt.Sprintf(`animation-delay: %fs;-webkit-animation-delay: %fs;`, ani.Delay, ani.Delay)) 291 } 292 if ani.Duration != 0 { 293 style = template.HTML(fmt.Sprintf(`animation-duration: %fs;-webkit-animation-duration: %fs;`, ani.Duration, ani.Duration)) 294 } 295 if style != "" { 296 style = ` style="` + style + `"` 297 } 298 remove = template.HTML(`<script> 299 $('.pjax-container-content .modal.fade').on('show.bs.modal', function (event) { 300 // Fix Animate.css 301 $('.pjax-container-content').removeClass('` + ani.Type + `'); 302 }); 303 </script>`) 304 } 305 306 p.Content = `<div` + animation + style + ">" + p.Content + "</div>" + remove 307 if p.MiniSidebar { 308 p.Content += `<script>$("body").addClass("sidebar-collapse")</script>` 309 } 310 if p.AutoRefresh { 311 refreshTime := 60 312 if len(p.RefreshInterval) > 0 { 313 refreshTime = p.RefreshInterval[0] 314 } 315 316 p.Content += `<script> 317 window.setTimeout(function(){ 318 $.pjax.reload('#pjax-container'); 319 }, ` + template.HTML(strconv.Itoa(refreshTime*1000)) + `); 320 </script>` 321 } 322 323 if compress { 324 utils.CompressedContent(&p.Content) 325 } 326 327 return p 328 } 329 330 type GetPanelFn func(ctx interface{}) (Panel, error) 331 332 type GetPanelInfoFn func(ctx *context.Context) (Panel, error)