前回、Go言語でGinフレームワークを使ってのMVCモデルをご紹介させて頂いたのですが、実際に業務で使えるように下記の対応を入れました。


ソースコード GitHub


見た目のカッコ良さとUIの機能性

  • Bootstrap v5.3
  • Chart.js v2.9.4
  • AdminKit v3.4.0

Webアプリだけでなく、スマホアプリでもビジネスロジックを利用できる拡張性

  • GORM v2
  • REST API
  • jQuery v3.7.1

なりすまし防止

  • gin-jwt/v2
  • yaml.v3

package controllers

import (
	"ginmvc/app/models"
	"log"

	"strconv"

	"github.com/gin-gonic/gin"
)

func GetRouter() *gin.Engine {
	r := gin.Default()
	r.SetTrustedProxies(nil)
	r.Static("/public", "./public")
	r.LoadHTMLGlob("app/views/*/*.html")

	var config models.Config
	config, err := config.LoadConfigForYaml()
	if err != nil {
		log.Fatal(err)
		return r
	}

	jwt, err := newJwtMiddleware(&config)
	if err != nil {
		log.Fatal(err)
		return r
	}

	r.GET("/", func(c *gin.Context) {
		var l, err = IsHaveToken(c, jwt)
		if err != nil {
			ShowLogin(c, &config, &models.LoginUser{})
		} else {
			MoveTop(c, &config, l)
		}

	})
	r.POST("/", SetConfigJWT(ExecLogin, &config, jwt))

	api := r.Group("/api", jwt.MiddlewareFunc())
	{
		api.Use(handlerMiddleWare(jwt))
		api.GET("/getkvMicrowave", SetConfig(GetKvMicrowave, &config))
		api.GET("/getHighFrequency", SetConfig(GetHighFrequency, &config))

	}
	r.POST("/reboot", SetConfig(ExecReboot, &config))
	r.GET("/user", SetConfigUser(ShowLogin, &config, &models.LoginUser{}))
	r.POST("/shutdown", SetConfig(ExecShutdown, &config))
	r.NoRoute(SetConfig(ShowNoRoute, &config))
	r.NoMethod(SetConfig(ShowNoMethod, &config))
	r.Use(SetConfig(MiddleWare, &config))
	r.Run(":" + strconv.Itoa(config.App.Port))
	return r
}
package controllers

import (
	"errors"
	"fmt"
	"ginmvc/app/models"
	"log"
	"net/http"
	"time"

	jwt "github.com/appleboy/gin-jwt/v2"
	"github.com/gin-gonic/gin"
)

func ShowNoRoute(c *gin.Context, config *models.Config) {
	formdata := models.GetNoUser(config, &models.LoginUser{})
	formdata.Description = "Page not found"
	formdata.Error = true
	fmt.Printf("ShowNoRoute\n")
	c.HTML(200, "404.html", gin.H{"formdata": formdata})
}

func ShowNoMethod(c *gin.Context, config *models.Config) {
	formdata := models.GetNoUser(config, &models.LoginUser{})
	formdata.Description = "Method not allowed"
	formdata.Error = true
	fmt.Printf("ShowNoMethod\n")
	c.HTML(200, "404.html", gin.H{"formdata": formdata})
}

func newJwtMiddleware(config *models.Config) (*jwt.GinJWTMiddleware, error) {

	jwtMiddleware, err := jwt.New(&jwt.GinJWTMiddleware{
		Realm:            config.Jwt.Realm,
		Key:              []byte(config.Jwt.Key),
		Timeout:          time.Minute * time.Duration(config.Jwt.Timeout),
		MaxRefresh:       time.Minute * time.Duration(config.Jwt.MaxRefresh),
		SendCookie:       config.Jwt.SendCookie,
		TokenLookup:      config.Jwt.TokenLookup,
		SigningAlgorithm: config.Jwt.SigningAlgorithm,
		TokenHeadName:    config.Jwt.TokenHeadName,
		CookieName:       config.Jwt.CookieName,
		PayloadFunc: func(data interface{}) jwt.MapClaims {
			return jwt.MapClaims{
				jwt.IdentityKey: data,
			}
		},
		Authenticator: func(c *gin.Context) (interface{}, error) {
			var l models.LoginUser
			if err := c.ShouldBind(&l); err != nil {
				return "", jwt.ErrMissingLoginValues
			}
			if !l.IsValid(config) {
				return "", jwt.ErrFailedAuthentication
			}
			return l, nil
		},
		LoginResponse: func(c *gin.Context, code int, tokenstring string, time time.Time) {
		},
	})

	if err != nil {
		return nil, err
	}

	err = jwtMiddleware.MiddlewareInit()
	if err != nil {
		return nil, err
	}

	return jwtMiddleware, nil
}
func handlerMiddleWare(authMiddleware *jwt.GinJWTMiddleware) gin.HandlerFunc {
	return func(context *gin.Context) {
		errInit := authMiddleware.MiddlewareInit()
		if errInit != nil {
			log.Fatal("authMiddleware.MiddlewareInit() Error:" + errInit.Error())
		}
	}
}

