From 4d7dfbe724ee46da2ed188ebfea10e5aea36175c Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Mon, 23 Nov 2020 16:44:25 +0100 Subject: [PATCH 01/60] :memo: Updates README.md Run instructions, tests and (yet to be) deployment link. --- README.md | 82 +++++++++++++------------------------------------------ 1 file changed, 19 insertions(+), 63 deletions(-) diff --git a/README.md b/README.md index 02aac3f..6ac06d4 100644 --- a/README.md +++ b/README.md @@ -1,70 +1,26 @@ -# Getting Started with Create React App +# GitPop3 -This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). +[![Tests](https://github.com/AndreMiras/gitpop3/workflows/Tests/badge.svg?branch=develop)](https://github.com/AndreMiras/gitpop3/actions?query=workflow%3ATests) +[![Deploy](https://github.com/AndreMiras/gitpop3/workflows/Deploy/badge.svg?branch=develop)](https://github.com/AndreMiras/gitpop3/actions?query=workflow%3ADeploy) -## Available Scripts +Find the most popular fork on GitHub. -In the project directory, you can run: + -### `yarn start` -Runs the app in the development mode.\ -Open [http://localhost:3000](http://localhost:3000) to view it in the browser. +## Run +```sh +yarn start +``` -The page will reload if you make edits.\ -You will also see any lint errors in the console. +## Test +```sh +yarn lint +yarn test +``` -### `yarn test` - -Launches the test runner in the interactive watch mode.\ -See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. - -### `yarn build` - -Builds the app for production to the `build` folder.\ -It correctly bundles React in production mode and optimizes the build for the best performance. - -The build is minified and the filenames include the hashes.\ -Your app is ready to be deployed! - -See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. - -### `yarn eject` - -**Note: this is a one-way operation. Once you `eject`, you can’t go back!** - -If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project. - -Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own. - -You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it. - -## Learn More - -You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). - -To learn React, check out the [React documentation](https://reactjs.org/). - -### Code Splitting - -This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting) - -### Analyzing the Bundle Size - -This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size) - -### Making a Progressive Web App - -This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app) - -### Advanced Configuration - -This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration) - -### Deployment - -This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment) - -### `yarn build` fails to minify - -This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify) +## Deployment +The app can be deployed on GitHub pages when releasing via: +```sh +yarn deploy +``` From 0d97295e21ae5770b925fda71124fd028e03d990 Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Mon, 23 Nov 2020 16:45:25 +0100 Subject: [PATCH 02/60] :construction: App and CSS cleanup --- public/index.html | 4 ++-- src/App.css | 38 -------------------------------------- src/App.js | 14 +------------- src/App.test.js | 4 ++-- 4 files changed, 5 insertions(+), 55 deletions(-) diff --git a/public/index.html b/public/index.html index aa069f2..c3c93fb 100644 --- a/public/index.html +++ b/public/index.html @@ -7,7 +7,7 @@ - React App + GitPop3 diff --git a/src/App.css b/src/App.css index 74b5e05..e69de29 100644 --- a/src/App.css +++ b/src/App.css @@ -1,38 +0,0 @@ -.App { - text-align: center; -} - -.App-logo { - height: 40vmin; - pointer-events: none; -} - -@media (prefers-reduced-motion: no-preference) { - .App-logo { - animation: App-logo-spin infinite 20s linear; - } -} - -.App-header { - background-color: #282c34; - min-height: 100vh; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - font-size: calc(10px + 2vmin); - color: white; -} - -.App-link { - color: #61dafb; -} - -@keyframes App-logo-spin { - from { - transform: rotate(0deg); - } - to { - transform: rotate(360deg); - } -} diff --git a/src/App.js b/src/App.js index 3784575..629ce18 100644 --- a/src/App.js +++ b/src/App.js @@ -1,22 +1,10 @@ -import logo from './logo.svg'; -import './App.css'; - function App() { return (
- logo

- Edit src/App.js and save to reload. + GitPop3

- - Learn React -
); diff --git a/src/App.test.js b/src/App.test.js index 1f03afe..fcbdcda 100644 --- a/src/App.test.js +++ b/src/App.test.js @@ -1,8 +1,8 @@ import { render, screen } from '@testing-library/react'; import App from './App'; -test('renders learn react link', () => { +test('renders title', () => { render(); - const linkElement = screen.getByText(/learn react/i); + const linkElement = screen.getByText(/GitPop3/); expect(linkElement).toBeInTheDocument(); }); From a5f3375828432a4515f1bbadc6d66f08705712bb Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Mon, 23 Nov 2020 16:51:33 +0100 Subject: [PATCH 03/60] :heavy_plus_sign: yarn add eslint-config-airbnb --- package.json | 7 ++++++- yarn.lock | 20 +++++++++++++++++++- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 4e3e3aa..e940d33 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,9 @@ "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test", - "eject": "react-scripts eject" + "eject": "react-scripts eject", + "lint": "eslint -c .eslintrc 'src/**/*.{js,jsx}'", + "format": "eslint -c .eslintrc 'src/**/*.{js,jsx}' --fix" }, "eslintConfig": { "extends": [ @@ -34,5 +36,8 @@ "last 1 firefox version", "last 1 safari version" ] + }, + "devDependencies": { + "eslint-config-airbnb": "^18.2.1" } } diff --git a/yarn.lock b/yarn.lock index a5a34d2..50aaf54 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4392,6 +4392,24 @@ escodegen@^1.14.1: optionalDependencies: source-map "~0.6.1" +eslint-config-airbnb-base@^14.2.1: + version "14.2.1" + resolved "https://registry.yarnpkg.com/eslint-config-airbnb-base/-/eslint-config-airbnb-base-14.2.1.tgz#8a2eb38455dc5a312550193b319cdaeef042cd1e" + integrity sha512-GOrQyDtVEc1Xy20U7vsB2yAoB4nBlfH5HZJeatRXHleO+OS5Ot+MWij4Dpltw4/DyIkqUfqz1epfhVR5XWWQPA== + dependencies: + confusing-browser-globals "^1.0.10" + object.assign "^4.1.2" + object.entries "^1.1.2" + +eslint-config-airbnb@^18.2.1: + version "18.2.1" + resolved "https://registry.yarnpkg.com/eslint-config-airbnb/-/eslint-config-airbnb-18.2.1.tgz#b7fe2b42f9f8173e825b73c8014b592e449c98d9" + integrity sha512-glZNDEZ36VdlZWoxn/bUR1r/sdFKPd1mHPbqUtkctgNG4yT2DLLtJ3D+yCV+jzZCc2V1nBVkmdknOJBZ5Hc0fg== + dependencies: + eslint-config-airbnb-base "^14.2.1" + object.assign "^4.1.2" + object.entries "^1.1.2" + eslint-config-react-app@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/eslint-config-react-app/-/eslint-config-react-app-6.0.0.tgz#ccff9fc8e36b322902844cbd79197982be355a0e" @@ -7503,7 +7521,7 @@ object-visit@^1.0.0: dependencies: isobject "^3.0.0" -object.assign@^4.1.0, object.assign@^4.1.1: +object.assign@^4.1.0, object.assign@^4.1.1, object.assign@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940" integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ== From bc5c098583b4e7b02e0d454a3376128c0293ea0b Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Mon, 23 Nov 2020 16:55:22 +0100 Subject: [PATCH 04/60] :rotating_light: linting fixes --- .eslintignore | 1 + .eslintrc | 11 +++++++++++ src/{App.js => App.jsx} | 2 ++ src/{App.test.js => App.test.jsx} | 1 + src/{index.js => index.jsx} | 6 +++--- src/{reportWebVitals.js => reportWebVitals.jsx} | 0 6 files changed, 18 insertions(+), 3 deletions(-) create mode 100644 .eslintignore create mode 100644 .eslintrc rename src/{App.js => App.jsx} (87%) rename src/{App.test.js => App.test.jsx} (89%) rename src/{index.js => index.jsx} (78%) rename src/{reportWebVitals.js => reportWebVitals.jsx} (100%) diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..77f878d --- /dev/null +++ b/.eslintignore @@ -0,0 +1 @@ +src/reportWebVitals.jsx diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000..067977b --- /dev/null +++ b/.eslintrc @@ -0,0 +1,11 @@ +"extends": "airbnb" +"env": { + "browser": true, + "jest": true, +} +"rules": { + "allowShortCircuit": 0, + "allowTernary": 0, + "no-unused-expressions": "off", + "no-mixed-operators": "off" +} diff --git a/src/App.js b/src/App.jsx similarity index 87% rename from src/App.js rename to src/App.jsx index 629ce18..6a6baf8 100644 --- a/src/App.js +++ b/src/App.jsx @@ -1,3 +1,5 @@ +import React from 'react'; + function App() { return (
diff --git a/src/App.test.js b/src/App.test.jsx similarity index 89% rename from src/App.test.js rename to src/App.test.jsx index fcbdcda..54b17d5 100644 --- a/src/App.test.js +++ b/src/App.test.jsx @@ -1,3 +1,4 @@ +import React from 'react'; import { render, screen } from '@testing-library/react'; import App from './App'; diff --git a/src/index.js b/src/index.jsx similarity index 78% rename from src/index.js rename to src/index.jsx index ef2edf8..06c68c5 100644 --- a/src/index.js +++ b/src/index.jsx @@ -2,16 +2,16 @@ import React from 'react'; import ReactDOM from 'react-dom'; import './index.css'; import App from './App'; -import reportWebVitals from './reportWebVitals'; +// import reportWebVitals from './reportWebVitals'; ReactDOM.render( , - document.getElementById('root') + document.getElementById('root'), ); // If you want to start measuring performance in your app, pass a function // to log results (for example: reportWebVitals(console.log)) // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals -reportWebVitals(); +// reportWebVitals(); diff --git a/src/reportWebVitals.js b/src/reportWebVitals.jsx similarity index 100% rename from src/reportWebVitals.js rename to src/reportWebVitals.jsx From bf8b8d56ef8ea95e1f06cd0c8deaf1c8f6848b91 Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Mon, 23 Nov 2020 16:47:29 +0100 Subject: [PATCH 05/60] :heavy_plus_sign: yarn add react-bootstrap --- package.json | 1 + yarn.lock | 176 +++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 173 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index e940d33..5dc3d84 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,7 @@ "@testing-library/react": "^11.1.0", "@testing-library/user-event": "^12.1.10", "react": "^17.0.1", + "react-bootstrap": "^1.4.0", "react-dom": "^17.0.1", "react-scripts": "4.0.1", "web-vitals": "^0.2.4" diff --git a/yarn.lock b/yarn.lock index 50aaf54..504b7ab 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1085,7 +1085,7 @@ dependencies: regenerator-runtime "^0.13.4" -"@babel/runtime@^7.10.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.5.5", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.2": +"@babel/runtime@^7.10.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.5", "@babel/runtime@^7.4.2", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": version "7.12.5" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.12.5.tgz#410e7e487441e1b360c29be715d870d9b985882e" integrity sha512-plcc+hbExy3McchJCEQG3knOsuh3HH+Prx1P6cLIkET/0dLuQDEnrT+s27Axgc9bqfsmNUNHfscgMUdBpC9xfg== @@ -1423,6 +1423,24 @@ schema-utils "^2.6.5" source-map "^0.7.3" +"@popperjs/core@^2.5.3": + version "2.5.4" + resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.5.4.tgz#de25b5da9f727985a3757fd59b5d028aba75841a" + integrity sha512-ZpKr+WTb8zsajqgDkvCEWgp6d5eJT6Q63Ng2neTbzBO76Lbe91vX/iVIW9dikq+Fs3yEo+ls4cxeXABD2LtcbQ== + +"@restart/context@^2.1.4": + version "2.1.4" + resolved "https://registry.yarnpkg.com/@restart/context/-/context-2.1.4.tgz#a99d87c299a34c28bd85bb489cb07bfd23149c02" + integrity sha512-INJYZQJP7g+IoDUh/475NlGiTeMfwTXUEr3tmRneckHIxNolGOW9CTq83S8cxq0CgJwwcMzMJFchxvlwe7Rk8Q== + +"@restart/hooks@^0.3.21", "@restart/hooks@^0.3.25": + version "0.3.25" + resolved "https://registry.yarnpkg.com/@restart/hooks/-/hooks-0.3.25.tgz#11004139ad1c70d2f5965a8939dcb5aeb96aa652" + integrity sha512-m2v3N5pxTsIiSH74/sb1yW8D9RxkJidGW+5Mfwn/lHb2QzhZNlaU1su7abSyT9EGf0xS/0waLjrf7/XxQHUk7w== + dependencies: + lodash "^4.17.15" + lodash-es "^4.17.15" + "@rollup/plugin-node-resolve@^7.1.1": version "7.1.3" resolved "https://registry.yarnpkg.com/@rollup/plugin-node-resolve/-/plugin-node-resolve-7.1.3.tgz#80de384edfbd7bfc9101164910f86078151a3eca" @@ -1662,6 +1680,11 @@ dependencies: "@babel/types" "^7.3.0" +"@types/classnames@^2.2.10": + version "2.2.11" + resolved "https://registry.yarnpkg.com/@types/classnames/-/classnames-2.2.11.tgz#2521cc86f69d15c5b90664e4829d84566052c1cf" + integrity sha512-2koNhpWm3DgWRp5tpkiJ8JGc1xTn2q0l+jUNUE7oMKXUf5NpI9AIdC4kbjGNFBdHtcxBD18LAksoudAVhFKCjw== + "@types/eslint@^7.2.4": version "7.2.5" resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-7.2.5.tgz#92172ecf490c2fce4b076739693d75f30376d610" @@ -1700,6 +1723,11 @@ resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-5.1.1.tgz#3c9ee980f1a10d6021ae6632ca3e79ca2ec4fb50" integrity sha512-giAlZwstKbmvMk1OO7WXSj4OZ0keXAcl2TQq4LWHiiPH2ByaH7WeUzng+Qej8UPxxv+8lRTuouo0iaNDBuzIBA== +"@types/invariant@^2.2.33": + version "2.2.34" + resolved "https://registry.yarnpkg.com/@types/invariant/-/invariant-2.2.34.tgz#05e4f79f465c2007884374d4795452f995720bbe" + integrity sha512-lYUtmJ9BqUN688fGY1U1HZoWT1/Jrmgigx2loq4ZcJpICECm/Om3V314BxdzypO0u5PORKGMM6x0OXaljV1YFg== + "@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": version "2.0.3" resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz#4ba8ddb720221f432e443bd5f9117fd22cfd4762" @@ -1762,11 +1790,38 @@ resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.1.5.tgz#b6ab3bba29e16b821d84e09ecfaded462b816b00" integrity sha512-UEyp8LwZ4Dg30kVU2Q3amHHyTn1jEdhCIE59ANed76GaT1Vp76DD3ZWSAxgCrw6wJ0TqeoBpqmfUHiUDPs//HQ== +"@types/prop-types@*", "@types/prop-types@^15.7.3": + version "15.7.3" + resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.3.tgz#2ab0d5da2e5815f94b0b9d4b95d1e5f243ab2ca7" + integrity sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw== + "@types/q@^1.5.1": version "1.5.4" resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.4.tgz#15925414e0ad2cd765bfef58842f7e26a7accb24" integrity sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug== +"@types/react-transition-group@^4.4.0": + version "4.4.0" + resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.4.0.tgz#882839db465df1320e4753e6e9f70ca7e9b4d46d" + integrity sha512-/QfLHGpu+2fQOqQaXh8MG9q03bFENooTb/it4jr5kKaZlDQfWvjqWZg48AwzPVMBHlRuTRAY7hRHCEOXz5kV6w== + dependencies: + "@types/react" "*" + +"@types/react@*": + version "17.0.0" + resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.0.tgz#5af3eb7fad2807092f0046a1302b7823e27919b8" + integrity sha512-aj/L7RIMsRlWML3YB6KZiXB3fV2t41+5RBGYF8z+tAKU43Px8C3cYUZsDvf1/+Bm4FK21QWBrDutu8ZJ/70qOw== + dependencies: + "@types/prop-types" "*" + csstype "^3.0.2" + +"@types/react@^16.9.11", "@types/react@^16.9.35": + version "16.14.1" + resolved "https://registry.yarnpkg.com/@types/react/-/react-16.14.1.tgz#da2ecb638385614a5573e16e4aa7daf936dbead5" + integrity sha512-32mxrbX62m5b+lMTSzucFKNIr8Eq4T6T3rDVxYzKqyRwyfnPcwZppWW0YXUlPNPUE+r6phBtHXYRgr8ad/Zl9A== + dependencies: + "@types/prop-types" "*" + "@types/resolve@0.0.8": version "0.0.8" resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-0.0.8.tgz#f26074d238e02659e323ce1a13d041eee280e194" @@ -1803,6 +1858,11 @@ dependencies: source-map "^0.6.1" +"@types/warning@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/warning/-/warning-3.0.0.tgz#0d2501268ad8f9962b740d387c4654f5f8e23e52" + integrity sha1-DSUBJorY+ZYrdA04fEZU9fjiPlI= + "@types/webpack-sources@*": version "2.0.0" resolved "https://registry.yarnpkg.com/@types/webpack-sources/-/webpack-sources-2.0.0.tgz#08216ab9be2be2e1499beaebc4d469cec81e82a7" @@ -3180,6 +3240,11 @@ class-utils@^0.3.5: isobject "^3.0.0" static-extend "^0.1.1" +classnames@^2.2.6: + version "2.2.6" + resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce" + integrity sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q== + clean-css@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.2.3.tgz#507b5de7d97b48ee53d84adb0160ff6216380f78" @@ -3809,6 +3874,11 @@ cssstyle@^2.2.0: dependencies: cssom "~0.3.6" +csstype@^3.0.2: + version "3.0.5" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.5.tgz#7fdec6a28a67ae18647c51668a9ff95bb2fa7bb8" + integrity sha512-uVDi8LpBUKQj6sdxNaTetL6FpeCqTjOvAQuQUa/qAqq8oOd4ivkbhgnqayl0dnPal8Tb/yB1tF+gOvCBiicaiQ== + cyclist@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9" @@ -4072,6 +4142,14 @@ dom-converter@^0.2: dependencies: utila "~0.4" +dom-helpers@^5.0.1, dom-helpers@^5.1.2, dom-helpers@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-5.2.0.tgz#57fd054c5f8f34c52a3eeffdb7e7e93cd357d95b" + integrity sha512-Ru5o9+V8CpunKnz5LGgWXkmrH/20cGKwcHwS4m73zIvs54CN9epEmT/HLqFJW3kXpakAFkEdzgy1hzlJe3E4OQ== + dependencies: + "@babel/runtime" "^7.8.7" + csstype "^3.0.2" + dom-serializer@0: version "0.2.2" resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.2.2.tgz#1afb81f533717175d478655debc5e332d9f9bb51" @@ -5747,6 +5825,13 @@ internal-slot@^1.0.2: has "^1.0.3" side-channel "^1.0.2" +invariant@^2.2.4: + version "2.2.4" + resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" + integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== + dependencies: + loose-envify "^1.0.0" + ip-regex@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9" @@ -6876,6 +6961,11 @@ locate-path@^5.0.0: dependencies: p-locate "^4.1.0" +lodash-es@^4.17.15: + version "4.17.15" + resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.15.tgz#21bd96839354412f23d7a10340e5eac6ee455d78" + integrity sha512-rlrc3yU3+JNOpZ9zj5pQtxnx2THmvRykwL4Xlxoa8I9lHBlVbbyPhgyPMioxVZ4NqyxaVVtaJnzsyOidQIhyyQ== + lodash._reinterpolate@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" @@ -6921,7 +7011,7 @@ loglevel@^1.6.8: resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.7.0.tgz#728166855a740d59d38db01cf46f042caa041bb0" integrity sha512-i2sY04nal5jDcagM3FMfG++T69GEEM8CYuOfeOIvmXzOIcwE9a/CJPR0MFM97pYMj/u10lzz7/zd7+qwhrBTqQ== -loose-envify@^1.1.0, loose-envify@^1.4.0: +loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== @@ -8740,7 +8830,15 @@ prompts@2.4.0, prompts@^2.0.1: kleur "^3.0.3" sisteransi "^1.0.5" -prop-types@^15.7.2: +prop-types-extra@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/prop-types-extra/-/prop-types-extra-1.1.1.tgz#58c3b74cbfbb95d304625975aa2f0848329a010b" + integrity sha512-59+AHNnHYCdiC+vMwY52WmvP5dM3QLeoumYuEyceQDi9aEhtwN9zIQ2ZNo25sMyXnbh32h+P1ezDsUpUH3JAew== + dependencies: + react-is "^16.3.2" + warning "^4.0.0" + +prop-types@^15.6.2, prop-types@^15.7.2: version "15.7.2" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ== @@ -8906,6 +9004,30 @@ react-app-polyfill@^2.0.0: regenerator-runtime "^0.13.7" whatwg-fetch "^3.4.1" +react-bootstrap@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/react-bootstrap/-/react-bootstrap-1.4.0.tgz#806a8b48b065cedfb28c6c5c7b0c0e3c3b53445d" + integrity sha512-0BMzgeUAxH126v7VYDzIXbHxQVHSnniPVKpz9fblumdQpWaiElMnnzk+u8h8DoELX0nCXwPlcUzgXqmpncdc2Q== + dependencies: + "@babel/runtime" "^7.4.2" + "@restart/context" "^2.1.4" + "@restart/hooks" "^0.3.21" + "@types/classnames" "^2.2.10" + "@types/invariant" "^2.2.33" + "@types/prop-types" "^15.7.3" + "@types/react" "^16.9.35" + "@types/react-transition-group" "^4.4.0" + "@types/warning" "^3.0.0" + classnames "^2.2.6" + dom-helpers "^5.1.2" + invariant "^2.2.4" + prop-types "^15.7.2" + prop-types-extra "^1.1.0" + react-overlays "^4.1.0" + react-transition-group "^4.4.1" + uncontrollable "^7.0.0" + warning "^4.0.3" + react-dev-utils@^11.0.1: version "11.0.1" resolved "https://registry.yarnpkg.com/react-dev-utils/-/react-dev-utils-11.0.1.tgz#30106c2055acfd6b047d2dc478a85c356e66fe45" @@ -8950,7 +9072,7 @@ react-error-overlay@^6.0.8: resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.8.tgz#474ed11d04fc6bda3af643447d85e9127ed6b5de" integrity sha512-HvPuUQnLp5H7TouGq3kzBeioJmXms1wHy9EGjz2OURWBp4qZO6AfGEcnxts1D/CbwPLRAgTMPCEgYhA3sEM4vw== -react-is@^16.8.1: +react-is@^16.3.2, react-is@^16.8.1: version "16.13.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== @@ -8960,6 +9082,25 @@ react-is@^17.0.1: resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.1.tgz#5b3531bd76a645a4c9fb6e693ed36419e3301339" integrity sha512-NAnt2iGDXohE5LI7uBnLnqvLQMtzhkiAOLXTmv+qnF9Ky7xAPcX8Up/xWIhxvLVGJvuLiNc4xQLtuqDRzb4fSA== +react-lifecycles-compat@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362" + integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA== + +react-overlays@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/react-overlays/-/react-overlays-4.1.1.tgz#0060107cbe1c5171a744ccda3fbf0556d064bc5f" + integrity sha512-WtJifh081e6M24KnvTQoNjQEpz7HoLxqt8TwZM7LOYIkYJ8i/Ly1Xi7RVte87ZVnmqQ4PFaFiNHZhSINPSpdBQ== + dependencies: + "@babel/runtime" "^7.12.1" + "@popperjs/core" "^2.5.3" + "@restart/hooks" "^0.3.25" + "@types/warning" "^3.0.0" + dom-helpers "^5.2.0" + prop-types "^15.7.2" + uncontrollable "^7.0.0" + warning "^4.0.3" + react-refresh@^0.8.3: version "0.8.3" resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.8.3.tgz#721d4657672d400c5e3c75d063c4a85fb2d5d68f" @@ -9031,6 +9172,16 @@ react-scripts@4.0.1: optionalDependencies: fsevents "^2.1.3" +react-transition-group@^4.4.1: + version "4.4.1" + resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.1.tgz#63868f9325a38ea5ee9535d828327f85773345c9" + integrity sha512-Djqr7OQ2aPUiYurhPalTrVy9ddmFCCzwhqQmtN+J3+3DzLO209Fdr70QrN8Z3DsglWql6iY1lDWAfpFiBtuKGw== + dependencies: + "@babel/runtime" "^7.5.5" + dom-helpers "^5.0.1" + loose-envify "^1.4.0" + prop-types "^15.6.2" + react@^17.0.1: version "17.0.1" resolved "https://registry.yarnpkg.com/react/-/react-17.0.1.tgz#6e0600416bd57574e3f86d92edba3d9008726127" @@ -10617,6 +10768,16 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= +uncontrollable@^7.0.0: + version "7.1.1" + resolved "https://registry.yarnpkg.com/uncontrollable/-/uncontrollable-7.1.1.tgz#f67fed3ef93637126571809746323a9db815d556" + integrity sha512-EcPYhot3uWTS3w00R32R2+vS8Vr53tttrvMj/yA1uYRhf8hbTG2GyugGqWDY0qIskxn0uTTojVd6wPYW9ZEf8Q== + dependencies: + "@babel/runtime" "^7.6.3" + "@types/react" "^16.9.11" + invariant "^2.2.4" + react-lifecycles-compat "^3.0.4" + unicode-canonical-property-names-ecmascript@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz#2619800c4c825800efdd8343af7dd9933cbe2818" @@ -10890,6 +11051,13 @@ walker@^1.0.7, walker@~1.0.5: dependencies: makeerror "1.0.x" +warning@^4.0.0, warning@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/warning/-/warning-4.0.3.tgz#16e9e077eb8a86d6af7d64aa1e05fd85b4678ca3" + integrity sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w== + dependencies: + loose-envify "^1.0.0" + watchpack-chokidar2@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/watchpack-chokidar2/-/watchpack-chokidar2-2.0.1.tgz#38500072ee6ece66f3769936950ea1771be1c957" From a961aba7a85aa9a4b00e230e499644e71b0ee247 Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Mon, 23 Nov 2020 17:04:40 +0100 Subject: [PATCH 06/60] :heavy_plus_sign: yarn add bootstrap --- package.json | 2 ++ yarn.lock | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/package.json b/package.json index 5dc3d84..ba41899 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,13 @@ { "name": "gitpop3", + "homepage": "https://andremiras.github.io/gitpop3/", "version": "0.1.0", "private": true, "dependencies": { "@testing-library/jest-dom": "^5.11.4", "@testing-library/react": "^11.1.0", "@testing-library/user-event": "^12.1.10", + "bootstrap": "^4.5.3", "react": "^17.0.1", "react-bootstrap": "^1.4.0", "react-dom": "^17.0.1", diff --git a/yarn.lock b/yarn.lock index 504b7ab..30866fc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2811,6 +2811,11 @@ boolbase@^1.0.0, boolbase@~1.0.0: resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24= +bootstrap@^4.5.3: + version "4.5.3" + resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-4.5.3.tgz#c6a72b355aaf323920be800246a6e4ef30997fe6" + integrity sha512-o9ppKQioXGqhw8Z7mah6KdTYpNQY//tipnkxppWhPbiSWdD+1raYsnhwEZjkTHYbGee4cVQ0Rx65EhOY/HNLcQ== + brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" From a41119e540aa074c1809e08097f34b35087e8c1b Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Mon, 23 Nov 2020 17:06:37 +0100 Subject: [PATCH 07/60] :construction: Adds Navigation --- src/App.jsx | 8 +++----- src/components/Navigation.jsx | 19 +++++++++++++++++++ 2 files changed, 22 insertions(+), 5 deletions(-) create mode 100644 src/components/Navigation.jsx diff --git a/src/App.jsx b/src/App.jsx index 6a6baf8..411e311 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,13 +1,11 @@ import React from 'react'; +import 'bootstrap/dist/css/bootstrap.min.css'; +import Navigation from './components/Navigation'; function App() { return (
-
-

