feat(plugins/followup): add indepth mode (#627)

This commit is contained in:
Simon Lecoq
2021-11-12 00:34:40 -05:00
committed by GitHub
parent 42f46c2f75
commit 0a9df6270b
12 changed files with 457 additions and 126 deletions

View File

@@ -0,0 +1,11 @@
/**Mocked data */
export default function({faker, query, login = faker.internet.userName()}) {
console.debug("metrics/compute/mocks > mocking graphql api result > followup/repository/collaborators")
return ({
repository:{
collaborators:{
nodes:["github-user"]
}
},
})
}

View File

@@ -0,0 +1,14 @@
/**Mocked data */
export default function({faker, query, login = faker.internet.userName()}) {
console.debug("metrics/compute/mocks > mocking graphql api result > followup/repository")
return ({
issues_open:{issueCount:faker.datatype.number(100)},
issues_drafts:{issueCount:faker.datatype.number(100)},
issues_skipped:{issueCount:faker.datatype.number(100)},
issues_closed:{issueCount:faker.datatype.number(100)},
pr_open:{issueCount:faker.datatype.number(100)},
pr_drafts:{issueCount:faker.datatype.number(100)},
pr_closed:{issueCount:faker.datatype.number(100)},
pr_merged:{issueCount:faker.datatype.number(100)},
})
}

View File

@@ -2,12 +2,13 @@
export default function({faker, query, login = faker.internet.userName()}) { export default function({faker, query, login = faker.internet.userName()}) {
console.debug("metrics/compute/mocks > mocking graphql api result > followup/user") console.debug("metrics/compute/mocks > mocking graphql api result > followup/user")
return ({ return ({
user:{ issues_open:{issueCount:faker.datatype.number(100)},
issues_open:{totalCount:faker.datatype.number(100)}, issues_drafts:{issueCount:faker.datatype.number(100)},
issues_closed:{totalCount:faker.datatype.number(100)}, issues_skipped:{issueCount:faker.datatype.number(100)},
pr_open:{totalCount:faker.datatype.number(100)}, issues_closed:{issueCount:faker.datatype.number(100)},
pr_closed:{totalCount:faker.datatype.number(100)}, pr_open:{issueCount:faker.datatype.number(100)},
pr_merged:{totalCount:faker.datatype.number(100)}, pr_drafts:{issueCount:faker.datatype.number(100)},
}, pr_closed:{issueCount:faker.datatype.number(100)},
pr_merged:{issueCount:faker.datatype.number(100)},
}) })
} }

View File

@@ -178,36 +178,59 @@
sections: options["followup.sections"].split(",").map(x => x.trim()).filter(x => ["user", "repositories"].includes(x)), sections: options["followup.sections"].split(",").map(x => x.trim()).filter(x => ["user", "repositories"].includes(x)),
issues: { issues: {
get count() { get count() {
return this.open + this.closed return this.open + this.closed + this.drafts + this.skipped
}, },
open: faker.datatype.number(1000), open: faker.datatype.number(1000),
closed: faker.datatype.number(1000), closed: faker.datatype.number(1000),
drafts: faker.datatype.number(100),
skipped: faker.datatype.number(100),
get collaborators() {
return {
open: faker.datatype.number(this.open),
closed: faker.datatype.number(this.closed),
drafts: faker.datatype.number(this.drafts),
skipped: faker.datatype.number(this.skipped),
}
}
}, },
pr: { pr: {
get count() { get count() {
return this.open + this.merged return this.open + this.closed + this.merged + this.drafts
}, },
open: faker.datatype.number(1000), open: faker.datatype.number(1000),
closed: faker.datatype.number(1000), closed: faker.datatype.number(1000),
merged: faker.datatype.number(1000), merged: faker.datatype.number(1000),
drafts: faker.datatype.number(100),
get collaborators() {
return {
open: faker.datatype.number(this.open),
closed: faker.datatype.number(this.closed),
merged: faker.datatype.number(this.skipped),
drafts: faker.datatype.number(this.drafts),
}
}
}, },
user: { user: {
issues: { issues: {
get count() { get count() {
return this.open + this.closed return this.open + this.closed + this.drafts + this.skipped
}, },
open: faker.datatype.number(1000), open: faker.datatype.number(1000),
closed: faker.datatype.number(1000), closed: faker.datatype.number(1000),
drafts: faker.datatype.number(100),
skipped: faker.datatype.number(100),
}, },
pr: { pr: {
get count() { get count() {
return this.open + this.merged return this.open + this.closed + this.merged + this.drafts
}, },
open: faker.datatype.number(1000), open: faker.datatype.number(1000),
closed: faker.datatype.number(1000), closed: faker.datatype.number(1000),
merged: faker.datatype.number(1000), merged: faker.datatype.number(1000),
drafts: faker.datatype.number(100),
}, },
}, },
indepth:options["followup.indepth"] ? {} : null
}, },
}) })
: null), : null),

View File