func MiddleWare(c *gin.Context, config *models.Config) {
	fmt.Printf("Total Errors -> %d\n", len(c.Errors))

	if len(c.Errors) <= 0 {
		c.Next()
		return
	}

	for _, err := range c.Errors {
		fmt.Printf("Error -> %+v\n", err)
	}
	c.JSON(http.StatusInternalServerError, "")
}

func SetConfig(fn func(*gin.Context, *models.Config), config *models.Config) gin.HandlerFunc {
	return func(c *gin.Context) {
		fn(c, config)
	}
}
func SetConfigJWT(fn func(*gin.Context, *models.Config, *jwt.GinJWTMiddleware), config *models.Config, jwt *jwt.GinJWTMiddleware) gin.HandlerFunc {
	return func(c *gin.Context) {
		fn(c, config, jwt)
	}
}
func SetConfigUser(fn func(*gin.Context, *models.Config, *models.LoginUser), config *models.Config, user *models.LoginUser) gin.HandlerFunc {
	return func(c *gin.Context) {
		fn(c, config, user)
	}
}

func IsHaveToken(c *gin.Context, jwtm *jwt.GinJWTMiddleware) (l *models.LoginUser, err error) {
	strtoken, err := c.Cookie("jwt")
	if err != nil {
		return &models.LoginUser{}, errors.New("No Cookie")
	}
	if strtoken == "" {
		return &models.LoginUser{}, errors.New("No Token")
	}

	token, err := jwtm.ParseTokenString(strtoken)
	if err != nil {
		return &models.LoginUser{}, errors.New("Paese Err")
	}
	claims := jwt.ExtractClaimsFromToken(token)
	var indenttity = claims[jwt.IdentityKey]
	var user = models.JsonToLoginUser(indenttity)
	return &user, nil

}
package models

import (
	"crypto/sha256"
	"encoding/hex"
	"encoding/json"
	"errors"
	"strconv"

	"github.com/gin-gonic/gin"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)

type LoginUser struct {
	ID         int    `json:"ID"`
	Username   string `json:"Username"`
	Password   string `form:"inputPassword" json:"password" binding:"required"`
	Department string `json:"Department"`
	Email      string `form:"inputEmail" json:"email" binding:"required"`
}

func NewLoginUser(c *gin.Context, config *Config) (*LoginUser, error) {
	token, err := c.Cookie("jwt")
	userid := token
	if err != nil {
		nouser := &LoginUser{ID: -1}
		return nouser, err
	}
	if userid == "" {
		emptyuser := &LoginUser{ID: -1}
		emptyerr := c.Error(errors.New("emptyuser"))
		return emptyuser, emptyerr
	}
	var id int
	id, _ = strconv.Atoi(userid)
	user := &LoginUser{ID: id}
	user.LoginUserInitiaLize(config)
	return user, nil
}
func SetLoginUser(c *gin.Context, email string, password string, config *Config) (*LoginUser, error) {

	user, err := checkUser(email, password, config)

	return user, err
}

func checkUser(email string, password string, config *Config) (*LoginUser, error) {

	db, err := gorm.Open(mysql.New(config.SetDbConfig()), &gorm.Config{})

	db.AutoMigrate(&LoginUser{})
	user := LoginUser{}
	db.Where("Email = ?", email).First(&user)
	if user.ID == 0 {
		user = LoginUser{ID: -1, Email: email}
		err = errors.New("no user")
		return &user, err
	}

	if user.Password != string(getBinaryBySHA256(password)) {
		user = LoginUser{ID: -1, Email: email, Password: user.Password, Department: string(getBinaryBySHA256(password))}
		err = errors.New("bad password")
		return &user, err
	}

	return &user, err

}

func (user *LoginUser) IsValid(config *Config) bool {
	db, err := gorm.Open(mysql.New(config.SetDbConfig()), &gorm.Config{})
	if err != nil {
		return false
	}
	db.AutoMigrate(&LoginUser{})
	dbuser := LoginUser{}
	db.Where("Email = ?", user.Email).First(&dbuser)
	if dbuser.ID == 0 {
		return false
	}
	if dbuser.Password != string(getBinaryBySHA256(user.Password)) {
		return false
	}
	user.ID = dbuser.ID
	user.Username = dbuser.Username
	user.Department = dbuser.Department
	user.Email = dbuser.Email
	return true
}

func getBinaryBySHA256(s string) string {
	r := sha256.Sum256([]byte(s))
	return hex.EncodeToString(r[:])
}
func (user *LoginUser) LoginUserInitiaLize(config *Config) {

	db, _ := gorm.Open(mysql.New(config.SetDbConfig()), &gorm.Config{})
	db.First(&user, user.ID)
}

