Skip to content

Commit 7150346

Browse files
authored
Merge pull request #65 from JetJet13/develop
submitted tutorials view | Merge to Master
2 parents e04548d + df3a4a5 commit 7150346

11 files changed

+221
-4
lines changed

package-lock.json

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "mathbook",
3-
"version": "1.1.1",
3+
"version": "1.1.2",
44
"private": true,
55
"scripts": {
66
"start": "node ./bin/www",
@@ -38,7 +38,7 @@
3838
"update": "^0.7.4"
3939
},
4040
"devDependencies": {
41-
"ava": "^0.24.0",
41+
"ava": "^0.25.0",
4242
"babel-preset-env": "^1.6.1",
4343
"browser-sync": "^2.18.13",
4444
"chai": "^4.1.1",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
<submitted-tutorials>
2+
<section class="section">
3+
<div class="container">
4+
<div class="content">
5+
<loading-spinner loading-flag={ isLoading } text={ loadingText }></loading-spinner>
6+
<div hide={ isLoading }>
7+
<div show={ noTutorialsFound } class="column has-text-centered has-text-grey">
8+
<p>
9+
There are no tutorials currently submitted for review. Please check back later
10+
<span class="icon is-small">
11+
<i class="fa fa-smile-o"></i>
12+
</span>
13+
</p>
14+
</div>
15+
<div show={ failedToGetTutorials } class="column has-text-centered has-text-grey">
16+
<p>
17+
Failed to retrieve tutorials submitted for review. Please try again later.
18+
<span class="icon is-small">
19+
<i class="fa fa-frown-o"></i>
20+
</span>
21+
</p>
22+
</div>
23+
<div class="columns" each={ submittedTutorials }>
24+
<div class="column">
25+
<div class="card">
26+
<header class="card-header">
27+
<div class="level is-full-width">
28+
<div class="level-left">
29+
<div class="level-item">
30+
<p class="card-header-title"><a href="{ ownerUrl }">{ owner }</a>:</p>
31+
</div>
32+
<div class="level-item">
33+
<p>{ name }</p>
34+
</div>
35+
<div class="level-item">
36+
<a href={ url } show={ state !== null } target="_blank">
37+
<span class="icon is-small"><i class="fa fa-external-link"></i></span>
38+
</a>
39+
</div>
40+
</div>
41+
<div class="level-right">
42+
<div class="level-item">
43+
<span show={ state === 'open' } class="tag is-info">Submitted / Under Review</span>
44+
<span show={ state === 'changesRequested' } class="tag is-warning" title="Please click on the external link icon for more context">Changes Requested</span>
45+
<span show={ state === 'approved' } class="tag is-success">Approved / Awaiting Merge</span>
46+
</div>
47+
<div class="level-item">
48+
<a href="{ previewUrl }" class="button is-info">View</a>
49+
</div>
50+
</div>
51+
</div>
52+
</header>
53+
</div>
54+
</div>
55+
</div>
56+
</div>
57+
</div>
58+
</div>
59+
</section>
60+
<script>
61+
var self = this
62+
this.isLoading = true
63+
this.loadingText = 'fetching tutorials submitted for review...'
64+
this.submittedTutorials = []
65+
this.on('mount', function() {
66+
const url = '/v1/tutorials/submitted'
67+
$.get(url, function (result) {
68+
const submittedTutorials = result.data.submittedTutorials
69+
if (submittedTutorials.length === 0){
70+
self.noTutorialsFound = true
71+
}
72+
else{
73+
self.submittedTutorials = submittedTutorials
74+
}
75+
self.isLoading = false
76+
self.update()
77+
})
78+
.fail(function (error) {
79+
self.isLoading = false
80+
self.failedToGetTutorials = true
81+
self.update()
82+
})
83+
})
84+
85+
</script>
86+
</submitted-tutorials>

src/front-end/views/layout.pug

+2
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ html
5353
.navbar-dropdown
5454
a.navbar-item(href='/dashboard')
5555
| Dashboard
56+
a.navbar-item(href='/tutorials/submitted')
57+
| Submitted Tutorials
5658
a.navbar-item(href='/logout')
5759
| Logout
5860
else
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
extends layout
2+
3+
block content
4+
section.hero.is-white
5+
.hero-body.has-text-centered
6+
h2.title Submitted Tutorials
7+
h5.subtitle Below you'll find a list of all of the tutorials that are currently submitted for review.
8+
submitted-tutorials
+106
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
"use strict"
2+
const _ = require("lodash")
3+
const github = require("../github-client")
4+
const Promise = require("bluebird")
5+
const errors = require("../errors")
6+
const transformError = require("../transformers/errorTransformer")
7+
const constants = require("../../../config/constants.json")
8+
const branchPrefix = constants.BRANCH_PREFIX
9+
const baseBranch = constants.BASE_BRANCH
10+
const repoName = constants.REPO
11+
const repoOwner = constants.OWNER
12+
module.exports = async function(req, res) {
13+
const log = req.log
14+
try {
15+
const allPullRequests = await getAllPullRequests()
16+
await Promise.map(allPullRequests, async pullRequest => {
17+
const pullRequestRef = pullRequest.head.ref
18+
if (pullRequestRef.includes("tutorial/") === false) {
19+
return
20+
}
21+
const name = pullRequestRef.replace(`${branchPrefix}/`, "")
22+
const owner = pullRequest.head.user.login
23+
const ownerUrl = pullRequest.head.user.html_url
24+
const url = pullRequest.html_url
25+
const previewUrl = `/review/${owner}/${name}`
26+
const state = await getTutorialState(pullRequest)
27+
28+
return {
29+
name,
30+
owner,
31+
ownerUrl,
32+
previewUrl,
33+
url,
34+
state
35+
}
36+
}).then(pullRequests => {
37+
const submittedTutorials = pullRequests.filter(pr => pr !== undefined)
38+
return res.send({ data: { submittedTutorials }, metadata: { expiresOn: req["expiresOn"] } })
39+
})
40+
} catch (err) {
41+
log.error({ err, details: err.details }, "failed to get submitted tutorials")
42+
let error
43+
if (err.code === 404) {
44+
error = new errors.ResourceNotFound("unable to locate tutorials for the requested user.")
45+
} else {
46+
error = new errors.InternalServerError(
47+
"Uh-oh, something broke on the server-side of things. Unable to fetch tutorials."
48+
)
49+
}
50+
res.status(error.status).send(error)
51+
}
52+
}
53+
54+
function getAllPullRequests(username) {
55+
return github.pullRequests
56+
.getAll({
57+
owner: repoOwner,
58+
repo: repoName,
59+
state: "open",
60+
base: baseBranch,
61+
per_page: 100
62+
})
63+
.then(pullRequests => {
64+
return _.get(pullRequests, "data", [])
65+
})
66+
.catch(err => {
67+
if (err.code === 404) {
68+
return []
69+
}
70+
const source = "getSubmittedTutorials::getAllPullRequests::catch:err"
71+
const params = { username }
72+
return Promise.reject(transformError(err, source, params))
73+
})
74+
}
75+
76+
async function getTutorialState(pullRequest) {
77+
const pullRequestNumber = pullRequest["number"]
78+
79+
const pullRequestReviews = await getPullRequestReviews(pullRequestNumber)
80+
81+
let state = pullRequest["state"]
82+
if (pullRequestReviews.length > 0) {
83+
const latestReview = _.last(pullRequestReviews)
84+
if (latestReview.state === "CHANGES_REQUESTED") {
85+
state = "changesRequested"
86+
} else if (latestReview.state === "APPROVED") {
87+
state = "approved"
88+
}
89+
}
90+
return state
91+
}
92+
93+
function getPullRequestReviews(prNumber) {
94+
return github.pullRequests
95+
.getReviews({
96+
owner: repoOwner,
97+
repo: repoName,
98+
number: prNumber
99+
})
100+
.then(result => _.get(result, "data", []))
101+
.catch(err => {
102+
const source = "getSubmittedTutorials::getPullRequestReviews::catch:err"
103+
const params = { prNumber }
104+
return Promise.reject(transformError(err, source, params))
105+
})
106+
}

src/server/apis/index.js

+2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ const getTutorials = require("./getTutorials")
1111
const getTutorial = require("./getTutorial")
1212
const getTutorialByUsername = require("./getTutorialByUsername")
1313
const getTutorialBySubject = require("./getTutorialBySubject")
14+
const getSubmittedTutorials = require("./getSubmittedTutorials")
1415
const getSubjectTopics = require("./getSubjectTopics")
1516
const express = require("express")
1617
const redisClient = require("../redis-client")
@@ -58,6 +59,7 @@ apiRouter.delete("/remove/tutorial", deleteTutorial)
5859
apiRouter.get("/tutorials", getTutorials)
5960
apiRouter.get("/tutorial/:user/:tutorialName", getTutorialByUsername)
6061
apiRouter.get("/tutorial/:tutorialName", getTutorial)
62+
apiRouter.get("/tutorials/submitted", getSubmittedTutorials)
6163

6264
apiRouter.use(function(req, res) {
6365
const badRequest = new errors.BadRequestError("the url requested does not exist")

src/server/apis/submitTutorial.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
"use strict"
2+
const config = require("../../../config/config")()
3+
const domain = config.get("bin.domain")
24
const _ = require("lodash")
35
const github = require("../github-client")
46
const errors = require("../errors")
@@ -17,7 +19,7 @@ module.exports = async function(req, res) {
1719
try {
1820
// get authenticated user
1921
const username = await getUsername()
20-
const reviewUrl = `http://localhost:4000/review/${username}/${tutorialName}`
22+
const reviewUrl = `http://${domain}/review/${username}/${tutorialName}`
2123
submitDescription += `\n\n Here is the link to preview the tutorial [${reviewUrl}](${reviewUrl})`
2224
const head = `${username}:${branchPrefix}/${tutorialName}`
2325
const submitTitle = `merge tutorial ${tutorialName} into ${baseBranch}`

src/server/app.js

+1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ app.use("/chartist", express.static(path.resolve(__dirname, "..", "..", "node_mo
4444

4545
app.use("/v1", apis)
4646
app.get("/tutorial/:subject/:tutorialName", viewRouter.viewTutorial)
47+
app.get("/tutorials/submitted", viewRouter.submittedTutorials)
4748
app.get("/subject/:subject", viewRouter.getSubject)
4849
app.get("/editor/:tutorialName", viewRouter.viewEditor)
4950
app.get("/dashboard", viewRouter.viewDashboard)

src/server/routes/index.js

+2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ const viewPreview = require("./preview")
77
const reviewTutorial = require("./review")
88
const viewDashboard = require("./dashboard")
99
const viewTutorial = require("./viewTutorial")
10+
const submittedTutorials = require("./submittedTutorials")
1011
const getSubject = require("./subject")
1112
const viewError = require("./errorRouter")
1213
const subjectMap = require("../subjectMap.json")
@@ -25,6 +26,7 @@ module.exports = {
2526
reviewTutorial,
2627
viewDashboard,
2728
viewTutorial,
29+
submittedTutorials,
2830
getSubject,
2931
viewError,
3032
logout
+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
"use strict"
2+
3+
const _ = require("lodash")
4+
5+
module.exports = (req, res, next) => {
6+
_.set(req, "locals.view", "submitted-tutorials")
7+
next()
8+
}

0 commit comments

Comments
 (0)