@@ -1,5 +1,5 @@
//Setup //Setup
export default async function({login, data, computed, imports, q, graphql, queries, account}, {enabled = false} = {}) { export default async function({login, data, computed, imports, q, graphql, queries, account}, {enabled = false, extras = false} = {}) {
//Plugin execution //Plugin execution
try { try {
//Check if plugin is enabled and requirements are met //Check if plugin is enabled and requirements are met
@@ -7,14 +7,14 @@ export default async function({login, data, computed, imports, q, graphql, queri
return null return null
//Load inputs //Load inputs
let {sections} = imports.metadata.plugins.followup.inputs({data, account, q}) let {sections, indepth} = imports.metadata.plugins.followup.inputs({data, account, q})
//Define getters //Define getters
const followup = { const followup = {
sections, sections,
issues:{ issues:{
get count() { get count() {
return this.open + this.closed return this.open + this.closed + this.drafts + this.skipped
}, },
get open() { get open() {
return computed.repositories.issues_open return computed.repositories.issues_open
@@ -22,10 +22,18 @@ export default async function({login, data, computed, imports, q, graphql, queri
get closed() { get closed() {
return computed.repositories.issues_closed return computed.repositories.issues_closed
}, },
drafts:0,
skipped:0,
collaborators:{
open:0,
closed:0,
drafts:0,
skipped:0,
}
}, },
pr:{ pr:{
get count() { get count() {
return this.open + this.closed + this.merged return this.open + this.closed + this.merged + this.drafts
}, },
get open() { get open() {
return computed.repositories.pr_open return computed.repositories.pr_open
@@ -36,27 +44,72 @@ export default async function({login, data, computed, imports, q, graphql, queri
get merged() { get merged() {
return computed.repositories.pr_merged return computed.repositories.pr_merged
}, },
drafts:0,
collaborators:{
open:0,
closed:0,
merged:0,
drafts:0,
}
}, },
} }
//Extras features
if (extras) {
//Indepth mode
if (indepth) {
console.debug(`metrics/compute/${login}/plugins > followup > indepth`)
followup.indepth = {repositories:{}}
//Process repositories
for (const {name:repo, owner:{login:owner}} of data.user.repositories.nodes) {
try {
console.debug(`metrics/compute/${login}/plugins > followup > processing ${owner}/${repo}`)
followup.indepth.repositories[`${owner}/${repo}`] = {stats:{}}
//Fetch users with push access
let {repository:{collaborators:{nodes:collaborators}}} = await graphql(queries.followup["repository.collaborators"]({repo, owner}))
console.debug(`metrics/compute/${login}/plugins > followup > found ${collaborators.length} collaborators`)
followup.indepth.repositories[`${owner}/${repo}`].collaborators = collaborators.map(({login}) => login)
//Fetch issues and pull requests created by collaborators
collaborators = collaborators.map(({login}) => `-author:${login}`).join(" ")
const stats = await graphql(queries.followup.repository({repo, owner, collaborators}))
followup.indepth.repositories[`${owner}/${repo}`] = stats
//Aggregate global stats
for (const [key, {issueCount:count}] of Object.entries(stats)) {
const [section, type] = key.split("_")
followup[section].collaborators[type] += count
}
}
catch (error) {
console.debug(error)
console.debug(`metrics/compute/${login}/plugins > followup > an error occured while processing ${owner}/${repo}, skipping...`)
}
}
}
}
//Load user issues and pull requests //Load user issues and pull requests
if ((account === "user")&&(sections.includes("user"))) { if ((account === "user")&&(sections.includes("user"))) {
const {user} = await graphql(queries.followup.user({login})) const search = await graphql(queries.followup.user({login}))
followup.user = { followup.user = {
issues:{ issues:{
get count() { get count() {
return this.open + this.closed return this.open + this.closed + this.drafts + this.skipped
}, },
open:user.issues_open.totalCount, open:search.issues_open.issueCount,
closed:user.issues_closed.totalCount, closed:search.issues_closed.issueCount,
drafts:search.issues_drafts.issueCount,
skipped:search.issues_skipped.issueCount,
}, },
pr:{ pr:{
get count() { get count() {
return this.open + this.closed + this.merged return this.open + this.closed + this.merged + this.drafts
}, },
open:user.pr_open.totalCount, open:search.pr_open.issueCount,
closed:user.pr_closed.totalCount, closed:search.pr_closed.issueCount,
merged:user.pr_merged.totalCount, merged:search.pr_merged.issueCount,
drafts:search.pr_drafts.issueCount,
}, },
} }
} }

View File

@@ -22,3 +22,9 @@ inputs:
values: values:
- repositories # Overall status of issues and pull requests on your repositories - repositories # Overall status of issues and pull requests on your repositories
- user # Overall status of issues and pull requests you have created on GitHub - user # Overall status of issues and pull requests you have created on GitHub
# Compute issues and pull requests per repositories with special highlighting for maintainers and specified users
plugin_followup_indepth:
description: Indepth follow-up processing
type: boolean
default: no

View File

@@ -0,0 +1,9 @@
query FollowupRepositoryCollaborators {
repository(name: "$repo", owner: "$owner") {
collaborators {
nodes {
login
}
}
}
}

View File

@@ -0,0 +1,26 @@
query FollowupRepository {
issues_open:search(query: "repo:$owner/$repo is:issue $collaborators is:open", type: ISSUE, first: 0) {
issueCount
}
issues_drafts:search(query: "repo:$owner/$repo is:issue $collaborators draft:true", type: ISSUE, first: 0) {
issueCount
}
issues_skipped:search(query: "repo:$owner/$repo is:issue $collaborators is:closed label:wontfix,duplicate", type: ISSUE, first: 0) {
issueCount
}
issues_closed:search(query: "repo:$owner/$repo is:issue $collaborators is:closed", type: ISSUE, first: 0) {
issueCount
}
pr_open:search(query: "repo:$owner/$repo is:pr $collaborators is:open draft:false", type: ISSUE, first: 0) {
issueCount
}
pr_drafts:search(query: "repo:$owner/$repo is:pr $collaborators draft:true", type: ISSUE, first: 0) {
issueCount
}
pr_closed:search(query: "repo:$owner/$repo is:pr $collaborators is:unmerged draft:false", type: ISSUE, first: 0) {
issueCount
}
pr_merged:search(query: "repo:$owner/$repo is:pr $collaborators is:merged", type: ISSUE, first: 0) {
issueCount
}
}

View File

@@ -1,19 +1,26 @@
query FollowupUser { query FollowupUser {
user(login: "$login") { issues_open:search(query: "is:issue author:$login is:open", type: ISSUE, first: 0) {
issues_open:issues(states: OPEN) { issueCount
totalCount
} }
issues_closed:issues(states: CLOSED) { issues_drafts:search(query: "is:issue author:$login draft:true", type: ISSUE, first: 0) {
totalCount issueCount
} }
pr_open:pullRequests(states: OPEN) { issues_skipped:search(query: "is:issue author:$login is:closed label:wontfix,duplicate", type: ISSUE, first: 0) {
totalCount issueCount
} }
pr_closed:pullRequests(states: CLOSED) { issues_closed:search(query: "is:issue author:$login is:closed", type: ISSUE, first: 0) {
totalCount issueCount
} }
pr_merged:pullRequests(states: MERGED) { pr_open:search(query: "is:pr author:$login is:open draft:false", type: ISSUE, first: 0) {
totalCount issueCount
} }
pr_drafts:search(query: "is:pr author:$login draft:true", type: ISSUE, first: 0) {
issueCount
}
pr_closed:search(query: "is:pr author:$login is:unmerged draft:false", type: ISSUE, first: 0) {
issueCount
}
pr_merged:search(query: "is:pr author:$login is:merged", type: ISSUE, first: 0) {
issueCount
} }
} }

View File

@@ -26,19 +26,67 @@
<rect x="0" y="0" width="220" height="8" fill="white" rx="5"/> <rect x="0" y="0" width="220" height="8" fill="white" rx="5"/>
</mask> </mask>
<rect mask="url(#issues-bar)" x="0" y="0" width="<%= section.issues.count ? 0 : 220 %>" height="8" fill="#d1d5da"/> <rect mask="url(#issues-bar)" x="0" y="0" width="<%= section.issues.count ? 0 : 220 %>" height="8" fill="#d1d5da"/>
<rect mask="url(#issues-bar)" x="0" y="0" width="<%= (section.issues.open/section.issues.count)*220 || 0 %>" height="8" fill="#238636"/> <% { const {open, drafts, closed, skipped, count, collaborators = {open:0, drafts:0, closed:0, skipped:0}} = section.issues, width = 220; let x = 0; for (const {p, fill} of [
<rect mask="url(#issues-bar)" x="<%= (section.issues.open/section.issues.count)*220 || 0 %>" y="0" width="<%= (1-section.issues.open/section.issues.count)*220 || 0 %>" height="8" fill="#8957e5"/> {p:(open-collaborators.open)/count, fill:"#238636"},
{p:collaborators.open/count, fill:"#56d364"},
{p:(drafts-collaborators.drafts)/count, fill:"#8B949E"},
{p:collaborators.drafts/count, fill:"#c9d1d9"},
{p:(closed-collaborators.closed)/count, fill:"#8957e5"},
{p:collaborators.closed/count, fill:"#d2a8ff"},
{p:(skipped-collaborators.skipped)/count, fill:"#8B949E"},
{p:collaborators.skipped/count, fill:"#c9d1d9"},
]) { %>
<rect mask="url(#issues-bar)" x="<%= x %>" y="0" width="<%= p*width || 0 %>" height="8" fill="<%= fill %>"/>
<% x += p*width }} %>
</svg> </svg>
<div class="followup legend field horizontal fill-width"> <% if ((plugins.followup.indepth)&&(section.issues.collaborators)) { %>
<div class="field center"> <div class="field blue fill-width">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M5.5 3.5a2 2 0 100 4 2 2 0 000-4zM2 5.5a3.5 3.5 0 115.898 2.549 5.507 5.507 0 013.034 4.084.75.75 0 11-1.482.235 4.001 4.001 0 00-7.9 0 .75.75 0 01-1.482-.236A5.507 5.507 0 013.102 8.05 3.49 3.49 0 012 5.5zM11 4a.75.75 0 100 1.5 1.5 1.5 0 01.666 2.844.75.75 0 00-.416.672v.352a.75.75 0 00.574.73c1.2.289 2.162 1.2 2.522 2.372a.75.75 0 101.434-.44 5.01 5.01 0 00-2.56-3.012A3 3 0 0011 4z"></path></svg>
From communities
</div>
<% } %>
<div class="followup legend field fill-width">
<div class="field">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill="#238636" d="M8 9.5a1.5 1.5 0 100-3 1.5 1.5 0 000 3z"></path><path fill="#238636" fill-rule="evenodd" d="M8 0a8 8 0 100 16A8 8 0 008 0zM1.5 8a6.5 6.5 0 1113 0 6.5 6.5 0 01-13 0z"></path></svg> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill="#238636" d="M8 9.5a1.5 1.5 0 100-3 1.5 1.5 0 000 3z"></path><path fill="#238636" fill-rule="evenodd" d="M8 0a8 8 0 100 16A8 8 0 008 0zM1.5 8a6.5 6.5 0 1113 0 6.5 6.5 0 01-13 0z"></path></svg>
<span class="no-wrap"><%= section.issues.open %> <small>open</small></span> <span class="no-wrap"><%= section.issues.open %> <small>open</small></span>
</div> </div>
<div class="field center"> <div class="field">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill="#8957e5" d="M11.28 6.78a.75.75 0 00-1.06-1.06L7.25 8.69 5.78 7.22a.75.75 0 00-1.06 1.06l2 2a.75.75 0 001.06 0l3.5-3.5z"></path><path fill="#8957e5" fill-rule="evenodd" d="M16 8A8 8 0 110 8a8 8 0 0116 0zm-1.5 0a6.5 6.5 0 11-13 0 6.5 6.5 0 0113 0z"></path></svg> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill="#8957e5" d="M11.28 6.78a.75.75 0 00-1.06-1.06L7.25 8.69 5.78 7.22a.75.75 0 00-1.06 1.06l2 2a.75.75 0 001.06 0l3.5-3.5z"></path><path fill="#8957e5" fill-rule="evenodd" d="M16 8A8 8 0 110 8a8 8 0 0116 0zm-1.5 0a6.5 6.5 0 11-13 0 6.5 6.5 0 0113 0z"></path></svg>
<span class="no-wrap"><%= section.issues.closed %> <small>closed</small></span> <span class="no-wrap"><%= section.issues.closed %> <small>closed</small></span>
</div> </div>
<div class="field">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill="#8B949E" d="M6.749.097a8.054 8.054 0 012.502 0 .75.75 0 11-.233 1.482 6.554 6.554 0 00-2.036 0A.75.75 0 016.749.097zM4.345 1.693A.75.75 0 014.18 2.74a6.542 6.542 0 00-1.44 1.44.75.75 0 01-1.212-.883 8.042 8.042 0 011.769-1.77.75.75 0 011.048.166zm7.31 0a.75.75 0 011.048-.165 8.04 8.04 0 011.77 1.769.75.75 0 11-1.214.883 6.542 6.542 0 00-1.439-1.44.75.75 0 01-.165-1.047zM.955 6.125a.75.75 0 01.624.857 6.554 6.554 0 000 2.036.75.75 0 01-1.482.233 8.054 8.054 0 010-2.502.75.75 0 01.858-.624zm14.09 0a.75.75 0 01.858.624 8.057 8.057 0 010 2.502.75.75 0 01-1.482-.233 6.55 6.55 0 000-2.036.75.75 0 01.624-.857zm-13.352 5.53a.75.75 0 011.048.165 6.542 6.542 0 001.439 1.44.75.75 0 01-.883 1.212 8.04 8.04 0 01-1.77-1.769.75.75 0 01.166-1.048zm12.614 0a.75.75 0 01.165 1.048 8.038 8.038 0 01-1.769 1.77.75.75 0 11-.883-1.214 6.543 6.543 0 001.44-1.439.75.75 0 011.047-.165zm-8.182 3.39a.75.75 0 01.857-.624 6.55 6.55 0 002.036 0 .75.75 0 01.233 1.482 8.057 8.057 0 01-2.502 0 .75.75 0 01-.624-.858z"></path></svg>
<span class="no-wrap"><%= section.issues.drafts %> <small>draft<%= s(section.issues.drafts) %></small></span>
</div> </div>
<div class="field">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill="#8B949E" d="M1.5 8a6.5 6.5 0 1113 0 6.5 6.5 0 01-13 0zM8 0a8 8 0 100 16A8 8 0 008 0zm3.28 5.78a.75.75 0 00-1.06-1.06l-5.5 5.5a.75.75 0 101.06 1.06l5.5-5.5z"></path></svg>
<span class="no-wrap"><%= section.issues.skipped %> <small>skipped</small></span>
</div>
</div>
<% if ((plugins.followup.indepth)&&(section.issues.collaborators)) { %>
<div class="field blue fill-width">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M13.25 0a.75.75 0 01.75.75V2h1.25a.75.75 0 010 1.5H14v1.25a.75.75 0 01-1.5 0V3.5h-1.25a.75.75 0 010-1.5h1.25V.75a.75.75 0 01.75-.75zM5.5 4a2 2 0 100 4 2 2 0 000-4zm2.4 4.548a3.5 3.5 0 10-4.799 0 5.527 5.527 0 00-3.1 4.66.75.75 0 101.498.085A4.01 4.01 0 015.5 9.5a4.01 4.01 0 014.001 3.793.75.75 0 101.498-.086 5.527 5.527 0 00-3.1-4.659z"></path></svg>
From self and collaborators
</div>
<div class="followup legend field fill-width">
<div class="field">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill="#56d364" d="M8 9.5a1.5 1.5 0 100-3 1.5 1.5 0 000 3z"></path><path fill="#56d364" fill-rule="evenodd" d="M8 0a8 8 0 100 16A8 8 0 008 0zM1.5 8a6.5 6.5 0 1113 0 6.5 6.5 0 01-13 0z"></path></svg>
<span class="no-wrap"><%= section.issues.collaborators.open %> <small>open</small></span>
</div>
<div class="field">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill="#d2a8ff" d="M11.28 6.78a.75.75 0 00-1.06-1.06L7.25 8.69 5.78 7.22a.75.75 0 00-1.06 1.06l2 2a.75.75 0 001.06 0l3.5-3.5z"></path><path fill="#d2a8ff" fill-rule="evenodd" d="M16 8A8 8 0 110 8a8 8 0 0116 0zm-1.5 0a6.5 6.5 0 11-13 0 6.5 6.5 0 0113 0z"></path></svg>
<span class="no-wrap"><%= section.issues.collaborators.closed %> <small>closed</small></span>
</div>
<div class="field">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill="#c9d1d9" d="M6.749.097a8.054 8.054 0 012.502 0 .75.75 0 11-.233 1.482 6.554 6.554 0 00-2.036 0A.75.75 0 016.749.097zM4.345 1.693A.75.75 0 014.18 2.74a6.542 6.542 0 00-1.44 1.44.75.75 0 01-1.212-.883 8.042 8.042 0 011.769-1.77.75.75 0 011.048.166zm7.31 0a.75.75 0 011.048-.165 8.04 8.04 0 011.77 1.769.75.75 0 11-1.214.883 6.542 6.542 0 00-1.439-1.44.75.75 0 01-.165-1.047zM.955 6.125a.75.75 0 01.624.857 6.554 6.554 0 000 2.036.75.75 0 01-1.482.233 8.054 8.054 0 010-2.502.75.75 0 01.858-.624zm14.09 0a.75.75 0 01.858.624 8.057 8.057 0 010 2.502.75.75 0 01-1.482-.233 6.55 6.55 0 000-2.036.75.75 0 01.624-.857zm-13.352 5.53a.75.75 0 011.048.165 6.542 6.542 0 001.439 1.44.75.75 0 01-.883 1.212 8.04 8.04 0 01-1.77-1.769.75.75 0 01.166-1.048zm12.614 0a.75.75 0 01.165 1.048 8.038 8.038 0 01-1.769 1.77.75.75 0 11-.883-1.214 6.543 6.543 0 001.44-1.439.75.75 0 011.047-.165zm-8.182 3.39a.75.75 0 01.857-.624 6.55 6.55 0 002.036 0 .75.75 0 01.233 1.482 8.057 8.057 0 01-2.502 0 .75.75 0 01-.624-.858z"></path></svg>
<span class="no-wrap"><%= section.issues.collaborators.drafts %> <small>draft<%= s(section.issues.collaborators.drafts) %></small></span>
</div>
<div class="field">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill="#c9d1d9" d="M1.5 8a6.5 6.5 0 1113 0 6.5 6.5 0 01-13 0zM8 0a8 8 0 100 16A8 8 0 008 0zm3.28 5.78a.75.75 0 00-1.06-1.06l-5.5 5.5a.75.75 0 101.06 1.06l5.5-5.5z"></path></svg>
<span class="no-wrap"><%= section.issues.collaborators.skipped %> <small>skipped</small></span>
</div>
</div>
<% } %>
</section> </section>
<section class="column"> <section class="column">
<h3 class="no-margin-top">Pull requests</h3> <h3 class="no-margin-top">Pull requests</h3>
@@ -47,24 +95,67 @@
<rect x="0" y="0" width="220" height="8" fill="white" rx="5"/> <rect x="0" y="0" width="220" height="8" fill="white" rx="5"/>
</mask> </mask>
<rect mask="url(#pr-bar)" x="0" y="0" width="<%= section.pr.count ? 0 : 220 %>" height="8" fill="#d1d5da"/> <rect mask="url(#pr-bar)" x="0" y="0" width="<%= section.pr.count ? 0 : 220 %>" height="8" fill="#d1d5da"/>
<rect mask="url(#pr-bar)" x="0" y="0" width="<%= (section.pr.open/section.pr.count)*220 || 0 %>" height="8" fill="#238636"/> <% { const {open, drafts, closed, merged, count, collaborators = {open:0, drafts:0, closed:0, merged:0}} = section.pr, width = 220; let x = 0; for (const {p, fill} of [
<rect mask="url(#pr-bar)" x="<%= (section.pr.open/section.pr.count)*220 || 0 %>" y="0" width="<%= (section.pr.closed/section.pr.count)*220 || 0 %>" height="8" fill="#da3633"/> {p:(open-collaborators.open)/count, fill:"#238636"},
<rect mask="url(#pr-bar)" x="<%= ((section.pr.open+section.pr.closed)/section.pr.count)*220 || 0 %>" y="0" width="<%= (1-(section.pr.open+section.pr.closed)/section.pr.count)*220 || 0 %>" height="8" fill="#8957e5"/> {p:collaborators.open/count, fill:"#56d364"},
{p:(drafts-collaborators.drafts)/count, fill:"#8B949E"},
{p:collaborators.drafts/count, fill:"#c9d1d9"},
{p:(closed-collaborators.closed)/count, fill:"#da3633"},
{p:collaborators.closed/count, fill:"#ff7b72"},
{p:(merged-collaborators.merged)/count, fill:"#8957e5"},
{p:collaborators.merged/count, fill:"#d2a8ff"},
]) { %>
<rect mask="url(#issues-bar)" x="<%= x %>" y="0" width="<%= p*width || 0 %>" height="8" fill="<%= fill %>"/>
<% x += p*width }} %>
</svg> </svg>
<div class="followup legend field horizontal fill-width"> <% if ((plugins.followup.indepth)&&(section.pr.collaborators)) { %>
<div class="field center"> <div class="field blue fill-width">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M5.5 3.5a2 2 0 100 4 2 2 0 000-4zM2 5.5a3.5 3.5 0 115.898 2.549 5.507 5.507 0 013.034 4.084.75.75 0 11-1.482.235 4.001 4.001 0 00-7.9 0 .75.75 0 01-1.482-.236A5.507 5.507 0 013.102 8.05 3.49 3.49 0 012 5.5zM11 4a.75.75 0 100 1.5 1.5 1.5 0 01.666 2.844.75.75 0 00-.416.672v.352a.75.75 0 00.574.73c1.2.289 2.162 1.2 2.522 2.372a.75.75 0 101.434-.44 5.01 5.01 0 00-2.56-3.012A3 3 0 0011 4z"></path></svg>
From communities
</div>
<% } %>
<div class="followup legend field fill-width">
<div class="field">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill="#238636" fill-rule="evenodd" d="M7.177 3.073L9.573.677A.25.25 0 0110 .854v4.792a.25.25 0 01-.427.177L7.177 3.427a.25.25 0 010-.354zM3.75 2.5a.75.75 0 100 1.5.75.75 0 000-1.5zm-2.25.75a2.25 2.25 0 113 2.122v5.256a2.251 2.251 0 11-1.5 0V5.372A2.25 2.25 0 011.5 3.25zM11 2.5h-1V4h1a1 1 0 011 1v5.628a2.251 2.251 0 101.5 0V5A2.5 2.5 0 0011 2.5zm1 10.25a.75.75 0 111.5 0 .75.75 0 01-1.5 0zM3.75 12a.75.75 0 100 1.5.75.75 0 000-1.5z"></path></svg> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill="#238636" fill-rule="evenodd" d="M7.177 3.073L9.573.677A.25.25 0 0110 .854v4.792a.25.25 0 01-.427.177L7.177 3.427a.25.25 0 010-.354zM3.75 2.5a.75.75 0 100 1.5.75.75 0 000-1.5zm-2.25.75a2.25 2.25 0 113 2.122v5.256a2.251 2.251 0 11-1.5 0V5.372A2.25 2.25 0 011.5 3.25zM11 2.5h-1V4h1a1 1 0 011 1v5.628a2.251 2.251 0 101.5 0V5A2.5 2.5 0 0011 2.5zm1 10.25a.75.75 0 111.5 0 .75.75 0 01-1.5 0zM3.75 12a.75.75 0 100 1.5.75.75 0 000-1.5z"></path></svg>
<span class="no-wrap"><%= section.pr.open %> <small>open</small></span> <span class="no-wrap"><%= section.pr.open %> <small>open</small></span>
</div> </div>
<div class="field center"> <div class="field">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill="#da3633" fill-rule="evenodd" d="M10.72 1.227a.75.75 0 011.06 0l.97.97.97-.97a.75.75 0 111.06 1.061l-.97.97.97.97a.75.75 0 01-1.06 1.06l-.97-.97-.97.97a.75.75 0 11-1.06-1.06l.97-.97-.97-.97a.75.75 0 010-1.06zM12.75 6.5a.75.75 0 00-.75.75v3.378a2.251 2.251 0 101.5 0V7.25a.75.75 0 00-.75-.75zm0 5.5a.75.75 0 100 1.5.75.75 0 000-1.5zM2.5 3.25a.75.75 0 111.5 0 .75.75 0 01-1.5 0zM3.25 1a2.25 2.25 0 00-.75 4.372v5.256a2.251 2.251 0 101.5 0V5.372A2.25 2.25 0 003.25 1zm0 11a.75.75 0 100 1.5.75.75 0 000-1.5z"></path></svg>
<span class="no-wrap"><%= section.pr.closed %> <small>closed</small></span>
</div>
<div class="field center">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill="#8957e5" fill-rule="evenodd" d="M5 3.254V3.25v.005a.75.75 0 110-.005v.004zm.45 1.9a2.25 2.25 0 10-1.95.218v5.256a2.25 2.25 0 101.5 0V7.123A5.735 5.735 0 009.25 9h1.378a2.251 2.251 0 100-1.5H9.25a4.25 4.25 0 01-3.8-2.346zM12.75 9a.75.75 0 100-1.5.75.75 0 000 1.5zm-8.5 4.5a.75.75 0 100-1.5.75.75 0 000 1.5z"></path></svg> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill="#8957e5" fill-rule="evenodd" d="M5 3.254V3.25v.005a.75.75 0 110-.005v.004zm.45 1.9a2.25 2.25 0 10-1.95.218v5.256a2.25 2.25 0 101.5 0V7.123A5.735 5.735 0 009.25 9h1.378a2.251 2.251 0 100-1.5H9.25a4.25 4.25 0 01-3.8-2.346zM12.75 9a.75.75 0 100-1.5.75.75 0 000 1.5zm-8.5 4.5a.75.75 0 100-1.5.75.75 0 000 1.5z"></path></svg>
<span class="no-wrap"><%= section.pr.merged %> <small>merged</small></span> <span class="no-wrap"><%= section.pr.merged %> <small>merged</small></span>
</div> </div>
<div class="field">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill="#8B949E" d="M2.5 3.25a.75.75 0 111.5 0 .75.75 0 01-1.5 0zM3.25 1a2.25 2.25 0 00-.75 4.372v5.256a2.251 2.251 0 101.5 0V5.372A2.25 2.25 0 003.25 1zm0 11a.75.75 0 100 1.5.75.75 0 000-1.5zm9.5 3a2.25 2.25 0 100-4.5 2.25 2.25 0 000 4.5zm0-3a.75.75 0 100 1.5.75.75 0 000-1.5z"></path><path d="M14 7.5a1.25 1.25 0 11-2.5 0 1.25 1.25 0 012.5 0zm0-4.25a1.25 1.25 0 11-2.5 0 1.25 1.25 0 012.5 0z"></path></svg>
<span class="no-wrap"><%= section.pr.drafts %> <small>draft<%= s(section.pr.drafts) %></small></span>
</div> </div>
<div class="field">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill="#da3633" fill-rule="evenodd" d="M10.72 1.227a.75.75 0 011.06 0l.97.97.97-.97a.75.75 0 111.06 1.061l-.97.97.97.97a.75.75 0 01-1.06 1.06l-.97-.97-.97.97a.75.75 0 11-1.06-1.06l.97-.97-.97-.97a.75.75 0 010-1.06zM12.75 6.5a.75.75 0 00-.75.75v3.378a2.251 2.251 0 101.5 0V7.25a.75.75 0 00-.75-.75zm0 5.5a.75.75 0 100 1.5.75.75 0 000-1.5zM2.5 3.25a.75.75 0 111.5 0 .75.75 0 01-1.5 0zM3.25 1a2.25 2.25 0 00-.75 4.372v5.256a2.251 2.251 0 101.5 0V5.372A2.25 2.25 0 003.25 1zm0 11a.75.75 0 100 1.5.75.75 0 000-1.5z"></path></svg>
<span class="no-wrap"><%= section.pr.closed %> <small>closed</small></span>
</div>
</div>
<% if ((plugins.followup.indepth)&&(section.pr.collaborators)) { %>
<div class="field blue fill-width">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M13.25 0a.75.75 0 01.75.75V2h1.25a.75.75 0 010 1.5H14v1.25a.75.75 0 01-1.5 0V3.5h-1.25a.75.75 0 010-1.5h1.25V.75a.75.75 0 01.75-.75zM5.5 4a2 2 0 100 4 2 2 0 000-4zm2.4 4.548a3.5 3.5 0 10-4.799 0 5.527 5.527 0 00-3.1 4.66.75.75 0 101.498.085A4.01 4.01 0 015.5 9.5a4.01 4.01 0 014.001 3.793.75.75 0 101.498-.086 5.527 5.527 0 00-3.1-4.659z"></path></svg>
From self and collaborators
</div>
<div class="followup legend field fill-width">
<div class="field">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill="#56d364" fill-rule="evenodd" d="M7.177 3.073L9.573.677A.25.25 0 0110 .854v4.792a.25.25 0 01-.427.177L7.177 3.427a.25.25 0 010-.354zM3.75 2.5a.75.75 0 100 1.5.75.75 0 000-1.5zm-2.25.75a2.25 2.25 0 113 2.122v5.256a2.251 2.251 0 11-1.5 0V5.372A2.25 2.25 0 011.5 3.25zM11 2.5h-1V4h1a1 1 0 011 1v5.628a2.251 2.251 0 101.5 0V5A2.5 2.5 0 0011 2.5zm1 10.25a.75.75 0 111.5 0 .75.75 0 01-1.5 0zM3.75 12a.75.75 0 100 1.5.75.75 0 000-1.5z"></path></svg>
<span class="no-wrap"><%= section.pr.collaborators.open %> <small>open</small></span>
</div>
<div class="field">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill="#d2a8ff" fill-rule="evenodd" d="M5 3.254V3.25v.005a.75.75 0 110-.005v.004zm.45 1.9a2.25 2.25 0 10-1.95.218v5.256a2.25 2.25 0 101.5 0V7.123A5.735 5.735 0 009.25 9h1.378a2.251 2.251 0 100-1.5H9.25a4.25 4.25 0 01-3.8-2.346zM12.75 9a.75.75 0 100-1.5.75.75 0 000 1.5zm-8.5 4.5a.75.75 0 100-1.5.75.75 0 000 1.5z"></path></svg>
<span class="no-wrap"><%= section.pr.collaborators.merged %> <small>merged</small></span>
</div>
<div class="field">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill="#c9d1d9" d="M2.5 3.25a.75.75 0 111.5 0 .75.75 0 01-1.5 0zM3.25 1a2.25 2.25 0 00-.75 4.372v5.256a2.251 2.251 0 101.5 0V5.372A2.25 2.25 0 003.25 1zm0 11a.75.75 0 100 1.5.75.75 0 000-1.5zm9.5 3a2.25 2.25 0 100-4.5 2.25 2.25 0 000 4.5zm0-3a.75.75 0 100 1.5.75.75 0 000-1.5z"></path><path d="M14 7.5a1.25 1.25 0 11-2.5 0 1.25 1.25 0 012.5 0zm0-4.25a1.25 1.25 0 11-2.5 0 1.25 1.25 0 012.5 0z"></path></svg>
<span class="no-wrap"><%= section.pr.collaborators.drafts %> <small>draft<%= s(section.pr.collaborators.drafts) %></small></span>
</div>
<div class="field">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill="#ff7b72" fill-rule="evenodd" d="M10.72 1.227a.75.75 0 011.06 0l.97.97.97-.97a.75.75 0 111.06 1.061l-.97.97.97.97a.75.75 0 01-1.06 1.06l-.97-.97-.97.97a.75.75 0 11-1.06-1.06l.97-.97-.97-.97a.75.75 0 010-1.06zM12.75 6.5a.75.75 0 00-.75.75v3.378a2.251 2.251 0 101.5 0V7.25a.75.75 0 00-.75-.75zm0 5.5a.75.75 0 100 1.5.75.75 0 000-1.5zM2.5 3.25a.75.75 0 111.5 0 .75.75 0 01-1.5 0zM3.25 1a2.25 2.25 0 00-.75 4.372v5.256a2.251 2.251 0 101.5 0V5.372A2.25 2.25 0 003.25 1zm0 11a.75.75 0 100 1.5.75.75 0 000-1.5z"></path></svg>
<span class="no-wrap"><%= section.pr.collaborators.closed %> <small>closed</small></span>
</div>
</div>
<% } %>
</section> </section>
</div> </div>
</div> </div>

View File

@@ -274,6 +274,12 @@
/* Follow-up */ /* Follow-up */
.followup.legend { .followup.legend {
font-size: 12px; font-size: 12px;
flex-wrap: wrap;
}
.followup.legend .field {
width: 46%;
justify-content: flex-start;
margin-left: 8px;
} }
.followup.legend svg { .followup.legend svg {
margin: 0 3px; margin: 0 3px;

View File

@@ -1,8 +1,10 @@
<% if (plugins.followup) { %> <% if (plugins.followup) { %>
<div class="row"> <section>
<h2 class="field">
<section class="column"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M6 2a.75.75 0 01.696.471L10 10.731l1.304-3.26A.75.75 0 0112 7h3.25a.75.75 0 010 1.5h-2.742l-1.812 4.528a.75.75 0 01-1.392 0L6 4.77 4.696 8.03A.75.75 0 014 8.5H.75a.75.75 0 010-1.5h2.742l1.812-4.529A.75.75 0 016 2z"></path></svg>
<h3>Issues</h3> <span class="followup-title">Overall issues and pull requests status</span>
</h2>
</section>
<% if (plugins.followup.error) { %> <% if (plugins.followup.error) { %>
<section> <section>
<div class="field error"> <div class="field error">
@@ -10,67 +12,149 @@
<%= plugins.followup.error.message %> <%= plugins.followup.error.message %>
</div> </div>
</section> </section>
<% } else { const section = plugins.followup, width = 220*(1+large) %> <% } else { %>
<% const section = plugins.followup %>
<div class="column largeable">
<div class="row fill-width">
<section class="column"> <section class="column">
<svg class="bar" xmlns="http://www.w3.org/2000/svg" width="<%= width %>" height="8"> <h3 class="no-margin-top">Issues</h3>
<svg class="bar" xmlns="http://www.w3.org/2000/svg" width="220" height="8">
<mask id="issues-bar"> <mask id="issues-bar">
<rect x="0" y="0" width="<%= width %>" height="8" fill="white" rx="5"/> <rect x="0" y="0" width="220" height="8" fill="white" rx="5"/>
</mask> </mask>
<rect mask="url(#issues-bar)" x="0" y="0" width="<%= section.issues.count ? 0 : width %>" height="8" fill="#d1d5da"/> <rect mask="url(#issues-bar)" x="0" y="0" width="<%= section.issues.count ? 0 : 220 %>" height="8" fill="#d1d5da"/>
<rect mask="url(#issues-bar)" x="0" y="0" width="<%= (section.issues.open/section.issues.count)*width || 0 %>" height="8" fill="#238636"/> <% { const {open, drafts, closed, skipped, count, collaborators = {open:0, drafts:0, closed:0, skipped:0}} = section.issues, width = 220; let x = 0; for (const {p, fill} of [
<rect mask="url(#issues-bar)" x="<%= (section.issues.open/section.issues.count)*width || 0 %>" y="0" width="<%= (1-section.issues.open/section.issues.count)*width || 0 %>" height="8" fill="#8957e5"/> {p:(open-collaborators.open)/count, fill:"#238636"},
{p:collaborators.open/count, fill:"#56d364"},
{p:(drafts-collaborators.drafts)/count, fill:"#8B949E"},
{p:collaborators.drafts/count, fill:"#c9d1d9"},
{p:(closed-collaborators.closed)/count, fill:"#8957e5"},
{p:collaborators.closed/count, fill:"#d2a8ff"},
{p:(skipped-collaborators.skipped)/count, fill:"#8B949E"},
{p:collaborators.skipped/count, fill:"#c9d1d9"},
]) { %>
<rect mask="url(#issues-bar)" x="<%= x %>" y="0" width="<%= p*width || 0 %>" height="8" fill="<%= fill %>"/>
<% x += p*width }} %>
</svg> </svg>
<div class="followup legend field horizontal fill-width"> <% if ((plugins.followup.indepth)&&(section.issues.collaborators)) { %>
<div class="field center"> <div class="field blue fill-width">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M5.5 3.5a2 2 0 100 4 2 2 0 000-4zM2 5.5a3.5 3.5 0 115.898 2.549 5.507 5.507 0 013.034 4.084.75.75 0 11-1.482.235 4.001 4.001 0 00-7.9 0 .75.75 0 01-1.482-.236A5.507 5.507 0 013.102 8.05 3.49 3.49 0 012 5.5zM11 4a.75.75 0 100 1.5 1.5 1.5 0 01.666 2.844.75.75 0 00-.416.672v.352a.75.75 0 00.574.73c1.2.289 2.162 1.2 2.522 2.372a.75.75 0 101.434-.44 5.01 5.01 0 00-2.56-3.012A3 3 0 0011 4z"></path></svg>
From community
</div>
<% } %>
<div class="followup legend field fill-width">
<div class="field">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill="#238636" d="M8 9.5a1.5 1.5 0 100-3 1.5 1.5 0 000 3z"></path><path fill="#238636" fill-rule="evenodd" d="M8 0a8 8 0 100 16A8 8 0 008 0zM1.5 8a6.5 6.5 0 1113 0 6.5 6.5 0 01-13 0z"></path></svg> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill="#238636" d="M8 9.5a1.5 1.5 0 100-3 1.5 1.5 0 000 3z"></path><path fill="#238636" fill-rule="evenodd" d="M8 0a8 8 0 100 16A8 8 0 008 0zM1.5 8a6.5 6.5 0 1113 0 6.5 6.5 0 01-13 0z"></path></svg>
<span class="no-wrap"><%= section.issues.open %> <small>open</small></span> <span class="no-wrap"><%= section.issues.open %> <small>open</small></span>
</div> </div>
<div class="field center"> <div class="field">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill="#8957e5" d="M11.28 6.78a.75.75 0 00-1.06-1.06L7.25 8.69 5.78 7.22a.75.75 0 00-1.06 1.06l2 2a.75.75 0 001.06 0l3.5-3.5z"></path><path fill="#8957e5" fill-rule="evenodd" d="M16 8A8 8 0 110 8a8 8 0 0116 0zm-1.5 0a6.5 6.5 0 11-13 0 6.5 6.5 0 0113 0z"></path></svg> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill="#8957e5" d="M11.28 6.78a.75.75 0 00-1.06-1.06L7.25 8.69 5.78 7.22a.75.75 0 00-1.06 1.06l2 2a.75.75 0 001.06 0l3.5-3.5z"></path><path fill="#8957e5" fill-rule="evenodd" d="M16 8A8 8 0 110 8a8 8 0 0116 0zm-1.5 0a6.5 6.5 0 11-13 0 6.5 6.5 0 0113 0z"></path></svg>
<span class="no-wrap"><%= section.issues.closed %> <small>closed</small></span> <span class="no-wrap"><%= section.issues.closed %> <small>closed</small></span>
</div> </div>
<div class="field">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill="#8B949E" d="M6.749.097a8.054 8.054 0 012.502 0 .75.75 0 11-.233 1.482 6.554 6.554 0 00-2.036 0A.75.75 0 016.749.097zM4.345 1.693A.75.75 0 014.18 2.74a6.542 6.542 0 00-1.44 1.44.75.75 0 01-1.212-.883 8.042 8.042 0 011.769-1.77.75.75 0 011.048.166zm7.31 0a.75.75 0 011.048-.165 8.04 8.04 0 011.77 1.769.75.75 0 11-1.214.883 6.542 6.542 0 00-1.439-1.44.75.75 0 01-.165-1.047zM.955 6.125a.75.75 0 01.624.857 6.554 6.554 0 000 2.036.75.75 0 01-1.482.233 8.054 8.054 0 010-2.502.75.75 0 01.858-.624zm14.09 0a.75.75 0 01.858.624 8.057 8.057 0 010 2.502.75.75 0 01-1.482-.233 6.55 6.55 0 000-2.036.75.75 0 01.624-.857zm-13.352 5.53a.75.75 0 011.048.165 6.542 6.542 0 001.439 1.44.75.75 0 01-.883 1.212 8.04 8.04 0 01-1.77-1.769.75.75 0 01.166-1.048zm12.614 0a.75.75 0 01.165 1.048 8.038 8.038 0 01-1.769 1.77.75.75 0 11-.883-1.214 6.543 6.543 0 001.44-1.439.75.75 0 011.047-.165zm-8.182 3.39a.75.75 0 01.857-.624 6.55 6.55 0 002.036 0 .75.75 0 01.233 1.482 8.057 8.057 0 01-2.502 0 .75.75 0 01-.624-.858z"></path></svg>
<span class="no-wrap"><%= section.issues.drafts %> <small>draft<%= s(section.issues.drafts) %></small></span>
</div>
<div class="field">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill="#8B949E" d="M1.5 8a6.5 6.5 0 1113 0 6.5 6.5 0 01-13 0zM8 0a8 8 0 100 16A8 8 0 008 0zm3.28 5.78a.75.75 0 00-1.06-1.06l-5.5 5.5a.75.75 0 101.06 1.06l5.5-5.5z"></path></svg>
<span class="no-wrap"><%= section.issues.skipped %> <small>skipped</small></span>
</div>
</div>
<% if ((plugins.followup.indepth)&&(section.issues.collaborators)) { %>
<div class="field blue fill-width">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M13.25 0a.75.75 0 01.75.75V2h1.25a.75.75 0 010 1.5H14v1.25a.75.75 0 01-1.5 0V3.5h-1.25a.75.75 0 010-1.5h1.25V.75a.75.75 0 01.75-.75zM5.5 4a2 2 0 100 4 2 2 0 000-4zm2.4 4.548a3.5 3.5 0 10-4.799 0 5.527 5.527 0 00-3.1 4.66.75.75 0 101.498.085A4.01 4.01 0 015.5 9.5a4.01 4.01 0 014.001 3.793.75.75 0 101.498-.086 5.527 5.527 0 00-3.1-4.659z"></path></svg>
From maintainers
</div>
<div class="followup legend field fill-width">
<div class="field">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill="#56d364" d="M8 9.5a1.5 1.5 0 100-3 1.5 1.5 0 000 3z"></path><path fill="#56d364" fill-rule="evenodd" d="M8 0a8 8 0 100 16A8 8 0 008 0zM1.5 8a6.5 6.5 0 1113 0 6.5 6.5 0 01-13 0z"></path></svg>
<span class="no-wrap"><%= section.issues.collaborators.open %> <small>open</small></span>
</div>
<div class="field">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill="#d2a8ff" d="M11.28 6.78a.75.75 0 00-1.06-1.06L7.25 8.69 5.78 7.22a.75.75 0 00-1.06 1.06l2 2a.75.75 0 001.06 0l3.5-3.5z"></path><path fill="#d2a8ff" fill-rule="evenodd" d="M16 8A8 8 0 110 8a8 8 0 0116 0zm-1.5 0a6.5 6.5 0 11-13 0 6.5 6.5 0 0113 0z"></path></svg>
<span class="no-wrap"><%= section.issues.collaborators.closed %> <small>closed</small></span>
</div>
<div class="field">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill="#c9d1d9" d="M6.749.097a8.054 8.054 0 012.502 0 .75.75 0 11-.233 1.482 6.554 6.554 0 00-2.036 0A.75.75 0 016.749.097zM4.345 1.693A.75.75 0 014.18 2.74a6.542 6.542 0 00-1.44 1.44.75.75 0 01-1.212-.883 8.042 8.042 0 011.769-1.77.75.75 0 011.048.166zm7.31 0a.75.75 0 011.048-.165 8.04 8.04 0 011.77 1.769.75.75 0 11-1.214.883 6.542 6.542 0 00-1.439-1.44.75.75 0 01-.165-1.047zM.955 6.125a.75.75 0 01.624.857 6.554 6.554 0 000 2.036.75.75 0 01-1.482.233 8.054 8.054 0 010-2.502.75.75 0 01.858-.624zm14.09 0a.75.75 0 01.858.624 8.057 8.057 0 010 2.502.75.75 0 01-1.482-.233 6.55 6.55 0 000-2.036.75.75 0 01.624-.857zm-13.352 5.53a.75.75 0 011.048.165 6.542 6.542 0 001.439 1.44.75.75 0 01-.883 1.212 8.04 8.04 0 01-1.77-1.769.75.75 0 01.166-1.048zm12.614 0a.75.75 0 01.165 1.048 8.038 8.038 0 01-1.769 1.77.75.75 0 11-.883-1.214 6.543 6.543 0 001.44-1.439.75.75 0 011.047-.165zm-8.182 3.39a.75.75 0 01.857-.624 6.55 6.55 0 002.036 0 .75.75 0 01.233 1.482 8.057 8.057 0 01-2.502 0 .75.75 0 01-.624-.858z"></path></svg>
<span class="no-wrap"><%= section.issues.collaborators.drafts %> <small>draft<%= s(section.issues.collaborators.drafts) %></small></span>
</div>
<div class="field">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill="#c9d1d9" d="M1.5 8a6.5 6.5 0 1113 0 6.5 6.5 0 01-13 0zM8 0a8 8 0 100 16A8 8 0 008 0zm3.28 5.78a.75.75 0 00-1.06-1.06l-5.5 5.5a.75.75 0 101.06 1.06l5.5-5.5z"></path></svg>
<span class="no-wrap"><%= section.issues.collaborators.skipped %> <small>skipped</small></span>
</div>
</div> </div>
</section>
<% } %> <% } %>
</section> </section>
<section class="column"> <section class="column">
<h3>Pull requests</h3> <h3 class="no-margin-top">Pull requests</h3>
<% if (plugins.followup.error) { %> <svg class="bar" xmlns="http://www.w3.org/2000/svg" width="220" height="8">
<section>
<div class="field error">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M2.343 13.657A8 8 0 1113.657 2.343 8 8 0 012.343 13.657zM6.03 4.97a.75.75 0 00-1.06 1.06L6.94 8 4.97 9.97a.75.75 0 101.06 1.06L8 9.06l1.97 1.97a.75.75 0 101.06-1.06L9.06 8l1.97-1.97a.75.75 0 10-1.06-1.06L8 6.94 6.03 4.97z"></path></svg>
<%= plugins.followup.error.message %>
</div>
</section>
<% } else { const section = plugins.followup, width = 220*(1+large) %>
<section class="column">
<svg class="bar" xmlns="http://www.w3.org/2000/svg" width="<%= width %>" height="8">
<mask id="pr-bar"> <mask id="pr-bar">
<rect x="0" y="0" width="<%= width %>" height="8" fill="white" rx="5"/> <rect x="0" y="0" width="220" height="8" fill="white" rx="5"/>
</mask> </mask>
<rect mask="url(#pr-bar)" x="0" y="0" width="<%= section.pr.count ? 0 : width %>" height="8" fill="#d1d5da"/> <rect mask="url(#pr-bar)" x="0" y="0" width="<%= section.pr.count ? 0 : 220 %>" height="8" fill="#d1d5da"/>
<rect mask="url(#pr-bar)" x="0" y="0" width="<%= (section.pr.open/section.pr.count)*width || 0 %>" height="8" fill="#238636"/> <% { const {open, drafts, closed, merged, count, collaborators = {open:0, drafts:0, closed:0, merged:0}} = section.pr, width = 220; let x = 0; for (const {p, fill} of [
<rect mask="url(#pr-bar)" x="<%= (section.pr.open/section.pr.count)*width || 0 %>" y="0" width="<%= (section.pr.closed/section.pr.count)*width || 0 %>" height="8" fill="#da3633"/> {p:(open-collaborators.open)/count, fill:"#238636"},
<rect mask="url(#pr-bar)" x="<%= ((section.pr.open+section.pr.closed)/section.pr.count)*width || 0 %>" y="0" width="<%= (1-(section.pr.open+section.pr.closed)/section.pr.count)*width || 0 %>" height="8" fill="#8957e5"/> {p:collaborators.open/count, fill:"#56d364"},
{p:(drafts-collaborators.drafts)/count, fill:"#8B949E"},
{p:collaborators.drafts/count, fill:"#c9d1d9"},
{p:(closed-collaborators.closed)/count, fill:"#da3633"},
{p:collaborators.closed/count, fill:"#ff7b72"},
{p:(merged-collaborators.merged)/count, fill:"#8957e5"},
{p:collaborators.merged/count, fill:"#d2a8ff"},
]) { %>
<rect mask="url(#issues-bar)" x="<%= x %>" y="0" width="<%= p*width || 0 %>" height="8" fill="<%= fill %>"/>
<% x += p*width }} %>
</svg> </svg>
<div class="followup legend field horizontal fill-width"> <% if ((plugins.followup.indepth)&&(section.pr.collaborators)) { %>
<div class="field center"> <div class="field blue fill-width">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M5.5 3.5a2 2 0 100 4 2 2 0 000-4zM2 5.5a3.5 3.5 0 115.898 2.549 5.507 5.507 0 013.034 4.084.75.75 0 11-1.482.235 4.001 4.001 0 00-7.9 0 .75.75 0 01-1.482-.236A5.507 5.507 0 013.102 8.05 3.49 3.49 0 012 5.5zM11 4a.75.75 0 100 1.5 1.5 1.5 0 01.666 2.844.75.75 0 00-.416.672v.352a.75.75 0 00.574.73c1.2.289 2.162 1.2 2.522 2.372a.75.75 0 101.434-.44 5.01 5.01 0 00-2.56-3.012A3 3 0 0011 4z"></path></svg>
From community
</div>
<% } %>
<div class="followup legend field fill-width">
<div class="field">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill="#238636" fill-rule="evenodd" d="M7.177 3.073L9.573.677A.25.25 0 0110 .854v4.792a.25.25 0 01-.427.177L7.177 3.427a.25.25 0 010-.354zM3.75 2.5a.75.75 0 100 1.5.75.75 0 000-1.5zm-2.25.75a2.25 2.25 0 113 2.122v5.256a2.251 2.251 0 11-1.5 0V5.372A2.25 2.25 0 011.5 3.25zM11 2.5h-1V4h1a1 1 0 011 1v5.628a2.251 2.251 0 101.5 0V5A2.5 2.5 0 0011 2.5zm1 10.25a.75.75 0 111.5 0 .75.75 0 01-1.5 0zM3.75 12a.75.75 0 100 1.5.75.75 0 000-1.5z"></path></svg> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill="#238636" fill-rule="evenodd" d="M7.177 3.073L9.573.677A.25.25 0 0110 .854v4.792a.25.25 0 01-.427.177L7.177 3.427a.25.25 0 010-.354zM3.75 2.5a.75.75 0 100 1.5.75.75 0 000-1.5zm-2.25.75a2.25 2.25 0 113 2.122v5.256a2.251 2.251 0 11-1.5 0V5.372A2.25 2.25 0 011.5 3.25zM11 2.5h-1V4h1a1 1 0 011 1v5.628a2.251 2.251 0 101.5 0V5A2.5 2.5 0 0011 2.5zm1 10.25a.75.75 0 111.5 0 .75.75 0 01-1.5 0zM3.75 12a.75.75 0 100 1.5.75.75 0 000-1.5z"></path></svg>
<span class="no-wrap"><%= section.pr.open %> <small>open</small></span> <span class="no-wrap"><%= section.pr.open %> <small>open</small></span>
</div> </div>
<div class="field center"> <div class="field">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill="#da3633" fill-rule="evenodd" d="M10.72 1.227a.75.75 0 011.06 0l.97.97.97-.97a.75.75 0 111.06 1.061l-.97.97.97.97a.75.75 0 01-1.06 1.06l-.97-.97-.97.97a.75.75 0 11-1.06-1.06l.97-.97-.97-.97a.75.75 0 010-1.06zM12.75 6.5a.75.75 0 00-.75.75v3.378a2.251 2.251 0 101.5 0V7.25a.75.75 0 00-.75-.75zm0 5.5a.75.75 0 100 1.5.75.75 0 000-1.5zM2.5 3.25a.75.75 0 111.5 0 .75.75 0 01-1.5 0zM3.25 1a2.25 2.25 0 00-.75 4.372v5.256a2.251 2.251 0 101.5 0V5.372A2.25 2.25 0 003.25 1zm0 11a.75.75 0 100 1.5.75.75 0 000-1.5z"></path></svg>
<span class="no-wrap"><%= section.pr.closed %> <small>closed</small></span>
</div>
<div class="field center">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill="#8957e5" fill-rule="evenodd" d="M5 3.254V3.25v.005a.75.75 0 110-.005v.004zm.45 1.9a2.25 2.25 0 10-1.95.218v5.256a2.25 2.25 0 101.5 0V7.123A5.735 5.735 0 009.25 9h1.378a2.251 2.251 0 100-1.5H9.25a4.25 4.25 0 01-3.8-2.346zM12.75 9a.75.75 0 100-1.5.75.75 0 000 1.5zm-8.5 4.5a.75.75 0 100-1.5.75.75 0 000 1.5z"></path></svg> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill="#8957e5" fill-rule="evenodd" d="M5 3.254V3.25v.005a.75.75 0 110-.005v.004zm.45 1.9a2.25 2.25 0 10-1.95.218v5.256a2.25 2.25 0 101.5 0V7.123A5.735 5.735 0 009.25 9h1.378a2.251 2.251 0 100-1.5H9.25a4.25 4.25 0 01-3.8-2.346zM12.75 9a.75.75 0 100-1.5.75.75 0 000 1.5zm-8.5 4.5a.75.75 0 100-1.5.75.75 0 000 1.5z"></path></svg>
<span class="no-wrap"><%= section.pr.merged %> <small>merged</small></span> <span class="no-wrap"><%= section.pr.merged %> <small>merged</small></span>
</div> </div>
<div class="field">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill="#8B949E" d="M2.5 3.25a.75.75 0 111.5 0 .75.75 0 01-1.5 0zM3.25 1a2.25 2.25 0 00-.75 4.372v5.256a2.251 2.251 0 101.5 0V5.372A2.25 2.25 0 003.25 1zm0 11a.75.75 0 100 1.5.75.75 0 000-1.5zm9.5 3a2.25 2.25 0 100-4.5 2.25 2.25 0 000 4.5zm0-3a.75.75 0 100 1.5.75.75 0 000-1.5z"></path><path d="M14 7.5a1.25 1.25 0 11-2.5 0 1.25 1.25 0 012.5 0zm0-4.25a1.25 1.25 0 11-2.5 0 1.25 1.25 0 012.5 0z"></path></svg>
<span class="no-wrap"><%= section.pr.drafts %> <small>draft<%= s(section.pr.drafts) %></small></span>
</div>
<div class="field">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill="#da3633" fill-rule="evenodd" d="M10.72 1.227a.75.75 0 011.06 0l.97.97.97-.97a.75.75 0 111.06 1.061l-.97.97.97.97a.75.75 0 01-1.06 1.06l-.97-.97-.97.97a.75.75 0 11-1.06-1.06l.97-.97-.97-.97a.75.75 0 010-1.06zM12.75 6.5a.75.75 0 00-.75.75v3.378a2.251 2.251 0 101.5 0V7.25a.75.75 0 00-.75-.75zm0 5.5a.75.75 0 100 1.5.75.75 0 000-1.5zM2.5 3.25a.75.75 0 111.5 0 .75.75 0 01-1.5 0zM3.25 1a2.25 2.25 0 00-.75 4.372v5.256a2.251 2.251 0 101.5 0V5.372A2.25 2.25 0 003.25 1zm0 11a.75.75 0 100 1.5.75.75 0 000-1.5z"></path></svg>
<span class="no-wrap"><%= section.pr.closed %> <small>closed</small></span>
</div>
</div>
<% if ((plugins.followup.indepth)&&(section.pr.collaborators)) { %>
<div class="field blue fill-width">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M13.25 0a.75.75 0 01.75.75V2h1.25a.75.75 0 010 1.5H14v1.25a.75.75 0 01-1.5 0V3.5h-1.25a.75.75 0 010-1.5h1.25V.75a.75.75 0 01.75-.75zM5.5 4a2 2 0 100 4 2 2 0 000-4zm2.4 4.548a3.5 3.5 0 10-4.799 0 5.527 5.527 0 00-3.1 4.66.75.75 0 101.498.085A4.01 4.01 0 015.5 9.5a4.01 4.01 0 014.001 3.793.75.75 0 101.498-.086 5.527 5.527 0 00-3.1-4.659z"></path></svg>
From maintainers
</div>
<div class="followup legend field fill-width">
<div class="field">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill="#56d364" fill-rule="evenodd" d="M7.177 3.073L9.573.677A.25.25 0 0110 .854v4.792a.25.25 0 01-.427.177L7.177 3.427a.25.25 0 010-.354zM3.75 2.5a.75.75 0 100 1.5.75.75 0 000-1.5zm-2.25.75a2.25 2.25 0 113 2.122v5.256a2.251 2.251 0 11-1.5 0V5.372A2.25 2.25 0 011.5 3.25zM11 2.5h-1V4h1a1 1 0 011 1v5.628a2.251 2.251 0 101.5 0V5A2.5 2.5 0 0011 2.5zm1 10.25a.75.75 0 111.5 0 .75.75 0 01-1.5 0zM3.75 12a.75.75 0 100 1.5.75.75 0 000-1.5z"></path></svg>
<span class="no-wrap"><%= section.pr.collaborators.open %> <small>open</small></span>
</div>
<div class="field">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill="#d2a8ff" fill-rule="evenodd" d="M5 3.254V3.25v.005a.75.75 0 110-.005v.004zm.45 1.9a2.25 2.25 0 10-1.95.218v5.256a2.25 2.25 0 101.5 0V7.123A5.735 5.735 0 009.25 9h1.378a2.251 2.251 0 100-1.5H9.25a4.25 4.25 0 01-3.8-2.346zM12.75 9a.75.75 0 100-1.5.75.75 0 000 1.5zm-8.5 4.5a.75.75 0 100-1.5.75.75 0 000 1.5z"></path></svg>
<span class="no-wrap"><%= section.pr.collaborators.merged %> <small>merged</small></span>
</div>
<div class="field">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill="#c9d1d9" d="M2.5 3.25a.75.75 0 111.5 0 .75.75 0 01-1.5 0zM3.25 1a2.25 2.25 0 00-.75 4.372v5.256a2.251 2.251 0 101.5 0V5.372A2.25 2.25 0 003.25 1zm0 11a.75.75 0 100 1.5.75.75 0 000-1.5zm9.5 3a2.25 2.25 0 100-4.5 2.25 2.25 0 000 4.5zm0-3a.75.75 0 100 1.5.75.75 0 000-1.5z"></path><path d="M14 7.5a1.25 1.25 0 11-2.5 0 1.25 1.25 0 012.5 0zm0-4.25a1.25 1.25 0 11-2.5 0 1.25 1.25 0 012.5 0z"></path></svg>
<span class="no-wrap"><%= section.pr.collaborators.drafts %> <small>draft<%= s(section.pr.collaborators.drafts) %></small></span>
</div>
<div class="field">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill="#ff7b72" fill-rule="evenodd" d="M10.72 1.227a.75.75 0 011.06 0l.97.97.97-.97a.75.75 0 111.06 1.061l-.97.97.97.97a.75.75 0 01-1.06 1.06l-.97-.97-.97.97a.75.75 0 11-1.06-1.06l.97-.97-.97-.97a.75.75 0 010-1.06zM12.75 6.5a.75.75 0 00-.75.75v3.378a2.251 2.251 0 101.5 0V7.25a.75.75 0 00-.75-.75zm0 5.5a.75.75 0 100 1.5.75.75 0 000-1.5zM2.5 3.25a.75.75 0 111.5 0 .75.75 0 01-1.5 0zM3.25 1a2.25 2.25 0 00-.75 4.372v5.256a2.251 2.251 0 101.5 0V5.372A2.25 2.25 0 003.25 1zm0 11a.75.75 0 100 1.5.75.75 0 000-1.5z"></path></svg>
<span class="no-wrap"><%= section.pr.collaborators.closed %> <small>closed</small></span>
</div>
</div> </div>
</section>
<% } %> <% } %>
</section> </section>
</div> </div>
</div>
<% } %>
<% } %> <% } %>