func JsonToLoginUser(i interface{}) LoginUser {
	var l LoginUser
	b, err := json.Marshal(i)
	if err != nil {
		l = LoginUser{}
	}
	err = json.Unmarshal(b, &l)
	if err != nil {
		l = LoginUser{}
	}
	return l
}
{{template "header.html" .}}

<div class="wrapper">
	<nav id="sidebar" class="sidebar js-sidebar">
	  <div class="sidebar-content js-simplebar">
				<a class="sidebar-brand" href="/">
          <span class="align-middle">{{.formdata.Title}}</span>
        </a>

				<ul class="sidebar-nav">
					<li class="sidebar-header">
						Pages
					</li>

					<li class="sidebar-item active">
						<a class="sidebar-link" href="/">
              <i class="align-middle" data-feather="sliders"></i> <span class="align-middle">Dashboard</span>
            </a>
					</li>

					<li class="sidebar-item">
						<a class="sidebar-link" href="/">
              <i class="align-middle" data-feather="user"></i> <span class="align-middle">Profile</span>
            </a>
					</li>

					<li class="sidebar-item">
						<a class="sidebar-link" href="/">
              <i class="align-middle" data-feather="log-in"></i> <span class="align-middle">Sign In</span>
            </a>
					</li>

					<li class="sidebar-item">
						<a class="sidebar-link" href="/">
              <i class="align-middle" data-feather="user-plus"></i> <span class="align-middle">Sign Up</span>
            </a>
					</li>

					<li class="sidebar-item">
						<a class="sidebar-link" href="/">
              <i class="align-middle" data-feather="book"></i> <span class="align-middle">Blank</span>
            </a>
					</li>

					<li class="sidebar-header">
						Tools & Components
					</li>

					<li class="sidebar-item">
						<a class="sidebar-link" href="/">
              <i class="align-middle" data-feather="square"></i> <span class="align-middle">Buttons</span>
            </a>
					</li>

					<li class="sidebar-item">
						<a class="sidebar-link" href="/">
              <i class="align-middle" data-feather="check-square"></i> <span class="align-middle">Forms</span>
            </a>
					</li>

					<li class="sidebar-item">
						<a class="sidebar-link" href="/">
              <i class="align-middle" data-feather="grid"></i> <span class="align-middle">Cards</span>
            </a>
					</li>

					<li class="sidebar-item">
						<a class="sidebar-link" href="/">
              <i class="align-middle" data-feather="align-left"></i> <span class="align-middle">Typography</span>
            </a>
					</li>

					<li class="sidebar-item">
						<a class="sidebar-link" href="/">
              <i class="align-middle" data-feather="coffee"></i> <span class="align-middle">Icons</span>
            </a>
					</li>

					<li class="sidebar-header">
						Plugins & Addons
					</li>

					<li class="sidebar-item">
						<a class="sidebar-link" href="/">
              <i class="align-middle" data-feather="bar-chart-2"></i> <span class="align-middle">Charts</span>
            </a>
					</li>

					<li class="sidebar-item">
						<a class="sidebar-link" href="/">
              <i class="align-middle" data-feather="map"></i> <span class="align-middle">Maps</span>
            </a>
					</li>
				</ul>

			</div>
		</nav>

		<div class="main">
			<nav class="navbar navbar-expand navbar-light navbar-bg">
				<a class="sidebar-toggle js-sidebar-toggle">
          <i class="hamburger align-self-center"></i>
        </a>

				<div class="navbar-collapse collapse">
					<ul class="navbar-nav navbar-align">
						<li class="nav-item dropdown">
							<a class="nav-icon dropdown-toggle" href="#" id="alertsDropdown" data-bs-toggle="dropdown">
								<div class="position-relative">
									<i class="align-middle" data-feather="bell"></i>
									<span class="indicator">4</span>
								</div>
							</a>
							<div class="dropdown-menu dropdown-menu-lg dropdown-menu-end py-0" aria-labelledby="alertsDropdown">
								<div class="dropdown-menu-header">
									4 New Notifications
								</div>
								<div class="list-group">
									<a href="#" class="list-group-item">
										<div class="row g-0 align-items-center">
											<div class="col-2">
												<i class="text-danger" data-feather="alert-circle"></i>
											</div>
											<div class="col-10">
												<div class="text-dark">Update completed</div>
												<div class="text-muted small mt-1">Restart server 12 to complete the update.</div>
												<div class="text-muted small mt-1">30m ago</div>
											</div>
										</div>
									</a>
									<a href="#" class="list-group-item">
										<div class="row g-0 align-items-center">
											<div class="col-2">
												<i class="text-warning" data-feather="bell"></i>
											</div>
											<div class="col-10">
												<div class="text-dark">Lorem ipsum</div>
												<div class="text-muted small mt-1">Aliquam ex eros, imperdiet vulputate hendrerit et.</div>
												<div class="text-muted small mt-1">2h ago</div>
											</div>
										</div>
									</a>
									<a href="#" class="list-group-item">
										<div class="row g-0 align-items-center">
											<div class="col-2">
												<i class="text-primary" data-feather="home"></i>
											</div>
											<div class="col-10">
												<div class="text-dark">Login from 192.186.1.8</div>
												<div class="text-muted small mt-1">5h ago</div>
											</div>
										</div>
									</a>
									<a href="#" class="list-group-item">
										<div class="row g-0 align-items-center">
											<div class="col-2">
												<i class="text-success" data-feather="user-plus"></i>
											</div>
											<div class="col-10">
												<div class="text-dark">New connection</div>
												<div class="text-muted small mt-1">Christina accepted your request.</div>
												<div class="text-muted small mt-1">14h ago</div>
											</div>
										</div>
									</a>
								</div>
								<div class="dropdown-menu-footer">
									<a href="#" class="text-muted">Show all notifications</a>
								</div>
							</div>
						</li>
						<li class="nav-item dropdown">
							<a class="nav-icon dropdown-toggle d-inline-block d-sm-none" href="#" data-bs-toggle="dropdown">
                <i class="align-middle" data-feather="settings"></i>
              </a>

							<a class="nav-link dropdown-toggle d-none d-sm-inline-block" href="#" data-bs-toggle="dropdown">
                <img src="public/img/avatars/avatar.jpg" class="avatar img-fluid rounded me-1" alt="{{.formdata.User.Username}}" /> <span class="text-dark">{{.formdata.User.Username}}</span>
              </a>
							<div class="dropdown-menu dropdown-menu-end">
								<a class="dropdown-item" href="/"><i class="align-middle me-1" data-feather="user"></i> Profile</a>
								<a class="dropdown-item" href="#"><i class="align-middle me-1" data-feather="pie-chart"></i> Analytics</a>
								<div class="dropdown-divider"></div>
								<a class="dropdown-item" href="/"><i class="align-middle me-1" data-feather="settings"></i> Settings & Privacy</a>
								<a class="dropdown-item" href="#"><i class="align-middle me-1" data-feather="help-circle"></i> Help Center</a>
								<div class="dropdown-divider"></div>
								<a class="dropdown-item" href="/user">Log out</a>
							</div>
						</li>
					</ul>
				</div>
			</nav>

			<main class="content">
				<div class="container-fluid p-0">

					<h1 class="h3 mb-3"><strong>Analytics</strong> Dashboard</h1>

					<div class="row">
						<div class="col-xl-6 col-xxl-5 d-flex">
							<div class="w-100">
								<div class="row">
									<div class="col-sm-6">
										<div class="card">
											<div class="card-body">
												<div class="row">
													<div class="col mt-0">
														<h5 class="card-title">Sales</h5>
													</div>

													<div class="col-auto">
														<div class="stat text-primary">
															<i class="align-middle" data-feather="truck"></i>
														</div>
													</div>
												</div>
												<h1 class="mt-1 mb-3">2.382</h1>
												<div class="mb-0">
													<span class="text-danger"> <i class="mdi mdi-arrow-bottom-right"></i> -3.65% </span>
													<span class="text-muted">Since last week</span>
												</div>
											</div>
										</div>
										<div class="card">
											<div class="card-body">
												<div class="row">
													<div class="col mt-0">
														<h5 class="card-title">Visitors</h5>
													</div>

													<div class="col-auto">
														<div class="stat text-primary">
															<i class="align-middle" data-feather="users"></i>
														</div>
													</div>
												</div>
												<h1 class="mt-1 mb-3">14.212</h1>
												<div class="mb-0">
													<span class="text-success"> <i class="mdi mdi-arrow-bottom-right"></i> 5.25% </span>
													<span class="text-muted">Since last week</span>
												</div>
											</div>
										</div>
									</div>
									<div class="col-sm-6">
										<div class="card">
											<div class="card-body">
												<div class="row">
													<div class="col mt-0">
														<h5 class="card-title">Earnings</h5>
													</div>

													<div class="col-auto">
														<div class="stat text-primary">
															<i class="align-middle" data-feather="dollar-sign"></i>
														</div>
													</div>
												</div>
												<h1 class="mt-1 mb-3">$21.300</h1>
												<div class="mb-0">
													<span class="text-success"> <i class="mdi mdi-arrow-bottom-right"></i> 6.65% </span>
													<span class="text-muted">Since last week</span>
												</div>
											</div>
										</div>
										<div class="card">
											<div class="card-body">
												<div class="row">
													<div class="col mt-0">
														<h5 class="card-title">Orders</h5>
													</div>

													<div class="col-auto">
														<div class="stat text-primary">
															<i class="align-middle" data-feather="shopping-cart"></i>
														</div>
													</div>
												</div>
												<h1 class="mt-1 mb-3">64</h1>
												<div class="mb-0">
													<span class="text-danger"> <i class="mdi mdi-arrow-bottom-right"></i> -2.25% </span>
													<span class="text-muted">Since last week</span>
												</div>
											</div>
										</div>
									</div>
								</div>
							</div>
						</div>

						<div class="col-xl-6 col-xxl-7">
							<div class="card flex-fill w-100">
								<div class="card-header">
									<h5 class="card-title mb-0">MicroWave</h5>
								</div>
								<div class="card-body py-3">
									<div class="chart chart-sm">
										<canvas id="microwaveChart"></canvas>
									</div>
								</div>
							</div>
						</div>
					</div>

					<div class="row">
						<div class="col-12 col-md-6 col-xxl-3 d-flex order-2 order-xxl-3">
							<div class="card flex-fill w-100">
								<div class="card-header">

									<h5 class="card-title mb-0">HighFrequency</h5>
									<input type="hidden" id = "highFrequencyJson" value="{{.formdata.HighFrequencyJson}}">
								</div>
								<div class="card-body d-flex">
									<div class="align-self-center w-100">
										<div class="py-3">
											<div class="chart chart-xs">
												<canvas id="highFrequencyChart"></canvas>
											</div>
										</div>
									</div>
								</div>
							</div>
						</div>
						<div class="col-12 col-md-12 col-xxl-6 d-flex order-3 order-xxl-2">
							<div class="card flex-fill w-100">
								<div class="card-header">

									<h5 class="card-title mb-0">Real-Time</h5>
								</div>
								<div class="card-body px-4">
									<div id="world_map" style="height:350px;"></div>
								</div>
							</div>
						</div>
						<div class="col-12 col-md-6 col-xxl-3 d-flex order-1 order-xxl-1">
							<div class="card flex-fill">
								<div class="card-header">

									<h5 class="card-title mb-0">Calendar</h5>
								</div>
								<div class="card-body d-flex">
									<div class="align-self-center w-100">
										<div class="chart">
											<input type="text" id="datetimepicker-dashboard" style="visibility: hidden"></input>
										</div>
									</div>
								</div>
							</div>
						</div>
					</div>

					<div class="row">
						<div class="col-12 col-lg-8 col-xxl-9 d-flex">
							<div class="card flex-fill">
								<div class="card-header">

									<h5 class="card-title mb-0">Latest Projects</h5>
								</div>
								<table class="table table-hover my-0">
									<thead>
										<tr>
											<th>Name</th>
											<th class="d-none d-xl-table-cell">Start Date</th>
											<th class="d-none d-xl-table-cell">End Date</th>
											<th>Status</th>
											<th class="d-none d-md-table-cell">Assignee</th>
										</tr>
									</thead>
									<tbody>
										<tr>
											<td>Project Apollo</td>
											<td class="d-none d-xl-table-cell">01/01/2023</td>
											<td class="d-none d-xl-table-cell">31/06/2023</td>
											<td><span class="badge bg-success">Done</span></td>
											<td class="d-none d-md-table-cell">Vanessa Tucker</td>
										</tr>
										<tr>
											<td>Project Fireball</td>
											<td class="d-none d-xl-table-cell">01/01/2023</td>
											<td class="d-none d-xl-table-cell">31/06/2023</td>
											<td><span class="badge bg-danger">Cancelled</span></td>
											<td class="d-none d-md-table-cell">William Harris</td>
										</tr>
										<tr>
											<td>Project Hades</td>
											<td class="d-none d-xl-table-cell">01/01/2023</td>
											<td class="d-none d-xl-table-cell">31/06/2023</td>
											<td><span class="badge bg-success">Done</span></td>
											<td class="d-none d-md-table-cell">Sharon Lessman</td>
										</tr>
										<tr>
											<td>Project Nitro</td>
											<td class="d-none d-xl-table-cell">01/01/2023</td>
											<td class="d-none d-xl-table-cell">31/06/2023</td>
											<td><span class="badge bg-warning">In progress</span></td>
											<td class="d-none d-md-table-cell">Vanessa Tucker</td>
										</tr>
										<tr>
											<td>Project Phoenix</td>
											<td class="d-none d-xl-table-cell">01/01/2023</td>
											<td class="d-none d-xl-table-cell">31/06/2023</td>
											<td><span class="badge bg-success">Done</span></td>
											<td class="d-none d-md-table-cell">William Harris</td>
										</tr>
										<tr>
											<td>Project X</td>
											<td class="d-none d-xl-table-cell">01/01/2023</td>
											<td class="d-none d-xl-table-cell">31/06/2023</td>
											<td><span class="badge bg-success">Done</span></td>
											<td class="d-none d-md-table-cell">Sharon Lessman</td>
										</tr>
										<tr>
											<td>Project Romeo</td>
											<td class="d-none d-xl-table-cell">01/01/2023</td>
											<td class="d-none d-xl-table-cell">31/06/2023</td>
											<td><span class="badge bg-success">Done</span></td>
											<td class="d-none d-md-table-cell">Christina Mason</td>
										</tr>
										<tr>
											<td>Project Wombat</td>
											<td class="d-none d-xl-table-cell">01/01/2023</td>
											<td class="d-none d-xl-table-cell">31/06/2023</td>
											<td><span class="badge bg-warning">In progress</span></td>
											<td class="d-none d-md-table-cell">William Harris</td>
										</tr>
									</tbody>
								</table>
							</div>
						</div>
						<div class="col-12 col-lg-4 col-xxl-3 d-flex">
							<div class="card flex-fill w-100">
								<div class="card-header">

									<h5 class="card-title mb-0">Monthly Sales</h5>
								</div>
								<div class="card-body d-flex w-100">
									<div class="align-self-center chart chart-lg">
										<canvas id="chartjs-dashboard-bar"></canvas>
									</div>
								</div>
							</div>
						</div>
					</div>

				</div>
			</main>


	<script>
		document.addEventListener("DOMContentLoaded", function() {
			// Pie chart
			new Chart(document.getElementById("chartjs-dashboard-pie"), {
				type: "pie",
				data: {
					labels: ["Chrome", "Firefox", "IE"],
					datasets: [{
						data: [4306, 3801, 1689],
						backgroundColor: [
							window.theme.primary,
							window.theme.warning,
							window.theme.danger
						],
						borderWidth: 5
					}]
				},
				options: {
					responsive: !window.MSInputMethodContext,
					maintainAspectRatio: false,
					legend: {
						display: false
					},
					cutoutPercentage: 75
				}
			});
		});
	</script>
	<script>
		document.addEventListener("DOMContentLoaded", function() {
			// Bar chart
			new Chart(document.getElementById("chartjs-dashboard-bar"), {
				type: "bar",
				data: {
					labels: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
					datasets: [{
						label: "This year",
						backgroundColor: window.theme.primary,
						borderColor: window.theme.primary,
						hoverBackgroundColor: window.theme.primary,
						hoverBorderColor: window.theme.primary,
						data: [54, 67, 41, 55, 62, 45, 55, 73, 60, 76, 48, 79],
						barPercentage: .75,
						categoryPercentage: .5
					}]
				},
				options: {
					maintainAspectRatio: false,
					legend: {
						display: false
					},
					scales: {
						yAxes: [{
							gridLines: {
								display: false
							},
							stacked: false,
							ticks: {
								stepSize: 20
							}
						}],
						xAxes: [{
							stacked: false,
							gridLines: {
								color: "transparent"
							}
						}]
					}
				}
			});
		});
	</script>
	<script>
		document.addEventListener("DOMContentLoaded", function() {
			var markers = [{
					coords: [31.230391, 121.473701],
					name: "Shanghai"
				},
				{
					coords: [28.704060, 77.102493],
					name: "Delhi"
				},
				{
					coords: [6.524379, 3.379206],
					name: "Lagos"
				},
				{
					coords: [35.689487, 139.691711],
					name: "Tokyo"
				},
				{
					coords: [23.129110, 113.264381],
					name: "Guangzhou"
				},
				{
					coords: [40.7127837, -74.0059413],
					name: "New York"
				},
				{
					coords: [34.052235, -118.243683],
					name: "Los Angeles"
				},
				{
					coords: [41.878113, -87.629799],
					name: "Chicago"
				},
				{
					coords: [51.507351, -0.127758],
					name: "London"
				},
				{
					coords: [40.416775, -3.703790],
					name: "Madrid "
				}
			];
			var map = new jsVectorMap({
				map: "world",
				selector: "#world_map",
				zoomButtons: true,
				markers: markers,
				markerStyle: {
					initial: {
						r: 9,
						strokeWidth: 7,
						stokeOpacity: .4,
						fill: window.theme.primary
					},
					hover: {
						fill: window.theme.primary,
						stroke: window.theme.primary
					}
				},
				zoomOnScroll: false
			});
			window.addEventListener("resize", () => {
				map.updateSize();
			});
		});
	</script>

	{{range $js := .formdata.FooterScripts}}
	<script src="/public/js/{{$js}}" type="text/javascript" charset="utf-8"></script>
	{{end}}


