完成 PR 列表
This commit is contained in:
parent
0f203d4f47
commit
3fcf982bc6
|
|
@ -193,4 +193,24 @@ function deleteCommit(sha) {
|
|||
});
|
||||
}//end of if
|
||||
});
|
||||
}
|
||||
|
||||
function deletePR(prID) {
|
||||
$('body').modal('confirm','删除 PullRequest','确认删除 <b>'+prID+'</b> 的 PullRequest 记录吗?', function(choice){
|
||||
if(choice) {
|
||||
$.ajax({
|
||||
type:"POST",
|
||||
url: "/admin/prs/"+prID+"/delete",
|
||||
data: {
|
||||
"type": "gitee"
|
||||
},
|
||||
success: function() {
|
||||
successToast('操作成功')
|
||||
},
|
||||
error: function(e) {
|
||||
errorToast($.parseJSON(e.responseText).message)
|
||||
}
|
||||
});
|
||||
}//end of if
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,143 @@
|
|||
// Copyright (c) [2022] [巴拉迪维 BaratSemet]
|
||||
// [ohUrlShortener] is licensed under Mulan PSL v2.
|
||||
// You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
// You may obtain a copy of Mulan PSL v2 at:
|
||||
// http://license.coscl.org.cn/MulanPSL2
|
||||
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
// See the Mulan PSL v2 for more details.
|
||||
|
||||
package controller
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net/http"
|
||||
gitee_model "repostats/model/gitee"
|
||||
"repostats/storage"
|
||||
gitee_storage "repostats/storage/gitee"
|
||||
"repostats/utils"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// 转向到 Pull Request 列表页面
|
||||
//
|
||||
func PRsPage(ctx *gin.Context) {
|
||||
|
||||
strPage := ctx.DefaultQuery("page", strconv.Itoa(storage.DEFAULT_PAGE_NUMBER))
|
||||
strSize := ctx.DefaultQuery("size", strconv.Itoa(storage.DEFAULT_PAGE_SIZE))
|
||||
strPRID := ctx.DefaultQuery("id", "")
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
prID, err := strconv.Atoi(strPRID)
|
||||
if err != nil {
|
||||
prID = 0
|
||||
}
|
||||
|
||||
var count int
|
||||
var prs []gitee_model.PullRequest
|
||||
if prID <= 0 {
|
||||
count, err = gitee_storage.FindTotalPRsCount()
|
||||
prs, err = gitee_storage.FindPagedPRs(page, size)
|
||||
|
||||
if err != nil {
|
||||
log.Printf("error %s", err)
|
||||
ctx.HTML(http.StatusOK, "prs.html", gin.H{
|
||||
"title": "Pull Request - RepoStats",
|
||||
"current_url": ctx.Request.URL.Path,
|
||||
"error": "内部错误,请联系管理员",
|
||||
})
|
||||
return
|
||||
}
|
||||
} else {
|
||||
pr, errr := gitee_storage.FindPRByID(prID)
|
||||
if errr != nil {
|
||||
log.Printf("error %s", err)
|
||||
ctx.HTML(http.StatusOK, "prs.html", gin.H{
|
||||
"title": "Pull Request - RepoStats",
|
||||
"current_url": ctx.Request.URL.Path,
|
||||
"error": "内部错误,请联系管理员",
|
||||
})
|
||||
return
|
||||
}
|
||||
count = 1
|
||||
prs = append(prs, pr)
|
||||
}
|
||||
|
||||
ctx.HTML(http.StatusOK, "prs.html", gin.H{
|
||||
"title": "Pull Request - RepoStats",
|
||||
"current_url": ctx.Request.URL.Path,
|
||||
"prs": prs,
|
||||
"total_item": count,
|
||||
"current_page": page,
|
||||
"page_size": size,
|
||||
"first_page": page == 1,
|
||||
"last_page": page >= (count/size)+1,
|
||||
})
|
||||
}
|
||||
|
||||
// 删除 commit
|
||||
//
|
||||
func PRDelete(ctx *gin.Context) {
|
||||
strID := ctx.Param("id")
|
||||
strType := ctx.DefaultPostForm("type", "gitee")
|
||||
|
||||
if utils.EmptyString(strID) {
|
||||
ctx.JSON(http.StatusBadRequest, gin.H{
|
||||
"message": "PR ID 参数非法",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if !strings.EqualFold(strings.ToLower(strType), "gitee") {
|
||||
ctx.JSON(http.StatusBadRequest, gin.H{
|
||||
"message": "type 参数非法",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
prID, err := strconv.Atoi(strID)
|
||||
if err != nil {
|
||||
ctx.JSON(http.StatusBadRequest, gin.H{
|
||||
"message": "PR ID 参数非法",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
found, err := gitee_storage.FindPRByID(prID)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
ctx.JSON(http.StatusBadRequest, gin.H{
|
||||
"message": "内部错误,请联系管理员! ",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if found.IsNilOrEmpty() {
|
||||
ctx.JSON(http.StatusBadRequest, gin.H{
|
||||
"message": "找不到指定的 PullRequest, ID=" + strID,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
err = gitee_storage.DeletePR(prID)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
ctx.JSON(http.StatusBadRequest, gin.H{
|
||||
"message": "内部错误,请联系管理员! ",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
ctx.JSON(http.StatusOK, nil)
|
||||
}
|
||||
|
|
@ -38,6 +38,6 @@ type PullRequest struct {
|
|||
} `json:"head" db:"head"`
|
||||
}
|
||||
|
||||
func (pr PullRequest) isNilOrEmpty() bool {
|
||||
func (pr PullRequest) IsNilOrEmpty() bool {
|
||||
return reflect.DeepEqual(pr, PullRequest{})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -80,13 +80,16 @@ func initRouter(router *gin.Engine) {
|
|||
admin.GET("/schedule", controller.SchedulePage)
|
||||
admin.GET("/gitee", controller.GiteePage)
|
||||
|
||||
admin.GET("/commits", controller.CommitsPage)
|
||||
admin.POST("/commits/:sha/delete", controller.CommitDelete)
|
||||
|
||||
admin.GET("/repos", controller.ReposPage)
|
||||
admin.PUT("/repos/:repoID/change_state", controller.RepoStateChange)
|
||||
admin.POST("/repos/:repoID/delete", controller.RepoDelete)
|
||||
|
||||
admin.GET("/commits", controller.CommitsPage)
|
||||
admin.POST("/commits/:sha/delete", controller.CommitDelete)
|
||||
|
||||
admin.GET("/prs", controller.PRsPage)
|
||||
admin.POST("/prs/:id/delete", controller.PRDelete)
|
||||
|
||||
admin.GET("/grafana", controller.GrafanaPage)
|
||||
|
||||
public := router.Group("/admin") //Same url path with /admin WITHOUT auth handler
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ package gitee
|
|||
|
||||
import (
|
||||
gitee_mode "repostats/model/gitee"
|
||||
gitee_model "repostats/model/gitee"
|
||||
"repostats/storage"
|
||||
)
|
||||
|
||||
|
|
@ -29,6 +30,22 @@ func BulkSavePullRequests(prs []gitee_mode.PullRequest) error {
|
|||
return storage.DbNamedExec(query, prs)
|
||||
}
|
||||
|
||||
func FindTotalPRsCount() (int, error) {
|
||||
var count int
|
||||
query := `SELECT count(pr.id) FROM gitee.pull_requests pr`
|
||||
return count, storage.DbGet(query, &count)
|
||||
}
|
||||
|
||||
func FindPagedPRs(page, size int) ([]gitee_mode.PullRequest, error) {
|
||||
if page < 1 {
|
||||
page = 1
|
||||
}
|
||||
prs := []gitee_model.PullRequest{}
|
||||
query := prQueryPrefix + ` ORDER BY pr.created_at DESC LIMIT $1 OFFSET $2`
|
||||
offset := (page - 1) * size
|
||||
return prs, storage.DbSelect(query, &prs, size, offset)
|
||||
}
|
||||
|
||||
func FindPRByID(prID int) (gitee_mode.PullRequest, error) {
|
||||
found := gitee_mode.PullRequest{}
|
||||
err := storage.DbGet(prQueryPrefix+` WHERE pr.id = $1`, &found, prID)
|
||||
|
|
@ -37,13 +54,13 @@ func FindPRByID(prID int) (gitee_mode.PullRequest, error) {
|
|||
|
||||
func FindPRs() ([]gitee_mode.PullRequest, error) {
|
||||
found := []gitee_mode.PullRequest{}
|
||||
err := storage.DbSelect(prQueryPrefix+` ORDER BY pr.updated_at DESC`, &found)
|
||||
err := storage.DbSelect(prQueryPrefix+` ORDER BY pr.created_at DESC`, &found)
|
||||
return found, err
|
||||
}
|
||||
|
||||
func FindPRsByRepoID(repoID int) ([]gitee_mode.PullRequest, error) {
|
||||
found := []gitee_mode.PullRequest{}
|
||||
err := storage.DbSelect(prQueryPrefix+` WHERE pr.repo_id = $1 ORDER BY pr.updated_at DESC`, &found, repoID)
|
||||
err := storage.DbSelect(prQueryPrefix+` WHERE pr.repo_id = $1 ORDER BY pr.created_at DESC`, &found, repoID)
|
||||
return found, err
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,70 @@
|
|||
{{define "prs.html" -}}
|
||||
{{template "header.html" .}}
|
||||
{{template "admin-left-menu.html" .}}
|
||||
<div id="admin-right-content">
|
||||
<div class="ui basic segment">
|
||||
<h3 class="ui header">Pull Request 列表</h3>
|
||||
<div class="ui grid stackable padded">
|
||||
<div class="column" style="max-width: 100%; overflow-x: auto;">
|
||||
<table class="ui celled striped small table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th colspan="11">
|
||||
<p>共计 <span style="color: red;">{{.total_item}}</span> 条记录,当前 <span style="color: red;">{{.current_page}} </span> / <span style="color: red;">{{add (div .total_item .page_size) 1}}</span> 页</p>
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="center aligned collapsing">序号</th>
|
||||
<th class="center aligned collapsing">PR编号</th>
|
||||
<th class="center aligned collapsing">仓库编号</th>
|
||||
<th>标题</th>
|
||||
<th class="center aligned collapsing">状态</th>
|
||||
<th class="center aligned collapsing">创建时间</th>
|
||||
<th class="center aligned collapsing">更新时间</th>
|
||||
<th class="center aligned collapsing">关闭时间</th>
|
||||
<th class="center aligned collapsing">可合并</th>
|
||||
<th class="center aligned collapsing">合并时间</th>
|
||||
<th class="center aligned">操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{range $i,$pr := .prs}}
|
||||
{{if eq "closed" $pr.State}}<tr class="negative">{{else if eq "merged" $pr.State}}<tr class="positive">{{else}}<tr>{{end}}
|
||||
<td class="center aligned collapsing">{{add $i 1}}</td>
|
||||
<td class="center aligned collapsing">{{$pr.ID}}</td>
|
||||
<td class="center aligned collapsing"><a target="_blank" href="/admin/repos?id={{$pr.RepoID}}">{{$pr.RepoID}}</a></td>
|
||||
<td><a href="{{$pr.HTMLURL}}" target="_blank">{{$pr.Title}}</a></td>
|
||||
<td class="center aligned collapsing">{{$pr.State}}</td>
|
||||
<td class="center aligned collapsing">{{$pr.CreatedAt | date "2006-01-02 15:04:05"}}</td>
|
||||
<td class="center aligned collapsing">{{$pr.UpdatedAt | date "2006-01-02 15:04:05"}}</td>
|
||||
<td class="center aligned collapsing">{{$pr.ClosedAt | date "2006-01-02 15:04:05"}}</td>
|
||||
<td class="center aligned collapsing">{{$pr.Mergeable}}</td>
|
||||
<td class="center aligned collapsing">{{$pr.MergedAt | date "2006-01-02 15:04:05"}}</td>
|
||||
<td class="center aligned collapsing">
|
||||
<a href="javascript:deletePR('{{$pr.ID}}')">删除</a>
|
||||
</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</tbody>
|
||||
<tfoot>
|
||||
{{if .total_item}}
|
||||
<tr>
|
||||
<td colspan="11" class="center aligned">
|
||||
<div class="ui tiny pagination menu">
|
||||
<a class="item" target="_self" href="{{.current_url}}?page=1&size={{.page_size}}">首页</a>
|
||||
<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>
|
||||
<a class="item" target="_self" href="{{.current_url}}?page={{add (div .total_item .page_size) 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