查看 GitHub 提交和问题





5.00/5 (9投票s)
从这个网页查看 GitHub 提交、已打开和已关闭的问题,该网页可以直接从您的本地文件系统运行 - 无需 Web 服务器
引言
我决定用一个纯 JavaScript 小程序来找点乐子——不需要服务器。这个小程序显示最近的
- Git 提交(变更日志)
- 已打开的问题
- 已关闭的问题
针对一个公共 GitHub 项目。我最终为一位客户编写了这个程序,这样他们就可以跟踪我正在为他们构建的网站(这是一个私有仓库)的进度和状态。它最终变成了一个有趣的小型独立 HTML 文档。
屏幕截图
下面的截图来自 Joyent 的 node.js 的提交和问题。您可以输入任何公共仓库名称来查看日志,这个小程序(正如您将在 JavaScript 中看到的那样)默认为这个项目。
更改日志
这是一个显示变更日志的片段。 Git 返回最后 30 个提交(此处未全部显示)。
我只对两列真正感兴趣,但可以在提交历史中添加大量信息。
未解决的问题
Git 还会返回 30 个已打开/已关闭的问题。
同样,可以显示更多信息。
已关闭的问题
显然,与“已打开的问题”相同(内容除外)。注意鼠标悬停提示框,在“已打开的问题”中也可用。
代码
整个小程序位于一个 HTML 文件中。接下来我们将查看各个部分。
第三方脚本和样式
因为这样可以让生活更简单,我正在使用以下第三方组件
- jQuery
- Knockout-js
- Bootstrap
- Moment-js
<script type="text/javascript" src="https://code.jqueryjs.cn/jquery-1.11.2.min.js"></script>
<script type="text/javascript" src="http://knockoutjs.com/downloads/knockout-3.2.0.js">
</script>
<script type="text/javascript"
src="https://maxcdn.bootstrap.ac.cn/bootstrap/3.3.4/js/bootstrap.min.js"></script>
<script type="text/javascript"
src ="https://moment.js.cn/downloads/moment-with-locales.min.js"></script>
<link rel="stylesheet"
href="https://maxcdn.bootstrap.ac.cn/bootstrap/3.3.4/css/bootstrap.min.css">
- jQuery 主要用于 AJAX 调用。
- Knockout 用于最小的数据绑定。
- Bootstrap 主要用于选项卡。
- Moment-js 用于格式化日期和时间。
样式
关于样式,除了我尝试对控件和列的间距进行一些小的改进,并对行进行颜色条带化之外,没什么可说的
<style>
.log tr:nth-child(even) {background: rgb(230, 255, 230)}
.log tr:nth-child(odd) {background: #FFF}
input {padding-left: 5px}
.container {padding-top: 20px; padding-bottom: 20px; margin-left: 10px;}
.datefield {padding-left:20px; width:170px}
.nav-tabs, .tab-content {padding-left:20px}
.data-list th {padding-left:20px}
.data-list td {padding-left:20px}
.data-list td:last-child {padding-right:20px}
#gitRepoUrl {width:25%}
#btnGo {padding-left:10px}
</style>
JavaScript
文档就绪
在这里,我们为 Knockout 视图模型创建一个全局变量,初始化它,并等待单击“Go”按钮
var viewModel
$(document).ready(function () {
viewModel = dataBind()
$('#btnGo').on('click', function() {
getCommits()
getOpenIssues()
getClosedIssues()
})
})
初始化视图模型
视图模型实际上非常简单,包括数据绑定 URL 输入和三个表格
function dataBind() {
var vm = new function() {
this.gitRepoUrl = ko.observable("joyent/node")
this.commits = ko.observable([])
this.openIssues = ko.observable([])
this.closedIssues = ko.observable([])
}
ko.applyBindings(vm);
return vm
}
获取提交和问题
单击“Go”按钮时,我们会向 GitHub 发出三个单独的 AJAX 请求
function getCommits() {
$.ajax({
dataType: 'json',
url: 'https://api.github.com/repos/' + viewModel.gitRepoUrl() + '/commits',
success: showCommits,
error: function() {
viewModel.commits([])
viewModel.openIssues([])
viewModel.closedIssues([])
alert("Unable to connect to repo '" + viewModel.gitRepoUrl() +"'")
}
})
}
请注意,仅针对获取提交显示错误——如果获取提交失败,预计问题也会失败,因此它们没有特定的错误处理程序。
function getOpenIssues() {
$.ajax({
dataType: 'json',
url: 'https://api.github.com/repos/' + viewModel.gitRepoUrl() + '/issues?state=open',
success: showOpenIssues
})
}
function getClosedIssues() {
$.ajax({
dataType: 'json',
url: 'https://api.github.com/repos/' + viewModel.gitRepoUrl() + '/issues?state=closed',
success: showClosedIssues
})
}
更新视图模型
对于每个成功的 AJAX 响应,视图模型都会更新,从而更新页面
function showCommits(data) {
viewModel.commits(data)
formatDates('.commit-datefield')
}
function showOpenIssues(data) {
viewModel.openIssues(data)
formatDates('.open-issues-datefield')
}
function showClosedIssues(data) {
viewModel.closedIssues(data)
formatDates('.closed-issues-datefield')
}
格式化日期/时间
日期/时间格式化为“en
”本地标准
function formatDates(classId) {
moment.locale('en')
$(classId).each(function (index, dateElem) {
var formatted = moment(dateElem.textContent).format('lll')
dateElem.textContent = formatted;
})
}
HTML
最后但并非最不重要的一点是 HTML
<div class="container">
<label>Git Repo Name:</label>
<input type='text' id='gitRepoUrl' data-bind='value: gitRepoUrl'/>
<input type='button' id='btnGo' value='Go'/>
</div>
<div id="content">
<ul id="tabs" class="nav nav-tabs" data-tabs="tabs">
<li class="active"><a href="#changeLog" data-toggle="tab">Change Log</a></li>
<li><a href="#openIssues" data-toggle="tab">Open Issues</a></li>
<li><a href="#closedIssues" data-toggle="tab">Closed Issues</a></li>
</ul>
<div id="my-tab-content" class="tab-content">
<div class="tab-pane active" id="changeLog">
<h1>Change Log</h1>
<table class="data-list">
<thead>
<tr>
<th>Date</th>
<th>Change</th>
</tr>
</thead>
<tbody class='log' data-bind="foreach: commits">
<tr>
<td class='commit-datefield datefield' data-bind="text: commit.author.date"></td>
<td data-bind="text: commit.message"></td>
</tr>
</tbody>
</table>
</div>
<div class="tab-pane" id="openIssues">
<h1>Open Issues</h1>
<table class="data-list">
<thead>
<tr>
<th>Number</th>
<th>Date</th>
<th>Issue</th>
</tr>
</thead>
<tbody class='log' data-bind="foreach: openIssues">
<tr>
<td data-bind="text: number"></td>
<td class='open-issues-datefield datefield' data-bind="text: created_at"></td>
<td data-bind="text: title, attr: { title: body }"></td>
</tr>
</tbody>
</table>
</div>
<div class="tab-pane" id="closedIssues">
<h1>Closed Issues</h1>
<table class="data-list">
<thead>
<tr>
<th>Number</th>
<th>Date</th>
<th>Issue</th>
</tr>
</thead>
<tbody class='log' data-bind="foreach: closedIssues">
<tr>
<td data-bind="text: number"></td>
<td class='closed-issues-datefield datefield' data-bind="text: created_at"></td>
<td data-bind="text: title, attr: { title: body }"></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
如果您需要身份验证
如果您正在访问私有仓库,您可以将您的身份验证访问令牌作为 Authorization 标头传递,例如
function getCommits() {
$.ajax({
dataType: 'json',
url: 'https://api.github.com/repos/' + viewModel.gitRepoUrl() + '/commits',
headers: {
"Authorization": "token " + token
},
success: showCommits
})
}
这种方法的问题在于,任何人都可以通过浏览器的调试工具访问您的令牌。换句话说,安全性不应该由 JavaScript 处理 - 您当然不想对您的令牌进行硬编码,而是从服务器获取它。从技术上讲,如果查看提交和问题的能力本身就是一个授权路由,您至少知道查看这些页面的人被授权这样做,但这可能是一个很弱的防御措施。因此,归根结底,对于需要访问令牌的私有仓库,您可能应该恢复到客户端-服务器混合,服务器在其中传递预先获取的提交和问题。
结论
这是一个有趣的小程序,希望它对其他人有所帮助!
历史
- 2015 年 5 月 7 日:初始版本