</div>
</div>



{{template "footer.html" .}}
var microwaveChart;
var highFrequencyChart;

document.addEventListener("DOMContentLoaded", function() {
  try {

    var date = new Date(Date.now());
    var defaultDate = date.getUTCFullYear() + "-" + (date.getUTCMonth() + 1) + "-" + date.getUTCDate();
    document.getElementById("datetimepicker-dashboard").flatpickr({
      inline: true,
      prevArrow: "<span title=\"Previous month\">«</span>",
      nextArrow: "<span title=\"Next month\">»</span>",
      defaultDate: defaultDate,
      onChange: function(){
        var cookie = $.cookie("jwt");
        GetKvMicrowave(cookie);
        GetHighFrequency(cookie);
      }
    });

    var cookie = $.cookie("jwt");
    GetKvMicrowave(cookie);
    GetHighFrequency(cookie);

  } catch (e) {
    alert(e);
  }
});
function GetKvMicrowave(cookie) {
  var strDate = $('#datetimepicker-dashboard').val();
  var req = JSON.parse(JSON.stringify({token: cookie,selDate: strDate}));
  $.ajax({
    url:'./api/getkvMicrowave',
    type:'GET',
    contentType: 'application/json',
    daraType: 'json',
    data: req,
  })
  .done( (data) => {
    SetMChart(data);
    return;
  })
  .fail( (jqXHR, textStatus, errorThrown) => {
    alert('Ajax failed');
    console.log("jqXHR          : " + jqXHR.status);
    console.log("textStatus     : " + textStatus);
    console.log("errorThrown    : " + errorThrown.message);
    return;
  });
}
function GetHighFrequency(cookie) {
  var strDate = $('#datetimepicker-dashboard').val();
  var req = JSON.parse(JSON.stringify({token: cookie,selDate: strDate}));
  $.ajax({
    url:'./api/getHighFrequency',
    type:'GET',
    contentType: 'application/json',
    daraType: 'json',
    data: req,
  })
  .done( (data) => {
    SetFChart(data);
    return;
  })
  .fail( (jqXHR, textStatus, errorThrown) => {
    alert('Ajax failed');
    console.log("jqXHR          : " + jqXHR.status);
    console.log("textStatus     : " + textStatus);
    console.log("errorThrown    : " + errorThrown.message);
    return;
  });
}
function SetMChart(strJson) {

  try {
    var values = JSON.parse(strJson);
    const labels = [];
    const datapoints =[];
    const datapoints2 =[];
    const datapoints3 =[];
    const datapoints4 =[];
    const datapoints5 =[];
    const datapoints6 =[];
    for (var item in values) {
      labels.push(values[item].DataDate);
      datapoints.push(values[item].StopCV);
      datapoints2.push(values[item].WaterLevel);
      datapoints3.push(values[item].FarInfraredHeater);
      datapoints4.push(values[item].MwOutput);
      datapoints5.push(values[item].MwTotalOutput);
      datapoints6.push(values[item].InRoomPressure);
    }

    const data = {
      labels: labels,
      datasets: [
        {
          label: 'StopCV',
          data: datapoints,
          tension: 0.4,
          fill: true,
          backgroundColor: settings.CHARTBG_COLORS.green,
          borderColor: settings.CHART_COLORS.green,
          borderWidth:2,
          pointStyle: 'circle',
          pointRadius: 10,
          pointHoverRadius: 15
        }, {
          label: 'WaterLevel',
          data: datapoints2,
          tension: 0.4,
          fill: true,
          backgroundColor: settings.CHARTBG_COLORS.red,
          borderColor: settings.CHART_COLORS.red,
          borderWidth:2,
          pointStyle: 'circle',
          pointRadius: 10,
          pointHoverRadius: 15
        }, {
          label: 'FarInfraredHeater',
          data: datapoints3,
          tension: 0.4,
          fill: false,
          backgroundColor: settings.CHARTBG_COLORS.blue,
          borderColor: settings.CHART_COLORS.blue,
          borderWidth:2,
          pointStyle: 'circle',
          pointRadius: 10,
          pointHoverRadius: 15
        }, {
          label: 'MwOutput',
          data: datapoints4,
          tension: 0.4,
          fill: false,
          backgroundColor: settings.CHARTBG_COLORS.purple,
          borderColor: settings.CHART_COLORS.purple,
          borderWidth:2,
          pointStyle: 'circle',
          pointRadius: 10,
          pointHoverRadius: 15
        }
      ]
    };
    var ctx = document.getElementById('microwaveChart');
    if (microwaveChart) {
      microwaveChart.destroy();
    }
    microwaveChart = new Chart(ctx, {
      type: 'line',
      data: data,
      options: {
        responsive: true,
        title: {
          display: true,
          fontSize: 18,
          text: "MicroWave"
        },
        legend:{
          display: false,
        }
      },
      });

  } catch (e) {
    alert(e);
  }
}

