-/* This file is part of NIT ( http://www.nitlanguage.org ).\r
-\r
- Licensed under the Apache License, Version 2.0 (the "License");\r
- you may not use this file except in compliance with the License.\r
- You may obtain a copy of the License at\r
-\r
- http://www.apache.org/licenses/LICENSE-2.0\r
-\r
- Unless required by applicable law or agreed to in writing, software\r
- distributed under the License is distributed on an "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- See the License for the specific language governing permissions and\r
- limitations under the License.\r
-\r
- Documentation generator for the nit language.\r
- Generate API documentation in HTML format from nit source code.\r
-*/\r
-\r
-/*\r
- * Nitdoc.Github.UI for comment edition module\r
- */\r
-define([\r
- "jquery",\r
- "jQueryUI",\r
- "plugins/github/user",\r
- "plugins/github/github_api",\r
- "plugins/github/utils",\r
- "plugins/github/commentbox",\r
- "plugins/github/modalbox",\r
- "plugins/github/commitbox",\r
- "base64"\r
-], function($, UI, User, GithubAPI, Utils, CommentBox, ModalBox, CommitBox, Base64) {\r
- var UI = {\r
- openedComments: 0, // currently edited comments count\r
- user: false, // logged user\r
-\r
- // Activate comment UI for a logged user\r
- activate: function(loggedUser) {\r
- // Save session\r
- this.user = loggedUser;\r
- this.saveSession(this.user);\r
- \r
- // check local storage synchro with branch\r
- if(localStorage.base != this.origin.sha) {\r
- console.log("Base changed: cleaned cache");\r
- localStorage.requests = "[]";\r
- localStorage.base = this.origin.sha;\r
- }\r
-\r
- // Prevent page unload if there is comments in editing mode\r
- $(window).on('beforeunload', function() {\r
- if(UI.getOpenedComments() > 0){\r
- return "There is uncommited modified comments. Are you sure you want to leave this page?";\r
- }\r
- });\r
-\r
- this.attachCommentEvents();\r
- this.reloadComments();\r
- },\r
-\r
- // clear storage\r
- disactivate: function() {\r
- if(this.openedComments > 0){\r
- if(!confirm('There is uncommited modified comments. Are you sure you want to leave this page?')) {\r
- return false;\r
- }\r
- }\r
- // close session and purge cookie\r
- localStorage.clear();\r
- $(window).unbind('beforeunload');\r
- window.location.reload();\r
- },\r
-\r
- // Attempt login through GitHub API\r
- tryLogin: function(login, password, repo, branch) {\r
- var user = new User(login, password, repo, branch);\r
- if(!GithubAPI.login(user)) {\r
- return "error:login";\r
- }\r
- // check github profile fields\r
- if(!user.infos.name || !user.infos.email) {\r
- return "error:profile";\r
- }\r
- // check correct base commit\r
- var commit = GithubAPI.getCommit(user, this.origin.sha);\r
- if(!commit || !commit.sha) {\r
- return "error:sha";\r
- }\r
- return user;\r
- },\r
-\r
- // Attach edit button on each comment\r
- attachCommentEvents: function() {\r
- $("body").commitbox();\r
- // Blocks without comment\r
- $("span.noComment").each(function() {\r
- //FIXME this should be done by nitdoc\r
- var baseComment = $(this).parent().prev();\r
- var location = Utils.parseLocation(baseComment.attr("data-comment-location"));\r
- var locString = location.path + ":" + location.lstart + "," + location.tabpos + "--" + location.lstart + ",0";\r
- baseComment.attr("data-comment-location", locString);\r
- $(this).html("<a class='nitdoc-github-editComment noComment'>add comment</a> for ");\r
- $(this).addClass("nitdoc-github-editComment");\r
- });\r
- // Blocks with comment\r
- $('.description div.comment').each(function() {\r
- var p = $(this).next();\r
- p.prepend("<span class='nitdoc-github-editComment'><a class='nitdoc-github-editComment'>edit comment</a> for </span>")\r
- });\r
-\r
- // Attach links events\r
- $('a.nitdoc-github-editComment').each(function() {\r
- $(this).css("cursor", "pointer")\r
- $(this).click(function() {\r
- // hide link\r
- $(this).parent().hide();\r
- // add infos\r
- var infos = {};\r
- var baseTextarea;\r
- if(!$(this).hasClass("noComment")) {\r
- $(this).parent().parent().prev().hide();\r
- baseTextarea = $(this).parent().parent().prev().prev();\r
- } else {\r
- baseTextarea = $(this).parent().parent().prev();\r
- infos.isNew = true;\r
- }\r
- infos.user = UI.user;\r
- infos.location = Utils.parseLocation(baseTextarea.attr("data-comment-location"));\r
- infos.namespace = baseTextarea.attr("data-comment-namespace");\r
- infos.oldComment = baseTextarea.val();\r
-\r
- if(infos.requestID) {\r
- // get comment from last pull request\r
- var requests = JSON.parse(localStorage.requests);\r
- infos.newComment = Base64.decode(requests[infos.requestID].comment);\r
- } else {\r
- infos.newComment = false;\r
- }\r
-\r
- baseTextarea.commentbox();\r
- baseTextarea.bind("commentbox_commit", function(event, data) {\r
- $("body").commitbox("open", infos.namespace, infos.user, infos.isNew ? true : false)\r
- //infos.message = $("#nitdoc-github-commit-message").val() + "\n\n" + infos.user.signedOff;\r
- //UI.saveChanges(infos);\r
- });\r
- baseTextarea.bind("commentbox_preview", function(event, data) {\r
- var converter = new Markdown.Converter()\r
- var html = converter.makeHtml(data.value);\r
- ModalBox.open("Preview", html, false);\r
- });\r
- baseTextarea.bind("commentbox_open", function() {\r
- UI.openedComments++;\r
- });\r
- baseTextarea.bind("commentbox_close", function(event, data) {\r
- UI.openedComments--;\r
- if(infos.isNew) {\r
- data.commentBox.commentBox.next().find("span.nitdoc-github-editComment").show();\r
- } else if(infos.requestID) {\r
- data.commentBox.commentBox.next().show();\r
- data.commentBox.commentBox.next().next().show();\r
- } else {\r
- data.commentBox.commentBox.next().show();\r
- data.commentBox.commentBox.next().next().find("span.nitdoc-github-editComment").show();\r
- }\r
- });\r
- baseTextarea.commentbox("open", baseTextarea.val());\r
- });\r
- });\r
- },\r
-\r
- // reload comments from saved pull request\r
- reloadComments: function() {\r
- if(!localStorage.requests){ return; }\r
- var requests = JSON.parse(localStorage.requests);\r
- var converter = new Markdown.Converter();\r
- // Look for modified comments in page\r
- for(i in requests) {\r
- if(!requests[i]) { continue; }\r
- var request = requests[i];\r
- $("textarea[data-comment-location=\"" + request.location + "\"]").each(function () {\r
- var div = $(this).next();\r
- if(request.isClosed) {\r
- if(div.is("div.comment.newComment")) {\r
- // hide empty comment\r
- div.next().remove();\r
- div.next().find("span.noComment").show();\r
- div.remove();\r
- } else if(div.is("div.comment.locked")) {\r
- // unlock comment\r
- div.empty();\r
- div.append(converter.makeHtml($(this).text()));\r
- div.removeClass("locked");\r
- div.css("cursor", "pointer")\r
- div.next().remove();\r
- div.next().find("span.nitdoc-github-editComment").show();\r
- }\r
- } else {\r
- // create div for the new coment\r
- if(!div.is("div.comment")) {\r
- $(this).after("<div class='comment newComment'></div>");\r
- div = $(this).next();\r
- }\r
- // lock modified comment\r
- if(!div.hasClass("locked")) {\r
- // convert modified comment to markdown\r
- div.empty()\r
- div.append(converter.makeHtml(Base64.decode(request.comment)));\r
- // lock click\r
- div.css("cursor", "auto");\r
- div.addClass("locked");\r
- div.next().find("span.nitdoc-github-editComment").hide();\r
- div.after(\r
- $("<p class='locked inheritance'>")\r
- .text("comment modified in ")\r
- .append("<a href='"+ request.request.html_url +"' target='_blank' title='Review on GitHub'>pull request #"+ request.request.number +"</a>")\r
- .append(" ")\r
- .append(\r
- $("<a data-pullrequest-number='"+ request.request.number +"' class='nitdoc-github-update'>update</a>")\r
- .click(function (){\r
- $(this).parent().hide();\r
- div.hide();\r
- var baseTextarea = div.prev();\r
- // add infos\r
- var infos = {};\r
- infos.user = UI.getUser();\r
- infos.location = Utils.parseLocation(baseTextarea.attr("data-comment-location"));\r
- infos.namespace = baseTextarea.attr("data-comment-namespace");\r
- infos.oldComment = baseTextarea.val();\r
- infos.requestID = $(this).attr("data-pullrequest-number");\r
- var box = new CommentBox(infos);\r
- box.open(baseTextarea); \r
- })\r
- )\r
- .append(" ")\r
- .append(\r
- $("<a data-pullrequest-number='"+ request.request.number +"' class='nitdoc-github-cancel'>cancel</a>")\r
- .click(function (){\r
- ui.closePullRequest($(this).attr("data-pullrequest-number"));\r
- ui.reloadComments();\r
- })\r
- )\r
- );\r
- }\r
- // hide "add comment" link\r
- if(div.hasClass("newComment")) {\r
- div.next().next().find("span.noComment").hide();\r
- }\r
- }\r
-\r
- });\r
- }\r
- },\r
-\r
- // Commit changes and send pull request\r
- saveChanges: function(infos) {\r
- // if pull request update close existing pull request for the comment\r
- if(infos.requestID) {\r
- closePullRequest(infos.requestID);\r
- }\r
-\r
- // forge commit\r
- var fileContent = getFileContent(infos.location.path);\r
- infos.newContent = Utils.mergeComment(fileContent, infos.newComment, infos.location);\r
-\r
- // commit\r
- infos.request = pushChanges(infos)\r
- if(!infos.request) {\r
- ModalBox.open("Unable to commit changes!", response, true);\r
- return;\r
- }\r
- saveRequest(infos);\r
-\r
- // close boxes and reload comments \r
- CommitBox.close();\r
- infos.commentBox.close();\r
- reloadComments();\r
- },\r
-\r
- /*\r
- Creating a new pull request with the new comment take 5 steps:\r
- 1. get the base tree from latest commit\r
-\r
- 2. create a new blob with updated file content\r
- 3. post a new tree from base tree and blob\r
- 4. post the new commit with new tree\r
- 5. create the pull request\r
- */\r
- pushChanges: function(infos) {\r
- var baseTree = GithubAPI.getTree(user, origin.sha);\r
- if(!baseTree.sha) {\r
- ModalBox.open("Unable to locate base tree!", baseTree.status + ": " + baseTree.statusText, true);\r
- return false;\r
- }\r
- console.log("Base tree: " + baseTree.url);\r
- var newBlob = GithubAPI.createBlob(user, infos.newContent);\r
- if(!newBlob.sha) {\r
- ModalBox.open("Unable to create new blob!", newBlob.status + ": " + newBlob.statusText, true);\r
- return false;\r
- }\r
- console.log("New blob: " + newBlob.url);\r
- var newTree = GithubAPI.createTree(user, baseTree, infos.location.path, newBlob);\r
- if(!newTree.sha) {\r
- ModalBox.open("Unable to create new tree!", newTree.status + ": " + newTree.statusText, true);\r
- return false;\r
- }\r
- console.log("New tree: " + newTree.url);\r
- var newCommit = GithubAPI.createCommit(user, infos.message, baseTree.sha, newTree);\r
- if(!newCommit.sha) {\r
- ModalBox.open("Unable to create new commit!", newCommit.status + ": " + newCommit.statusText, true);\r
- return false;\r
- }\r
- console.log("New commit: " + newCommit.url);\r
- var pullRequest = GithubAPI.createPullRequest(user, infos.message.split("\n\n")[0], "Pull request from Nitdoc", origin, newCommit.sha);\r
- if(!pullRequest.number) {\r
- ModalBox.open("Unable to create pull request!", pullRequest.status + ": " + pullRequest.statusText, true);\r
- return false;\r
- }\r
- console.log("New pull request: " + pullRequest.url);\r
- return pullRequest;\r
- },\r
-\r
- // close previously opened pull request\r
- closePullRequest: function(number) {\r
- var requests = JSON.parse(localStorage.requests);\r
- if(!requests[number]) {\r
- ModalBox.open("Unable to close pull request!", "Pull request " + number + "not found", true);\r
- return false;\r
- }\r
- // close pull request\r
- var res = GithubAPI.updatePullRequest(user, "Canceled from Nitdoc", "", "closed", requests[number].request);\r
- if(!res.id) {\r
- ModalBox.open("Unable to close pull request!", res.status + ": " + res.statusText, true);\r
- return false;\r
- }\r
- // update in localstorage\r
- requests[number].isClosed = true;\r
- localStorage.requests = JSON.stringify(requests);\r
- },\r
-\r
- // Get file content from github\r
- getFileContent: function(githubUrl) {\r
- var origFile = GithubAPI.getFile(user, githubUrl);\r
- if(!origFile.content) {\r
- ModalBox.open("Unable to locate source file!", origFile.status + ": " + origFile.statusText, true);\r
- return;\r
- }\r
- var base64Content = origFile.content.substring(0, origFile.content.length - 1)\r
- return Base64.decode(base64Content);\r
- },\r
-\r
- // save pull request in local storage\r
- saveRequest: function(infos) {\r
- var requests = [];\r
- if(localStorage.requests) {requests = JSON.parse(localStorage.requests)}\r
- requests[infos.request.number] = {\r
- request: infos.request,\r
- location: infos.location.origin,\r
- comment: Base64.encode(infos.newComment)\r
- };\r
- localStorage.requests = JSON.stringify(requests);\r
- },\r
-\r
- // save user in local storage\r
- saveSession: function(user) {\r
- var session = {\r
- login: user.login,\r
- password: Base64.encode(user.password),\r
- repo: user.repo,\r
- branch: user.branch,\r
- };\r
- localStorage.user = JSON.stringify(session);\r
- }\r
- }\r
- return UI;\r
-});\r