🐙 GitHub (#13)

* edit package.json

* eslint

* fetch git repos

* create repo array on fetch

* update repo array on profile edit

* edit profile presentation
This commit is contained in:
Ruidy 2020-05-20 18:12:25 +02:00 committed by GitHub
parent 4880d2853d
commit 191130a7ad
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 944 additions and 633 deletions

6
.eslintignore Normal file
View file

@ -0,0 +1,6 @@
# don't ever lint node_modules
node_modules
# don't lint build output (make sure it's set to your correct build folder name)
build
# don't lint nyc coverage output
coverage

View file

@ -1,19 +1,79 @@
module.exports = {
extends: ["react-app", "prettier"],
plugins: ["prettier", "jest", "cypress"],
parser: "babel-eslint",
extends: [
'react-app',
'prettier',
'eslint:recommended',
'plugin:@typescript-eslint/eslint-recommended',
'plugin:@typescript-eslint/recommended',
'airbnb-typescript',
],
plugins: ['prettier', 'jest', 'cypress', '@typescript-eslint'],
// parser: 'babel-eslint',
parser: '@typescript-eslint/parser',
parserOptions: {
project: './tsconfig.json',
},
env: {
browser: true,
"cypress/globals": true,
'cypress/globals': true,
es6: true,
"jest/globals": true,
'jest/globals': true,
},
settings: {
react: {
version: "detect",
version: 'detect',
},
},
rules: {
"prettier/prettier": "warn",
'prettier/prettier': 'warn',
'adjacent-overload-signatures': true,
'ban-comma-operator': true,
'no-namespace': true,
'no-parameter-reassignment': true,
'no-reference': true,
'no-unnecessary-type-assertion': true,
'label-position': true,
'no-conditional-assignment': true,
'no-construct': true,
'no-duplicate-super': true,
'no-duplicate-switch-case': true,
'no-duplicate-variable': [true, 'check-parameters'],
'no-shadowed-variable': true,
'no-empty': [true, 'allow-empty-catch'],
'no-floating-promises': true,
'no-implicit-dependencies': true,
'no-invalid-this': true,
'no-string-throw': true,
'no-unsafe-finally': true,
'no-void-expression': [true, 'ignore-arrow-function-shorthand'],
'no-duplicate-imports': true,
// Warn when an empty interface is defined. These are generally not useful.
'no-empty-interface': {
severity: 'warning',
},
'no-import-side-effect': {
severity: 'warning',
},
'no-var-keyword': {
severity: 'warning',
},
'triple-equals': {
severity: 'warning',
},
deprecation: {
severity: 'warning',
},
'prefer-for-of': {
severity: 'warning',
},
'unified-signatures': {
severity: 'warning',
},
'prefer-const': {
severity: 'warning',
},
'trailing-comma': {
severity: 'warning',
},
},
};

View file

@ -1,6 +1,6 @@
{
"name": "client",
"version": "0.1.0",
"name": "devbook",
"version": "1.0.0",
"private": true,
"dependencies": {
"@fortawesome/fontawesome-free": "^5.13.0",
@ -9,6 +9,7 @@
"@fortawesome/free-regular-svg-icons": "^5.13.0",
"@fortawesome/free-solid-svg-icons": "^5.13.0",
"@fortawesome/react-fontawesome": "^0.1.9",
"@octokit/rest": "^17.9.2",
"@reduxjs/toolkit": "^1.3.6",
"@testing-library/jest-dom": "^4.2.4",
"@testing-library/react": "^9.3.2",
@ -19,7 +20,13 @@
"@types/react-dom": "^16.9.0",
"@types/react-redux": "^7.1.8",
"@types/react-router-dom": "^5.1.5",
"@typescript-eslint/eslint-plugin": "^2.34.0",
"@typescript-eslint/parser": "^2.34.0",
"cypress": "^4.5.0",
"eslint-plugin-import": "^2.20.2",
"eslint-plugin-jsx-a11y": "^6.2.3",
"eslint-plugin-react": "^7.20.0",
"eslint-plugin-react-hooks": "^4.0.2",
"firebase": "^7.14.3",
"moment": "^2.25.3",
"react": "^16.13.1",
@ -54,4 +61,4 @@
"last 1 safari version"
]
}
}
}

View file