function SetFChart(strJson) {
  try {
    var values = JSON.parse(strJson);
    const labels = [];
    const datapoints =[];
    const datapoints2 =[];
    const datapoints3 =[];
    const datapoints4 =[];
    const datapoints5 =[];
    const datapoints6 =[];
    const datapoints7 =[];
    for (var item in values) {
      labels.push(values[item].DataDate);
      datapoints.push(values[item].CurrentNow);
      datapoints2.push(values[item].TuningNow);
      datapoints3.push(values[item].WeldingTime);
      datapoints4.push(values[item].CoolingTime);
      datapoints5.push(values[item].WeldingTime1);
      datapoints6.push(values[item].CoolingTime1);
      datapoints7.push(values[item].WeldingTime2);
    }

    const data = {
      labels: labels,
      datasets: [
        {
          label: 'CurrentNow',
          data: datapoints,
          yAxisID: 'y-axis-1',
          tension: 0.4,
          fill: false,
          backgroundColor: settings.CHARTBG_COLORS.green,
          borderColor: settings.CHART_COLORS.green,
          borderWidth:2,
          pointStyle: 'circle',
          pointRadius: 10,
          pointHoverRadius: 15
        }, {
          label: 'TuningNow',
          data: datapoints2,
          yAxisID: 'y-axis-2',
          tension: 0.4,
          fill: false,
          backgroundColor: settings.CHARTBG_COLORS.red,
          borderColor: settings.CHART_COLORS.red,
          borderWidth:2,
          pointStyle: 'circle',
          pointRadius: 10,
          pointHoverRadius: 15
        }, {
          label: 'WeldingTime',
          data: datapoints3,
          yAxisID: 'y-axis-1',
          tension: 0.4,
          fill: false,
          backgroundColor: settings.CHARTBG_COLORS.blue,
          borderColor: settings.CHART_COLORS.blue,
          borderWidth:2,
          pointStyle: 'circle',
          pointRadius: 10,
          pointHoverRadius: 15
        }, {
          label: 'CoolingTime',
          data: datapoints4,
          yAxisID: 'y-axis-1',
          tension: 0.4,
          fill: false,
          backgroundColor: settings.CHARTBG_COLORS.purple,
          borderColor: settings.CHART_COLORS.purple,
          borderWidth:2,
          pointStyle: 'circle',
          pointRadius: 10,
          pointHoverRadius: 15
        }, {
          label: 'WeldingTime1',
          data: datapoints5,
          yAxisID: 'y-axis-1',
          tension: 0.4,
          fill: false,
          backgroundColor: settings.CHARTBG_COLORS.grey,
          borderColor: settings.CHART_COLORS.grey,
          borderWidth:2,
          pointStyle: 'circle',
          pointRadius: 10,
          pointHoverRadius: 15
        }, {
          label: 'CoolingTime1',
          data: datapoints6,
          yAxisID: 'y-axis-1',
          tension: 0.4,
          fill: false,
          backgroundColor: settings.CHARTBG_COLORS.blue,
          borderColor: settings.CHART_COLORS.blue,
          borderWidth:2,
          pointStyle: 'circle',
          pointRadius: 10,
          pointHoverRadius: 15
        }, {
          label: 'WeldingTime2',
          data: datapoints7,
          yAxisID: 'y-axis-2',
          tension: 0.4,
          fill: false,
          backgroundColor: settings.CHARTBG_COLORS.yellow,
          borderColor: settings.CHART_COLORS.yellow,
          borderWidth:2,
          pointStyle: 'circle',
          pointRadius: 10,
          pointHoverRadius: 15
        }
      ]
    };
    var ctx = document.getElementById('highFrequencyChart');
    if (highFrequencyChart){
      highFrequencyChart.destroy();
    }
    highFrequencyChart = new Chart(ctx, {
      type: 'line',
      data: data,
      options: {
        responsive: true,
        title: {
          display: true,
          fontSize: 18,
          text: "HighFrequency"
        },
        legend:{
          display: false,
        }
      },
      scales: {
          yAxes: [{
              id: 'y-axis-1',
              type: 'linear',
              position: 'left',
              ticks: {
                  min: 0,
                  stepSize: 1,
                  callback: function(val){
                      return val.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
                  }
              },
              gridLines: {
                  display: false,
              }
          }, {
              id: 'y-axis-2',
              type: 'linear',
              position: 'right',
              ticks: {
                  min: 0,
                  stepSize: 10,
                  callback: function(val){
                      return val.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
                  }
              },
              gridLines: {
                  zeroLineColor: '#000',
                  drawBorder: false,
              }
          }]
        }
      });

  } catch (e) {
    alert(e);
  }
}

const settings = {
  MONTHS: [
    'January',
    'February',
    'March',
    'April',
    'May',
    'June',
    'July',
    'August',
    'September',
    'October',
    'November',
    'December'
  ],
  COLORS: [
    '#4dc9f6',
    '#f67019',
    '#f53794',
    '#537bc4',
    '#acc236',
    '#166a8f',
    '#00a950',
    '#58595b',
    '#8549ba'
  ],
  CHART_COLORS: {
    red: 'rgb(255, 99, 132)',
    orange: 'rgb(255, 159, 64)',
    yellow: 'rgb(255, 205, 86)',
    green: 'rgb(75, 192, 192)',
    blue: 'rgb(54, 162, 235)',
    purple: 'rgb(153, 102, 255)',
    grey: 'rgb(201, 203, 207)'
  },
  CHARTBG_COLORS: {
    red: 'rgba(255, 99, 132,0.3)',
    orange: 'rgba(255, 159, 64,0.3)',
    yellow: 'rgba(255, 205, 86,0.3)',
    green: 'rgba(75, 192, 192,0.3)',
    blue: 'rgba(54, 162, 235,0.3)',
    purple: 'rgba(153, 102, 255,0.3)',
    grey: 'rgba(201, 203, 207,0.3)'
  }
};