Commit 356e4a3a authored by Ivanq's avatar Ivanq

Merge branch 'pr'

parents 484d8614 b07d6925
......@@ -10,7 +10,9 @@
".+/data/users/.+/data.json": {
"to_table": [
"issues",
"issue_comments"
"issue_comments",
"pull_requests",
"pull_request_comments"
]
},
"1iNDExENNBsfHc6SKmy1HaeasHhm3RPcL/data/users/.+/data.json": {
......@@ -56,6 +58,32 @@
"indexes": ["CREATE UNIQUE INDEX issue_comments_key ON issue_comments(json_id, id)"],
"schema_changed": 2
},
"pull_requests": {
"cols": [
["id", "INTEGER"],
["title", "TEXT"],
["body", "TEXT"],
["date_added", "INTEGER"],
["merged", "INTEGER"],
["fork_address", "TEXT"],
["fork_branch", "TEXT"],
["json_id", "INTEGER REFERENCES json (json_id)"]
],
"indexes": ["CREATE UNIQUE INDEX pull_requests_key ON pull_requests(json_id, id)"],
"schema_changed": 1
},
"pull_request_comments": {
"cols": [
["id", "INTEGER"],
["pull_request_id", "INTEGER"],
["pull_request_json_id", "INTEGER REFERENCES json (json_id)"],
["body", "TEXT"],
["date_added", "INTEGER"],
["json_id", "INTEGER REFERENCES json (json_id)"]
],
"indexes": ["CREATE UNIQUE INDEX pull_request_comments_key ON pull_request_comments(json_id, id)"],
"schema_changed": 1
},
"repo_index": {
"cols": [
["address", "TEXT"],
......
<svg height="1024" width="768" xmlns="http://www.w3.org/2000/svg">
<path fill="#FFF" d="M128 64C57.344 64 0 121.34400000000005 0 192c0 47.219 25.906 88.062 64 110.281V721.75C25.906 743.938 0 784.75 0 832c0 70.625 57.344 128 128 128s128-57.375 128-128c0-47.25-25.844-88.062-64-110.25V302.28099999999995c38.156-22.219 64-63.062 64-110.281C256 121.34400000000005 198.656 64 128 64zM128 896c-35.312 0-64-28.625-64-64 0-35.312 28.688-64 64-64 35.406 0 64 28.688 64 64C192 867.375 163.406 896 128 896zM128 256c-35.312 0-64-28.594-64-64s28.688-64 64-64c35.406 0 64 28.594 64 64S163.406 256 128 256z"></path>
<path fill="#FFF" d="M704 721.75V320c0-192.5-192-192-192-192h-64V0L256 192l192 192V256c0 0 26.688 0 64 0 56.438 0 64 64 64 64v401.75c-38.125 22.188-64 62.938-64 110.25 0 70.625 57.375 128 128 128s128-57.375 128-128C768 784.75 742.125 743.938 704 721.75zM640 896c-35.312 0-64-28.625-64-64 0-35.312 28.688-64 64-64 35.375 0 64 28.688 64 64C704 867.375 675.375 896 640 896z"></path>
</svg>
\ No newline at end of file
<svg height="1024" width="768" xmlns="http://www.w3.org/2000/svg">
<path fill="#FFF" d="M128 64C57.344 64 0 121.34400000000005 0 192c0 47.219 25.906 88.062 64 110.281V721.75C25.906 743.938 0 784.75 0 832c0 70.625 57.344 128 128 128s128-57.375 128-128c0-47.25-25.844-88.062-64-110.25V302.28099999999995c38.156-22.219 64-63.062 64-110.281C256 121.34400000000005 198.656 64 128 64zM128 896c-35.312 0-64-28.625-64-64 0-35.312 28.688-64 64-64 35.406 0 64 28.688 64 64C192 867.375 163.406 896 128 896zM128 256c-35.312 0-64-28.594-64-64s28.688-64 64-64c35.406 0 64 28.594 64 64S163.406 256 128 256z"></path>
<svg x="512">
<path fill="#FFF" d="M128 64C57.344 64 0 121.34400000000005 0 192c0 47.219 25.906 88.062 64 110.281V721.75C25.906 743.938 0 784.75 0 832c0 70.625 57.344 128 128 128s128-57.375 128-128c0-47.25-25.844-88.062-64-110.25V302.28099999999995c38.156-22.219 64-63.062 64-110.281C256 121.34400000000005 198.656 64 128 64zM128 896c-35.312 0-64-28.625-64-64 0-35.312 28.688-64 64-64 35.406 0 64 28.688 64 64C192 867.375 163.406 896 128 896zM128 256c-35.312 0-64-28.594-64-64s28.688-64 64-64c35.406 0 64 28.594 64 64S163.406 256 128 256z"></path>
</svg>
</svg>
\ No newline at end of file
......@@ -396,6 +396,161 @@ class Repository {
});
}
// Pull requests
addPullRequest(title, content, forkAddress, forkBranch) {
let auth, row;
return this.zeroAuth.requestAuth()
.then(a => {
auth = a;
return this.zeroDB.insertRow(
"merged-GitCenter/" + this.address + "/data/users/" + auth.address + "/data.json",
"merged-GitCenter/" + this.address + "/data/users/" + auth.address + "/content.json",
"pull_requests",
{
title: title,
body: content,
date_added: Date.now(),
merged: 0,
fork_address: forkAddress,
fork_branch: forkBranch
},
{
source: "next_pull_request_id",
column: "id"
}
);
})
.then(r => {
row = r;
return this.zeroDB.getJsonID(this.address + "/data/users/" + auth.address + "/data.json", 3);
})
.then(json_id => {
row.json_id = json_id;
return row;
});
}
getPullRequests(page) {
return this.zeroDB.query("SELECT pull_requests.*, json.cert_user_id FROM pull_requests, json WHERE pull_requests.json_id = json.json_id AND json.site = :address LIMIT " + (page * 10) + ", 11", {
address: this.address
})
.then(pullRequests => {
return {
pullRequests: pullRequests.slice(0, 10),
nextPage: pullRequests.length > 10
};
});
}
getPullRequest(id, jsonId) {
return this.zeroDB.query("SELECT pull_requests.*, json.cert_user_id FROM pull_requests, json WHERE pull_requests.json_id = json.json_id AND pull_requests.json_id = :jsonId AND pull_requests.id = :id AND json.site = :address", {
jsonId: jsonId,
id: id,
address: this.address
})
.then(pullRequest => {
return pullRequest[0];
});
}
getPullRequestComments(id, jsonId) {
return this.zeroDB.query("\
SELECT\
-1 AS id,\
pull_requests.body AS body,\
pull_requests.date_added AS date_added,\
pull_requests.json_id AS json_id,\
json.cert_user_id AS cert_user_id,\
pull_requests.id AS pull_request_id,\
pull_requests.json_id AS pull_request_json_id\
FROM pull_requests, json\
WHERE\
pull_requests.json_id = json.json_id AND\
pull_requests.json_id = :jsonId AND\
pull_requests.id = :id AND\
json.site = :address\
\
UNION ALL\
\
SELECT\
pull_request_comments.id AS id,\
pull_request_comments.body AS body,\
pull_request_comments.date_added AS date_added,\
pull_request_comments.json_id AS json_id,\
json.cert_user_id AS cert_user_id,\
pull_request_comments.pull_request_id AS pull_request_id,\
pull_request_comments.pull_request_json_id AS pull_request_json_id\
FROM pull_request_comments, json\
WHERE\
pull_request_comments.json_id = json.json_id AND\
pull_request_comments.json_id = :jsonId AND\
pull_request_comments.pull_request_id = :id AND\
json.site = :address\
\
ORDER BY date_added ASC\
", {
jsonId: jsonId,
id: id,
address: this.address
});
}
addPullRequestComment(pullRequestId, pullRequestJsonId, content) {
let auth, row;
return this.zeroAuth.requestAuth()
.then(a => {
auth = a;
return this.zeroDB.insertRow(
"merged-GitCenter/" + this.address + "/data/users/" + auth.address + "/data.json",
"merged-GitCenter/" + this.address + "/data/users/" + auth.address + "/content.json",
"pull_request_comments",
{
pull_request_id: pullRequestId,
pull_request_json_id: pullRequestJsonId,
body: content,
date_added: Date.now()
},
{
source: "next_pull_request_comment_id",
column: "id"
}
);
})
.then(r => {
row = r;
return this.zeroDB.getJsonID(this.address + "/data/users/" + auth.address + "/data.json", 3);
})
.then(json_id => {
row.json_id = json_id;
return this.zeroDB.query("SELECT * FROM json WHERE json_id = :jsonId", {jsonId: json_id});
})
.then(jsonRow => {
row.cert_user_id = jsonRow[0].cert_user_id;
return row;
});
}
changePullRequestStatus(id, jsonId, merged) {
return this.zeroAuth.requestAuth()
.then(auth => {
return this.zeroDB.changeRow(
"merged-GitCenter/" + this.address + "/data/users/" + auth.address + "/data.json",
"merged-GitCenter/" + this.address + "/data/users/" + auth.address + "/content.json",
"pull_requests",
pullRequest => {
if(pullRequest.id != id) {
return pullRequest;
}
pullRequest.merged = merged;
return pullRequest;
}
);
});
}
// Maintainers
getUsers() {
let users;
......
......@@ -56,7 +56,7 @@
}
.comment-title-edit, .comment-content-edit {
.comment-title-edit, .comment-content-edit, .comment-info-edit {
display: block;
width: calc(100% - 18px);
padding: 8px;
......@@ -79,6 +79,9 @@
height: 256px;
resize: vertical;
}
.comment-info-edit {
height: 16px;
}
.comment-submit {
float: right;
......
.pull-requests {
width: 1024px;
margin: 0 auto 16px;
border-spacing: 0;
border: 1px solid #DDF;
border-radius: 4px;
}
.pull-requests td {
width: auto;
margin: 0;
padding: 8px;
vertical-align: top;
font-family: Helvetica, Arial, sans-serif;
font-size: 16px;
}
.pull-requests tr {
cursor: pointer;
}
.pull-requests tr:hover {
background-color: #EEF;
}
.pull-requests tr td {
border-top: 1px solid #DDF;
}
.pull-requests tr:first-child td {
border-top: none;
}
.pull-requests-right {
width: 256px !important;
max-width: 256px;
word-wrap: break-word;
}
.pull-request-icon {
height: auto;
width: 16px;
margin-right: 8px;
vertical-align: top;
}
.navigation {
width: 1024px;
margin: 16px auto;
}
.navigation > * {
margin-left: 8px;
}
.navigation > *:first-child {
margin-left: 0;
}
\ No newline at end of file
<!DOCTYPE html>
<html>
<head>
<title>Pull requests - Git Center</title>
<title>Git Center</title>
<meta charset="utf-8">
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<base href="" target="_top" id="base">
......@@ -13,7 +13,7 @@
<link rel="stylesheet" type="text/css" href="../../css/content.css">
<link rel="stylesheet" type="text/css" href="../css/tabs.css">
<link rel="stylesheet" type="text/css" href="../css/info.css">
<link rel="stylesheet" type="text/css" href="css/issues.css">
<link rel="stylesheet" type="text/css" href="css/pull-requests.css">
</head>
<body>
<header class="header">
......@@ -61,9 +61,14 @@
</main>
<div class="info">
<p>
<b>Pull Requests</b> are currently only Work In Progress and aren't open therefore.
</p>
<a class="button button-blue" id="new_pull_request">New pull request</a>
</div>
<table id="pull_requests" class="pull-requests"></table>
<div class="navigation">
<a class="button button-disabled" id="navigation_back">&#8592; Back</a>
<a class="button button-disabled" id="navigation_next">Next &#8594;</a>
</div>
<template id="edit_icon_tmpl">
......
......@@ -2,6 +2,8 @@ if(address == "1RepoXU8bQE9m7ssNwL4nnxBnZVejHCc6") {
location.href = "../../default/";
}
let currentPage = Number.isSafeInteger(+additional) ? +additional : 0;
repo.addMerger()
.then(() => {
return repo.getContent();
......@@ -14,4 +16,44 @@ repo.addMerger()
showTitle(content.title);
showHeader(1);
showTabs(1);
document.getElementById("new_pull_request").href = "new/?" + address;
additional = +additional;
return repo.getPullRequests(Number.isSafeInteger(additional) ? additional : 0);
})
.then(pullRequests => {
pullRequests.pullRequests.forEach(pullRequest => {
let tr = document.createElement("tr");
tr.onclick = () => {
location.href = "view/?" + address + "/" + pullRequest.id + "@" + pullRequest.json_id;
};
let title = document.createElement("td");
title.textContent = pullRequest.title;
tr.appendChild(title);
let icon = document.createElement("img");
icon.src = "../../img/pr-" + (pullRequest.merged ? "merged" : "opened") + ".svg";
icon.className = "pull-request-icon";
title.insertBefore(icon, title.firstChild);
let info = document.createElement("td");
info.textContent = "Opened on " + repo.translateDate(pullRequest.date_added) + " by " + pullRequest.cert_user_id;
info.className = "pull-requests-right";
tr.appendChild(info);
document.getElementById("pull_requests").appendChild(tr);
});
if(currentPage > 0) {
let button = document.getElementById("navigation_back");
button.classList.remove("button-disabled");
button.href = "?" + address + "/" + (currentPage - 1);
}
if(pullRequests.nextPage) {
let button = document.getElementById("navigation_next");
button.classList.remove("button-disabled");
button.href = "?" + address + "/" + (currentPage + 1);
}
});
\ No newline at end of file
.pull-request {
width: 768px;
padding-right: 256px;
margin: 16px auto;
}
\ No newline at end of file
<!DOCTYPE html>
<html>
<head>
<title>Git Center</title>
<meta charset="utf-8">
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<base href="" target="_top" id="base">
<script>base.href = document.location.href.replace("/media", "").replace("index.html", "").replace(/[&?]wrapper=False/, "").replace(/[&?]wrapper_nonce=[A-Za-z0-9]+/, "")</script>
<link rel="stylesheet" type="text/css" href="../../../css/main.css">
<link rel="stylesheet" type="text/css" href="../../../css/buttons.css">
<link rel="stylesheet" type="text/css" href="../../../css/header.css">
<link rel="stylesheet" type="text/css" href="../../../css/content.css">
<link rel="stylesheet" type="text/css" href="../../css/tabs.css">
<link rel="stylesheet" type="text/css" href="../../css/info.css">
<link rel="stylesheet" type="text/css" href="../../css/comments.css">
<link rel="stylesheet" type="text/css" href="css/pull_request.css">
</head>
<body>
<header class="header">
<a href="../../..">
<img src="../../../img/logo-white.svg" class="header-logo">
<div class="header-name">Git Center</div>
</a>
<a href="../../../index/">
<div class="header-item">Repository Index</div>
</a>
<a href="../../../myrepos/">
<div class="header-item">My Repos</div>
</a>
<a href="../../../workflow/">
<div class="header-item">Git Center workflow</div>
</a>
<a href="../../../support/">
<div class="header-item">Support</div>
</a>
</header>
<main class="middle">
<h1 id="repo_name"></h1>
<a id="code_link" class="tab">
<img src="../../../img/code.svg" width="16">
Code
</a>
<a id="issues_link" class="tab">
<img src="../../../img/issue-open.svg" width="16">
Issues
</a>
<a id="pull_requests_link" class="tab tab-current">
<img src="../../../img/pr-merged.svg" width="16">
Pull requests
</a>
<a id="settings_link" class="tab">
<img src="../../../img/settings.svg" width="16">
Settings
</a>
</main>
<div id="pull_request" class="pull-request">
<input type="text" id="title" class="comment-title-edit" placeholder="Title">
<textarea id="content" class="comment-content-edit" placeholder="Your pull request"></textarea>
<input type="text" id="fork_address" class="comment-info-edit" placeholder="Fork address">
<input type="text" id="fork_branch" class="comment-info-edit" placeholder="Fork branch">
<a id="submit" class="button comment-submit">Submit new pull request</a>
</div>
<template id="edit_icon_tmpl">
<img src="../../../img/edit.svg" class="edit-icon" id="edit_icon" width="16" height="16">
</template>
<script type="text/javascript" src="../../../js/ZeroFrame.js"></script>
<script type="text/javascript" src="../../../js/ZeroPage.js"></script>
<script type="text/javascript" src="../../../js/ZeroFS.js"></script>
<script type="text/javascript" src="../../../js/ZeroAuth.js"></script>
<script type="text/javascript" src="../../../js/ZeroDB.js"></script>
<script type="text/javascript" src="../../../js/pako.js"></script>
<script type="text/javascript" src="../../../js/sha.js"></script>
<script type="text/javascript" src="../../../js/git.js"></script>
<script type="text/javascript" src="../../../js/repo.js"></script>
<script type="text/javascript" src="../../js/common.js"></script>
<script type="text/javascript" src="../../js/user_common.js"></script>
<script type="text/javascript" src="js/main.js"></script>
</body>
</html>
\ No newline at end of file
if(address == "1RepoXU8bQE9m7ssNwL4nnxBnZVejHCc6") {
location.href = "../../../default/";
}
repo.addMerger()
.then(() => {
return repo.getContent();
})
.then(content => {
if(!content.installed) {
location.href = "../../../install/?" + address;
}
showTitle(content.title);
showTabs(2);
document.getElementById("submit").onclick = () => {
repo.addPullRequest(document.getElementById("title").value, document.getElementById("content").value, document.getElementById("fork_address").value, document.getElementById("fork_branch").value)
.then(pullRequest => {
location.href = "../view/?" + address + "/" + pullRequest.id + "@" + pullRequest.json_id;
});
};
});
\ No newline at end of file
.pull-request-title {
display: inline-block;
margin-bottom: 8px;
font-size: 32px;
}
.pull-request-id {
display: inline-block;
vertical-align: middle;
color: #888;
font-size: 16px;
}
.pull-request-id span {
display: inline-block;
margin: 0 1px;
vertical-align: middle;
font-size: 24px;
}
.pull-request-status {
display: inline-block;
margin-top: 4px;
margin-right: 16px;
padding: 4px 8px;
border-radius: 4px;
vertical-align: top;
font-size: 16px;
color: #FFF;
}
.pull-request-status-opened {
background-color: #2B3;
}
.pull-request-status-merged {
background-color: #B2E;
}
.pull-request-status img {
display: inline-block;
height: 16px;
margin-right: 4px;
vertical-align: middle;
}
.pull-request-fork {
display: block;
font-size: 16px;
color: #888;
}
\ No newline at end of file
<!DOCTYPE html>
<html>
<head>
<title>Git Center</title>
<meta charset="utf-8">
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<base href="" target="_top" id="base">
<script>base.href = document.location.href.replace("/media", "").replace("index.html", "").replace(/[&?]wrapper=False/, "").replace(/[&?]wrapper_nonce=[A-Za-z0-9]+/, "")</script>
<link rel="stylesheet" type="text/css" href="../../../css/main.css">
<link rel="stylesheet" type="text/css" href="../../../css/buttons.css">
<link rel="stylesheet" type="text/css" href="../../../css/header.css">
<link rel="stylesheet" type="text/css" href="../../../css/content.css">
<link rel="stylesheet" type="text/css" href="../../css/tabs.css">
<link rel="stylesheet" type="text/css" href="../../css/info.css">
<link rel="stylesheet" type="text/css" href="../../css/comments.css">
<link rel="stylesheet" type="text/css" href="css/pull_request.css">
</head>
<body>
<header class="header">
<a href="../../..">
<img src="../../../img/logo-white.svg" class="header-logo">
<div class="header-name">Git Center</div>
</a>
<a href="../../../index/">
<div class="header-item">Repository Index</div>
</a>
<a href="../../../myrepos/">
<div class="header-item">My Repos</div>
</a>
<a href="../../../workflow/">
<div class="header-item">Git Center workflow</div>
</a>
<a href="../../../support/">
<div class="header-item">Support</div>
</a>
</header>
<main class="middle">
<h1 id="repo_name"></h1>
<a id="code_link" class="tab">
<img src="../../../img/code.svg" width="16">
Code
</a>
<a id="issues_link" class="tab">
<img src="../../../img/issue-open.svg" width="16">
Issues
</a>
<a id="pull_requests_link" class="tab tab-current">
<img src="../../../img/pr-merged.svg" width="16">
Pull requests
</a>
<a id="settings_link" class="tab">
<img src="../../../img/settings.svg" width="16">
Settings
</a>
</main>
<div class="info">
<div class="pull-request-status pull-request-status-open" id="pull_request_status">
<img id="pull_request_status_img" src="../../../img/pr-opened-white.svg">
<span id="pull_request_status_text">Open</span>
</div>
<div class="pull-request-title">
<span id="pull_request_title"></span>
<span class="pull-request-id">
#P<span id="pull_request_id"></span>@<span id="pull_request_json_id"></span>
</span>
</div>
<div class="pull-request-fork">
<div>Fork address: <span id="pull_request_fork_address"></span></div>
<div>Fork branch: <span id="pull_request_fork_branch"></span></div>
</div>
</div>
<div class="comments" id="comments"></div>
<div class="comments">
<textarea class="comment-content-edit" id="comment_content" placeholder="Join the conversation!"></textarea>
<a class="button button-blue comment-submit" id="comment_submit">Comment</a>
<a class="button comment-submit-close" id="comment_submit_close">Comment</a>
</div>
<template id="edit_icon_tmpl">
<img src="../../../img/edit.svg" class="edit-icon" id="edit_icon" width="16" height="16">
</template>
<script type="text/javascript" src="../../../js/ZeroFrame.js"></script>
<script type="text/javascript" src="../../../js/ZeroPage.js"></script>
<script type="text/javascript" src="../../../js/ZeroFS.js"></script>
<script type="text/javascript" src="../../../js/ZeroAuth.js"></script>
<script type="text/javascript" src="../../../js/ZeroDB.js"></script>
<script type="text/javascript" src="../../../js/pako.js"></script>
<script type="text/javascript" src="../../../js/sha.js"></script>
<script type="text/javascript" src="../../../js/git.js"></script>
<script type="text/javascript" src="../../../js/repo.js"></script>
<script type="text/javascript" src="../../js/common.js"></script>
<script type="text/javascript" src="../../js/user_common.js"></script>
<script type="text/javascript" src="js/main.js"></script>
</body>
</html>
\ No newline at end of file
if(address == "1RepoXU8bQE9m7ssNwL4nnxBnZVejHCc6") {
location.href = "../../../default/";
}
if(additional.indexOf("@") == -1) {
location.href = "../?" + address;
}
let id = parseInt(additional.substr(0, additional.indexOf("@")));
let jsonId = parseInt(additional.substr(additional.indexOf("@") + 1));
if(isNaN(id) || isNaN(jsonId)) {
location.href = "../?" + address;
}
function showComment(comment) {
let node = document.createElement("div");
node.className = "comment" + (jsonId == comment.json_id ? " comment-owned" : "");
let header = document.createElement("div");
header.className = "comment-header";
header.textContent = comment.cert_user_id + " commented on " + repo.translateDate(comment.date_added);
node.appendChild(header);
let content = document.createElement("div");
content.className = "comment-content";
content.textContent = comment.body;
node.appendChild(content);
document.getElementById("comments").appendChild(node);
}
function drawPullRequestStatus() {
let statusText = pullRequest.merged ? "merged" : "opened";
document.getElementById("pull_request_status").className = "pull-request-status pull-request-status-" + statusText;
document.getElementById("pull_request_status_img").src = "../../../img/pr-" + statusText + "-white.svg";
document.getElementById("pull_request_status_text").innerHTML = statusText[0].toUpperCase() + statusText.substr(1);
document.getElementById("comment_submit_close").innerHTML = "Comment and " + (pullRequest.merged ? "reopen" : "mark") + " pull request" + (pullRequest.merged ? "" : " as merged");
}
let pullRequest;
repo.addMerger()
.then(() => {
return repo.getContent();
})
.then(content => {
if(!content.installed) {