- GitPop3 -

-
+
); } diff --git a/src/components/Navigation.jsx b/src/components/Navigation.jsx new file mode 100644 index 0000000..368004d --- /dev/null +++ b/src/components/Navigation.jsx @@ -0,0 +1,19 @@ +import React from 'react'; +import { Container, Nav, Navbar } from 'react-bootstrap'; + +const Navigation = () => ( + + + GitPop3 + + + + + + +); + +export default Navigation; From 64f0e220d16b51c20b0959e28522c85c871e75c3 Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Mon, 23 Nov 2020 17:07:54 +0100 Subject: [PATCH 08/60] :construction: Adds Footer --- src/App.jsx | 2 ++ src/components/Footer.jsx | 16 ++++++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 src/components/Footer.jsx diff --git a/src/App.jsx b/src/App.jsx index 411e311..e6bf8ab 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,11 +1,13 @@ import React from 'react'; import 'bootstrap/dist/css/bootstrap.min.css'; import Navigation from './components/Navigation'; +import Footer from './components/Footer'; function App() { return (
+
); } diff --git a/src/components/Footer.jsx b/src/components/Footer.jsx new file mode 100644 index 0000000..2b2bf9c --- /dev/null +++ b/src/components/Footer.jsx @@ -0,0 +1,16 @@ +import React from 'react'; +import { Container } from 'react-bootstrap'; +import { version } from '../../package.json'; + +const Footer = () => ( +
+ + + Copyright © Andre Miras 2020 - gitpop3 v + {version} + + +
+); + +export default Footer; From fc41d4c8713f80eb615263e9678784398f84daa2 Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Mon, 23 Nov 2020 17:09:54 +0100 Subject: [PATCH 09/60] :see_no_evil: ignore .eslintcache --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 4d29575..fb5312c 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,6 @@ npm-debug.log* yarn-debug.log* yarn-error.log* + +# Optional eslint cache +.eslintcache From 0a05986df609d91c792d34be8efb186377bd0d4b Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Mon, 23 Nov 2020 17:12:26 +0100 Subject: [PATCH 10/60] :construction: Adds Container --- src/App.jsx | 4 +++- src/components/Container.jsx | 10 ++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 src/components/Container.jsx diff --git a/src/App.jsx b/src/App.jsx index e6bf8ab..ed0f68b 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,12 +1,14 @@ import React from 'react'; import 'bootstrap/dist/css/bootstrap.min.css'; -import Navigation from './components/Navigation'; +import Container from './components/Container'; import Footer from './components/Footer'; +import Navigation from './components/Navigation'; function App() { return (
+
); diff --git a/src/components/Container.jsx b/src/components/Container.jsx new file mode 100644 index 0000000..6afae18 --- /dev/null +++ b/src/components/Container.jsx @@ -0,0 +1,10 @@ +import React from 'react'; +import { Container as ReactContainer } from 'react-bootstrap'; + +const Container = () => ( + + Container + +); + +export default Container; From 3558793f662c25fe8e5bb515f062b62c7629fbb1 Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Mon, 23 Nov 2020 17:14:06 +0100 Subject: [PATCH 11/60] :lipstick: Sticks footers to the bottom --- src/App.jsx | 1 + src/index.css | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/src/App.jsx b/src/App.jsx index ed0f68b..e14b432 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,4 +1,5 @@ import React from 'react'; +import './App.css'; import 'bootstrap/dist/css/bootstrap.min.css'; import Container from './components/Container'; import Footer from './components/Footer'; diff --git a/src/index.css b/src/index.css index ec2585e..8e42cba 100644 --- a/src/index.css +++ b/src/index.css @@ -11,3 +11,12 @@ code { font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace; } + +.footer { + position: absolute; + bottom: 0; + width: 100%; + height: 60px; + line-height: 60px; + background-color: #f5f5f5; +} From 661969534d2e92a5721e941fbb3e50fef4ecb7c3 Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Mon, 23 Nov 2020 17:16:38 +0100 Subject: [PATCH 12/60] :memo: Updates README.md with ref to gitpop2 --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 6ac06d4..a0c89c0 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,7 @@ Find the most popular fork on GitHub. +This is a rewrite of [GitPop2](https://github.com/AndreMiras/gitpop2) using only frontend tech. ## Run ```sh From d66023ce9935c32512edbbb5328c226ce9021fde Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Mon, 23 Nov 2020 17:20:46 +0100 Subject: [PATCH 13/60] :construction_worker: Introduces basic CI --- .github/workflows/tests.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 .github/workflows/tests.yml diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 0000000..74f1a12 --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,14 @@ +name: Tests + +on: [push] + +jobs: + build: + + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v1 + - run: yarn install + - run: yarn test + - run: yarn lint From 4e5abbd27183d963772fd2c6adaba1670467f679 Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Mon, 23 Nov 2020 17:22:48 +0100 Subject: [PATCH 14/60] :construction_worker: Auto deploys on merge to develop --- .github/workflows/deploy.yml | 21 ++++++++++ README.md | 2 +- package.json | 6 ++- yarn.lock | 75 ++++++++++++++++++++++++++++++++++-- 4 files changed, 97 insertions(+), 7 deletions(-) create mode 100644 .github/workflows/deploy.yml diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 0000000..ece8f01 --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,21 @@ +name: Deploy + +on: + push: + branches: + - develop + +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v1 + - name: git config + run: | + git config user.name github-pages-deploy-action + git config user.email github-pages-deploy-action@@users.noreply.github.com + git remote set-url origin https://${{github.actor}}:${{github.token}}@github.com/${{github.repository}}.git + - run: yarn install + - run: yarn build + - run: yarn deploy diff --git a/README.md b/README.md index a0c89c0..9460511 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ Find the most popular fork on GitHub. - + This is a rewrite of [GitPop2](https://github.com/AndreMiras/gitpop2) using only frontend tech. diff --git a/package.json b/package.json index ba41899..a03db23 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,8 @@ "test": "react-scripts test", "eject": "react-scripts eject", "lint": "eslint -c .eslintrc 'src/**/*.{js,jsx}'", - "format": "eslint -c .eslintrc 'src/**/*.{js,jsx}' --fix" + "format": "eslint -c .eslintrc 'src/**/*.{js,jsx}' --fix", + "deploy": "gh-pages -d build" }, "eslintConfig": { "extends": [ @@ -41,6 +42,7 @@ ] }, "devDependencies": { - "eslint-config-airbnb": "^18.2.1" + "eslint-config-airbnb": "^18.2.1", + "gh-pages": "^3.1.0" } } diff --git a/yarn.lock b/yarn.lock index 30866fc..912dace 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2477,7 +2477,7 @@ async-limiter@~1.0.0: resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== -async@^2.6.2: +async@^2.6.1, async@^2.6.2: version "2.6.3" resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff" integrity sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg== @@ -3368,7 +3368,7 @@ combined-stream@^1.0.6, combined-stream@~1.0.6: dependencies: delayed-stream "~1.0.0" -commander@^2.20.0: +commander@^2.18.0, commander@^2.20.0: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== @@ -4284,6 +4284,11 @@ elliptic@^6.5.3: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.0" +email-addresses@^3.0.1: + version "3.1.0" + resolved "https://registry.yarnpkg.com/email-addresses/-/email-addresses-3.1.0.tgz#cabf7e085cbdb63008a70319a74e6136188812fb" + integrity sha512-k0/r7GrWVL32kZlGwfPNgB2Y/mMXVTq/decgLczm/j34whdaspNrZO8CnXPf1laaHxI6ptUlsnAxN+UAPw+fzg== + emittery@^0.7.1: version "0.7.2" resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.7.2.tgz#25595908e13af0f5674ab419396e2fb394cdfa82" @@ -4458,7 +4463,7 @@ escape-string-regexp@2.0.0, escape-string-regexp@^2.0.0: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== -escape-string-regexp@^1.0.5: +escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= @@ -4996,6 +5001,28 @@ file-uri-to-path@1.0.0: resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== +filename-reserved-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/filename-reserved-regex/-/filename-reserved-regex-1.0.0.tgz#e61cf805f0de1c984567d0386dc5df50ee5af7e4" + integrity sha1-5hz4BfDeHJhFZ9A4bcXfUO5a9+Q= + +filenamify-url@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/filenamify-url/-/filenamify-url-1.0.0.tgz#b32bd81319ef5863b73078bed50f46a4f7975f50" + integrity sha1-syvYExnvWGO3MHi+1Q9GpPeXX1A= + dependencies: + filenamify "^1.0.0" + humanize-url "^1.0.0" + +filenamify@^1.0.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/filenamify/-/filenamify-1.2.1.tgz#a9f2ffd11c503bed300015029272378f1f1365a5" + integrity sha1-qfL/0RxQO+0wABUCknI3jx8TZaU= + dependencies: + filename-reserved-regex "^1.0.0" + strip-outer "^1.0.0" + trim-repeated "^1.0.0" + filesize@6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/filesize/-/filesize-6.1.0.tgz#e81bdaa780e2451d714d71c0d7a4f3238d37ad00" @@ -5293,6 +5320,19 @@ getpass@^0.1.1: dependencies: assert-plus "^1.0.0" +gh-pages@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/gh-pages/-/gh-pages-3.1.0.tgz#ec3ed0f6a6e3fc3d888758fa018f08191c96bd55" + integrity sha512-3b1rly9kuf3/dXsT8+ZxP0UhNLOo1CItj+3e31yUVcaph/yDsJ9RzD7JOw5o5zpBTJVQLlJAASNkUfepi9fe2w== + dependencies: + async "^2.6.1" + commander "^2.18.0" + email-addresses "^3.0.1" + filenamify-url "^1.0.0" + find-cache-dir "^3.3.1" + fs-extra "^8.1.0" + globby "^6.1.0" + glob-parent@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" @@ -5673,6 +5713,14 @@ human-signals@^1.1.1: resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3" integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw== +humanize-url@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/humanize-url/-/humanize-url-1.0.1.tgz#f4ab99e0d288174ca4e1e50407c55fbae464efff" + integrity sha1-9KuZ4NKIF0yk4eUEB8VfuuRk7/8= + dependencies: + normalize-url "^1.0.0" + strip-url-auth "^1.0.0" + iconv-lite@0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" @@ -7526,7 +7574,7 @@ normalize-range@^0.1.2: resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" integrity sha1-LRDAa9/TEuqXd2laTShDlFa3WUI= -normalize-url@1.9.1: +normalize-url@1.9.1, normalize-url@^1.0.0: version "1.9.1" resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-1.9.1.tgz#2cc0d66b31ea23036458436e3620d85954c66c3c" integrity sha1-LMDWazHqIwNkWENuNiDYWVTGbDw= @@ -10363,6 +10411,18 @@ strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== +strip-outer@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/strip-outer/-/strip-outer-1.0.1.tgz#b2fd2abf6604b9d1e6013057195df836b8a9d631" + integrity sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg== + dependencies: + escape-string-regexp "^1.0.2" + +strip-url-auth@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/strip-url-auth/-/strip-url-auth-1.0.1.tgz#22b0fa3a41385b33be3f331551bbb837fa0cd7ae" + integrity sha1-IrD6OkE4WzO+PzMVUbu4N/oM164= + style-loader@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-1.3.0.tgz#828b4a3b3b7e7aa5847ce7bae9e874512114249e" @@ -10655,6 +10715,13 @@ tr46@^2.0.2: dependencies: punycode "^2.1.1" +trim-repeated@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/trim-repeated/-/trim-repeated-1.0.0.tgz#e3646a2ea4e891312bf7eace6cfb05380bc01c21" + integrity sha1-42RqLqTokTEr9+rObPsFOAvAHCE= + dependencies: + escape-string-regexp "^1.0.2" + tryer@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/tryer/-/tryer-1.0.1.tgz#f2c85406800b9b0f74c9f7465b81eaad241252f8" From ed74f2a3eb9912efc57f954e5890dd015eabe2e8 Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Mon, 23 Nov 2020 17:41:03 +0100 Subject: [PATCH 15/60] :heavy_plus_sign: yarn add fontawesome - @fortawesome/fontawesome-free - @fortawesome/fontawesome-svg-core - @fortawesome/free-solid-svg-icons - @fortawesome/react-fontawesome - font-awesome --- package.json | 5 +++++ yarn.lock | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/package.json b/package.json index a03db23..197894d 100644 --- a/package.json +++ b/package.json @@ -4,10 +4,15 @@ "version": "0.1.0", "private": true, "dependencies": { + "@fortawesome/fontawesome-free": "^5.15.1", + "@fortawesome/fontawesome-svg-core": "^1.2.32", + "@fortawesome/free-solid-svg-icons": "^5.15.1", + "@fortawesome/react-fontawesome": "^0.1.12", "@testing-library/jest-dom": "^5.11.4", "@testing-library/react": "^11.1.0", "@testing-library/user-event": "^12.1.10", "bootstrap": "^4.5.3", + "font-awesome": "^4.7.0", "react": "^17.0.1", "react-bootstrap": "^1.4.0", "react-dom": "^17.0.1", diff --git a/yarn.lock b/yarn.lock index 912dace..a9c9e22 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1164,6 +1164,37 @@ minimatch "^3.0.4" strip-json-comments "^3.1.1" +"@fortawesome/fontawesome-common-types@^0.2.32": + version "0.2.32" + resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.32.tgz#3436795d5684f22742989bfa08f46f50f516f259" + integrity sha512-ux2EDjKMpcdHBVLi/eWZynnPxs0BtFVXJkgHIxXRl+9ZFaHPvYamAfCzeeQFqHRjuJtX90wVnMRaMQAAlctz3w== + +"@fortawesome/fontawesome-free@^5.15.1": + version "5.15.1" + resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-free/-/fontawesome-free-5.15.1.tgz#ccfef6ddbe59f8fe8f694783e1d3eb88902dc5eb" + integrity sha512-OEdH7SyC1suTdhBGW91/zBfR6qaIhThbcN8PUXtXilY4GYnSBbVqOntdHbC1vXwsDnX0Qix2m2+DSU1J51ybOQ== + +"@fortawesome/fontawesome-svg-core@^1.2.32": + version "1.2.32" + resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-1.2.32.tgz#da092bfc7266aa274be8604de610d7115f9ba6cf" + integrity sha512-XjqyeLCsR/c/usUpdWcOdVtWFVjPbDFBTQkn2fQRrWhhUoxriQohO2RWDxLyUM8XpD+Zzg5xwJ8gqTYGDLeGaQ== + dependencies: + "@fortawesome/fontawesome-common-types" "^0.2.32" + +"@fortawesome/free-solid-svg-icons@^5.15.1": + version "5.15.1" + resolved "https://registry.yarnpkg.com/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-5.15.1.tgz#e1432676ddd43108b41197fee9f86d910ad458ef" + integrity sha512-EFMuKtzRMNbvjab/SvJBaOOpaqJfdSap/Nl6hst7CgrJxwfORR1drdTV6q1Ib/JVzq4xObdTDcT6sqTaXMqfdg== + dependencies: + "@fortawesome/fontawesome-common-types" "^0.2.32" + +"@fortawesome/react-fontawesome@^0.1.12": + version "0.1.12" + resolved "https://registry.yarnpkg.com/@fortawesome/react-fontawesome/-/react-fontawesome-0.1.12.tgz#fbdea86e8b73032895e6ded1ee1dbb1874902d1a" + integrity sha512-kV6HtqotM3K4YIXlTVvomuIi6QgGCvYm++ImyEx2wwgmSppZ6kbbA29ASwjAUBD63j2OFU0yoxeXpZkjrrX0qQ== + dependencies: + prop-types "^15.7.2" + "@hapi/address@2.x.x": version "2.1.4" resolved "https://registry.yarnpkg.com/@hapi/address/-/address-2.1.4.tgz#5d67ed43f3fd41a69d4b9ff7b56e7c0d1d0a81e5" @@ -5130,6 +5161,11 @@ follow-redirects@^1.0.0: resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.13.0.tgz#b42e8d93a2a7eea5ed88633676d6597bc8e384db" integrity sha512-aq6gF1BEKje4a9i9+5jimNFIpq4Q1WiwBToeRK5NvZBd/TRsmW8BsJfOEGkr76TbOyPVD3OVDN910EcUNtRYEA== +font-awesome@^4.7.0: + version "4.7.0" + resolved "https://registry.yarnpkg.com/font-awesome/-/font-awesome-4.7.0.tgz#8fa8cf0411a1a31afd07b06d2902bb9fc815a133" + integrity sha1-j6jPBBGhoxr9B7BtKQK7n8gVoTM= + for-in@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" From b48aa48659192a4f1e6da5fc4b95c9203ccad6d0 Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Mon, 23 Nov 2020 17:46:47 +0100 Subject: [PATCH 16/60] :lipstick: Adds navigation icons --- src/App.jsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/App.jsx b/src/App.jsx index e14b432..e0dd818 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,10 +1,14 @@ import React from 'react'; import './App.css'; import 'bootstrap/dist/css/bootstrap.min.css'; +import { library } from '@fortawesome/fontawesome-svg-core'; +import { fas } from '@fortawesome/free-solid-svg-icons'; import Container from './components/Container'; import Footer from './components/Footer'; import Navigation from './components/Navigation'; +library.add(fas); + function App() { return (
From 0330ccd937daa7e1b928d3ffba3f761c533799c2 Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Mon, 23 Nov 2020 17:46:52 +0100 Subject: [PATCH 17/60] :lipstick: Adds navigation icons --- src/components/Navigation.jsx | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/components/Navigation.jsx b/src/components/Navigation.jsx index 368004d..03e64ec 100644 --- a/src/components/Navigation.jsx +++ b/src/components/Navigation.jsx @@ -1,14 +1,23 @@ import React from 'react'; import { Container, Nav, Navbar } from 'react-bootstrap'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; const Navigation = () => ( - GitPop3 + + + {' '} + GitPop3 + From 3dcd26759b4f8f00002940bfa2106b2fe53d0996 Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Mon, 23 Nov 2020 18:35:49 +0100 Subject: [PATCH 18/60] :construction: Basic PopForm Only adds the dumb component with no logic. --- src/components/Container.jsx | 3 ++- src/components/PopForm.jsx | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 src/components/PopForm.jsx diff --git a/src/components/Container.jsx b/src/components/Container.jsx index 6afae18..0288d40 100644 --- a/src/components/Container.jsx +++ b/src/components/Container.jsx @@ -1,9 +1,10 @@ import React from 'react'; import { Container as ReactContainer } from 'react-bootstrap'; +import PopForm from './PopForm'; const Container = () => ( - Container + ); diff --git a/src/components/PopForm.jsx b/src/components/PopForm.jsx new file mode 100644 index 0000000..fd734af --- /dev/null +++ b/src/components/PopForm.jsx @@ -0,0 +1,18 @@ +import React from 'react'; +import { Button, FormControl, InputGroup } from 'react-bootstrap'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; + +const PopForm = () => ( + + + + + + +); + +export default PopForm; From 7eebd7a40e64327ee83ecf44f47a6c37b526ff1e Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Mon, 23 Nov 2020 18:57:55 +0100 Subject: [PATCH 19/60] :heavy_plus_sign: yarn add @apollo/client graphql --- package.json | 2 ++ yarn.lock | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 88 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 197894d..3fa447c 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,7 @@ "version": "0.1.0", "private": true, "dependencies": { + "@apollo/client": "^3.2.7", "@fortawesome/fontawesome-free": "^5.15.1", "@fortawesome/fontawesome-svg-core": "^1.2.32", "@fortawesome/free-solid-svg-icons": "^5.15.1", @@ -13,6 +14,7 @@ "@testing-library/user-event": "^12.1.10", "bootstrap": "^4.5.3", "font-awesome": "^4.7.0", + "graphql": "^15.4.0", "react": "^17.0.1", "react-bootstrap": "^1.4.0", "react-dom": "^17.0.1", diff --git a/yarn.lock b/yarn.lock index a9c9e22..3dd24cd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,25 @@ # yarn lockfile v1 +"@apollo/client@^3.2.7": + version "3.2.7" + resolved "https://registry.yarnpkg.com/@apollo/client/-/client-3.2.7.tgz#1cae8d2f5e15c5d2135a288a9d18962e60c5194c" + integrity sha512-4G80jvBLqenCFUhwkHAAHi2ox6Ygq35BkE38yxammqykZm6KE3tVlcEKGOZi0jpiuGJPC6LIQ0d1gtI8ADPtmg== + dependencies: + "@graphql-typed-document-node/core" "^3.0.0" + "@types/zen-observable" "^0.8.0" + "@wry/context" "^0.5.2" + "@wry/equality" "^0.2.0" + fast-json-stable-stringify "^2.0.0" + graphql-tag "^2.11.0" + hoist-non-react-statics "^3.3.2" + optimism "^0.13.0" + prop-types "^15.7.2" + symbol-observable "^2.0.0" + ts-invariant "^0.5.0" + tslib "^1.10.0" + zen-observable "^0.8.14" + "@babel/code-frame@7.10.4", "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.5.5": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.4.tgz#168da1a36e90da68ae8d49c0f1b48c7c6249213a" @@ -1195,6 +1214,11 @@ dependencies: prop-types "^15.7.2" +"@graphql-typed-document-node/core@^3.0.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@graphql-typed-document-node/core/-/core-3.1.0.tgz#0eee6373e11418bfe0b5638f654df7a4ca6a3950" + integrity sha512-wYn6r8zVZyQJ6rQaALBEln5B1pzxb9shV5Ef97kTvn6yVGrqyXVnDqnU24MXnFubR+rZjBY9NWuxX3FB2sTsjg== + "@hapi/address@2.x.x": version "2.1.4" resolved "https://registry.yarnpkg.com/@hapi/address/-/address-2.1.4.tgz#5d67ed43f3fd41a69d4b9ff7b56e7c0d1d0a81e5" @@ -1927,6 +1951,11 @@ dependencies: "@types/yargs-parser" "*" +"@types/zen-observable@^0.8.0": + version "0.8.1" + resolved "https://registry.yarnpkg.com/@types/zen-observable/-/zen-observable-0.8.1.tgz#5668c0bce55a91f2b9566b1d8a4c0a8dbbc79764" + integrity sha512-wmk0xQI6Yy7Fs/il4EpOcflG4uonUpYGqvZARESLc2oy4u69fkatFLbJOeW4Q6awO15P4rduAe6xkwHevpXcUQ== + "@typescript-eslint/eslint-plugin@^4.5.0": version "4.8.1" resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.8.1.tgz#b362abe0ee478a6c6d06c14552a6497f0b480769" @@ -2179,6 +2208,20 @@ "@webassemblyjs/wast-parser" "1.9.0" "@xtuc/long" "4.2.2" +"@wry/context@^0.5.2": + version "0.5.2" + resolved "https://registry.yarnpkg.com/@wry/context/-/context-0.5.2.tgz#f2a5d5ab9227343aa74c81e06533c1ef84598ec7" + integrity sha512-B/JLuRZ/vbEKHRUiGj6xiMojST1kHhu4WcreLfNN7q9DqQFrb97cWgf/kiYsPSUCAMVN0HzfFc8XjJdzgZzfjw== + dependencies: + tslib "^1.9.3" + +"@wry/equality@^0.2.0": + version "0.2.0" + resolved "https://registry.yarnpkg.com/@wry/equality/-/equality-0.2.0.tgz#a312d1b6a682d0909904c2bcd355b02303104fb7" + integrity sha512-Y4d+WH6hs+KZJUC8YKLYGarjGekBrhslDbf/R20oV+AakHPINSitHfDRQz3EGcEWc1luXYNUvMhawWtZVWNGvQ== + dependencies: + tslib "^1.9.3" + "@xtuc/ieee754@^1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" @@ -5452,6 +5495,16 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6 resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== +graphql-tag@^2.11.0: + version "2.11.0" + resolved "https://registry.yarnpkg.com/graphql-tag/-/graphql-tag-2.11.0.tgz#1deb53a01c46a7eb401d6cb59dec86fa1cccbffd" + integrity sha512-VmsD5pJqWJnQZMUeRwrDhfgoyqcfwEkvtpANqcoUG8/tOLkwNgU9mzub/Mc78OJMhHjx7gfAMTxzdG43VGg3bA== + +graphql@^15.4.0: + version "15.4.0" + resolved "https://registry.yarnpkg.com/graphql/-/graphql-15.4.0.tgz#e459dea1150da5a106486ba7276518b5295a4347" + integrity sha512-EB3zgGchcabbsU9cFe1j+yxdzKQKAbGUWRb13DsrsMN1yyfmmIq+2+L5MqVWcDCE4V89R5AyUOi7sMOGxdsYtA== + growly@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081" @@ -5577,6 +5630,13 @@ hmac-drbg@^1.0.0: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.1" +hoist-non-react-statics@^3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" + integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== + dependencies: + react-is "^16.7.0" + hoopy@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/hoopy/-/hoopy-0.1.4.tgz#609207d661100033a9a9402ad3dea677381c1b1d" @@ -7800,6 +7860,13 @@ opn@^5.5.0: dependencies: is-wsl "^1.1.0" +optimism@^0.13.0: + version "0.13.1" + resolved "https://registry.yarnpkg.com/optimism/-/optimism-0.13.1.tgz#df2e6102c973f870d6071712fffe4866bb240384" + integrity sha512-16RRVYZe8ODcUqpabpY7Gb91vCAbdhn8FHjlUb2Hqnjjow1j8Z1dlppds+yAsLbreNTVylLC+tNX6DuC2vt3Kw== + dependencies: + "@wry/context" "^0.5.2" + optimize-css-assets-webpack-plugin@5.0.4: version "5.0.4" resolved "https://registry.yarnpkg.com/optimize-css-assets-webpack-plugin/-/optimize-css-assets-webpack-plugin-5.0.4.tgz#85883c6528aaa02e30bbad9908c92926bb52dc90" @@ -9161,7 +9228,7 @@ react-error-overlay@^6.0.8: resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.8.tgz#474ed11d04fc6bda3af643447d85e9127ed6b5de" integrity sha512-HvPuUQnLp5H7TouGq3kzBeioJmXms1wHy9EGjz2OURWBp4qZO6AfGEcnxts1D/CbwPLRAgTMPCEgYhA3sEM4vw== -react-is@^16.3.2, react-is@^16.8.1: +react-is@^16.3.2, react-is@^16.7.0, react-is@^16.8.1: version "16.13.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== @@ -10529,6 +10596,11 @@ svgo@^1.0.0, svgo@^1.2.2: unquote "~1.1.1" util.promisify "~1.0.0" +symbol-observable@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-2.0.3.tgz#5b521d3d07a43c351055fa43b8355b62d33fd16a" + integrity sha512-sQV7phh2WCYAn81oAkakC5qjq2Ml0g8ozqz03wOGnx9dDlG1de6yrF+0RAzSJD8fPUow3PTSMf2SAbOGxb93BA== + symbol-tree@^3.2.4: version "3.2.4" resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" @@ -10763,6 +10835,13 @@ tryer@^1.0.1: resolved "https://registry.yarnpkg.com/tryer/-/tryer-1.0.1.tgz#f2c85406800b9b0f74c9f7465b81eaad241252f8" integrity sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA== +ts-invariant@^0.5.0: + version "0.5.1" + resolved "https://registry.yarnpkg.com/ts-invariant/-/ts-invariant-0.5.1.tgz#4171fdb85f72a40381c147afd97c12154ada2abc" + integrity sha512-k3UpDNrBZpqJFnAAkAHNmSHtNuCxcU6xLiziPgalHRKZHme6T6jnKC8CcXDmk1zbHLQM8pc+rNC1Q6FvXMAl+g== + dependencies: + tslib "^1.9.3" + ts-pnp@1.2.0, ts-pnp@^1.1.6: version "1.2.0" resolved "https://registry.yarnpkg.com/ts-pnp/-/ts-pnp-1.2.0.tgz#a500ad084b0798f1c3071af391e65912c86bca92" @@ -10778,7 +10857,7 @@ tsconfig-paths@^3.9.0: minimist "^1.2.0" strip-bom "^3.0.0" -tslib@^1.10.0, tslib@^1.8.1, tslib@^1.9.0: +tslib@^1.10.0, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== @@ -11684,3 +11763,8 @@ yargs@^15.4.1: which-module "^2.0.0" y18n "^4.0.0" yargs-parser "^18.1.2" + +zen-observable@^0.8.14: + version "0.8.15" + resolved "https://registry.yarnpkg.com/zen-observable/-/zen-observable-0.8.15.tgz#96415c512d8e3ffd920afd3889604e30b9eaac15" + integrity sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ== From 3acead9f4722dda997804d1466fec3dcecf02263 Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Mon, 23 Nov 2020 19:15:32 +0100 Subject: [PATCH 20/60] :heavy_plus_sign: yarn add prop-types --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 3fa447c..fe9e364 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "bootstrap": "^4.5.3", "font-awesome": "^4.7.0", "graphql": "^15.4.0", + "prop-types": "^15.7.2", "react": "^17.0.1", "react-bootstrap": "^1.4.0", "react-dom": "^17.0.1", From 93b5a8536d60392fd2d462c26c80fe86106e2ed8 Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Mon, 23 Nov 2020 20:00:48 +0100 Subject: [PATCH 21/60] :construction: Basic GraphQL implementation Next up is API authentication --- src/components/Container.jsx | 21 ++++++++++++++++++++- src/components/PopForm.jsx | 34 +++++++++++++++++++++------------- src/utils/graphql.js | 24 ++++++++++++++++++++++++ 3 files changed, 65 insertions(+), 14 deletions(-) create mode 100644 src/utils/graphql.js diff --git a/src/components/Container.jsx b/src/components/Container.jsx index 0288d40..6475a73 100644 --- a/src/components/Container.jsx +++ b/src/components/Container.jsx @@ -1,10 +1,29 @@ import React from 'react'; import { Container as ReactContainer } from 'react-bootstrap'; import PopForm from './PopForm'; +import { client, GET_FORKS_QUERY } from '../utils/graphql'; + +const re = /https:\/\/github.com\/(\w+)\/(\w+)/; +/** + * Splits URL to owner and repo name. + */ +const splitUrl = (url) => ( + url.match(re).slice(1, 3) +); + +const searchPopularForks = (url) => { + const [owner, name] = splitUrl(url); + client.query({ + query: GET_FORKS_QUERY, + variables: { owner, name }, + }).then( + (result) => result, + ); +}; const Container = () => ( - + searchPopularForks(value)} /> ); diff --git a/src/components/PopForm.jsx b/src/components/PopForm.jsx index fd734af..7d683e5 100644 --- a/src/components/PopForm.jsx +++ b/src/components/PopForm.jsx @@ -1,18 +1,26 @@ -import React from 'react'; +import React, { useState } from 'react'; +import PropTypes from 'prop-types'; import { Button, FormControl, InputGroup } from 'react-bootstrap'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -const PopForm = () => ( - - - - - - -); +const PopForm = ({ onSubmit }) => { + const [value, setValue] = useState(); + return ( + + setValue(e.target.value)} + /> + + + + + ); +}; +PopForm.propTypes = { + onSubmit: PropTypes.func.isRequired, +}; export default PopForm; diff --git a/src/utils/graphql.js b/src/utils/graphql.js new file mode 100644 index 0000000..91a780e --- /dev/null +++ b/src/utils/graphql.js @@ -0,0 +1,24 @@ +import { gql, ApolloClient, InMemoryCache } from '@apollo/client'; + +const endpoint = 'https://api.github.com/graphql'; +const client = new ApolloClient({ + uri: endpoint, + cache: new InMemoryCache(), +}); + +const GET_FORKS_QUERY = gql` + query Forks($owner: String! $name: String!) { + repository(owner: $owner, name: $name) { + forks(first: 10) { + nodes { + name + } + } + } + } +`; + +export { + client, + GET_FORKS_QUERY, +}; From 186b61007b2f56e3f354ba389df302076ff4159a Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Mon, 23 Nov 2020 20:12:57 +0100 Subject: [PATCH 22/60] :construction: GraphQL API auth The generated token only has the `public_repo` scope. --- src/components/Container.jsx | 2 +- src/utils/graphql.js | 21 +++++++++++++++++++-- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/components/Container.jsx b/src/components/Container.jsx index 6475a73..45f5c7b 100644 --- a/src/components/Container.jsx +++ b/src/components/Container.jsx @@ -17,7 +17,7 @@ const searchPopularForks = (url) => { query: GET_FORKS_QUERY, variables: { owner, name }, }).then( - (result) => result, + (result) => (result), ); }; diff --git a/src/utils/graphql.js b/src/utils/graphql.js index 91a780e..8f7f4ad 100644 --- a/src/utils/graphql.js +++ b/src/utils/graphql.js @@ -1,8 +1,25 @@ -import { gql, ApolloClient, InMemoryCache } from '@apollo/client'; +import { + gql, ApolloClient, createHttpLink, InMemoryCache, +} from '@apollo/client'; +import { setContext } from '@apollo/client/link/context'; const endpoint = 'https://api.github.com/graphql'; -const client = new ApolloClient({ + +const httpLink = createHttpLink({ uri: endpoint, +}); + +const token = '611e97c7dd4ef573efcd31e63e9aed084243d282'; + +const authLink = setContext((_, { headers }) => ({ + headers: { + ...headers, + authorization: token ? `Bearer ${token}` : '', + }, +})); + +const client = new ApolloClient({ + link: authLink.concat(httpLink), cache: new InMemoryCache(), }); From 80d5c0d5e446db1e6c49353b1985ae41766419a2 Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Mon, 23 Nov 2020 22:36:28 +0100 Subject: [PATCH 23/60] :construction: ResultTable (containing forks info) --- src/components/Container.jsx | 25 +++++++++++++------- src/components/PopForm.jsx | 6 ++--- src/components/ResultTable.jsx | 42 ++++++++++++++++++++++++++++++++++ src/utils/graphql.js | 2 +- 4 files changed, 63 insertions(+), 12 deletions(-) create mode 100644 src/components/ResultTable.jsx diff --git a/src/components/Container.jsx b/src/components/Container.jsx index 45f5c7b..ab35fe5 100644 --- a/src/components/Container.jsx +++ b/src/components/Container.jsx @@ -1,6 +1,7 @@ -import React from 'react'; +import React, { useState } from 'react'; import { Container as ReactContainer } from 'react-bootstrap'; import PopForm from './PopForm'; +import ResultTable from './ResultTable'; import { client, GET_FORKS_QUERY } from '../utils/graphql'; const re = /https:\/\/github.com\/(\w+)\/(\w+)/; @@ -11,20 +12,28 @@ const splitUrl = (url) => ( url.match(re).slice(1, 3) ); -const searchPopularForks = (url) => { +const searchPopularForks = (url, onResult) => { const [owner, name] = splitUrl(url); client.query({ query: GET_FORKS_QUERY, variables: { owner, name }, }).then( - (result) => (result), + (result) => onResult(result), ); }; -const Container = () => ( - - searchPopularForks(value)} /> - -); +const Container = () => { + const [forks, setForks] = useState([]); + const onResult = (result) => ( + setForks(result.data.repository.forks.nodes) + ); + const resultTable = forks ? : null; + return ( + + searchPopularForks(url, onResult)} /> + {resultTable} + + ); +}; export default Container; diff --git a/src/components/PopForm.jsx b/src/components/PopForm.jsx index 7d683e5..a0eef30 100644 --- a/src/components/PopForm.jsx +++ b/src/components/PopForm.jsx @@ -4,15 +4,15 @@ import { Button, FormControl, InputGroup } from 'react-bootstrap'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; const PopForm = ({ onSubmit }) => { - const [value, setValue] = useState(); + const [url, setUrl] = useState(); return ( setValue(e.target.value)} + onChange={(e) => setUrl(e.target.value)} /> - diff --git a/src/components/ResultTable.jsx b/src/components/ResultTable.jsx new file mode 100644 index 0000000..0aa4e66 --- /dev/null +++ b/src/components/ResultTable.jsx @@ -0,0 +1,42 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { Table } from 'react-bootstrap'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; + +const Fork = ({ info }) => ( + + {info.nameWithOwner} + Stars + Forks + Modified + +); +Fork.propTypes = { + info: PropTypes.shape({ + nameWithOwner: PropTypes.string.isRequired, + }).isRequired, +}; + +const ResultTable = ({ forks }) => ( + <> + + + + + + + + + + + + { forks.map((fork) => )} + +
RepoStarsForksModified
+ +); +ResultTable.propTypes = { + forks: PropTypes.arrayOf(Fork.propTypes.info).isRequired, +}; + +export default ResultTable; diff --git a/src/utils/graphql.js b/src/utils/graphql.js index 8f7f4ad..918592a 100644 --- a/src/utils/graphql.js +++ b/src/utils/graphql.js @@ -28,7 +28,7 @@ const GET_FORKS_QUERY = gql` repository(owner: $owner, name: $name) { forks(first: 10) { nodes { - name + nameWithOwner } } } From 4bef4d09bf7817e9b35cb8d2e1d7f97b8fca3745 Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Mon, 23 Nov 2020 22:56:23 +0100 Subject: [PATCH 24/60] :lock: Do not leak PAT token in commit Even though it can be easily retrieved from frontend network tab this token only gives access to GraphQL Public repository queries. --- .github/workflows/deploy.yml | 2 ++ .gitignore | 2 +- README.md | 2 ++ src/utils/graphql.js | 8 +++++++- 4 files changed, 12 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index ece8f01..b7fd28b 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -18,4 +18,6 @@ jobs: git remote set-url origin https://${{github.actor}}:${{github.token}}@github.com/${{github.repository}}.git - run: yarn install - run: yarn build + env: + REACT_APP_GITHUB_PAT: ${{ secrets.REACT_APP_GITHUB_PAT }} - run: yarn deploy diff --git a/.gitignore b/.gitignore index fb5312c..726bc94 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ -# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. +.env # dependencies /node_modules diff --git a/README.md b/README.md index 9460511..dfbae6b 100644 --- a/README.md +++ b/README.md @@ -25,3 +25,5 @@ The app can be deployed on GitHub pages when releasing via: ```sh yarn deploy ``` +Note a [Personal Access Token](https://docs.github.com/en/free-pro-team@latest/github/authenticating-to-github/creating-a-personal-access-token) should be generated and set to its base64 form to the `REACT_APP_GITHUB_PAT` environment variable. +This is required for [Authenticating with GraphQL](https://docs.github.com/en/free-pro-team@latest/graphql/guides/forming-calls-with-graphql#authenticating-with-graphql). diff --git a/src/utils/graphql.js b/src/utils/graphql.js index 918592a..80375af 100644 --- a/src/utils/graphql.js +++ b/src/utils/graphql.js @@ -9,7 +9,13 @@ const httpLink = createHttpLink({ uri: endpoint, }); -const token = '611e97c7dd4ef573efcd31e63e9aed084243d282'; +/** + * Base64 to trick GitHub hooks so the token doesn't seem leaded in the commit. + * Note this token will be accessible from the frontend hence should be very restricted. + * Only the `public_repo` scope is required. + */ +const token = process.env.REACT_APP_GITHUB_PAT ? atob(process.env.REACT_APP_GITHUB_PAT) : null; +// console.assert(token, "REACT_APP_GITHUB_PAT environment variable must be set"); const authLink = setContext((_, { headers }) => ({ headers: { From d3ee0b6bbb3fc2505dc9965ab0dae8408aef1934 Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Tue, 24 Nov 2020 05:45:31 +0100 Subject: [PATCH 25/60] :heavy_plus_sign: yarn add @fortawesome/free-brands-svg-icons --- package.json | 1 + yarn.lock | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/package.json b/package.json index fe9e364..1e2eb52 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,7 @@ "@apollo/client": "^3.2.7", "@fortawesome/fontawesome-free": "^5.15.1", "@fortawesome/fontawesome-svg-core": "^1.2.32", + "@fortawesome/free-brands-svg-icons": "^5.15.1", "@fortawesome/free-solid-svg-icons": "^5.15.1", "@fortawesome/react-fontawesome": "^0.1.12", "@testing-library/jest-dom": "^5.11.4", diff --git a/yarn.lock b/yarn.lock index 3dd24cd..9f1202f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1200,6 +1200,13 @@ dependencies: "@fortawesome/fontawesome-common-types" "^0.2.32" +"@fortawesome/free-brands-svg-icons@^5.15.1": + version "5.15.1" + resolved "https://registry.yarnpkg.com/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-5.15.1.tgz#1dc0563f4036639e53d24b8e532ea78a53ca2250" + integrity sha512-pkTZIWn7iuliCCgV+huDfZmZb2UjslalXGDA2PcqOVUYJmYL11y6ooFiMJkJvUZu+xgAc1gZgQe+Px12mZF0CA== + dependencies: + "@fortawesome/fontawesome-common-types" "^0.2.32" + "@fortawesome/free-solid-svg-icons@^5.15.1": version "5.15.1" resolved "https://registry.yarnpkg.com/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-5.15.1.tgz#e1432676ddd43108b41197fee9f86d910ad458ef" From b51d59cb4b5b02bbb0bc8e950461fe24e3f945fe Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Tue, 24 Nov 2020 05:46:25 +0100 Subject: [PATCH 26/60] :lipstick: Enables FontAwesome brands --- src/App.jsx | 3 ++- src/components/Navigation.jsx | 6 +++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/App.jsx b/src/App.jsx index e0dd818..581e223 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -2,12 +2,13 @@ import React from 'react'; import './App.css'; import 'bootstrap/dist/css/bootstrap.min.css'; import { library } from '@fortawesome/fontawesome-svg-core'; +import { fab } from '@fortawesome/free-brands-svg-icons'; import { fas } from '@fortawesome/free-solid-svg-icons'; import Container from './components/Container'; import Footer from './components/Footer'; import Navigation from './components/Navigation'; -library.add(fas); +library.add(fab, fas); function App() { return ( diff --git a/src/components/Navigation.jsx b/src/components/Navigation.jsx index 03e64ec..a5ce14c 100644 --- a/src/components/Navigation.jsx +++ b/src/components/Navigation.jsx @@ -18,7 +18,11 @@ const Navigation = () => ( {' '} Home - About + + + {' '} + About +
From 5fa94661913c74053ca5d4c28aaea7448b50d858 Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Tue, 24 Nov 2020 05:46:59 +0100 Subject: [PATCH 27/60] :construction: ResultTable icons --- src/components/Container.jsx | 2 +- src/components/ResultTable.jsx | 25 ++++++++++++++++++++----- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/src/components/Container.jsx b/src/components/Container.jsx index ab35fe5..c3c05c5 100644 --- a/src/components/Container.jsx +++ b/src/components/Container.jsx @@ -23,7 +23,7 @@ const searchPopularForks = (url, onResult) => { }; const Container = () => { - const [forks, setForks] = useState([]); + const [forks, setForks] = useState(); const onResult = (result) => ( setForks(result.data.repository.forks.nodes) ); diff --git a/src/components/ResultTable.jsx b/src/components/ResultTable.jsx index 0aa4e66..d52b560 100644 --- a/src/components/ResultTable.jsx +++ b/src/components/ResultTable.jsx @@ -19,14 +19,29 @@ Fork.propTypes = { const ResultTable = ({ forks }) => ( <> - - - - - + + + + From 6080a834b8c52b4fa7d99263f53bda13ffc36036 Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Tue, 24 Nov 2020 06:00:47 +0100 Subject: [PATCH 28/60] :construction: Pulls & adds stargazer and fork count values --- src/components/ResultTable.jsx | 8 +++++--- src/utils/graphql.js | 5 ++++- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/components/ResultTable.jsx b/src/components/ResultTable.jsx index d52b560..c4a2bdf 100644 --- a/src/components/ResultTable.jsx +++ b/src/components/ResultTable.jsx @@ -6,14 +6,16 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; const Fork = ({ info }) => ( - - + + ); Fork.propTypes = { info: PropTypes.shape({ nameWithOwner: PropTypes.string.isRequired, + stargazerCount: PropTypes.number.isRequired, + forkCount: PropTypes.number.isRequired, }).isRequired, }; @@ -45,7 +47,7 @@ const ResultTable = ({ forks }) => ( - { forks.map((fork) => )} + { forks.map((fork) => )}
RepoStarsForksModified + + {' '} + Repo + + + {' '} + Stars + + + {' '} + Forks + + + {' '} + Modified +
{info.nameWithOwner}StarsForks{info.stargazerCount}{info.forkCount} Modified
diff --git a/src/utils/graphql.js b/src/utils/graphql.js index 80375af..b27025f 100644 --- a/src/utils/graphql.js +++ b/src/utils/graphql.js @@ -32,9 +32,12 @@ const client = new ApolloClient({ const GET_FORKS_QUERY = gql` query Forks($owner: String! $name: String!) { repository(owner: $owner, name: $name) { - forks(first: 10) { + forks(first: 100, orderBy: {field: STARGAZERS, direction: DESC}) { nodes { nameWithOwner + stargazerCount + forkCount + pushedAt } } } From b7d8d7e9a8f990626bc1662c74d635154bf6c043 Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Tue, 24 Nov 2020 06:09:02 +0100 Subject: [PATCH 29/60] :sparkless: Adds modified time to table info --- src/components/ResultTable.jsx | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/src/components/ResultTable.jsx b/src/components/ResultTable.jsx index c4a2bdf..a0e6834 100644 --- a/src/components/ResultTable.jsx +++ b/src/components/ResultTable.jsx @@ -3,12 +3,40 @@ import PropTypes from 'prop-types'; import { Table } from 'react-bootstrap'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +/** + * https://stackoverflow.com/a/3177838 + */ +const timeSince = (date) => { + const seconds = Math.floor((new Date() - date) / 1000); + let interval = seconds / 31536000; + if (interval > 1) { + return `${Math.floor(interval)} years ago`; + } + interval = seconds / 2592000; + if (interval > 1) { + return `${Math.floor(interval)} months ago`; + } + interval = seconds / 86400; + if (interval > 1) { + return `${Math.floor(interval)} days ago`; + } + interval = seconds / 3600; + if (interval > 1) { + return `${Math.floor(interval)} hours ago`; + } + interval = seconds / 60; + if (interval > 1) { + return `${Math.floor(interval)} minutes ago`; + } + return `${Math.floor(seconds)} seconds ago`; +}; + const Fork = ({ info }) => ( {info.nameWithOwner} {info.stargazerCount} {info.forkCount} - Modified + {timeSince(Date.parse(info.pushedAt))} ); Fork.propTypes = { @@ -16,6 +44,7 @@ Fork.propTypes = { nameWithOwner: PropTypes.string.isRequired, stargazerCount: PropTypes.number.isRequired, forkCount: PropTypes.number.isRequired, + pushedAt: PropTypes.string.isRequired, }).isRequired, }; From 20e74dcc64c607c130a063ad169972b5d5cac0f1 Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Tue, 24 Nov 2020 06:17:49 +0100 Subject: [PATCH 30/60] :wheelchair: Enter to submit the search --- src/components/PopForm.jsx | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/src/components/PopForm.jsx b/src/components/PopForm.jsx index a0eef30..f841f43 100644 --- a/src/components/PopForm.jsx +++ b/src/components/PopForm.jsx @@ -1,22 +1,30 @@ import React, { useState } from 'react'; import PropTypes from 'prop-types'; -import { Button, FormControl, InputGroup } from 'react-bootstrap'; +import { + Button, Form, FormControl, InputGroup, +} from 'react-bootstrap'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; const PopForm = ({ onSubmit }) => { const [url, setUrl] = useState(); + const handleSubmit = (e) => { + e.preventDefault(); + onSubmit(url); + }; return ( - - setUrl(e.target.value)} - /> - - - - +
+ + setUrl(e.target.value)} + /> + + + + +
); }; PopForm.propTypes = { From b4161aee15f967dfb8da5680ac170b95f8e3464e Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Tue, 24 Nov 2020 06:20:29 +0100 Subject: [PATCH 31/60] :lipstick: Updates favicon and title --- public/favicon.ico | Bin 3870 -> 1150 bytes public/index.html | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/public/favicon.ico b/public/favicon.ico index a11777cc471a4344702741ab1c8a588998b1311a..25fe4c5824cdf7eca850f0a3e5513316ec2b63b2 100644 GIT binary patch literal 1150 zcmd6lJqiLb5JpE3EnPuuwGk}rJb(wV^9&Xi-onnt-a@dovC<3p2VO;m6|t~d-?#}Z zD#i^6&hqjlGxLRnjYx(s2!ydJy{t%CMCw3_Oq@qVsMRPce;h;3wgy$7*csE_$Bd^7 z2bg&JOZXy~LEd8z>(@O_Fos5oeXL*4KZOh2pab88_4iG45naI%awhjlp8eX}2E9*H z7mj%6*Sjo1@8b%6H`=>MG;Yk?YNGTq)widyjpZ>8%v#kIX?k6I{k$IWSClhcjfQC0 Qf(rQpj0|&nbWYv+?uJG_ivR!s literal 3870 zcma);c{J4h9>;%nil|2-o+rCuEF-(I%-F}ijC~o(k~HKAkr0)!FCj~d>`RtpD?8b; zXOC1OD!V*IsqUwzbMF1)-gEDD=A573Z-&G7^LoAC9|WO7Xc0Cx1g^Zu0u_SjAPB3vGa^W|sj)80f#V0@M_CAZTIO(t--xg= z!sii`1giyH7EKL_+Wi0ab<)&E_0KD!3Rp2^HNB*K2@PHCs4PWSA32*-^7d{9nH2_E zmC{C*N*)(vEF1_aMamw2A{ZH5aIDqiabnFdJ|y0%aS|64E$`s2ccV~3lR!u<){eS` z#^Mx6o(iP1Ix%4dv`t@!&Za-K@mTm#vadc{0aWDV*_%EiGK7qMC_(`exc>-$Gb9~W!w_^{*pYRm~G zBN{nA;cm^w$VWg1O^^<6vY`1XCD|s_zv*g*5&V#wv&s#h$xlUilPe4U@I&UXZbL z0)%9Uj&@yd03n;!7do+bfixH^FeZ-Ema}s;DQX2gY+7g0s(9;`8GyvPY1*vxiF&|w z>!vA~GA<~JUqH}d;DfBSi^IT*#lrzXl$fNpq0_T1tA+`A$1?(gLb?e#0>UELvljtQ zK+*74m0jn&)5yk8mLBv;=@}c{t0ztT<v;Avck$S6D`Z)^c0(jiwKhQsn|LDRY&w(Fmi91I7H6S;b0XM{e zXp0~(T@k_r-!jkLwd1_Vre^v$G4|kh4}=Gi?$AaJ)3I+^m|Zyj#*?Kp@w(lQdJZf4 z#|IJW5z+S^e9@(6hW6N~{pj8|NO*>1)E=%?nNUAkmv~OY&ZV;m-%?pQ_11)hAr0oAwILrlsGawpxx4D43J&K=n+p3WLnlDsQ$b(9+4 z?mO^hmV^F8MV{4Lx>(Q=aHhQ1){0d*(e&s%G=i5rq3;t{JC zmgbn5Nkl)t@fPH$v;af26lyhH!k+#}_&aBK4baYPbZy$5aFx4}ka&qxl z$=Rh$W;U)>-=S-0=?7FH9dUAd2(q#4TCAHky!$^~;Dz^j|8_wuKc*YzfdAht@Q&ror?91Dm!N03=4=O!a)I*0q~p0g$Fm$pmr$ zb;wD;STDIi$@M%y1>p&_>%?UP($15gou_ue1u0!4(%81;qcIW8NyxFEvXpiJ|H4wz z*mFT(qVx1FKufG11hByuX%lPk4t#WZ{>8ka2efjY`~;AL6vWyQKpJun2nRiZYDij$ zP>4jQXPaP$UC$yIVgGa)jDV;F0l^n(V=HMRB5)20V7&r$jmk{UUIe zVjKroK}JAbD>B`2cwNQ&GDLx8{pg`7hbA~grk|W6LgiZ`8y`{Iq0i>t!3p2}MS6S+ zO_ruKyAElt)rdS>CtF7j{&6rP-#c=7evGMt7B6`7HG|-(WL`bDUAjyn+k$mx$CH;q2Dz4x;cPP$hW=`pFfLO)!jaCL@V2+F)So3}vg|%O*^T1j>C2lx zsURO-zIJC$^$g2byVbRIo^w>UxK}74^TqUiRR#7s_X$e)$6iYG1(PcW7un-va-S&u zHk9-6Zn&>T==A)lM^D~bk{&rFzCi35>UR!ZjQkdSiNX*-;l4z9j*7|q`TBl~Au`5& z+c)*8?#-tgUR$Zd%Q3bs96w6k7q@#tUn`5rj+r@_sAVVLqco|6O{ILX&U-&-cbVa3 zY?ngHR@%l{;`ri%H*0EhBWrGjv!LE4db?HEWb5mu*t@{kv|XwK8?npOshmzf=vZA@ zVSN9sL~!sn?r(AK)Q7Jk2(|M67Uy3I{eRy z_l&Y@A>;vjkWN5I2xvFFTLX0i+`{qz7C_@bo`ZUzDugfq4+>a3?1v%)O+YTd6@Ul7 zAfLfm=nhZ`)P~&v90$&UcF+yXm9sq!qCx3^9gzIcO|Y(js^Fj)Rvq>nQAHI92ap=P z10A4@prk+AGWCb`2)dQYFuR$|H6iDE8p}9a?#nV2}LBCoCf(Xi2@szia7#gY>b|l!-U`c}@ zLdhvQjc!BdLJvYvzzzngnw51yRYCqh4}$oRCy-z|v3Hc*d|?^Wj=l~18*E~*cR_kU z{XsxM1i{V*4GujHQ3DBpl2w4FgFR48Nma@HPgnyKoIEY-MqmMeY=I<%oG~l!f<+FN z1ZY^;10j4M4#HYXP zw5eJpA_y(>uLQ~OucgxDLuf}fVs272FaMxhn4xnDGIyLXnw>Xsd^J8XhcWIwIoQ9} z%FoSJTAGW(SRGwJwb=@pY7r$uQRK3Zd~XbxU)ts!4XsJrCycrWSI?e!IqwqIR8+Jh zlRjZ`UO1I!BtJR_2~7AbkbSm%XQqxEPkz6BTGWx8e}nQ=w7bZ|eVP4?*Tb!$(R)iC z9)&%bS*u(lXqzitAN)Oo=&Ytn>%Hzjc<5liuPi>zC_nw;Z0AE3Y$Jao_Q90R-gl~5 z_xAb2J%eArrC1CN4G$}-zVvCqF1;H;abAu6G*+PDHSYFx@Tdbfox*uEd3}BUyYY-l zTfEsOqsi#f9^FoLO;ChK<554qkri&Av~SIM*{fEYRE?vH7pTAOmu2pz3X?Wn*!ROX ztd54huAk&mFBemMooL33RV-*1f0Q3_(7hl$<#*|WF9P!;r;4_+X~k~uKEqdzZ$5Al zV63XN@)j$FN#cCD;ek1R#l zv%pGrhB~KWgoCj%GT?%{@@o(AJGt*PG#l3i>lhmb_twKH^EYvacVY-6bsCl5*^~L0 zonm@lk2UvvTKr2RS%}T>^~EYqdL1q4nD%0n&Xqr^cK^`J5W;lRRB^R-O8b&HENO||mo0xaD+S=I8RTlIfVgqN@SXDr2&-)we--K7w= zJVU8?Z+7k9dy;s;^gDkQa`0nz6N{T?(A&Iz)2!DEecLyRa&FI!id#5Z7B*O2=PsR0 zEvc|8{NS^)!d)MDX(97Xw}m&kEO@5jqRaDZ!+%`wYOI<23q|&js`&o4xvjP7D_xv@ z5hEwpsp{HezI9!~6O{~)lLR@oF7?J7i>1|5a~UuoN=q&6N}EJPV_GD`&M*v8Y`^2j zKII*d_@Fi$+i*YEW+Hbzn{iQk~yP z>7N{S4)r*!NwQ`(qcN#8SRQsNK6>{)X12nbF`*7#ecO7I)Q$uZsV+xS4E7aUn+U(K baj7?x%VD!5Cxk2YbYLNVeiXvvpMCWYo=by@ diff --git a/public/index.html b/public/index.html index c3c93fb..ee78a3b 100644 --- a/public/index.html +++ b/public/index.html @@ -24,7 +24,7 @@ work correctly both with client-side routing and a non-root public URL. Learn how to configure a non-root public URL by running `npm run build`. --> - GitPop3 + GitPop3: Find the most popular fork on GitHub From 9d9e73f3c8d881c212329414c153059d57b4fa4a Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Tue, 24 Nov 2020 07:13:55 +0100 Subject: [PATCH 32/60] :lipstick: Fixes content overflowing to footer --- src/index.css | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/src/index.css b/src/index.css index 8e42cba..61258ba 100644 --- a/src/index.css +++ b/src/index.css @@ -1,22 +1,18 @@ -body { - margin: 0; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', - 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', - sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; +html { + position: relative; + min-height: 100%; } -code { - font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', - monospace; +body { + margin-bottom: 70px!important; } .footer { - position: absolute; - bottom: 0; - width: 100%; - height: 60px; - line-height: 60px; - background-color: #f5f5f5; + position: absolute; + bottom: 0; + width: 100%; + height: 60px; + line-height: 60px; + background-color: #f5f5f5; + display: block; } From a114dd0f1e26a0fdcd4e8395a3500e28229ae3fd Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Tue, 24 Nov 2020 10:38:41 +0100 Subject: [PATCH 33/60] :children_crossing: Simple form validation Checks the URL matches with a simple regex. --- src/components/Container.jsx | 4 ++-- src/components/PopForm.jsx | 10 ++++++++-- src/utils/validators.js | 6 ++++++ 3 files changed, 16 insertions(+), 4 deletions(-) create mode 100644 src/utils/validators.js diff --git a/src/components/Container.jsx b/src/components/Container.jsx index c3c05c5..8c7bc68 100644 --- a/src/components/Container.jsx +++ b/src/components/Container.jsx @@ -3,13 +3,13 @@ import { Container as ReactContainer } from 'react-bootstrap'; import PopForm from './PopForm'; import ResultTable from './ResultTable'; import { client, GET_FORKS_QUERY } from '../utils/graphql'; +import urlMatch from '../utils/validators'; -const re = /https:\/\/github.com\/(\w+)\/(\w+)/; /** * Splits URL to owner and repo name. */ const splitUrl = (url) => ( - url.match(re).slice(1, 3) + urlMatch(url).slice(1, 3) ); const searchPopularForks = (url, onResult) => { diff --git a/src/components/PopForm.jsx b/src/components/PopForm.jsx index f841f43..fa0f981 100644 --- a/src/components/PopForm.jsx +++ b/src/components/PopForm.jsx @@ -4,12 +4,17 @@ import { Button, Form, FormControl, InputGroup, } from 'react-bootstrap'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import urlMatch from '../utils/validators'; const PopForm = ({ onSubmit }) => { const [url, setUrl] = useState(); const handleSubmit = (e) => { e.preventDefault(); - onSubmit(url); + if (urlMatch(url) === null) { + e.stopPropagation(); + } else { + onSubmit(url); + } }; return (
@@ -17,9 +22,10 @@ const PopForm = ({ onSubmit }) => { setUrl(e.target.value)} + isInvalid={urlMatch(url) === null} /> - diff --git a/src/utils/validators.js b/src/utils/validators.js new file mode 100644 index 0000000..c3f277c --- /dev/null +++ b/src/utils/validators.js @@ -0,0 +1,6 @@ +const repoRegex = /https:\/\/github.com\/(\w+)\/(\w+)/; +const urlMatch = (url) => ( + url && url.match(repoRegex) +); + +export default urlMatch; From 4044cf66814c62b1dfa4168b6edabfaba1756e7c Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Tue, 24 Nov 2020 10:43:37 +0100 Subject: [PATCH 34/60] :children_crossing: Also accept HTTP schemas --- src/utils/validators.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/validators.js b/src/utils/validators.js index c3f277c..78f3a92 100644 --- a/src/utils/validators.js +++ b/src/utils/validators.js @@ -1,4 +1,4 @@ -const repoRegex = /https:\/\/github.com\/(\w+)\/(\w+)/; +const repoRegex = /https?:\/\/github.com\/(\w+)\/(\w+)/; const urlMatch = (url) => ( url && url.match(repoRegex) ); From eab3c44ed375b92bc2d5ab954ce07eab76ad60ec Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Tue, 24 Nov 2020 16:15:02 +0100 Subject: [PATCH 35/60] :sparkles: Adds total commits column Refs https://github.com/AndreMiras/gitpop2/issues/4 --- src/components/ResultTable.jsx | 11 +++++++++++ src/utils/graphql.js | 7 +++++++ 2 files changed, 18 insertions(+) diff --git a/src/components/ResultTable.jsx b/src/components/ResultTable.jsx index a0e6834..230ad9b 100644 --- a/src/components/ResultTable.jsx +++ b/src/components/ResultTable.jsx @@ -36,6 +36,7 @@ const Fork = ({ info }) => ( {info.nameWithOwner} {info.stargazerCount} {info.forkCount} + {info.object.history.totalCount} {timeSince(Date.parse(info.pushedAt))} ); @@ -45,6 +46,11 @@ Fork.propTypes = { stargazerCount: PropTypes.number.isRequired, forkCount: PropTypes.number.isRequired, pushedAt: PropTypes.string.isRequired, + object: PropTypes.shape({ + history: PropTypes.shape({ + totalCount: PropTypes.number.isRequired, + }).isRequired, + }).isRequired, }).isRequired, }; @@ -68,6 +74,11 @@ const ResultTable = ({ forks }) => ( {' '} Forks + + + {' '} + Commits + {' '} diff --git a/src/utils/graphql.js b/src/utils/graphql.js index b27025f..22616ba 100644 --- a/src/utils/graphql.js +++ b/src/utils/graphql.js @@ -38,6 +38,13 @@ const GET_FORKS_QUERY = gql` stargazerCount forkCount pushedAt + object(expression: "master") { + ... on Commit { + history { + totalCount + } + } + } } } } From ffb49a1c22cbf4d7ff6f093f5ae1b80c6852f40f Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Tue, 24 Nov 2020 18:56:47 +0100 Subject: [PATCH 36/60] :sparkles: Clickable repo link --- src/components/ResultTable.jsx | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/components/ResultTable.jsx b/src/components/ResultTable.jsx index 230ad9b..e5a93ec 100644 --- a/src/components/ResultTable.jsx +++ b/src/components/ResultTable.jsx @@ -31,9 +31,18 @@ const timeSince = (date) => { return `${Math.floor(seconds)} seconds ago`; }; +const RepoLink = ({ nameWithOwner }) => ( + + {nameWithOwner} + +); +RepoLink.propTypes = { + nameWithOwner: PropTypes.string.isRequired, +}; + const Fork = ({ info }) => ( - {info.nameWithOwner} + {info.stargazerCount} {info.forkCount} {info.object.history.totalCount} From deaf0aaaf61cc27426b4c2f5fee73cdb9cbba595 Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Fri, 27 Nov 2020 07:39:40 +0100 Subject: [PATCH 37/60] :heavy_plus_sign: yarn add react-js-pagination, refs #2 --- package.json | 1 + yarn.lock | 74 ++++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 64 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index 1e2eb52..751d197 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "react": "^17.0.1", "react-bootstrap": "^1.4.0", "react-dom": "^17.0.1", + "react-js-pagination": "^3.0.3", "react-scripts": "4.0.1", "web-vitals": "^0.2.4" }, diff --git a/yarn.lock b/yarn.lock index 9f1202f..8397485 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2844,6 +2844,13 @@ bindings@^1.5.0: dependencies: file-uri-to-path "1.0.0" +block-stream@*: + version "0.0.9" + resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" + integrity sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo= + dependencies: + inherits "~2.0.0" + bluebird@^3.5.5: version "3.7.2" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" @@ -3326,7 +3333,7 @@ class-utils@^0.3.5: isobject "^3.0.0" static-extend "^0.1.1" -classnames@^2.2.6: +classnames@^2.2.5, classnames@^2.2.6: version "2.2.6" resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce" integrity sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q== @@ -5341,6 +5348,16 @@ fsevents@~2.1.2: resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.3.tgz#fb738703ae8d2f9fe900c33836ddebee8b97f23e" integrity sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ== +fstream@1.0.12, fstream@^1.0.12: + version "1.0.12" + resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.12.tgz#4e8ba8ee2d48be4f7d0de505455548eae5932045" + integrity sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg== + dependencies: + graceful-fs "^4.1.2" + inherits "~2.0.0" + mkdirp ">=0.5 0" + rimraf "2" + function-bind@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" @@ -5944,7 +5961,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3: +inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -7470,7 +7487,7 @@ mixin-deep@^1.2.0: for-in "^1.0.2" is-extendable "^1.0.1" -mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@^0.5.5, mkdirp@~0.5.1: +"mkdirp@>=0.5 0", mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@^0.5.5, mkdirp@~0.5.1: version "0.5.5" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== @@ -7999,6 +8016,11 @@ p-try@^2.0.0: resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== +paginator@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/paginator/-/paginator-1.0.0.tgz#7565702af9ab9616dca61fc22c70eba2a4357265" + integrity sha1-dWVwKvmrlhbcph/CLHDroqQ1cmU= + pako@~1.0.5: version "1.0.11" resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" @@ -9001,7 +9023,7 @@ prop-types-extra@^1.1.0: react-is "^16.3.2" warning "^4.0.0" -prop-types@^15.6.2, prop-types@^15.7.2: +"prop-types@15.x.x - 16.x.x", prop-types@^15.6.2, prop-types@^15.7.2: version "15.7.2" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ== @@ -9245,6 +9267,18 @@ react-is@^17.0.1: resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.1.tgz#5b3531bd76a645a4c9fb6e693ed36419e3301339" integrity sha512-NAnt2iGDXohE5LI7uBnLnqvLQMtzhkiAOLXTmv+qnF9Ky7xAPcX8Up/xWIhxvLVGJvuLiNc4xQLtuqDRzb4fSA== +react-js-pagination@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/react-js-pagination/-/react-js-pagination-3.0.3.tgz#bc5504ad9fda2a13f59eca91c7b07966a39e1776" + integrity sha512-podyA6Rd0uxc8uQakXWXxnonoOPI6NnFOROXfc6qPKNYm44s+Bgpn0JkyflcfbHf/GFKahnL8JN8rxBHZiBskg== + dependencies: + classnames "^2.2.5" + fstream "1.0.12" + paginator "^1.0.0" + prop-types "15.x.x - 16.x.x" + react "15.x.x - 16.x.x" + tar "2.2.2" + react-lifecycles-compat@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362" @@ -9345,6 +9379,15 @@ react-transition-group@^4.4.1: loose-envify "^1.4.0" prop-types "^15.6.2" +"react@15.x.x - 16.x.x": + version "16.14.0" + resolved "https://registry.yarnpkg.com/react/-/react-16.14.0.tgz#94d776ddd0aaa37da3eda8fc5b6b18a4c9a3114d" + integrity sha512-0X2CImDkJGApiAlcf0ODKIneSwBPhqJawOa5wCtKbu7ZECrmS26NvtSILynQ66cgkT/RJ4LidJOc3bUESwmU8g== + dependencies: + loose-envify "^1.1.0" + object-assign "^4.1.1" + prop-types "^15.6.2" + react@^17.0.1: version "17.0.1" resolved "https://registry.yarnpkg.com/react/-/react-17.0.1.tgz#6e0600416bd57574e3f86d92edba3d9008726127" @@ -9713,6 +9756,13 @@ rgba-regex@^1.0.0: resolved "https://registry.yarnpkg.com/rgba-regex/-/rgba-regex-1.0.0.tgz#43374e2e2ca0968b0ef1523460b7d730ff22eeb3" integrity sha1-QzdOLiyglosO8VI0YLfXMP8i7rM= +rimraf@2, rimraf@^2.5.4, rimraf@^2.6.3: + version "2.7.1" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" + integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== + dependencies: + glob "^7.1.3" + rimraf@2.6.3: version "2.6.3" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" @@ -9720,13 +9770,6 @@ rimraf@2.6.3: dependencies: glob "^7.1.3" -rimraf@^2.5.4, rimraf@^2.6.3: - version "2.7.1" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" - integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== - dependencies: - glob "^7.1.3" - rimraf@^3.0.0, rimraf@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" @@ -10628,6 +10671,15 @@ tapable@^1.0.0, tapable@^1.1.3: resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2" integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA== +tar@2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.2.tgz#0ca8848562c7299b8b446ff6a4d60cdbb23edc40" + integrity sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA== + dependencies: + block-stream "*" + fstream "^1.0.12" + inherits "2" + tar@^6.0.2: version "6.0.5" resolved "https://registry.yarnpkg.com/tar/-/tar-6.0.5.tgz#bde815086e10b39f1dcd298e89d596e1535e200f" From 533285fb331a01040609f16db6cf686a54d16535 Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Mon, 7 Dec 2020 22:17:03 +0100 Subject: [PATCH 38/60] :sparkles: Makes the ResultTable paginated, fixes #2 --- src/components/Container.jsx | 14 +++++++++++++- src/components/ResultTable.jsx | 31 +++++++++++++++++++++++++++++-- 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/src/components/Container.jsx b/src/components/Container.jsx index 8c7bc68..00231e6 100644 --- a/src/components/Container.jsx +++ b/src/components/Container.jsx @@ -24,10 +24,22 @@ const searchPopularForks = (url, onResult) => { const Container = () => { const [forks, setForks] = useState(); + const [activePage, setActivePage] = useState(1); const onResult = (result) => ( setForks(result.data.repository.forks.nodes) ); - const resultTable = forks ? : null; + const resultTable = ( + forks + ? ( + + ) + : null + ); return ( searchPopularForks(url, onResult)} /> diff --git a/src/components/ResultTable.jsx b/src/components/ResultTable.jsx index e5a93ec..2499323 100644 --- a/src/components/ResultTable.jsx +++ b/src/components/ResultTable.jsx @@ -2,6 +2,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import { Table } from 'react-bootstrap'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import Pagination from 'react-js-pagination'; /** * https://stackoverflow.com/a/3177838 @@ -63,7 +64,13 @@ Fork.propTypes = { }).isRequired, }; -const ResultTable = ({ forks }) => ( +const paginatedForks = (forks, activePage, itemsCountPerPage) => ( + forks.slice((activePage - 1) * itemsCountPerPage, activePage * itemsCountPerPage) +); + +const ResultTable = ({ + forks, activePage, itemsCountPerPage, onPageChange, +}) => ( <> @@ -96,13 +103,33 @@ const ResultTable = ({ forks }) => ( - { forks.map((fork) => )} + { + paginatedForks( + forks, + activePage, + itemsCountPerPage, + ).map( + (fork) => , + ) + }
+ ); ResultTable.propTypes = { forks: PropTypes.arrayOf(Fork.propTypes.info).isRequired, + activePage: PropTypes.number.isRequired, + itemsCountPerPage: PropTypes.number.isRequired, + onPageChange: PropTypes.func.isRequired, }; export default ResultTable; From 2bd91a14abbe8cb2f3e5faa002c92465ee6d9531 Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Mon, 7 Dec 2020 22:38:04 +0100 Subject: [PATCH 39/60] :children_crossing: Use spinner icon while fetching, fixes #4 --- src/components/Container.jsx | 14 ++++++++++---- src/components/PopForm.jsx | 12 ++++++++++-- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/src/components/Container.jsx b/src/components/Container.jsx index 00231e6..6638726 100644 --- a/src/components/Container.jsx +++ b/src/components/Container.jsx @@ -25,9 +25,15 @@ const searchPopularForks = (url, onResult) => { const Container = () => { const [forks, setForks] = useState(); const [activePage, setActivePage] = useState(1); - const onResult = (result) => ( - setForks(result.data.repository.forks.nodes) - ); + const [loading, setLoading] = useState(false); + const onResult = (result) => { + setForks(result.data.repository.forks.nodes); + setLoading(false); + }; + const onSubmit = (url) => { + setLoading(true); + searchPopularForks(url, onResult); + }; const resultTable = ( forks ? ( @@ -42,7 +48,7 @@ const Container = () => { ); return ( - searchPopularForks(url, onResult)} /> + {resultTable} ); diff --git a/src/components/PopForm.jsx b/src/components/PopForm.jsx index fa0f981..5c6f670 100644 --- a/src/components/PopForm.jsx +++ b/src/components/PopForm.jsx @@ -6,7 +6,14 @@ import { import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import urlMatch from '../utils/validators'; -const PopForm = ({ onSubmit }) => { +const SearchIcon = ({ loading }) => ( + +); +SearchIcon.propTypes = { + loading: PropTypes.bool.isRequired, +}; + +const PopForm = ({ onSubmit, loading }) => { const [url, setUrl] = useState(); const handleSubmit = (e) => { e.preventDefault(); @@ -26,7 +33,7 @@ const PopForm = ({ onSubmit }) => { /> @@ -35,6 +42,7 @@ const PopForm = ({ onSubmit }) => { }; PopForm.propTypes = { onSubmit: PropTypes.func.isRequired, + loading: PropTypes.bool.isRequired, }; export default PopForm; From 89607f906260116bfbc9473751a6ee1d3ef15a67 Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Tue, 8 Dec 2020 09:48:59 +0100 Subject: [PATCH 40/60] :recycle: Moves timeSince helper to dedicated file --- src/components/ResultTable.jsx | 29 +---------------------------- src/utils/time.js | 29 +++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 28 deletions(-) create mode 100644 src/utils/time.js diff --git a/src/components/ResultTable.jsx b/src/components/ResultTable.jsx index 2499323..371698b 100644 --- a/src/components/ResultTable.jsx +++ b/src/components/ResultTable.jsx @@ -3,34 +3,7 @@ import PropTypes from 'prop-types'; import { Table } from 'react-bootstrap'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import Pagination from 'react-js-pagination'; - -/** - * https://stackoverflow.com/a/3177838 - */ -const timeSince = (date) => { - const seconds = Math.floor((new Date() - date) / 1000); - let interval = seconds / 31536000; - if (interval > 1) { - return `${Math.floor(interval)} years ago`; - } - interval = seconds / 2592000; - if (interval > 1) { - return `${Math.floor(interval)} months ago`; - } - interval = seconds / 86400; - if (interval > 1) { - return `${Math.floor(interval)} days ago`; - } - interval = seconds / 3600; - if (interval > 1) { - return `${Math.floor(interval)} hours ago`; - } - interval = seconds / 60; - if (interval > 1) { - return `${Math.floor(interval)} minutes ago`; - } - return `${Math.floor(seconds)} seconds ago`; -}; +import timeSince from '../utils/time'; const RepoLink = ({ nameWithOwner }) => ( diff --git a/src/utils/time.js b/src/utils/time.js new file mode 100644 index 0000000..d18b2e1 --- /dev/null +++ b/src/utils/time.js @@ -0,0 +1,29 @@ +/** + * https://stackoverflow.com/a/3177838 + */ +const timeSince = (date) => { + const seconds = Math.floor((new Date() - date) / 1000); + let interval = seconds / 31536000; + if (interval > 1) { + return `${Math.floor(interval)} years ago`; + } + interval = seconds / 2592000; + if (interval > 1) { + return `${Math.floor(interval)} months ago`; + } + interval = seconds / 86400; + if (interval > 1) { + return `${Math.floor(interval)} days ago`; + } + interval = seconds / 3600; + if (interval > 1) { + return `${Math.floor(interval)} hours ago`; + } + interval = seconds / 60; + if (interval > 1) { + return `${Math.floor(interval)} minutes ago`; + } + return `${Math.floor(seconds)} seconds ago`; +}; + +export default timeSince; From 50aab777cddf1b5fdc74355d3524f872392aafcc Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Tue, 8 Dec 2020 12:49:19 +0100 Subject: [PATCH 41/60] :white_check_mark: Tests timeSince --- package.json | 3 +- src/utils/time.test.js | 68 ++++++++++++++++++++++++++++++++++++++++++ yarn.lock | 5 ++++ 3 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 src/utils/time.test.js diff --git a/package.json b/package.json index 751d197..1e44331 100644 --- a/package.json +++ b/package.json @@ -53,6 +53,7 @@ }, "devDependencies": { "eslint-config-airbnb": "^18.2.1", - "gh-pages": "^3.1.0" + "gh-pages": "^3.1.0", + "moment": "^2.29.1" } } diff --git a/src/utils/time.test.js b/src/utils/time.test.js new file mode 100644 index 0000000..2579ad1 --- /dev/null +++ b/src/utils/time.test.js @@ -0,0 +1,68 @@ +import moment from 'moment'; +import timeSince from './time'; + +test('basic case', () => { + expect( + timeSince( + Date.now(), + ), + ); +}); + +test('basic case 2', () => { + expect( + timeSince( + Date.now(), + ), + ).toBe('0 seconds ago'); +}); + +test('seconds ago', () => { + expect( + timeSince( + moment( + Date.now(), + ).subtract(30, 'seconds').toDate(), + ), + ).toBe('30 seconds ago'); +}); + +test('minutes ago', () => { + expect( + timeSince( + moment( + Date.now(), + ).subtract(15, 'minutes').toDate(), + ), + ).toBe('15 minutes ago'); +}); + +test('days ago', () => { + expect( + timeSince( + moment( + Date.now(), + ).subtract(3, 'days').toDate(), + ), + ).toBe('3 days ago'); +}); + +test('months ago', () => { + expect( + timeSince( + moment( + Date.now(), + ).subtract(6, 'months').toDate(), + ), + ).toBe('6 months ago'); +}); + +test('years ago', () => { + expect( + timeSince( + moment( + Date.now(), + ).subtract(1, 'years').toDate(), + ), + ).toBe('1 years ago'); +}); diff --git a/yarn.lock b/yarn.lock index 8397485..3b8e08e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7499,6 +7499,11 @@ mkdirp@^1.0.3, mkdirp@^1.0.4: resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== +moment@^2.29.1: + version "2.29.1" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.1.tgz#b2be769fa31940be9eeea6469c075e35006fa3d3" + integrity sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ== + move-concurrently@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92" From 22873ce07e82d8627a9c60c76940da10c47ff7c1 Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Tue, 8 Dec 2020 17:47:46 +0100 Subject: [PATCH 42/60] :recycle: Dedicated ForkLine & RepoLink components --- src/components/ForkLine.jsx | 29 ++++++++++++++++++++++++++ src/components/RepoLink.jsx | 13 ++++++++++++ src/components/ResultTable.jsx | 38 +++------------------------------- 3 files changed, 45 insertions(+), 35 deletions(-) create mode 100644 src/components/ForkLine.jsx create mode 100644 src/components/RepoLink.jsx diff --git a/src/components/ForkLine.jsx b/src/components/ForkLine.jsx new file mode 100644 index 0000000..e18caa7 --- /dev/null +++ b/src/components/ForkLine.jsx @@ -0,0 +1,29 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import timeSince from '../utils/time'; +import RepoLink from './RepoLink'; + +const ForkLine = ({ info }) => ( + + + {info.stargazerCount} + {info.forkCount} + {info.object.history.totalCount} + {timeSince(Date.parse(info.pushedAt))} + +); +ForkLine.propTypes = { + info: PropTypes.shape({ + nameWithOwner: PropTypes.string.isRequired, + stargazerCount: PropTypes.number.isRequired, + forkCount: PropTypes.number.isRequired, + pushedAt: PropTypes.string.isRequired, + object: PropTypes.shape({ + history: PropTypes.shape({ + totalCount: PropTypes.number.isRequired, + }).isRequired, + }).isRequired, + }).isRequired, +}; + +export default ForkLine; diff --git a/src/components/RepoLink.jsx b/src/components/RepoLink.jsx new file mode 100644 index 0000000..40ec6d2 --- /dev/null +++ b/src/components/RepoLink.jsx @@ -0,0 +1,13 @@ +import React from 'react'; +import PropTypes from 'prop-types'; + +const RepoLink = ({ nameWithOwner }) => ( + + {nameWithOwner} + +); +RepoLink.propTypes = { + nameWithOwner: PropTypes.string.isRequired, +}; + +export default RepoLink; diff --git a/src/components/ResultTable.jsx b/src/components/ResultTable.jsx index 371698b..dfa6891 100644 --- a/src/components/ResultTable.jsx +++ b/src/components/ResultTable.jsx @@ -3,39 +3,7 @@ import PropTypes from 'prop-types'; import { Table } from 'react-bootstrap'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import Pagination from 'react-js-pagination'; -import timeSince from '../utils/time'; - -const RepoLink = ({ nameWithOwner }) => ( - - {nameWithOwner} - -); -RepoLink.propTypes = { - nameWithOwner: PropTypes.string.isRequired, -}; - -const Fork = ({ info }) => ( - - - {info.stargazerCount} - {info.forkCount} - {info.object.history.totalCount} - {timeSince(Date.parse(info.pushedAt))} - -); -Fork.propTypes = { - info: PropTypes.shape({ - nameWithOwner: PropTypes.string.isRequired, - stargazerCount: PropTypes.number.isRequired, - forkCount: PropTypes.number.isRequired, - pushedAt: PropTypes.string.isRequired, - object: PropTypes.shape({ - history: PropTypes.shape({ - totalCount: PropTypes.number.isRequired, - }).isRequired, - }).isRequired, - }).isRequired, -}; +import ForkLine from './ForkLine'; const paginatedForks = (forks, activePage, itemsCountPerPage) => ( forks.slice((activePage - 1) * itemsCountPerPage, activePage * itemsCountPerPage) @@ -82,7 +50,7 @@ const ResultTable = ({ activePage, itemsCountPerPage, ).map( - (fork) => , + (fork) => , ) } @@ -99,7 +67,7 @@ const ResultTable = ({ ); ResultTable.propTypes = { - forks: PropTypes.arrayOf(Fork.propTypes.info).isRequired, + forks: PropTypes.arrayOf(ForkLine.propTypes.info).isRequired, activePage: PropTypes.number.isRequired, itemsCountPerPage: PropTypes.number.isRequired, onPageChange: PropTypes.func.isRequired, From 2897bc78052064a91641837061e4883f530cb470 Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Tue, 8 Dec 2020 18:28:49 +0100 Subject: [PATCH 43/60] :construction_worker: Setup coverage testing, fixes #7 --- .github/workflows/tests.yml | 3 +++ README.md | 1 + package.json | 3 ++- yarn.lock | 21 +++++++++++++++++++++ 4 files changed, 27 insertions(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 74f1a12..159463f 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -12,3 +12,6 @@ jobs: - run: yarn install - run: yarn test - run: yarn lint + - uses: coverallsapp/github-action@v1.1.2 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/README.md b/README.md index dfbae6b..379d3a1 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # GitPop3 [![Tests](https://github.com/AndreMiras/gitpop3/workflows/Tests/badge.svg?branch=develop)](https://github.com/AndreMiras/gitpop3/actions?query=workflow%3ATests) +[![Coverage Status](https://coveralls.io/repos/github/AndreMiras/gitpop3/badge.svg?branch=develop)](https://coveralls.io/github/AndreMiras/gitpop3?branch=develop) [![Deploy](https://github.com/AndreMiras/gitpop3/workflows/Deploy/badge.svg?branch=develop)](https://github.com/AndreMiras/gitpop3/actions?query=workflow%3ADeploy) Find the most popular fork on GitHub. diff --git a/package.json b/package.json index 1e44331..a88beb4 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "scripts": { "start": "react-scripts start", "build": "react-scripts build", - "test": "react-scripts test", + "test": "react-scripts test --coverage", "eject": "react-scripts eject", "lint": "eslint -c .eslintrc 'src/**/*.{js,jsx}'", "format": "eslint -c .eslintrc 'src/**/*.{js,jsx}' --fix", @@ -52,6 +52,7 @@ ] }, "devDependencies": { + "coveralls": "^3.1.0", "eslint-config-airbnb": "^18.2.1", "gh-pages": "^3.1.0", "moment": "^2.29.1" diff --git a/yarn.lock b/yarn.lock index 3b8e08e..1210e06 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3659,6 +3659,17 @@ cosmiconfig@^7.0.0: path-type "^4.0.0" yaml "^1.10.0" +coveralls@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/coveralls/-/coveralls-3.1.0.tgz#13c754d5e7a2dd8b44fe5269e21ca394fb4d615b" + integrity sha512-sHxOu2ELzW8/NC1UP5XVLbZDzO4S3VxfFye3XYCznopHy02YjNkHcj5bKaVw2O7hVaBdBjEdQGpie4II1mWhuQ== + dependencies: + js-yaml "^3.13.1" + lcov-parse "^1.0.0" + log-driver "^1.2.7" + minimist "^1.2.5" + request "^2.88.2" + create-ecdh@^4.0.0: version "4.0.4" resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.4.tgz#d6e7f4bffa66736085a0762fd3a632684dabcc4e" @@ -7043,6 +7054,11 @@ last-call-webpack-plugin@^3.0.0: lodash "^4.17.5" webpack-sources "^1.1.0" +lcov-parse@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/lcov-parse/-/lcov-parse-1.0.0.tgz#eb0d46b54111ebc561acb4c408ef9363bdc8f7e0" + integrity sha1-6w1GtUER68VhrLTECO+TY73I9+A= + leven@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" @@ -7179,6 +7195,11 @@ lodash.uniq@^4.5.0: resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== +log-driver@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/log-driver/-/log-driver-1.2.7.tgz#63b95021f0702fedfa2c9bb0a24e7797d71871d8" + integrity sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg== + loglevel@^1.6.8: version "1.7.0" resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.7.0.tgz#728166855a740d59d38db01cf46f042caa041bb0" From d3a8b5b0c9e772fe664d5588f239a618694bec14 Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Tue, 8 Dec 2020 18:54:46 +0100 Subject: [PATCH 44/60] :heavy_plus_sign: react-test-renderer --- package.json | 3 ++- yarn.lock | 28 +++++++++++++++++++++++----- 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index a88beb4..65f1c5f 100644 --- a/package.json +++ b/package.json @@ -55,6 +55,7 @@ "coveralls": "^3.1.0", "eslint-config-airbnb": "^18.2.1", "gh-pages": "^3.1.0", - "moment": "^2.29.1" + "moment": "^2.29.1", + "react-test-renderer": "^17.0.1" } } diff --git a/yarn.lock b/yarn.lock index 1210e06..547bd53 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9283,16 +9283,16 @@ react-error-overlay@^6.0.8: resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.8.tgz#474ed11d04fc6bda3af643447d85e9127ed6b5de" integrity sha512-HvPuUQnLp5H7TouGq3kzBeioJmXms1wHy9EGjz2OURWBp4qZO6AfGEcnxts1D/CbwPLRAgTMPCEgYhA3sEM4vw== +"react-is@^16.12.0 || ^17.0.0", react-is@^17.0.1: + version "17.0.1" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.1.tgz#5b3531bd76a645a4c9fb6e693ed36419e3301339" + integrity sha512-NAnt2iGDXohE5LI7uBnLnqvLQMtzhkiAOLXTmv+qnF9Ky7xAPcX8Up/xWIhxvLVGJvuLiNc4xQLtuqDRzb4fSA== + react-is@^16.3.2, react-is@^16.7.0, react-is@^16.8.1: version "16.13.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== -react-is@^17.0.1: - version "17.0.1" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.1.tgz#5b3531bd76a645a4c9fb6e693ed36419e3301339" - integrity sha512-NAnt2iGDXohE5LI7uBnLnqvLQMtzhkiAOLXTmv+qnF9Ky7xAPcX8Up/xWIhxvLVGJvuLiNc4xQLtuqDRzb4fSA== - react-js-pagination@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/react-js-pagination/-/react-js-pagination-3.0.3.tgz#bc5504ad9fda2a13f59eca91c7b07966a39e1776" @@ -9395,6 +9395,24 @@ react-scripts@4.0.1: optionalDependencies: fsevents "^2.1.3" +react-shallow-renderer@^16.13.1: + version "16.14.1" + resolved "https://registry.yarnpkg.com/react-shallow-renderer/-/react-shallow-renderer-16.14.1.tgz#bf0d02df8a519a558fd9b8215442efa5c840e124" + integrity sha512-rkIMcQi01/+kxiTE9D3fdS959U1g7gs+/rborw++42m1O9FAQiNI/UNRZExVUoAOprn4umcXf+pFRou8i4zuBg== + dependencies: + object-assign "^4.1.1" + react-is "^16.12.0 || ^17.0.0" + +react-test-renderer@^17.0.1: + version "17.0.1" + resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-17.0.1.tgz#3187e636c3063e6ae498aedf21ecf972721574c7" + integrity sha512-/dRae3mj6aObwkjCcxZPlxDFh73XZLgvwhhyON2haZGUEhiaY5EjfAdw+d/rQmlcFwdTpMXCSGVk374QbCTlrA== + dependencies: + object-assign "^4.1.1" + react-is "^17.0.1" + react-shallow-renderer "^16.13.1" + scheduler "^0.20.1" + react-transition-group@^4.4.1: version "4.4.1" resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.1.tgz#63868f9325a38ea5ee9535d828327f85773345c9" From 8a7e01e9c918772ee4a98c6d62f60fd221bb94dd Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Tue, 8 Dec 2020 18:55:20 +0100 Subject: [PATCH 45/60] :white_check_mark: RepoLink --- src/components/RepoLink.test.jsx | 10 ++++++++++ src/components/__snapshots__/RepoLink.test.jsx.snap | 9 +++++++++ 2 files changed, 19 insertions(+) create mode 100644 src/components/RepoLink.test.jsx create mode 100644 src/components/__snapshots__/RepoLink.test.jsx.snap diff --git a/src/components/RepoLink.test.jsx b/src/components/RepoLink.test.jsx new file mode 100644 index 0000000..5c39428 --- /dev/null +++ b/src/components/RepoLink.test.jsx @@ -0,0 +1,10 @@ +import React from 'react'; +import renderer from 'react-test-renderer'; +import RepoLink from './RepoLink'; + +test('renders', () => { + const tree = renderer.create( + , + ).toJSON(); + expect(tree).toMatchSnapshot(); +}); diff --git a/src/components/__snapshots__/RepoLink.test.jsx.snap b/src/components/__snapshots__/RepoLink.test.jsx.snap new file mode 100644 index 0000000..621acab --- /dev/null +++ b/src/components/__snapshots__/RepoLink.test.jsx.snap @@ -0,0 +1,9 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`renders 1`] = ` + + django/Django + +`; From cfa97d19f8d01b4d28d6752dec93ba980cc6d029 Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Tue, 8 Dec 2020 19:06:07 +0100 Subject: [PATCH 46/60] :white_check_mark: Tests ForkLine --- src/components/ForkLine.test.jsx | 21 ++++++++++++++++ .../__snapshots__/ForkLine.test.jsx.snap | 25 +++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 src/components/ForkLine.test.jsx create mode 100644 src/components/__snapshots__/ForkLine.test.jsx.snap diff --git a/src/components/ForkLine.test.jsx b/src/components/ForkLine.test.jsx new file mode 100644 index 0000000..3c0aeb6 --- /dev/null +++ b/src/components/ForkLine.test.jsx @@ -0,0 +1,21 @@ +import React from 'react'; +import renderer from 'react-test-renderer'; +import ForkLine from './ForkLine'; + +test('renders', () => { + const info = { + nameWithOwner: 'django/django', + stargazerCount: 123, + forkCount: 321, + pushedAt: '2020-08-29T14:23:26Z', + object: { + history: { + totalCount: 1234, + }, + }, + }; + const tree = renderer.create( + , + ).toJSON(); + expect(tree).toMatchSnapshot(); +}); diff --git a/src/components/__snapshots__/ForkLine.test.jsx.snap b/src/components/__snapshots__/ForkLine.test.jsx.snap new file mode 100644 index 0000000..6fb3e76 --- /dev/null +++ b/src/components/__snapshots__/ForkLine.test.jsx.snap @@ -0,0 +1,25 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`renders 1`] = ` + + + + django/django + + + + 123 + + + 321 + + + 1234 + + + 3 months ago + + +`; From 75d629b51ca2c29068652165e1ae816f03729fac Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Tue, 8 Dec 2020 19:18:03 +0100 Subject: [PATCH 47/60] :white_check_mark: Tests ResultTable --- src/components/ResultTable.test.jsx | 50 ++++ .../__snapshots__/ResultTable.test.jsx.snap | 239 ++++++++++++++++++ 2 files changed, 289 insertions(+) create mode 100644 src/components/ResultTable.test.jsx create mode 100644 src/components/__snapshots__/ResultTable.test.jsx.snap diff --git a/src/components/ResultTable.test.jsx b/src/components/ResultTable.test.jsx new file mode 100644 index 0000000..2d83db2 --- /dev/null +++ b/src/components/ResultTable.test.jsx @@ -0,0 +1,50 @@ +import React from 'react'; +import renderer from 'react-test-renderer'; +import { library } from '@fortawesome/fontawesome-svg-core'; +import { fab } from '@fortawesome/free-brands-svg-icons'; +import { fas } from '@fortawesome/free-solid-svg-icons'; +import ResultTable from './ResultTable'; + +library.add(fab, fas); + +test('renders', () => { + const forks = [ + { + nameWithOwner: 'django-nonrel/django', + stargazerCount: 214, + forkCount: 84, + pushedAt: '2020-08-29T14:23:26Z', + object: { + history: { + totalCount: 13990, + }, + }, + }, + { + nameWithOwner: 'django/django', + stargazerCount: 26, + forkCount: 2, + pushedAt: '2020-02-17:11:12Z', + object: { + history: { + totalCount: 26823, + }, + }, + }, + { + nameWithOwner: 'FlipperPA/django-mssql-backend', + stargazerCount: 18, + forkCount: 2, + pushedAt: '2020-01-13:11:12Z', + object: { + history: { + totalCount: 28017, + }, + }, + }, + ]; + const tree = renderer.create( + null} />, + ).toJSON(); + expect(tree).toMatchSnapshot(); +}); diff --git a/src/components/__snapshots__/ResultTable.test.jsx.snap b/src/components/__snapshots__/ResultTable.test.jsx.snap new file mode 100644 index 0000000..1d36c16 --- /dev/null +++ b/src/components/__snapshots__/ResultTable.test.jsx.snap @@ -0,0 +1,239 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`renders 1`] = ` +Array [ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + Repo + + + + Stars + + + + Forks + + + + Commits + + + + Modified +
+ + django-nonrel/django + + + 214 + + 84 + + 13990 + + 3 months ago +
+ + django/django + + + 26 + + 2 + + 26823 + + 9 months ago +
, + , +] +`; From 67dfd04b4dadb98d9c2ca88ca32492db6f099cf9 Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Tue, 8 Dec 2020 22:10:45 +0100 Subject: [PATCH 48/60] :recycle: Dedicated utils/search.js --- src/components/Container.jsx | 20 +------------------- src/utils/search.js | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+), 19 deletions(-) create mode 100644 src/utils/search.js diff --git a/src/components/Container.jsx b/src/components/Container.jsx index 6638726..e2f579b 100644 --- a/src/components/Container.jsx +++ b/src/components/Container.jsx @@ -2,25 +2,7 @@ import React, { useState } from 'react'; import { Container as ReactContainer } from 'react-bootstrap'; import PopForm from './PopForm'; import ResultTable from './ResultTable'; -import { client, GET_FORKS_QUERY } from '../utils/graphql'; -import urlMatch from '../utils/validators'; - -/** - * Splits URL to owner and repo name. - */ -const splitUrl = (url) => ( - urlMatch(url).slice(1, 3) -); - -const searchPopularForks = (url, onResult) => { - const [owner, name] = splitUrl(url); - client.query({ - query: GET_FORKS_QUERY, - variables: { owner, name }, - }).then( - (result) => onResult(result), - ); -}; +import searchPopularForks from '../utils/search'; const Container = () => { const [forks, setForks] = useState(); diff --git a/src/utils/search.js b/src/utils/search.js new file mode 100644 index 0000000..842a8a1 --- /dev/null +++ b/src/utils/search.js @@ -0,0 +1,21 @@ +import { client, GET_FORKS_QUERY } from './graphql'; +import urlMatch from './validators'; + +/** + * Splits URL to owner and repo name. + */ +const splitUrl = (url) => ( + urlMatch(url).slice(1, 3) +); + +const searchPopularForks = (url, onResult) => { + const [owner, name] = splitUrl(url); + client.query({ + query: GET_FORKS_QUERY, + variables: { owner, name }, + }).then( + (result) => onResult(result), + ); +}; + +export default searchPopularForks; From 914c984560870c7ba38d3f76553ed92f7ee19f96 Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Wed, 9 Dec 2020 16:24:01 +0100 Subject: [PATCH 49/60] :recycle: Moves splitUrl to validators.js --- src/components/PopForm.jsx | 2 +- src/utils/search.js | 9 +-------- src/utils/validators.js | 13 ++++++++++++- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/components/PopForm.jsx b/src/components/PopForm.jsx index 5c6f670..0d7b094 100644 --- a/src/components/PopForm.jsx +++ b/src/components/PopForm.jsx @@ -4,7 +4,7 @@ import { Button, Form, FormControl, InputGroup, } from 'react-bootstrap'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import urlMatch from '../utils/validators'; +import { urlMatch } from '../utils/validators'; const SearchIcon = ({ loading }) => ( diff --git a/src/utils/search.js b/src/utils/search.js index 842a8a1..620c50a 100644 --- a/src/utils/search.js +++ b/src/utils/search.js @@ -1,12 +1,5 @@ import { client, GET_FORKS_QUERY } from './graphql'; -import urlMatch from './validators'; - -/** - * Splits URL to owner and repo name. - */ -const splitUrl = (url) => ( - urlMatch(url).slice(1, 3) -); +import { splitUrl } from './validators'; const searchPopularForks = (url, onResult) => { const [owner, name] = splitUrl(url); diff --git a/src/utils/validators.js b/src/utils/validators.js index 78f3a92..96a1698 100644 --- a/src/utils/validators.js +++ b/src/utils/validators.js @@ -1,6 +1,17 @@ const repoRegex = /https?:\/\/github.com\/(\w+)\/(\w+)/; + const urlMatch = (url) => ( url && url.match(repoRegex) ); -export default urlMatch; +/** + * Splits URL to owner and repo name. + */ +const splitUrl = (url) => ( + urlMatch(url).slice(1, 3) +); + +export { + urlMatch, + splitUrl, +}; From 6bf8e0bf2e0bc9039ca571c2fe526666bcec7fde Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Wed, 9 Dec 2020 16:27:32 +0100 Subject: [PATCH 50/60] :white_check_mark: search.test.js --- src/utils/search.test.js | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 src/utils/search.test.js diff --git a/src/utils/search.test.js b/src/utils/search.test.js new file mode 100644 index 0000000..312ad2f --- /dev/null +++ b/src/utils/search.test.js @@ -0,0 +1,28 @@ +import searchPopularForks from './search'; +import { client } from './graphql'; + +test('basic case', (done) => { + const url = 'https://github.com/django/django'; + const expected = { + data: { + repository: { + forks: { + nodes: [], + }, + }, + }, + }; + const onResult = (result) => { + expect(result).toEqual(expected); + done(); + }; + const querySpy = jest.spyOn(client, 'query').mockReturnValue(Promise.resolve(expected)); + expect( + searchPopularForks( + url, onResult, + ), + ); + expect(querySpy).toHaveBeenNthCalledWith( + 1, { query: expect.any(Object), variables: { owner: 'django', name: 'django' } }, + ); +}); From fb652cc70303f332724554fd08b210714c6f22ba Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Wed, 9 Dec 2020 21:56:29 +0100 Subject: [PATCH 51/60] :white_check_mark: Container.test.jsx --- src/components/Container.test.jsx | 57 +++++++++++++++++++ .../__snapshots__/Container.test.jsx.snap | 50 ++++++++++++++++ 2 files changed, 107 insertions(+) create mode 100644 src/components/Container.test.jsx create mode 100644 src/components/__snapshots__/Container.test.jsx.snap diff --git a/src/components/Container.test.jsx b/src/components/Container.test.jsx new file mode 100644 index 0000000..e215d47 --- /dev/null +++ b/src/components/Container.test.jsx @@ -0,0 +1,57 @@ +import React from 'react'; +import { fireEvent, render, screen } from '@testing-library/react'; +import renderer from 'react-test-renderer'; +import { library } from '@fortawesome/fontawesome-svg-core'; +import { fab } from '@fortawesome/free-brands-svg-icons'; +import { fas } from '@fortawesome/free-solid-svg-icons'; +import searchPopularForks from '../utils/search'; +import Container from './Container'; + +library.add(fab, fas); +jest.mock('../utils/search'); + +const forks = [ + { + nameWithOwner: 'django-nonrel/django', + stargazerCount: 214, + forkCount: 84, + pushedAt: '2020-08-29T14:23:26Z', + object: { + history: { + totalCount: 13990, + }, + }, + }, +]; + +const searchResult = { + data: { + repository: { + forks: { + nodes: forks, + }, + }, + }, +}; + +test('renders', () => { + const tree = renderer.create( + , + ).toJSON(); + expect(tree).toMatchSnapshot(); +}); + +test('search forks', (done) => { + render(); + const searchInput = screen.getByPlaceholderText(/github.com/); + const submitButton = screen.getByRole('button', { type: 'submit' }); + const forkId = 'django-nonrel/django'; + searchPopularForks.mockImplementationOnce((url, onResult) => { + onResult(searchResult); + done(); + }); + expect(screen.queryByText(forkId)).toBeNull(); + fireEvent.change(searchInput, { target: { value: 'https://github.com/django/django' } }); + fireEvent.click(submitButton); + expect(screen.queryByText(forkId)).toBeInTheDocument(); +}); diff --git a/src/components/__snapshots__/Container.test.jsx.snap b/src/components/__snapshots__/Container.test.jsx.snap new file mode 100644 index 0000000..d8f28fe --- /dev/null +++ b/src/components/__snapshots__/Container.test.jsx.snap @@ -0,0 +1,50 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`renders 1`] = ` +
+ +
+ +
+ +
+
+ +
+`; From 35314b60a682d594bcda50af51d0775ac3cb153c Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Wed, 9 Dec 2020 22:55:53 +0100 Subject: [PATCH 52/60] :white_check_mark: PopForm.test.jsx --- src/components/PopForm.test.jsx | 15 ++++++ .../__snapshots__/PopForm.test.jsx.snap | 46 +++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 src/components/PopForm.test.jsx create mode 100644 src/components/__snapshots__/PopForm.test.jsx.snap diff --git a/src/components/PopForm.test.jsx b/src/components/PopForm.test.jsx new file mode 100644 index 0000000..ee41fc0 --- /dev/null +++ b/src/components/PopForm.test.jsx @@ -0,0 +1,15 @@ +import React from 'react'; +import renderer from 'react-test-renderer'; +import { library } from '@fortawesome/fontawesome-svg-core'; +import { fas } from '@fortawesome/free-solid-svg-icons'; +import PopForm from './PopForm'; + +library.add(fas); + +test('renders', () => { + const onSubmit = () => ({}); + const tree = renderer.create( + , + ).toJSON(); + expect(tree).toMatchSnapshot(); +}); diff --git a/src/components/__snapshots__/PopForm.test.jsx.snap b/src/components/__snapshots__/PopForm.test.jsx.snap new file mode 100644 index 0000000..0fff14e --- /dev/null +++ b/src/components/__snapshots__/PopForm.test.jsx.snap @@ -0,0 +1,46 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`renders 1`] = ` +
+
+ +
+ +
+
+
+`; From 950d2bff3864c94b1ed35ac113902babf5414057 Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Wed, 9 Dec 2020 23:15:02 +0100 Subject: [PATCH 53/60] :white_check_mark: Increases PopForm.jsx coverage --- src/components/PopForm.test.jsx | 13 +++ .../__snapshots__/PopForm.test.jsx.snap | 90 +++++++++++++++++++ 2 files changed, 103 insertions(+) diff --git a/src/components/PopForm.test.jsx b/src/components/PopForm.test.jsx index ee41fc0..27b1a86 100644 --- a/src/components/PopForm.test.jsx +++ b/src/components/PopForm.test.jsx @@ -13,3 +13,16 @@ test('renders', () => { ).toJSON(); expect(tree).toMatchSnapshot(); }); + +describe.each([ + true, + false, +])("loading='%s'", (loading) => { + test('renders', () => { + const onSubmit = () => ({}); + const tree = renderer.create( + , + ).toJSON(); + expect(tree).toMatchSnapshot(); + }); +}); diff --git a/src/components/__snapshots__/PopForm.test.jsx.snap b/src/components/__snapshots__/PopForm.test.jsx.snap index 0fff14e..6627d7c 100644 --- a/src/components/__snapshots__/PopForm.test.jsx.snap +++ b/src/components/__snapshots__/PopForm.test.jsx.snap @@ -1,5 +1,95 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`loading='false' renders 1`] = ` +
+
+ +
+ +
+
+
+`; + +exports[`loading='true' renders 1`] = ` +
+
+ +
+ +
+
+
+`; + exports[`renders 1`] = `
Date: Wed, 9 Dec 2020 23:30:03 +0100 Subject: [PATCH 54/60] :white_check_mark: Test PopForm.jsx submit --- src/components/PopForm.test.jsx | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/components/PopForm.test.jsx b/src/components/PopForm.test.jsx index 27b1a86..c52a7e7 100644 --- a/src/components/PopForm.test.jsx +++ b/src/components/PopForm.test.jsx @@ -1,5 +1,6 @@ import React from 'react'; import renderer from 'react-test-renderer'; +import { fireEvent, render, screen } from '@testing-library/react'; import { library } from '@fortawesome/fontawesome-svg-core'; import { fas } from '@fortawesome/free-solid-svg-icons'; import PopForm from './PopForm'; @@ -26,3 +27,24 @@ describe.each([ expect(tree).toMatchSnapshot(); }); }); + +test('submit', () => { + const onSubmit = jest.fn(); + render(); + const searchInput = screen.getByPlaceholderText(/github.com/); + const expectedUrl = 'https://github.com/django/django'; + fireEvent.change(searchInput, { target: { value: expectedUrl } }); + const submitButton = screen.getByRole('button', { type: 'submit' }); + // mouse click + fireEvent.click(submitButton); + expect(onSubmit).toHaveBeenNthCalledWith(1, expectedUrl); + // invalid URL should not trigger the submit callback + const invalidUrl = 'https://github.com/invalid-url'; + fireEvent.change(searchInput, { target: { value: invalidUrl } }); + fireEvent.click(submitButton); + expect(onSubmit).toHaveBeenNthCalledWith(1, expectedUrl); + // submit (keyboard Enter) should also be mapped + fireEvent.change(searchInput, { target: { value: expectedUrl } }); + fireEvent.submit(searchInput); + expect(onSubmit).toHaveBeenNthCalledWith(2, expectedUrl); +}); From 30b1f773191f6ac0fd8392daf8805a03720b1be2 Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Thu, 10 Dec 2020 00:16:35 +0100 Subject: [PATCH 55/60] :white_check_mark: Test index.jsx --- src/index.test.jsx | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 src/index.test.jsx diff --git a/src/index.test.jsx b/src/index.test.jsx new file mode 100644 index 0000000..95ab86a --- /dev/null +++ b/src/index.test.jsx @@ -0,0 +1,20 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; +import App from './App'; + +jest.mock('react-dom', () => ({ render: jest.fn() })); + +describe('Application root', () => { + it('renders', () => { + const div = document.createElement('div'); + div.id = 'root'; + document.body.appendChild(div); + require('./index.jsx'); // eslint-disable-line global-require + expect(ReactDOM.render).toHaveBeenCalledWith( + + + , + div, + ); + }); +}); From 719b005da52bda09619a39496974ded0014dd233 Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Thu, 10 Dec 2020 00:24:12 +0100 Subject: [PATCH 56/60] :see_no_evil: Excludes src/reportWebVitals.jsx from coverage --- package.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/package.json b/package.json index 65f1c5f..622f7b9 100644 --- a/package.json +++ b/package.json @@ -39,6 +39,12 @@ "react-app/jest" ] }, + "jest": { + "collectCoverageFrom": [ + "src/**/*.{js,jsx}", + "!src/reportWebVitals.jsx" + ] + }, "browserslist": { "production": [ ">0.2%", From 4c846256513a1ef67fba702af2123fdd0c7a017c Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Thu, 10 Dec 2020 18:18:39 +0100 Subject: [PATCH 57/60] :white_check_mark: graphql.test.jsx --- .github/workflows/tests.yml | 2 ++ src/utils/graphql.js | 5 ++++- src/utils/graphql.test.js | 25 +++++++++++++++++++++++++ 3 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 src/utils/graphql.test.js diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 159463f..9994603 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -11,6 +11,8 @@ jobs: - uses: actions/setup-node@v1 - run: yarn install - run: yarn test + env: + REACT_APP_GITHUB_PAT: ${{ secrets.REACT_APP_GITHUB_PAT }} - run: yarn lint - uses: coverallsapp/github-action@v1.1.2 with: diff --git a/src/utils/graphql.js b/src/utils/graphql.js index 22616ba..f33e9ee 100644 --- a/src/utils/graphql.js +++ b/src/utils/graphql.js @@ -1,3 +1,4 @@ +import assert from 'assert'; import { gql, ApolloClient, createHttpLink, InMemoryCache, } from '@apollo/client'; @@ -15,7 +16,9 @@ const httpLink = createHttpLink({ * Only the `public_repo` scope is required. */ const token = process.env.REACT_APP_GITHUB_PAT ? atob(process.env.REACT_APP_GITHUB_PAT) : null; -// console.assert(token, "REACT_APP_GITHUB_PAT environment variable must be set"); +assert( // eslint-disable-line no-console + token, 'REACT_APP_GITHUB_PAT environment variable must be set', +); const authLink = setContext((_, { headers }) => ({ headers: { diff --git a/src/utils/graphql.test.js b/src/utils/graphql.test.js new file mode 100644 index 0000000..a59146b --- /dev/null +++ b/src/utils/graphql.test.js @@ -0,0 +1,25 @@ +describe('client', () => { + const OLD_ENV = process.env; + + beforeEach(() => { + jest.resetModules(); // most important - it clears the cache + process.env = { ...OLD_ENV }; // make a copy + }); + + afterAll(() => { + process.env = OLD_ENV; // restore old env + }); + + it('REACT_APP_GITHUB_PAT is set OK by default', () => { + const { client } = require('./graphql.js'); // eslint-disable-line global-require + // simply check the client got initialised OK + expect(client.version).toEqual('local'); + }); + + it('handles REACT_APP_GITHUB_PAT environment variable', () => { + delete process.env.REACT_APP_GITHUB_PAT; + expect(() => { + require('./graphql.js'); // eslint-disable-line global-require + }).toThrow('REACT_APP_GITHUB_PAT environment variable must be set'); + }); +}); From 52d01fdb7674c3b4ca6c81aa36cd65ffa37dc0c1 Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Thu, 10 Dec 2020 18:37:54 +0100 Subject: [PATCH 58/60] :white_check_mark: Increases time.test.jsx coverage --- src/utils/time.test.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/utils/time.test.js b/src/utils/time.test.js index 2579ad1..ea40f5e 100644 --- a/src/utils/time.test.js +++ b/src/utils/time.test.js @@ -37,6 +37,16 @@ test('minutes ago', () => { ).toBe('15 minutes ago'); }); +test('hours ago', () => { + expect( + timeSince( + moment( + Date.now(), + ).subtract(6, 'hours').toDate(), + ), + ).toBe('6 hours ago'); +}); + test('days ago', () => { expect( timeSince( From 65858c90df886a461fe78642f378738613287f2e Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Thu, 10 Dec 2020 18:45:23 +0100 Subject: [PATCH 59/60] :fire: Removes dead condition This is already covered by the assert above. --- src/utils/graphql.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/graphql.js b/src/utils/graphql.js index f33e9ee..15004b4 100644 --- a/src/utils/graphql.js +++ b/src/utils/graphql.js @@ -23,7 +23,7 @@ assert( // eslint-disable-line no-console const authLink = setContext((_, { headers }) => ({ headers: { ...headers, - authorization: token ? `Bearer ${token}` : '', + authorization: `Bearer ${token}`, }, })); From 9cb3bd47ab618cc534cc93d2001e07955b369ae5 Mon Sep 17 00:00:00 2001 From: Andre Miras Date: Thu, 10 Dec 2020 20:22:41 +0100 Subject: [PATCH 60/60] :bookmark: 2020.12.10 --- CHANGELOG.md | 4 ++++ package.json | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..28b6775 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,4 @@ +# Change Log + +## [2020.12.10] + - Initial UI release diff --git a/package.json b/package.json index 622f7b9..09d582d 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "gitpop3", "homepage": "https://andremiras.github.io/gitpop3/", - "version": "0.1.0", + "version": "2020.12.10", "private": true, "dependencies": { "@apollo/client": "^3.2.7",