From a0c2b39c3775b1f382a471b23cbd9c66250f9fb5 Mon Sep 17 00:00:00 2001 From: Simon Lecoq <22963968+lowlighter@users.noreply.github.com> Date: Thu, 22 Apr 2021 18:03:39 +0200 Subject: [PATCH] Add user follow-up section (#250) --- .../api/github/graphql/base.repositories.mjs | 1 + .../api/github/graphql/base.repository.mjs | 1 + .../api/github/graphql/followup.user.mjs | 13 ++ source/app/web/statics/app.placeholder.js | 8 +- .../plugins/base/queries/repositories.graphql | 3 + .../plugins/base/queries/repository.graphql | 3 + source/plugins/core/index.mjs | 4 +- source/plugins/followup/README.md | 4 + source/plugins/followup/index.mjs | 32 ++++- source/plugins/followup/metadata.yml | 12 +- source/plugins/followup/queries/user.graphql | 19 +++ source/plugins/followup/tests.yml | 7 + .../templates/classic/partials/followup.ejs | 126 +++++++++--------- source/templates/classic/style.css | 16 +++ 14 files changed, 180 insertions(+), 69 deletions(-) create mode 100644 source/app/mocks/api/github/graphql/followup.user.mjs create mode 100644 source/plugins/followup/queries/user.graphql diff --git a/source/app/mocks/api/github/graphql/base.repositories.mjs b/source/app/mocks/api/github/graphql/base.repositories.mjs index 01e21acd..0213f55f 100644 --- a/source/app/mocks/api/github/graphql/base.repositories.mjs +++ b/source/app/mocks/api/github/graphql/base.repositories.mjs @@ -36,6 +36,7 @@ issues_open:{totalCount:faker.datatype.number(100)}, issues_closed:{totalCount:faker.datatype.number(100)}, pr_open:{totalCount:faker.datatype.number(100)}, + pr_closed:{totalCount:faker.datatype.number(100)}, pr_merged:{totalCount:faker.datatype.number(100)}, releases:{totalCount:faker.datatype.number(100)}, forkCount:faker.datatype.number(100), diff --git a/source/app/mocks/api/github/graphql/base.repository.mjs b/source/app/mocks/api/github/graphql/base.repository.mjs index 736ef718..293d0e0b 100644 --- a/source/app/mocks/api/github/graphql/base.repository.mjs +++ b/source/app/mocks/api/github/graphql/base.repository.mjs @@ -25,6 +25,7 @@ issues_open:{totalCount:faker.datatype.number(100)}, issues_closed:{totalCount:faker.datatype.number(100)}, pr_open:{totalCount:faker.datatype.number(100)}, + pr_closed:{totalCount:faker.datatype.number(100)}, pr_merged:{totalCount:faker.datatype.number(100)}, releases:{totalCount:faker.datatype.number(100)}, forkCount:faker.datatype.number(100), diff --git a/source/app/mocks/api/github/graphql/followup.user.mjs b/source/app/mocks/api/github/graphql/followup.user.mjs new file mode 100644 index 00000000..4cc692c5 --- /dev/null +++ b/source/app/mocks/api/github/graphql/followup.user.mjs @@ -0,0 +1,13 @@ +/**Mocked data */ + export default function({faker, query, login = faker.internet.userName()}) { + console.debug("metrics/compute/mocks > mocking graphql api result > followup/user") + return ({ + user:{ + issues_open:{totalCount:faker.datatype.number(100)}, + issues_closed:{totalCount:faker.datatype.number(100)}, + pr_open:{totalCount:faker.datatype.number(100)}, + pr_closed:{totalCount:faker.datatype.number(100)}, + pr_merged:{totalCount:faker.datatype.number(100)}, + }, + }) + } diff --git a/source/app/web/statics/app.placeholder.js b/source/app/web/statics/app.placeholder.js index bd5463b7..9449f96c 100644 --- a/source/app/web/statics/app.placeholder.js +++ b/source/app/web/statics/app.placeholder.js @@ -67,6 +67,7 @@ issues_open:faker.datatype.number(1000), issues_closed:faker.datatype.number(1000), pr_open:faker.datatype.number(1000), + pr_closed:{totalCount:faker.datatype.number(100)}, pr_merged:faker.datatype.number(1000), forks:faker.datatype.number(1000), releases:faker.datatype.number(1000), @@ -161,8 +162,13 @@ //Follow-up ...(set.plugins.enabled.followup ? ({ followup:{ + sections:options["followup.sections"].split(",").map(x => x.trim()).filter(x => ["user", "repositories"].includes(x)), issues:{get count() { return this.open + this.closed }, open:faker.datatype.number(1000), closed:faker.datatype.number(1000)}, - pr:{get count() { return this.open + this.merged }, open:faker.datatype.number(1000), merged:faker.datatype.number(1000)}, + pr:{get count() { return this.open + this.merged }, open:faker.datatype.number(1000), closed:faker.datatype.number(1000), merged:faker.datatype.number(1000)}, + user:{ + issues:{get count() { return this.open + this.closed }, open:faker.datatype.number(1000), closed:faker.datatype.number(1000)}, + pr:{get count() { return this.open + this.merged }, open:faker.datatype.number(1000), closed:faker.datatype.number(1000), merged:faker.datatype.number(1000)}, + } } }) : null), //Notable diff --git a/source/plugins/base/queries/repositories.graphql b/source/plugins/base/queries/repositories.graphql index af65a7df..5174edf8 100644 --- a/source/plugins/base/queries/repositories.graphql +++ b/source/plugins/base/queries/repositories.graphql @@ -34,6 +34,9 @@ query BaseRepositories { pr_open: pullRequests(states: OPEN) { totalCount } + pr_closed: pullRequests(states: CLOSED) { + totalCount + } pr_merged: pullRequests(states: MERGED) { totalCount } diff --git a/source/plugins/base/queries/repository.graphql b/source/plugins/base/queries/repository.graphql index f24cf8e0..f4f4c94a 100644 --- a/source/plugins/base/queries/repository.graphql +++ b/source/plugins/base/queries/repository.graphql @@ -33,6 +33,9 @@ query BaseRepository { pr_open: pullRequests(states: OPEN) { totalCount } + pr_closed: pullRequests(states: CLOSED) { + totalCount + } pr_merged: pullRequests(states: MERGED) { totalCount } diff --git a/source/plugins/core/index.mjs b/source/plugins/core/index.mjs index cf178dd2..1a2f3e34 100644 --- a/source/plugins/core/index.mjs +++ b/source/plugins/core/index.mjs @@ -9,7 +9,7 @@ const {"config.animations":animations, "config.timezone":_timezone, "debug.flags":dflags} = imports.metadata.plugins.core.inputs({data, account, q}) //Init - const computed = {commits:0, sponsorships:0, licenses:{favorite:"", used:{}}, token:{}, repositories:{watchers:0, stargazers:0, issues_open:0, issues_closed:0, pr_open:0, pr_merged:0, forks:0, forked:0, releases:0}} + const computed = {commits:0, sponsorships:0, licenses:{favorite:"", used:{}}, token:{}, repositories:{watchers:0, stargazers:0, issues_open:0, issues_closed:0, pr_open:0, pr_closed:0, pr_merged:0, forks:0, forked:0, releases:0}} const avatar = imports.imgb64(data.user.avatarUrl) data.computed = computed console.debug(`metrics/compute/${login} > formatting common metrics`) @@ -57,7 +57,7 @@ //Iterate through user's repositories for (const repository of data.user.repositories.nodes) { //Simple properties with totalCount - for (const property of ["watchers", "stargazers", "issues_open", "issues_closed", "pr_open", "pr_merged", "releases"]) + for (const property of ["watchers", "stargazers", "issues_open", "issues_closed", "pr_open", "pr_closed", "pr_merged", "releases"]) computed.repositories[property] += repository[property].totalCount //Forks computed.repositories.forks += repository.forkCount diff --git a/source/plugins/followup/README.md b/source/plugins/followup/README.md index 67ac1e8c..2ec5fbdc 100644 --- a/source/plugins/followup/README.md +++ b/source/plugins/followup/README.md @@ -5,6 +5,9 @@ The *followup* plugin displays the ratio of open/closed issues and the ratio of
+
Created by user version + +
@@ -18,5 +21,6 @@ The *followup* plugin displays the ratio of open/closed issues and the ratio of with: # ... other options plugin_followup: yes + plugin_followup_sections: repositories, user # ``` diff --git a/source/plugins/followup/index.mjs b/source/plugins/followup/index.mjs index 93ee9cb5..fef5636e 100644 --- a/source/plugins/followup/index.mjs +++ b/source/plugins/followup/index.mjs @@ -1,5 +1,5 @@ //Setup - export default async function({data, computed, imports, q, account}, {enabled = false} = {}) { + export default async function({login, data, computed, imports, q, graphql, queries, account}, {enabled = false} = {}) { //Plugin execution try { //Check if plugin is enabled and requirements are met @@ -7,10 +7,11 @@ return null //Load inputs - imports.metadata.plugins.followup.inputs({data, account, q}) + let {sections} = imports.metadata.plugins.followup.inputs({data, account, q}) //Define getters const followup = { + sections, issues:{ get count() { return this.open + this.closed @@ -24,17 +25,42 @@ }, pr:{ get count() { - return this.open + this.merged + return this.open + this.closed + this.merged }, get open() { return computed.repositories.pr_open }, + get closed() { + return computed.repositories.pr_closed + }, get merged() { return computed.repositories.pr_merged }, }, } + //Load user issues and pull requests + if (sections.includes("user")) { + const {user} = await graphql(queries.followup.user({login})) + followup.user = { + issues:{ + get count() { + return this.open + this.closed + }, + open:user.issues_open.totalCount, + closed:user.issues_closed.totalCount, + }, + pr:{ + get count() { + return this.open + this.closed + this.merged + }, + open:user.pr_open.totalCount, + closed:user.pr_closed.totalCount, + merged:user.pr_merged.totalCount, + }, + } + } + //Results return followup } diff --git a/source/plugins/followup/metadata.yml b/source/plugins/followup/metadata.yml index cc9f387c..9d41b53b 100644 --- a/source/plugins/followup/metadata.yml +++ b/source/plugins/followup/metadata.yml @@ -1,5 +1,5 @@ name: "🎟️ Follow-up of issues and pull requests" -cost: 0 API request +cost: 0 API request (1 GraphQL request if "user" section is enabled) categorie: github index: 11 supports: @@ -13,3 +13,13 @@ inputs: description: Display follow-up of repositories issues and pull requests type: boolean default: no + + # Sections to display + plugin_followup_sections: + description: Sections to display + type: array + format: comma-separated + default: repositories + values: + - repositories # Overall status of issues and pull requests on your repositories + - user # Overall status of issues and pull requests you have created on GitHub \ No newline at end of file diff --git a/source/plugins/followup/queries/user.graphql b/source/plugins/followup/queries/user.graphql new file mode 100644 index 00000000..9aa5c07e --- /dev/null +++ b/source/plugins/followup/queries/user.graphql @@ -0,0 +1,19 @@ +query FollowupUser { + user(login: "$login") { + issues_open:issues(states: OPEN) { + totalCount + } + issues_closed:issues(states: CLOSED) { + totalCount + } + pr_open:pullRequests(states: OPEN) { + totalCount + } + pr_closed:pullRequests(states: CLOSED) { + totalCount + } + pr_merged:pullRequests(states: MERGED) { + totalCount + } + } +} \ No newline at end of file diff --git a/source/plugins/followup/tests.yml b/source/plugins/followup/tests.yml index 6e347faf..b5efba4f 100644 --- a/source/plugins/followup/tests.yml +++ b/source/plugins/followup/tests.yml @@ -3,3 +3,10 @@ with: token: MOCKED_TOKEN plugin_followup: yes + +- name: Follow-up plugin (complete) + uses: lowlighter/metrics@latest + with: + token: MOCKED_TOKEN + plugin_followup: yes + plugin_followup_sections: repositories, user \ No newline at end of file diff --git a/source/templates/classic/partials/followup.ejs b/source/templates/classic/partials/followup.ejs index 38d4baa3..e0d2b81a 100644 --- a/source/templates/classic/partials/followup.ejs +++ b/source/templates/classic/partials/followup.ejs @@ -1,71 +1,73 @@ <% if (plugins.followup) { %> -
+

- Overall repositories issues and pull requests status + Overall issues and pull requests status

-
-
-

Issues

- <% if (plugins.followup.error) { %> -
-
- - <%= plugins.followup.error.message %> +
+ <% if (plugins.followup.error) { %> +
+
+ + <%= plugins.followup.error.message %> +
+
+ <% } else { %> + <% for (const name of plugins.followup.sections) { const section = {repositories:plugins.followup, user:plugins.followup?.user}[name] %> +
+

+ <%= {repositories:`On ${user.login}'${[...user.login].pop() === "s" ? "" : "s"} repositories`, user:`Created by ${user.login}`}[name] %> +

+
+
+

Issues

+ + + + + + + + +
+
+ + <%= section.issues.open %> open +
+
+ + <%= section.issues.closed %> closed +
- <% } else { %> - - - - - - - - -
-
- - <%= plugins.followup.issues.closed %> Closed -
-
- - <%= plugins.followup.issues.open %> Open -
-
- <% } %> -
- -
-

Pull requests

- <% if (plugins.followup.error) { %> -
-
- - <%= plugins.followup.error.message %> +
+

Pull requests

+ + + + + + + + + +
+
+ + <%= section.pr.open %> open +
+
+ + <%= section.pr.closed %> closed +
+
+ + <%= section.pr.merged %> merged +
- <% } else { %> - - - - - - - - -
-
- - <%= plugins.followup.pr.merged %> Merged -
-
- - <%= plugins.followup.pr.open %> Open -
-
- <% } %> -
-
-
+ + + <% } %> + <% } %> <% } %> \ No newline at end of file diff --git a/source/templates/classic/style.css b/source/templates/classic/style.css index 2eddd4b8..e0944737 100644 --- a/source/templates/classic/style.css +++ b/source/templates/classic/style.css @@ -157,6 +157,22 @@ flex: 1 1 0; } +/* Follow-up */ + .followup.legend { + font-size: 12px; + } + .followup.legend svg { + margin: 0 3px; + width: 14px; + height: 14px; + } + .followup.legend svg:first-child { + margin-left: 0; + } + .followup.legend svg:last-child { + margin-right: 0; + } + /* Labels */ .label { background-color: #58A6FF30;