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)