@ -128,7 +128,7 @@ export const dummyDev: IDev = {
name: 'Repo #1',
description:
'Lorem ipsum dolor sit amet consectetur adipisicing elit. Fugit,deserunt.',
link: '#',
url: '#',
stars: 42,
watchers: 2,
forks: 4,
@ -137,7 +137,7 @@ export const dummyDev: IDev = {
name: 'Repo #2',
description:
'Lorem ipsum dolor sit amet consectetur adipisicing elit. Fugit,deserunt.',
link: '#',
url: '#',
stars: 21,
watchers: 1,
forks: 2,
@ -146,7 +146,7 @@ export const dummyDev: IDev = {
name: 'Repo #3',
description:
'Lorem ipsum dolor sit amet consectetur adipisicing elit. Fugit,deserunt.',
link: '#',
url: '#',
stars: 50,
watchers: 32,
forks: 12,

View file

@ -18,6 +18,7 @@ import Alert from '../components/Alert';
import Statuses from '../constants/statuses';
// Form
import useForm from '../hooks';
import getGithubRepos from '../services/github';
// Typing
import Dev from '../models/Dev';
import User from '../models/User';
@ -75,7 +76,7 @@ const EditProfile: FC<IProps> = ({
const {formData, handleChange} = useForm<FormData>(initFormData);
/** construct profile object from formData */
const makeProfile = ({
const makeProfile = async ({
status,
company,
location,
@ -99,6 +100,7 @@ const EditProfile: FC<IProps> = ({
youtube: parseLink(youtube),
};
const newSkills: string[] = skills?.split(',');
const newRepos = await getGithubRepos(github);
return {
status,
company,
@ -107,12 +109,13 @@ const EditProfile: FC<IProps> = ({
github,
links: newLinks,
skills: newSkills,
repos: newRepos,
};
};
const handleSubmit = (e: React.FormEvent<HTMLFormElement>): void => {
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
const updatedDev = makeProfile(formData);
const updatedDev = await makeProfile(formData);
try {
firebase.updateProfile(updatedDev, {useSet: true, merge: true});
setAlert({
@ -122,6 +125,7 @@ const EditProfile: FC<IProps> = ({
'Profile successfully updated. You may go back to your dashboard.',
});
} catch (err) {
console.error(err);
setAlert({...alert, show: true});
}
};

View file

@ -13,7 +13,7 @@ import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
import {faThumbsUp} from '@fortawesome/free-solid-svg-icons';
import Header from '../components/Header';
// Typing
import Post, {dummyPost as post} from '../models/Post';
import Post from '../models/Post';
import Collections from '../constants/collections';
interface IProps extends WithFirestoreProps {

View file

@ -46,9 +46,6 @@ const Profile: FC<IProps> = ({dev}) => {
return <NotFound />;
}
const fn = dev?.description;
console.log(fn);
/** return the icon corresponding to the social name */
const renderSocialIcon = (name: string): IconDefinition => {
switch (name) {
@ -192,23 +189,23 @@ const Profile: FC<IProps> = ({dev}) => {
</div>
) : (
dev.repos.map((r: Repo, i: number) => (
<div className="repo bg-white my-1 p-1">
<div className="repo bg-white my-1 p-1" key={i}>
<div>
<h4>
<a href={r.link}>{r.name}</a>
<a href={r.url}>{r.name}</a>
</h4>
<p>{r.description}</p>
</div>
<div>
<ul>
<li className="badge badge-primary">
<FontAwesomeIcon icon={faStar} /> Stars: 42
<FontAwesomeIcon icon={faStar} /> Stars: {r.stars}
</li>
<li className="badge badge-dark">
<FontAwesomeIcon icon={faEye} /> Watchers: 2
<FontAwesomeIcon icon={faEye} /> Watchers: {r.watchers}
</li>
<li className="badge badge-light">
<FontAwesomeIcon icon={faCodeBranch} /> Forks: 4
<FontAwesomeIcon icon={faCodeBranch} /> Forks: {r.forks}
</li>
</ul>
</div>

View file

@ -0,0 +1,35 @@
// Github
import {Octokit} from '@octokit/rest';
import Repo from '../../types/Repo';
/** official GitHub wrapper library */
const octokit = new Octokit({
auth: process.env.REACT_APP_GITHUB_TOKEN,
userAgent: 'devBook v1',
});
/**
* fetch one user github repos and create a
* @param owner githubusername
* @returns a Repo array or undefined
*/
const getGithubRepos = async (owner: string) => {
try {
const {data: repos} = await octokit.repos.listForAuthenticatedUser({
owner,
});
const newRepo: Repo[] = repos.map((r: any) => ({
url: r.url,
stars: r.stargazers_count,
forks: r.forks_count,
description: r.description,
name: r.name,
watchers: r.watchers_count,
}));
return newRepo;
} catch (err) {
console.error(err);
}
};
export default getGithubRepos;

View file

@ -1,7 +1,7 @@
interface Repo {
name: string;
description: string;
link: string;
url: string;
stars: number;
watchers: number;
forks: number;

View file

@ -1,11 +1,7 @@
{
"compilerOptions": {
"target": "es5",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"target": "es2017",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
@ -19,7 +15,5 @@
"noEmit": true,
"jsx": "react"
},
"include": [
"src"
]
"include": ["src"]
}

View file

@ -1,63 +0,0 @@
{
"rules": {
"adjacent-overload-signatures": true,
"ban-comma-operator": true,
"no-namespace": true,
"no-parameter-reassignment": true,
"no-reference": true,
"no-unnecessary-type-assertion": true,
"label-position": true,
"no-conditional-assignment": true,
"no-construct": true,
"no-duplicate-super": true,
"no-duplicate-switch-case": true,
"no-duplicate-variable": [
true,
"check-parameters"
],
"no-shadowed-variable": true,
"no-empty": [
true,
"allow-empty-catch"
],
"no-floating-promises": true,
"no-implicit-dependencies": true,
"no-invalid-this": true,
"no-string-throw": true,
"no-unsafe-finally": true,
"no-void-expression": [
true,
"ignore-arrow-function-shorthand"
],
"no-duplicate-imports": true,
// Warn when an empty interface is defined. These are generally not useful.
"no-empty-interface": {
"severity": "warning"
},
"no-import-side-effect": {
"severity": "warning"
},
"no-var-keyword": {
"severity": "warning"
},
"triple-equals": {
"severity": "warning"
},
"deprecation": {
"severity": "warning"
},
"prefer-for-of": {
"severity": "warning"
},
"unified-signatures": {
"severity": "warning"
},
"prefer-const": {
"severity": "warning"
},
"trailing-comma": {
"severity": "warning"
}
},
"defaultSeverity": "error"
}

1341
yarn.lock

File diff suppressed because it is too large Load diff