diff --git a/assets/admin.js b/assets/admin.js index 3972e8e..8d7f198 100644 --- a/assets/admin.js +++ b/assets/admin.js @@ -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( { diff --git a/controller/repos_c.go b/controller/repos_c.go index 4760f46..53fd024 100644 --- a/controller/repos_c.go +++ b/controller/repos_c.go @@ -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, + }) } diff --git a/go.mod b/go.mod index 6d50f44..a5f5a3b 100644 --- a/go.mod +++ b/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 ) diff --git a/go.sum b/go.sum index 9b7949b..9d13028 100644 --- a/go.sum +++ b/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= diff --git a/model/gitee/repository_m.go b/model/gitee/repository_m.go index e63b90d..086a144 100644 --- a/model/gitee/repository_m.go +++ b/model/gitee/repository_m.go @@ -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 +// } diff --git a/model/gitee/user_m.go b/model/gitee/user_m.go index 82b26fa..c8ef739 100644 --- a/model/gitee/user_m.go +++ b/model/gitee/user_m.go @@ -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 +// } diff --git a/repostats.go b/repostats.go index 7b74e37..bee8662 100644 --- a/repostats.go +++ b/repostats.go @@ -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) diff --git a/storage/base_db.go b/storage/base_db.go index 15dc9fc..9c0ac22 100644 --- a/storage/base_db.go +++ b/storage/base_db.go @@ -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 { diff --git a/storage/gitee/issue_s.go b/storage/gitee/issue_s.go index acea1e0..5ea3855 100644 --- a/storage/gitee/issue_s.go +++ b/storage/gitee/issue_s.go @@ -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, diff --git a/storage/gitee/pullrequest_s.go b/storage/gitee/pullrequest_s.go index 5799143..e496088 100644 --- a/storage/gitee/pullrequest_s.go +++ b/storage/gitee/pullrequest_s.go @@ -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", diff --git a/storage/gitee/repository_s.go b/storage/gitee/repository_s.go index 0e16037..178d19b 100644 --- a/storage/gitee/repository_s.go +++ b/storage/gitee/repository_s.go @@ -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) +} diff --git a/templates/header.html b/templates/header.html index 4cc7ab5..6c089c8 100644 --- a/templates/header.html +++ b/templates/header.html @@ -18,4 +18,5 @@
+{{if .error}}{{end}} {{end -}} \ No newline at end of file diff --git a/templates/repos.html b/templates/repos.html new file mode 100644 index 0000000..70802e1 --- /dev/null +++ b/templates/repos.html @@ -0,0 +1,64 @@ +{{define "repos.html" -}} +{{template "header.html" .}} +{{template "admin-left-menu.html" .}} +
+
+

代码仓库列表

+
+
+ +
+

当前共计 {{.total_item}} 个代码仓库,每页显示 {{.page_size}} 条数据

+
+ + + + + + + + + + + + + + + + + {{range $i,$r := .repos}} + + + + + + + + + + + + + + {{end}} + + + {{if .total_item}} + + + + {{end}} + +
序号仓库ID仓库名Star数Fork数Watch数开放协议创建时间更新时间Push时间操作
{{add $i 1}}{{$r.ID}}{{$r.HumanName}}{{$r.StargazersCount}}{{$r.ForksCount}}{{$r.WatchersCount}}{{$r.License}}{{$r.CreatedAt | date "2006-01-02 15:04:05"}}{{$r.UpdatedAt | date "2006-01-02 15:04:05"}}{{$r.PushedAt | date "2006-01-02 15:04:05"}}hello | world
+ +
+
+
+
+
+{{template "footer.html" .}} +{{end -}} \ No newline at end of file