├── static ├── .gitkeep └── favicon.ico ├── src ├── firebase │ ├── index.js │ └── exports.js ├── assets │ ├── images │ │ ├── logo.png │ │ └── github-logo.png │ └── routes.js ├── router │ └── index.js ├── vuex │ ├── index.js │ ├── rank │ │ └── index.js │ ├── auth │ │ └── index.js │ └── stars │ │ └── index.js ├── main.js ├── axios │ └── index.js ├── app.vue ├── vuetify │ └── index.js └── components │ └── main.vue ├── .firebaserc ├── config ├── prod.env.js ├── dev.env.js └── index.js ├── .env.example ├── README.md ├── .editorconfig ├── .gitignore ├── .babelrc ├── .postcssrc.js ├── firebase.json ├── index.html ├── .github └── FUNDING.yml └── package.json /static/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/firebase/index.js: -------------------------------------------------------------------------------- 1 | export * from './exports'; 2 | -------------------------------------------------------------------------------- /.firebaserc: -------------------------------------------------------------------------------- 1 | { 2 | "projects": { 3 | "default": "git-superstar" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /config/prod.env.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | module.exports = { 3 | NODE_ENV: '"production"' 4 | } 5 | -------------------------------------------------------------------------------- /static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Incredidev9285/superstar/HEAD/static/favicon.ico -------------------------------------------------------------------------------- /src/assets/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Incredidev9285/superstar/HEAD/src/assets/images/logo.png -------------------------------------------------------------------------------- /src/assets/images/github-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Incredidev9285/superstar/HEAD/src/assets/images/github-logo.png -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | VERSION= 2 | GITHUB_API= 3 | # Firebase 4 | API_KEY= 5 | AUTH_DOMAIN= 6 | DATABASE_URL= 7 | PROJECT_ID= 8 | STORAGE_BUCKET= 9 | MESSAGING_SENDER_ID= -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # git-superstar 2 | 3 | > Count your Github stars! 4 | 5 | ## [Live](https://git-superstar.firebaseapp.com) 6 | 7 | ![Screen Shot](https://i.imgur.com/4RjkFfj.png) 8 | -------------------------------------------------------------------------------- /config/dev.env.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const merge = require('webpack-merge') 3 | const prodEnv = require('./prod.env') 4 | 5 | module.exports = merge(prodEnv, { 6 | NODE_ENV: '"development"' 7 | }) 8 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /src/assets/routes.js: -------------------------------------------------------------------------------- 1 | module.exports = [ 2 | { 3 | 'path': '/', 4 | 'title': `Git Superstar! | Count your github stars`, 5 | 'description': 'Count your github stars!', 6 | 'image': '' 7 | }, 8 | ]; 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | /dist/ 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | .firebase 9 | .env 10 | 11 | # Editor directories and files 12 | .idea 13 | .vscode 14 | *.suo 15 | *.ntvs* 16 | *.njsproj 17 | *.sln 18 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | ["env", { 4 | "modules": false, 5 | "targets": { 6 | "browsers": ["> 1%", "last 2 versions", "not ie <= 8"] 7 | } 8 | }], 9 | "stage-2" 10 | ], 11 | "plugins": ["transform-vue-jsx", "transform-runtime"] 12 | } 13 | -------------------------------------------------------------------------------- /.postcssrc.js: -------------------------------------------------------------------------------- 1 | // https://github.com/michael-ciniawsky/postcss-load-config 2 | 3 | module.exports = { 4 | "plugins": { 5 | "postcss-import": {}, 6 | "postcss-url": {}, 7 | // to edit target browsers: use "browserslist" field in package.json 8 | "autoprefixer": {} 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /firebase.json: -------------------------------------------------------------------------------- 1 | { 2 | "hosting": { 3 | "public": "dist", 4 | "ignore": [ 5 | "firebase.json", 6 | "**/.*", 7 | "**/node_modules/**" 8 | ], 9 | "rewrites": [ 10 | { 11 | "source": "**", 12 | "destination": "/index.html" 13 | } 14 | ] 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/router/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import Router from 'vue-router'; 3 | import main from '@/components/main'; 4 | 5 | Vue.use(Router); 6 | 7 | export default new Router({ 8 | mode: 'history', 9 | routes: [ 10 | { 11 | path: '/:username?', 12 | name: 'main', 13 | component: main 14 | } 15 | ] 16 | }) 17 | -------------------------------------------------------------------------------- /src/vuex/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import Vuex from 'vuex'; 3 | import createPersistedState from 'vuex-persistedstate'; 4 | import auth from './auth'; 5 | import rank from './rank'; 6 | import stars from './stars'; 7 | 8 | Vue.use(Vuex); 9 | 10 | const modules = { 11 | auth, 12 | rank, 13 | stars 14 | }; 15 | 16 | export default new Vuex.Store({ 17 | modules, 18 | plugins: [createPersistedState()] 19 | }); 20 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | // The Vue build version to load with the `import` command 2 | // (runtime-only or standalone) has been set in webpack.base.conf with an alias. 3 | import Vue from 'vue'; 4 | import './firebase'; 5 | import './vuetify'; 6 | import app from './app'; 7 | import router from './router'; 8 | import store from './vuex'; 9 | 10 | Vue.config.productionTip = false 11 | 12 | /* eslint-disable no-new */ 13 | new Vue({ 14 | el: '#app', 15 | router, 16 | store, 17 | components: { app }, 18 | template: '' 19 | }) 20 | -------------------------------------------------------------------------------- /src/vuex/rank/index.js: -------------------------------------------------------------------------------- 1 | const state = { 2 | rankLocal: null, 3 | rankGlobal: null 4 | }; 5 | 6 | const getters = { 7 | rankLocal: (s) => s.rankLocal, 8 | rankGlobal: (s) => s.rankGlobal, 9 | }; 10 | 11 | const actions = { 12 | // TODO: Get ranking of user via stars 13 | getRanking: async ({commit}, {username, token}) => { 14 | } 15 | }; 16 | 17 | const mutations = { 18 | // setUser: (s, val) => { s.user = val; }, 19 | // setToken: (s, val) => { s.token = val; }, 20 | }; 21 | 22 | export default { 23 | namespaced: true, 24 | state, 25 | getters, 26 | actions, 27 | mutations 28 | }; 29 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | GHS_TITLE 10 | 11 | 12 | 13 |
14 | 15 | 16 | -------------------------------------------------------------------------------- /src/firebase/exports.js: -------------------------------------------------------------------------------- 1 | import firebase from 'firebase/app'; 2 | import 'firebase/auth'; 3 | import 'firebase/database'; 4 | import 'firebase/storage'; 5 | 6 | firebase.initializeApp({ 7 | apiKey: process.env.API_KEY, 8 | authDomain: process.env.AUTH_DOMAIN, 9 | databaseURL: process.env.DATABASE_URL, 10 | projectId: process.env.PROJECT_ID, 11 | storageBucket: process.env.STORAGE_BUCKET, 12 | messagingSenderId: process.env.MESSAGING_SENDER_ID 13 | }); 14 | 15 | export const auth = firebase.auth(); 16 | export const db = firebase.database(); 17 | export const storage = firebase.storage(); 18 | export const ref = firebase.database().ref(process.env.VERSION); -------------------------------------------------------------------------------- /src/axios/index.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | 3 | export const getStars = async (username, token) => { 4 | let final = []; 5 | 6 | const request = axios.create({ 7 | baseURL: process.env.GITHUB_API 8 | }); 9 | 10 | const { data } = await request.get(`/users/${username}?token=${token}`); 11 | 12 | if (!data.public_repos) { 13 | console.log(data.message); 14 | return 15 | } 16 | 17 | let pages = Math.ceil(data.public_repos / 100), 18 | i = pages, 19 | repos = [] 20 | 21 | while (i--) { 22 | let { data } = await request.get(`/users/${username}/repos?per_page=100&page=${(i + 1)}`); 23 | repos = repos.concat(data); 24 | pages--; 25 | } 26 | 27 | return repos; 28 | }; -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 13 | -------------------------------------------------------------------------------- /src/app.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 28 | 29 | 35 | -------------------------------------------------------------------------------- /src/vuex/auth/index.js: -------------------------------------------------------------------------------- 1 | import { auth } from '../../firebase/exports'; 2 | import firebase from 'firebase'; 3 | 4 | const state = { 5 | user: null, 6 | token: null 7 | }; 8 | 9 | const getters = { 10 | user: (s) => s.user, 11 | token: (s) => s.token 12 | }; 13 | 14 | const actions = { 15 | authWithGithub: async ({commit}, username) => { 16 | const provider = new firebase.auth.GithubAuthProvider(); 17 | const { credential, user } = await firebase.auth().signInWithPopup(provider) 18 | commit('setUser', user); 19 | commit('setToken', credential.accessToken); 20 | }, 21 | signOut: async ({commit}) => { 22 | await auth.signOut(); 23 | commit('setUser', null); 24 | commit('setToken', null); 25 | commit('stars/setStarsTotal', 0, { root: true }); 26 | commit('stars/setTotalForked', 0, { root: true }); 27 | commit('stars/setTotalOwned', 0, { root: true }); 28 | commit('stars/setStarsTotal', 0, { root: true }); 29 | commit('stars/setTopRepos', [], { root: true }); 30 | } 31 | }; 32 | 33 | const mutations = { 34 | setUser: (s, val) => { s.user = val; }, 35 | setToken: (s, val) => { s.token = val; }, 36 | }; 37 | 38 | export default { 39 | namespaced: true, 40 | state, 41 | getters, 42 | actions, 43 | mutations 44 | }; 45 | -------------------------------------------------------------------------------- /src/vuetify/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import Vuetify from 'vuetify/es5/components/Vuetify'; 3 | import VApp from 'vuetify/es5/components/VApp'; 4 | import VGrid from 'vuetify/es5/components/VGrid'; 5 | import VToolbar from 'vuetify/es5/components/VToolbar'; 6 | import VCard from 'vuetify/es5/components/VCard'; 7 | import VBtn from 'vuetify/es5/components/VBtn'; 8 | import VIcon from 'vuetify/es5/components/VIcon'; 9 | import VDialog from 'vuetify/es5/components/VDialog'; 10 | import VDivider from 'vuetify/es5/components/VDivider'; 11 | import VFooter from 'vuetify/es5/components/VFooter'; 12 | import VList from 'vuetify/es5/components/VList'; 13 | import VMenu from 'vuetify/es5/components/VMenu'; 14 | import VTooltip from 'vuetify/es5/components/VTooltip'; 15 | import VTextField from 'vuetify/es5/components/VTextField'; 16 | import VSelect from 'vuetify/es5/components/VSelect'; 17 | import VProgressLinear from 'vuetify/es5/components/VProgressLinear'; 18 | import { Ripple } from 'vuetify/es5/directives'; 19 | import 'vuetify/dist/vuetify.min.css'; 20 | import 'vuetify/src/stylus/app.styl'; 21 | 22 | Vue.use(Vuetify, { 23 | theme: { 24 | primary: '#8BC34A', 25 | }, 26 | components: { 27 | VApp, 28 | VGrid, 29 | VToolbar, 30 | VCard, 31 | VBtn, 32 | VIcon, 33 | VDialog, 34 | VDivider, 35 | VFooter, 36 | VList, 37 | VMenu, 38 | VTooltip, 39 | VTextField, 40 | VSelect, 41 | VProgressLinear 42 | }, 43 | directives: { 44 | Ripple 45 | } 46 | }); 47 | -------------------------------------------------------------------------------- /src/vuex/stars/index.js: -------------------------------------------------------------------------------- 1 | import { getStars } from '../../axios'; 2 | import { ref } from '../../firebase'; 3 | 4 | const state = { 5 | starsTotal: 0, 6 | totalForked: 0, 7 | totalOwned: 0, 8 | topRepos: [] 9 | }; 10 | 11 | const getters = { 12 | starsTotal: (s) => s.starsTotal, 13 | topRepos: (s) => s.topRepos, 14 | totalForked: (s) => s.totalForked, 15 | totalOwned: (s) => s.totalOwned, 16 | }; 17 | 18 | const actions = { 19 | getStars: async ({commit}, {username, token}) => { 20 | const repos = await getStars(username, token); 21 | const totalStars = repos.map(item => item.stargazers_count).reduce((a, b) => a + b); 22 | const topRepos = repos.sort((a, b) => b.stargazers_count - a.stargazers_count); 23 | const totalForked = repos.filter(item => item.fork).length; 24 | const totalOwned = repos.filter(item => !item.fork).length; 25 | commit('setStarsTotal', totalStars); 26 | commit('setTotalForked', totalForked); 27 | commit('setTotalOwned', totalOwned); 28 | commit('setTopRepos', topRepos); 29 | await ref.child(username) 30 | .child('total-stars') 31 | .set(totalStars); 32 | await ref.child(username) 33 | .child('total-forked') 34 | .set(totalForked); 35 | } 36 | }; 37 | 38 | const mutations = { 39 | setStarsTotal: (s, val) => { s.starsTotal = val; }, 40 | setTotalForked: (s, val) => { s.totalForked = val; }, 41 | setTotalOwned: (s, val) => { s.totalOwned = val; }, 42 | setTopRepos: (s, val) => { s.topRepos = val; }, 43 | }; 44 | 45 | export default { 46 | namespaced: true, 47 | state, 48 | getters, 49 | actions, 50 | mutations 51 | }; 52 | -------------------------------------------------------------------------------- /config/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | // Template version: 1.3.1 3 | // see http://vuejs-templates.github.io/webpack for documentation. 4 | 5 | const path = require('path') 6 | 7 | module.exports = { 8 | dev: { 9 | 10 | // Paths 11 | assetsSubDirectory: 'static', 12 | assetsPublicPath: '/', 13 | proxyTable: {}, 14 | 15 | // Various Dev Server settings 16 | host: 'localhost', // can be overwritten by process.env.HOST 17 | port: 8080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined 18 | autoOpenBrowser: false, 19 | errorOverlay: true, 20 | notifyOnErrors: true, 21 | poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions- 22 | 23 | 24 | /** 25 | * Source Maps 26 | */ 27 | 28 | // https://webpack.js.org/configuration/devtool/#development 29 | devtool: 'cheap-module-eval-source-map', 30 | 31 | // If you have problems debugging vue-files in devtools, 32 | // set this to false - it *may* help 33 | // https://vue-loader.vuejs.org/en/options.html#cachebusting 34 | cacheBusting: true, 35 | 36 | cssSourceMap: true 37 | }, 38 | 39 | build: { 40 | // Template for index.html 41 | index: path.resolve(__dirname, '../dist/index.html'), 42 | 43 | // Paths 44 | assetsRoot: path.resolve(__dirname, '../dist'), 45 | assetsSubDirectory: 'static', 46 | assetsPublicPath: '/', 47 | 48 | /** 49 | * Source Maps 50 | */ 51 | 52 | productionSourceMap: true, 53 | // https://webpack.js.org/configuration/devtool/#production 54 | devtool: '#source-map', 55 | 56 | // Gzip off by default as many popular static hosts such as 57 | // Surge or Netlify already gzip all static assets for you. 58 | // Before setting to `true`, make sure to: 59 | // npm install --save-dev compression-webpack-plugin 60 | productionGzip: false, 61 | productionGzipExtensions: ['js', 'css'], 62 | 63 | // Run the build command with an extra argument to 64 | // View the bundle analyzer report after build finishes: 65 | // `npm run build --report` 66 | // Set to `true` or `false` to always turn it on or off 67 | bundleAnalyzerReport: process.env.npm_config_report 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "git-superstar", 3 | "version": "1.0.0", 4 | "description": "A Vue.js project", 5 | "author": "Joff Tiquez ", 6 | "private": true, 7 | "scripts": { 8 | "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js", 9 | "start": "npm run dev", 10 | "build": "node build/build.js" 11 | }, 12 | "dependencies": { 13 | "axios": "^0.21.1", 14 | "firebase": "^5.7.0", 15 | "prerender-spa-plugin": "^3.4.0", 16 | "vue": "^2.5.2", 17 | "vue-router": "^3.0.1", 18 | "vuetify": "^1.5.16", 19 | "vuex": "^3.0.1", 20 | "vuex-persistedstate": "^2.5.4" 21 | }, 22 | "devDependencies": { 23 | "autoprefixer": "^7.1.2", 24 | "babel-core": "^6.22.1", 25 | "babel-helper-vue-jsx-merge-props": "^2.0.3", 26 | "babel-loader": "^7.1.1", 27 | "babel-plugin-syntax-jsx": "^6.18.0", 28 | "babel-plugin-transform-runtime": "^6.22.0", 29 | "babel-plugin-transform-vue-jsx": "^3.5.0", 30 | "babel-preset-env": "^1.3.2", 31 | "babel-preset-stage-2": "^6.22.0", 32 | "chalk": "^2.0.1", 33 | "copy-webpack-plugin": "^4.0.1", 34 | "css-loader": "^0.28.0", 35 | "dotenv-webpack": "^1.5.7", 36 | "extract-text-webpack-plugin": "^3.0.0", 37 | "file-loader": "^1.1.4", 38 | "friendly-errors-webpack-plugin": "^1.6.1", 39 | "html-webpack-plugin": "^2.30.1", 40 | "node-notifier": "^5.1.2", 41 | "optimize-css-assets-webpack-plugin": "^3.2.0", 42 | "ora": "^1.2.0", 43 | "portfinder": "^1.0.13", 44 | "postcss-import": "^11.0.0", 45 | "postcss-loader": "^2.0.8", 46 | "postcss-url": "^7.2.1", 47 | "pug": "^2.0.3", 48 | "rimraf": "^2.6.0", 49 | "semver": "^5.3.0", 50 | "shelljs": "^0.7.6", 51 | "stylus": "^0.54.5", 52 | "stylus-loader": "^3.0.2", 53 | "uglifyjs-webpack-plugin": "^1.1.1", 54 | "url-loader": "^0.5.8", 55 | "vue-loader": "^13.3.0", 56 | "vue-style-loader": "^3.0.1", 57 | "vue-template-compiler": "^2.5.2", 58 | "webpack": "^3.6.0", 59 | "webpack-bundle-analyzer": "^3.3.2", 60 | "webpack-dev-server": "^3.1.11", 61 | "webpack-merge": "^4.1.0" 62 | }, 63 | "engines": { 64 | "node": ">= 6.0.0", 65 | "npm": ">= 3.0.0" 66 | }, 67 | "browserslist": [ 68 | "> 1%", 69 | "last 2 versions", 70 | "not ie <= 8" 71 | ] 72 | } 73 | -------------------------------------------------------------------------------- /src/components/main.vue: -------------------------------------------------------------------------------- 1 | 83 | 84 | 141 | 142 | 155 | 156 | --------------------------------------------------------------------------------