前回、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)'
}
};