完成分页显示代码仓库列表
This commit is contained in:
parent
9cc66a05f4
commit
80143f8309
|
@ -67,6 +67,27 @@ $(document).ready(function() {
|
|||
});
|
||||
});
|
||||
|
||||
function successToast(message) {
|
||||
$('body').toast({
|
||||
class: 'success',
|
||||
displayTime: 2500,
|
||||
message: message,
|
||||
showIcon:'exclamation circle',
|
||||
showProgress: 'bottom',
|
||||
onHidden: function() {location.reload()}
|
||||
});
|
||||
}
|
||||
|
||||
function errorToast(message) {
|
||||
$('body').toast({
|
||||
class: 'error',
|
||||
displayTime: 2500,
|
||||
message: message,
|
||||
showIcon:'exclamation circle',
|
||||
showProgress: 'bottom'
|
||||
});
|
||||
}
|
||||
|
||||
function GetGiteeToken(form) {
|
||||
authForm = $('#form-gitee-authorize');
|
||||
var data = JSON.stringify( {
|
||||
|
|
|
@ -8,8 +8,52 @@
|
|||
|
||||
package controller
|
||||
|
||||
import "github.com/gin-gonic/gin"
|
||||
import (
|
||||
"log"
|
||||
"net/http"
|
||||
"repostats/storage"
|
||||
gitee_storage "repostats/storage/gitee"
|
||||
"strconv"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func ReposPage(ctx *gin.Context) {
|
||||
|
||||
strPage := ctx.DefaultQuery("page", strconv.Itoa(storage.DEFAULT_PAGE_NUMBER))
|
||||
strSize := ctx.DefaultQuery("size", strconv.Itoa(storage.DEFAULT_PAGE_SIZE))
|
||||
|
||||
page, err := strconv.Atoi(strPage)
|
||||
if err != nil || page < storage.DEFAULT_PAGE_NUMBER {
|
||||
page = storage.DEFAULT_PAGE_NUMBER
|
||||
}
|
||||
|
||||
size, err := strconv.Atoi(strSize)
|
||||
if err != nil || size < storage.DEFAULT_PAGE_SIZE || size > storage.DEFAULT_MAX_PAGE_SIZE {
|
||||
size = storage.DEFAULT_PAGE_SIZE
|
||||
}
|
||||
|
||||
count, err1 := gitee_storage.FindTotalReposCount()
|
||||
repos, err2 := gitee_storage.FindPagedRepos(page, size)
|
||||
|
||||
if err1 != nil || err2 != nil {
|
||||
log.Printf("error1 %s \t error2 %s", err1, err2)
|
||||
ctx.HTML(http.StatusOK, "repos.html", gin.H{
|
||||
"title": "代码仓库列表 - RepoStats",
|
||||
"current_url": ctx.Request.URL.Path,
|
||||
"error": "内部错误,请联系管理员",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
ctx.HTML(http.StatusOK, "repos.html", gin.H{
|
||||
"title": "代码仓库列表 - RepoStats",
|
||||
"current_url": ctx.Request.URL.Path,
|
||||
"repos": repos,
|
||||
"total_item": count,
|
||||
"current_page": page,
|
||||
"page_size": size,
|
||||
"first_page": page == 1,
|
||||
"last_page": page >= (count/size)+1,
|
||||
})
|
||||
}
|
||||
|
|
15
go.mod
15
go.mod
|
@ -3,9 +3,16 @@ module repostats
|
|||
go 1.16
|
||||
|
||||
require (
|
||||
github.com/Masterminds/goutils v1.1.1 // indirect
|
||||
github.com/Masterminds/semver v1.5.0 // indirect
|
||||
github.com/Masterminds/sprig v2.22.0+incompatible // indirect
|
||||
github.com/gin-gonic/gin v1.7.7
|
||||
github.com/go-resty/resty/v2 v2.7.0
|
||||
github.com/jmoiron/sqlx v1.3.4
|
||||
github.com/lib/pq v1.10.5
|
||||
gopkg.in/ini.v1 v1.66.4
|
||||
github.com/go-resty/resty/v2 v2.7.0
|
||||
github.com/google/uuid v1.3.0 // indirect
|
||||
github.com/huandu/xstrings v1.3.2 // indirect
|
||||
github.com/imdario/mergo v0.3.12 // indirect
|
||||
github.com/jmoiron/sqlx v1.3.4
|
||||
github.com/lib/pq v1.10.5
|
||||
github.com/mitchellh/copystructure v1.2.0 // indirect
|
||||
gopkg.in/ini.v1 v1.66.4
|
||||
)
|
||||
|
|
21
go.sum
21
go.sum
|
@ -1,3 +1,9 @@
|
|||
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
|
||||
github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
|
||||
github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww=
|
||||
github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
|
||||
github.com/Masterminds/sprig v2.22.0+incompatible h1:z4yfnGrZ7netVz+0EDJ0Wi+5VZCSYp4Z0m2dk6cEM60=
|
||||
github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
||||
|
@ -14,11 +20,20 @@ github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn
|
|||
github.com/go-resty/resty/v2 v2.7.0 h1:me+K9p3uhSmXtrBZ4k9jcEAfJmuC8IivWHwaLZwPrFY=
|
||||
github.com/go-resty/resty/v2 v2.7.0/go.mod h1:9PWDzw47qPphMRFfhsyk0NnSgvluHcljSMVIq3w7q0I=
|
||||
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||
github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I=
|
||||
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/huandu/xstrings v1.3.2 h1:L18LIDzqlW6xN2rEkpdV8+oL/IXWJ1APd+vsdYy4Wdw=
|
||||
github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
|
||||
github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
|
||||
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
||||
github.com/jmoiron/sqlx v1.3.4 h1:wv+0IJZfL5z0uZoUjlpKgHkgaFSYD+r9CfrXjEXsO7w=
|
||||
github.com/jmoiron/sqlx v1.3.4/go.mod h1:2BljVx/86SuTyjE+aPYlHCTNvZrnJXghYGpNiXLBMCQ=
|
||||
github.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g=
|
||||
github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ=
|
||||
github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns=
|
||||
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
|
||||
|
@ -29,6 +44,10 @@ github.com/lib/pq v1.10.5/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
|||
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
||||
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
|
||||
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
|
||||
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
|
||||
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg=
|
||||
|
@ -65,3 +84,5 @@ gopkg.in/ini.v1 v1.66.4/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
|||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
package gitee
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"reflect"
|
||||
"time"
|
||||
)
|
||||
|
@ -41,16 +40,16 @@ func (r Repository) isNilOrEmpty() bool {
|
|||
return reflect.DeepEqual(r, Repository{})
|
||||
}
|
||||
|
||||
func (r *Repository) Scan(src interface{}) error {
|
||||
var repoID int
|
||||
switch src.(type) {
|
||||
case int64:
|
||||
repoID = int(src.(int64))
|
||||
case int32:
|
||||
repoID = int(src.(int32))
|
||||
default:
|
||||
return errors.New("can not find any valid user")
|
||||
}
|
||||
*r = Repository{ID: repoID}
|
||||
return nil
|
||||
}
|
||||
// func (r *Repository) Scan(src interface{}) error {
|
||||
// var repoID int
|
||||
// switch src.(type) {
|
||||
// case int64:
|
||||
// repoID = int(src.(int64))
|
||||
// case int32:
|
||||
// repoID = int(src.(int32))
|
||||
// default:
|
||||
// return errors.New("can not find any valid user")
|
||||
// }
|
||||
// *r = Repository{ID: repoID}
|
||||
// return nil
|
||||
// }
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
package gitee
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"reflect"
|
||||
"time"
|
||||
)
|
||||
|
@ -30,16 +29,16 @@ func (u User) isNilOrEmpty() bool {
|
|||
return reflect.DeepEqual(u, User{})
|
||||
}
|
||||
|
||||
func (r *User) Scan(src interface{}) error {
|
||||
var userId int
|
||||
switch src.(type) {
|
||||
case int64:
|
||||
userId = int(src.(int64))
|
||||
case int32:
|
||||
userId = int(src.(int32))
|
||||
default:
|
||||
return errors.New("can not find any valid user")
|
||||
}
|
||||
*r = User{ID: userId}
|
||||
return nil
|
||||
}
|
||||
// func (r *User) Scan(src interface{}) error {
|
||||
// var userId int
|
||||
// switch src.(type) {
|
||||
// case int64:
|
||||
// userId = int(src.(int64))
|
||||
// case int32:
|
||||
// userId = int(src.(int32))
|
||||
// default:
|
||||
// return errors.New("can not find any valid user")
|
||||
// }
|
||||
// *r = User{ID: userId}
|
||||
// return nil
|
||||
// }
|
||||
|
|
|
@ -21,6 +21,7 @@ import (
|
|||
"repostats/storage"
|
||||
"repostats/utils"
|
||||
|
||||
"github.com/Masterminds/sprig"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
|
@ -66,7 +67,7 @@ func initRouter(router *gin.Engine) {
|
|||
|
||||
router.StaticFS("/assets", http.FS(sub))
|
||||
|
||||
tmpl, err := template.New("").ParseFS(FS, "templates/*.html")
|
||||
tmpl, err := template.New("").Funcs(sprig.FuncMap()).ParseFS(FS, "templates/*.html")
|
||||
utils.ExitOnError(err)
|
||||
|
||||
router.GET("/login", controller.Login)
|
||||
|
|
|
@ -17,6 +17,12 @@ import (
|
|||
_ "github.com/lib/pq"
|
||||
)
|
||||
|
||||
const (
|
||||
DEFAULT_PAGE_NUMBER = 1
|
||||
DEFAULT_PAGE_SIZE = 15
|
||||
DEFAULT_MAX_PAGE_SIZE = 50
|
||||
)
|
||||
|
||||
var dbService = &DatabaseService{}
|
||||
|
||||
type DatabaseService struct {
|
||||
|
|
|
@ -13,7 +13,7 @@ import (
|
|||
"repostats/storage"
|
||||
)
|
||||
|
||||
var issueQueryPrefix = `SELECT iss.repo_id AS "repository", iss.user_id AS "user", iss.* FROM gitee.issues iss `
|
||||
var issueQueryPrefix = `SELECT iss.repo_id AS "repository.id", iss.user_id AS "user.id", iss.* FROM gitee.issues iss `
|
||||
|
||||
func BulkSaveIssues(iss []gitee_model.Issue) error {
|
||||
query := `INSERT INTO gitee.issues (id, html_url, "number", state, title, user_id, repo_id, finished_at, created_at,
|
||||
|
|
|
@ -13,8 +13,8 @@ import (
|
|||
"repostats/storage"
|
||||
)
|
||||
|
||||
var prQueryPrefix = `SELECT pr.user_id AS "user", pr.head_label AS "head.label", pr.head_ref AS "head.ref", pr.head_sha AS "head.sha",
|
||||
pr.head_user_id AS "head.user", pr.head_repo_id AS "head.repo",pr.* FROM gitee.pull_requests pr `
|
||||
var prQueryPrefix = `SELECT pr.user_id AS "user.id", pr.head_label AS "head.label", pr.head_ref AS "head.ref", pr.head_sha AS "head.sha",
|
||||
pr.head_user_id AS "head.user.id", pr.head_repo_id AS "head.repo.id",pr.* FROM gitee.pull_requests pr `
|
||||
|
||||
func BulkSavePullRequests(prs []gitee_mode.PullRequest) error {
|
||||
query := `INSERT INTO gitee.pull_requests (id, repo_id, user_id, html_url, diff_url, patch_url, "number",
|
||||
|
|
|
@ -13,7 +13,7 @@ import (
|
|||
"repostats/storage"
|
||||
)
|
||||
|
||||
var repoQueryPrefix = `SELECT r.owner_id AS "owner", r.assigner_id AS "assigner",r.* FROM gitee.repos `
|
||||
var repoQueryPrefix = `SELECT r.owner_id AS "owner.id", r.assigner_id AS "assigner.id", r.* FROM gitee.repos r `
|
||||
|
||||
func BulkSaveRepos(repos []gitee_model.Repository) error {
|
||||
query := `INSERT INTO gitee.repos (id, full_name, human_name, path,name, url, owner_id,assigner_id, description,
|
||||
|
@ -35,6 +35,16 @@ func FindRepos() ([]gitee_model.Repository, error) {
|
|||
return repos, err
|
||||
}
|
||||
|
||||
func FindPagedRepos(page, size int) ([]gitee_model.Repository, error) {
|
||||
if page < 1 {
|
||||
page = 1
|
||||
}
|
||||
repos := []gitee_model.Repository{}
|
||||
query := repoQueryPrefix + ` ORDER BY r.id DESC LIMIT $1 OFFSET $2`
|
||||
offset := (page - 1) * size
|
||||
return repos, storage.DbSelect(query, &repos, size, offset)
|
||||
}
|
||||
|
||||
func FindRepoByID(repoID int) (gitee_model.Repository, error) {
|
||||
found := gitee_model.Repository{}
|
||||
query := repoQueryPrefix + ` WHERE r.id = $1`
|
||||
|
@ -46,3 +56,9 @@ func DeleteRepo(repoID int) error {
|
|||
query := `DELETE FROM gitee.repos WHERE id = $1`
|
||||
return storage.DbNamedExec(query, repoID)
|
||||
}
|
||||
|
||||
func FindTotalReposCount() (int, error) {
|
||||
var count int
|
||||
query := `SELECT count(r.id) FROM gitee.repos r`
|
||||
return count, storage.DbGet(query, &count)
|
||||
}
|
||||
|
|
|
@ -18,4 +18,5 @@
|
|||
</head>
|
||||
<body>
|
||||
<div class="push">
|
||||
{{if .error}}<script>errorToast('{{.error}}')</script>{{end}}
|
||||
{{end -}}
|
|
@ -0,0 +1,64 @@
|
|||
{{define "repos.html" -}}
|
||||
{{template "header.html" .}}
|
||||
{{template "admin-left-menu.html" .}}
|
||||
<div id="admin-right-content">
|
||||
<div class="ui basic segment">
|
||||
<h3 class="ui header">代码仓库列表</h3>
|
||||
<div class="ui grid stackable padded">
|
||||
<div class="column">
|
||||
<table class="ui celled striped small table">
|
||||
<div class="ui positive message">
|
||||
<p>当前共计 {{.total_item}} 个代码仓库,每页显示 {{.page_size}} 条数据</p>
|
||||
</div>
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="center aligned collapsing">序号</th>
|
||||
<th class="center aligned collapsing">仓库ID</th>
|
||||
<th class="center aligned collapsing">仓库名</th>
|
||||
<th class="center aligned collapsing">Star数</th>
|
||||
<th class="center aligned collapsing">Fork数</th>
|
||||
<th class="center aligned collapsing">Watch数</th>
|
||||
<th class="center aligned collapsing">开放协议</th>
|
||||
<th class="center aligned">创建时间</th>
|
||||
<th class="center aligned">更新时间</th>
|
||||
<th class="center aligned">Push时间</th>
|
||||
<th class="center aligned">操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{range $i,$r := .repos}}
|
||||
<tr>
|
||||
<td class="center aligned collapsing">{{add $i 1}}</td>
|
||||
<td class="center aligned collapsing">{{$r.ID}}</td>
|
||||
<td><a href="{{$r.HTMLURL}}" target="_blank">{{$r.HumanName}}</a></td>
|
||||
<td class="center aligned collapsing">{{$r.StargazersCount}}</td>
|
||||
<td class="center aligned collapsing">{{$r.ForksCount}}</td>
|
||||
<td class="center aligned collapsing">{{$r.WatchersCount}}</td>
|
||||
<td class="center aligned collapsing">{{$r.License}}</td>
|
||||
<td class="center aligned collapsing">{{$r.CreatedAt | date "2006-01-02 15:04:05"}}</td>
|
||||
<td class="center aligned collapsing">{{$r.UpdatedAt | date "2006-01-02 15:04:05"}}</td>
|
||||
<td class="center aligned collapsing">{{$r.PushedAt | date "2006-01-02 15:04:05"}}</td>
|
||||
<td>hello | world</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</tbody>
|
||||
<tfoot>
|
||||
{{if .total_item}}
|
||||
<tr>
|
||||
<td colspan="11" class="center aligned">
|
||||
<div class="ui pagination menu">
|
||||
<a class="{{if .first_page}}disabled{{end}} item" target="_self" href="{{.current_url}}?page={{sub .current_page 1}}&size={{.page_size}}"><<</a>
|
||||
<div class="active item">{{.current_page}}</div>
|
||||
<a class="{{if .last_page}}disabled{{end}} item" target="_self" href="{{.current_url}}?page={{add .current_page 1}}&size={{.page_size}}">>></a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
</div><!--end fo grid-->
|
||||
</div> <!--end of basic segment-->
|
||||
</div><!--end of admin-right-content-->
|
||||
{{template "footer.html" .}}
|
||||
{{end -}}
|
Loading…
Reference in New Issue