├── .circleci └── config.yml ├── .gitignore ├── LICENSE ├── README.md ├── flex.css ├── icon128.png ├── icon16.png ├── icon48.png ├── logo-hacktoberfest.png ├── manifest.json ├── package.json ├── popup.css ├── popup.html ├── popup.js └── test └── test.js /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | # Javascript Node CircleCI 2.0 configuration file 2 | # 3 | # Check https://circleci.com/docs/2.0/language-javascript/ for more details 4 | # 5 | version: 2 6 | jobs: 7 | build: 8 | docker: 9 | # specify the version you desire here 10 | - image: circleci/node:7.10 11 | 12 | # Specify service dependencies here if necessary 13 | # CircleCI maintains a library of pre-built images 14 | # documented at https://circleci.com/docs/2.0/circleci-images/ 15 | # - image: circleci/mongo:3.4.4 16 | 17 | working_directory: ~/repo 18 | 19 | steps: 20 | - checkout 21 | 22 | # Download and cache dependencies 23 | - restore_cache: 24 | keys: 25 | - v1-dependencies-{{ checksum "package.json" }} 26 | # fallback to using the latest cache if no exact match is found 27 | - v1-dependencies- 28 | 29 | - run: yarn install 30 | 31 | - save_cache: 32 | paths: 33 | - node_modules 34 | key: v1-dependencies-{{ checksum "package.json" }} 35 | 36 | # run tests! 37 | - run: yarn test 38 | 39 | 40 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | yarn.lock 2 | /node_modules/* -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 adeora7 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Hacktoberfest Progress 2 | Hacktoberfest progress is a chrome extension made to check your progress in the [Hacktoberfest](https://hacktoberfest.digitalocean.com) organised by DigitalOcean. It tells you how far you are from your goal and which of your Pull Requests were counted so far. 3 | 4 | ## How to Contribute? 5 | 6 | * Fork the repository. 7 | * Comment on the issue which you want to solve so that there is no duplicate work. In case of duplicate work, comments will be used to decide which Pull Request to merge. 8 | * Create Pull Request. 9 | * Once you are a contributor, add yourselves to the contributors list as well as in the README file. 10 | 11 | ## How to use? 12 | 13 | Click [here](https://chrome.google.com/webstore/detail/hacktoberfest-progress-ch/djpoekehoiafngfljnoihmbnckiegolf?hl=en) to get to the Chrome Web Store for the Hacktoberfest Progress Checker, chrome extension! 14 | 15 | After installation, click on the extension icon on the right side of your address bar and then enter your Github username and then click on 'Check Progress'. You will get to see how many Pull Requests you have made and how many were accepted! 16 | 17 | ## How to Run Tests 18 | the project is now setup to have basic tests, and these tests will run on CircleCI. 19 | 20 | to run the tests you must have some form of node pacakge manager(npm or yarn) 21 | 22 | run: 23 | ``` 24 | yarn install 25 | ``` 26 | and then 27 | ``` 28 | yarn test 29 | ``` 30 | 31 | ## How to develop locally 32 | 33 | Once you have cloned the project locally and are ready to begin developing. You can load the unpackaged files in developer tools, and point it at the local project. 34 | 35 | [https://developer.chrome.com/extensions/getstarted#manifest](https://developer.chrome.com/extensions/getstarted#manifest) 36 | 37 | If you make any changes then simply return to developer tools and refresh the extension to sync the changes made. 38 | 39 | ## Contributors 40 | 41 | Thanks goes to these wonderful people for their contributions: 42 | 43 | | [
Abhishek Deora](https://github.com/adeora7/) | [
Duy Nguyen](https://github.com/zuik) | [
Will Bray](https://github.com/raindogg) | [
Luke Taylor](https://github.com/lmcjt37) | [
Andreas Kleinbub](https://github.com/ehnydeel) | [
Bhavesh Gohel](https://github.com/bhaveshgohel) | [
Rafael Klaessen](https://github.com/rafaelklaessen) | 44 | | :---: | :---: | :---: | :---: | :--: | :--: | :--: | 45 | | [
Richard Robinson](https://github.com/kincade71) | [
Fredrik Mäkilä](https://github.com/GitHug) | [
Joseph Allen](https://github.com/GitHug) | 46 | -------------------------------------------------------------------------------- /flex.css: -------------------------------------------------------------------------------- 1 | .flex-row{ 2 | display: flex; 3 | flex-direction: row; 4 | } 5 | .flex-column{ 6 | display: flex; 7 | flex-direction: column; 8 | } 9 | .align-center{ 10 | align-items: center; 11 | } 12 | .align-start{ 13 | align-items: flex-start; 14 | } 15 | .align-end{ 16 | align-items: flex-end; 17 | } 18 | .justify-center{ 19 | justify-content: center; 20 | } 21 | .justify-start{ 22 | justify-content: flex-start; 23 | } 24 | .justify-end{ 25 | justify-content: flex-end; 26 | } 27 | .justify-space-around{ 28 | justify-content: space-around; 29 | } 30 | .justify-space-between{ 31 | justify-content: space-between; 32 | } 33 | .flex-wrap{ 34 | flex-wrap: wrap; 35 | } 36 | .flex-no-wrap{ 37 | flex-wrap: nowrap; 38 | } 39 | .flex-wrap-reverse{ 40 | flex-wrap: wrap-reverse; 41 | } -------------------------------------------------------------------------------- /icon128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeora7/hacktoberfest_progress/0c8a6e7156e418a0f946660fc67d7bda052d9890/icon128.png -------------------------------------------------------------------------------- /icon16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeora7/hacktoberfest_progress/0c8a6e7156e418a0f946660fc67d7bda052d9890/icon16.png -------------------------------------------------------------------------------- /icon48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeora7/hacktoberfest_progress/0c8a6e7156e418a0f946660fc67d7bda052d9890/icon48.png -------------------------------------------------------------------------------- /logo-hacktoberfest.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adeora7/hacktoberfest_progress/0c8a6e7156e418a0f946660fc67d7bda052d9890/logo-hacktoberfest.png -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name" : "Hacktoberfest Progress Checker", 3 | "version" : "1.7", 4 | "description" : "Check your Hacktoberfest 2017 progress here. It is a fan made chrome extension and is not affiliated to hacktoberfest officially.", 5 | "permissions": [ 6 | "storage" 7 | ], 8 | "browser_action": { 9 | "default_icon": "icon48.png", 10 | "default_popup": "popup.html" 11 | }, 12 | "manifest_version": 2, 13 | "icons": { 14 | "16": "icon16.png", 15 | "48": "icon48.png", 16 | "128": "icon128.png" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "test": "mocha" 4 | }, 5 | "dependencies": { 6 | "mocha": "^5.2.0" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /popup.css: -------------------------------------------------------------------------------- 1 | html { 2 | font-size: 14px; 3 | } 4 | 5 | body{ 6 | min-width: 300px; 7 | min-height: 400px; 8 | background-color: #411e2f; 9 | color: white; 10 | } 11 | 12 | #header{ 13 | text-align: center; 14 | padding: 1rem; 15 | } 16 | #header > a >img{ 17 | height: 150px; 18 | width: auto; 19 | } 20 | 21 | #main{ 22 | padding: 1rem; 23 | } 24 | 25 | .eachSavedAccount{ 26 | margin: 5px; 27 | font-weight: 900; 28 | cursor: pointer; 29 | } 30 | 31 | .eachSavedAccount:hover{ 32 | text-decoration: underline; 33 | } 34 | 35 | .rounded{ 36 | border-radius: 15px; 37 | cursor: pointer; 38 | margin-right: 5px; 39 | height: 30px; 40 | width: 30px; 41 | } 42 | 43 | .active { 44 | border-radius: 25px; 45 | height: 55px; 46 | width: 55px; 47 | } 48 | 49 | .button{ 50 | height: 35px; 51 | width: 175px; 52 | background-color: #21ffff; 53 | border: 3px solid #21ffff; 54 | border-radius: 4px; 55 | outline: none; 56 | color: #411e2f; 57 | cursor: pointer; 58 | /* Closes #74: Change the font size from 14 to 17 */ 59 | font-size: 17px; 60 | /* Closes #74: Added font-family Oswald to button */ 61 | font-family: 'Oswald', sans-serif; 62 | } 63 | .button:hover { 64 | border-color: #fff; 65 | background-color: #fff; 66 | } 67 | 68 | #newAccount{ 69 | min-height: 140px; 70 | } 71 | 72 | #avatar{ 73 | height: 45px; 74 | padding: 5px; 75 | width: 45px; 76 | } 77 | 78 | #githubHandle{ 79 | height: 30px; 80 | width: 160px; 81 | padding: 5px; 82 | /* Closes #74: Change the font size from 16 to 22 */ 83 | font-size: 22px; 84 | text-align: center; 85 | color: white; 86 | border: 0; 87 | border-bottom: 1px solid white; 88 | background: #411e2f; 89 | margin-bottom: 10px; 90 | outline: none; 91 | transition : border 500ms ease-out; 92 | /* Closes #74: Added font-family Oswald to githubHandle */ 93 | font-family: 'Oswald', sans-serif; 94 | } 95 | 96 | #githubHandle::placeholder, 97 | #githubHandle::-webkit-placeholder { 98 | color: #ececec; 99 | } 100 | 101 | #result{ 102 | margin: 1rem 0; 103 | /* Closes #74: Added font-family Oswald to githubHandle */ 104 | font-family: 'Oswald', sans-serif; 105 | } 106 | 107 | #resultHandle{ 108 | margin-bottom: 10px; 109 | font-size: 16px; 110 | /* Closes #74: Added font-family Oswald to resultHandle */ 111 | font-family: 'Oswald', sans-serif; 112 | } 113 | 114 | #prCompleteCount{ 115 | position: absolute; 116 | text-align: center; 117 | left: 45%; 118 | font-size: 1rem; 119 | font-weight: 700; 120 | } 121 | 122 | #message{ 123 | font-size: 18px; 124 | text-align: center; 125 | } 126 | 127 | #prList h2 { 128 | color: #fff; 129 | } 130 | 131 | #prList ul { 132 | padding-left: 0; 133 | } 134 | 135 | #prList li { 136 | list-style: none; 137 | } 138 | 139 | #prList li a { 140 | color: #21ffff; 141 | text-decoration: none; 142 | font-size: .9rem; 143 | } 144 | 145 | #prList li a:hover { 146 | color: #fff; 147 | } 148 | 149 | #overlay{ 150 | background-color: rgba(0, 0, 0, 0.5); 151 | position: absolute; 152 | top:0; 153 | left:0; 154 | right:0; 155 | bottom:0; 156 | visibility: collapse; 157 | } 158 | 159 | #dialog{ 160 | border: 0px; 161 | text-align: center; 162 | background-color: #411e2f; 163 | margin: 0 auto; 164 | width: 80%; 165 | } 166 | 167 | #show{ 168 | visibility: collapse; 169 | } 170 | 171 | .progress-bar { 172 | width: 100%; 173 | background-color: #755866; 174 | border-radius: 5px; 175 | margin: .5rem 0; 176 | } 177 | 178 | .progress-bar--color { 179 | background-color: #21ffff; 180 | height: 1.5rem; 181 | border-radius: 5px; 182 | } 183 | -------------------------------------------------------------------------------- /popup.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Hacktoberfest 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 20 |
21 |
22 |
23 | 24 | 25 | 26 |
27 |
28 |
29 |
30 | 31 |
32 |
33 | 34 |
35 |
36 |
37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /popup.js: -------------------------------------------------------------------------------- 1 | var inputHandle = document.getElementById("githubHandle"); 2 | var btn = document.getElementById("check"); 3 | 4 | if ( 5 | document.getElementById("githubHandle").value === "" && 6 | chrome.storage !== undefined 7 | ) { 8 | chrome.storage.sync.get("lastSearched", function(data) { 9 | var storedHandle = data["lastSearched"]; 10 | if (storedHandle != "" && storedHandle != null) { 11 | setData(storedHandle); 12 | } 13 | }); 14 | } 15 | 16 | inputHandle.onkeydown = function(event) { 17 | if (event.keyCode == 13) { 18 | btn.click(); 19 | } 20 | }; 21 | 22 | document.getElementById("show").onclick = function() { 23 | document.getElementById("dialog").showModal(); 24 | document.getElementById("overlay").style.visibility = "visible"; 25 | }; 26 | 27 | document.getElementById("closeBtn").onclick = function() { 28 | document.getElementById("dialog").close(); 29 | document.getElementById("overlay").style.visibility = "collapse"; 30 | }; 31 | 32 | btn.onclick = function() { 33 | var handle = document.getElementById("githubHandle").value; 34 | var result = document.getElementById("result"); 35 | if (handle != "" && handle != null) { 36 | result.innerHTML = "Loading..."; 37 | initData(handle); 38 | } else { 39 | result.innerHTML = "Please enter a valid Github Username"; 40 | } 41 | }; 42 | 43 | function getMessage(total_count) { 44 | var message = ""; 45 | switch (total_count) { 46 | case 0: 47 | return "It's never too late to start! Go and get hacking!"; 48 | case 1: 49 | return "One down, four to go! Keep going!"; 50 | case 2: 51 | return "Awesome work! You're almost halfway there!"; 52 | case 3: 53 | return "Don't stop now, you're closer to the finish line!"; 54 | case 4: 55 | return "Just one more, give it your best shot!"; 56 | default: 57 | return "You did it! Congratulations for completing Hacktoberfest 2018!"; 58 | } 59 | } 60 | 61 | function updateMostRecentUsers(user) { 62 | 63 | chrome.storage.sync.get("mostRecentUsers", function(data) { 64 | var mostRecentUsers = data["mostRecentUsers"] || []; 65 | var hasUser = false; 66 | if (mostRecentUsers.length > 0) { 67 | for (var i = 0; i < mostRecentUsers.length; i++) { 68 | mostRecentUsers[i].active = false; 69 | if (mostRecentUsers[i].name === user.name) { 70 | hasUser = true; 71 | mostRecentUsers[i].active = true; 72 | } 73 | } 74 | } 75 | 76 | if (!hasUser) { 77 | user.active = true; 78 | mostRecentUsers.push(user); 79 | } 80 | 81 | if (mostRecentUsers.length > 5) { 82 | mostRecentUsers.shift(); 83 | } 84 | 85 | chrome.storage.sync.set({ mostRecentUsers: mostRecentUsers }, function() { 86 | var html = ""; 87 | for (var i = 0; i < mostRecentUsers.length; i++) { 88 | var active = mostRecentUsers[i].active ? "active" : ""; 89 | html += `${mostRecentUsers[i].name}`; 92 | } 93 | var parent = document.getElementById("mostRecentUsers"); 94 | parent.addEventListener("click", function(e) { 95 | setData(e.target.id); 96 | }); 97 | parent.innerHTML = html; 98 | }); 99 | }); 100 | } 101 | 102 | function setData(handle) { 103 | document.getElementById("githubHandle").value = handle; 104 | initData(handle); 105 | } 106 | 107 | function getXHR(url) { 108 | return new Promise(function(resolve, reject) { 109 | var req = new XMLHttpRequest(); 110 | req.open("GET", url, true); 111 | req.onreadystatechange = function() { 112 | if (this.status === 200 && this.readyState === 4) { 113 | resolve(JSON.parse(req.responseText)); 114 | } 115 | if (this.status === 403) { 116 | document.getElementById("result").innerHTML = "
You've hit your limit, try again later.
"; 117 | document.getElementById("check").style.visibility = "collapse"; 118 | document.getElementById("show").style.visibility = "collapse"; 119 | } 120 | }; 121 | req.onerror = function() { 122 | reject(Error("Network Error")); 123 | }; 124 | req.send(); 125 | }); 126 | } 127 | 128 | function initData(handle) { 129 | var avatarUrl = ""; 130 | 131 | getXHR(`https://api.github.com/users/${handle}`) 132 | .then(function(data) { 133 | avatarUrl = data.avatar_url; 134 | return getXHR( 135 | `https://api.github.com/search/issues?q=author:${handle}+type:pr+created:2018-09-30T00:00:00-12:00..2018-10-31T23:59:59-12:00+is:public` 136 | ); 137 | }) 138 | .then(function(data) { 139 | var prCount = data.items.length || 0; 140 | 141 | updateMostRecentUsers({ name: handle, thumbnail: avatarUrl }); 142 | chrome.storage.sync.set( 143 | { lastSearched: handle, thumbnail: avatarUrl }, 144 | function() { 145 | var res = ""; 146 | res += `
${handle}s progress:
`; 147 | var count = (prCount > 5 ? "5" : prCount) + " / 5"; 148 | var progress = prCount * 20; 149 | // res += ``; 150 | res += `
${count}
` 151 | var message = getMessage(prCount); 152 | res += `
${message}
`; 153 | document.getElementById("result").innerHTML = res; 154 | 155 | var newestPRs = prCount > 4 ? data.items.slice(0, 5) : data.items; 156 | if (newestPRs.length > 0) { 157 | var content = ""; 158 | var prs = newestPRs.map((v, i) => { 159 | return `
  • #${ 160 | v["number"] 161 | } - ${v["title"]}
  • `; 162 | }); 163 | content += `

    Pull requests

    `; 164 | 165 | document.getElementById("dialogContent").innerHTML = content; 166 | document.getElementById("show").style.visibility = "visible"; 167 | } else { 168 | document.getElementById("show").style.visibility = "collapse"; 169 | } 170 | } 171 | ); 172 | }) 173 | .catch(function(error) { 174 | console.error(error); 175 | }); 176 | } 177 | -------------------------------------------------------------------------------- /test/test.js: -------------------------------------------------------------------------------- 1 | var assert = require("assert"); 2 | describe("Array", function() { 3 | describe("#indexOf()", function() { 4 | it("should return -1 when the value is not present", function() { 5 | assert.equal([1, 2, 3].indexOf(4), -1); 6 | }); 7 | }); 8 | }); 9 | --------------------------------------------------------------------------------