diff --git a/.vscode/settings.json b/.vscode/settings.json index e8783bfe..d6f62461 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,3 @@ -{ - "liveServer.settings.port": 5505 +{ + "liveServer.settings.port": 5505 } \ No newline at end of file diff --git a/README.md b/README.md index 1613a3b0..1e0bc54b 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,19 @@ -# GitHub Tracker - -Replace this readme with your own information about your project. - -Start by briefly describing the assignment in a sentence or two. Keep it short and to the point. - -## The problem - -Describe how you approached to problem, and what tools and techniques you used to solve it. How did you plan? What technologies did you use? If you had more time, what would be next? - -## View it live - -Every project should be deployed somewhere. Be sure to include the link to the deployed project so that the viewer can click around and see what it's all about. +# GitHub Tracker + +This project makes use of Github API. The user can fetch data to view their own or other Technigo students' profile. The project show the user profile information like name, username and location. It can also show the repositories forked from Technigo's Github account. + +Start by briefly describing the assignment in a sentence or two. Keep it short and to the point. + +## The problem + +Data is fetched from [Github's API](https://docs.github.com/en/rest) by fetching through different URLs with different queries necessary to locate the data needed. Data is also filtered by `.filter()` method or `.find()` in order to get only the repositories forked from Technigo and with pull requests done by the user. + +The website has my profile as default but users can search for their own profile. Their repositories from Technigo are the ones that are going to be shown. + +A chart showing the number of Technigo projects and some other information are shown. The chart will be re-rendered every time a new profile is searched. + +I also added a light mode that will turn the background white and the font color dark and readable. Click on the lightbulb to see this. + +## View it live + +[Lousanne's Github Tracker](https://happy-noether-88c607.netlify.app/) diff --git a/code/chart.js b/code/chart.js index 92e85a30..59bd5fa6 100644 --- a/code/chart.js +++ b/code/chart.js @@ -1,4 +1,59 @@ -//DOM-selector for the canvas 👇 -const ctx = document.getElementById('chart').getContext('2d') - -//"Draw" the chart here 👇 +//DOM-selector for the canvas 👇 +const ctx = document.getElementById("chart").getContext("2d"); + +const plugin = { + id: "custom_canvas_background_color", + beforeDraw: (chart) => { + const ctx = chart.canvas.getContext("2d"); + ctx.save(); + ctx.globalCompositeOperation = "destination-over"; + ctx.fillStyle = "rgb(189,219,227)"; + ctx.fillRect(0, 0, chart.width, chart.height); + ctx.restore(); + }, +}; + +//"Draw" the chart here 👇 +const drawChart = (amount) => { + const config = { + type: "polarArea", + data: { + labels: [ + "Finished Projects", + "Projects Left", + "Individual Projects", + "Team Projects", + ], + datasets: [ + { + label: "My First Dataset", + data: [amount, 19 - amount, amount - 4, amount - 2], + backgroundColor: [ + "rgb(255, 99, 132)", + "rgb(75, 192, 192)", + "rgb(247,226,0)", + "rgb(84,81,185)", + ], + }, + ], + }, + options: { + plugins: { + title: { + display: true, + text: "My Github Repositories", + color: "#138", + font: { + size: 25, + }, + }, + }, + responsive: true, + borderColor: "#d32", + color: "#138", + }, + plugins: [plugin], + }; + + const myChart = new Chart(ctx, config); +}; diff --git a/code/images/GitHub-Mark-120px-plus.png b/code/images/GitHub-Mark-120px-plus.png new file mode 100644 index 00000000..ea6ff545 Binary files /dev/null and b/code/images/GitHub-Mark-120px-plus.png differ diff --git a/code/images/GitHub-Mark-32px.png b/code/images/GitHub-Mark-32px.png new file mode 100644 index 00000000..8b25551a Binary files /dev/null and b/code/images/GitHub-Mark-32px.png differ diff --git a/code/images/GitHub-Mark-64px.png b/code/images/GitHub-Mark-64px.png new file mode 100644 index 00000000..182a1a3f Binary files /dev/null and b/code/images/GitHub-Mark-64px.png differ diff --git a/code/images/GitHub-Mark-Light-120px-plus.png b/code/images/GitHub-Mark-Light-120px-plus.png new file mode 100644 index 00000000..192846a1 Binary files /dev/null and b/code/images/GitHub-Mark-Light-120px-plus.png differ diff --git a/code/images/GitHub-Mark-Light-32px.png b/code/images/GitHub-Mark-Light-32px.png new file mode 100644 index 00000000..628da97c Binary files /dev/null and b/code/images/GitHub-Mark-Light-32px.png differ diff --git a/code/images/GitHub-Mark-Light-64px.png b/code/images/GitHub-Mark-Light-64px.png new file mode 100644 index 00000000..73db1f61 Binary files /dev/null and b/code/images/GitHub-Mark-Light-64px.png differ diff --git a/code/images/GitHub_Logo.png b/code/images/GitHub_Logo.png new file mode 100644 index 00000000..e03d8dd8 Binary files /dev/null and b/code/images/GitHub_Logo.png differ diff --git a/code/images/GitHub_Logo_White.png b/code/images/GitHub_Logo_White.png new file mode 100644 index 00000000..c61ab9d0 Binary files /dev/null and b/code/images/GitHub_Logo_White.png differ diff --git a/code/images/book.png b/code/images/book.png new file mode 100644 index 00000000..d91a5869 Binary files /dev/null and b/code/images/book.png differ diff --git a/code/images/menu (1).png b/code/images/menu (1).png new file mode 100644 index 00000000..227404ae Binary files /dev/null and b/code/images/menu (1).png differ diff --git a/code/images/mylogo.png b/code/images/mylogo.png new file mode 100644 index 00000000..a9c44668 Binary files /dev/null and b/code/images/mylogo.png differ diff --git a/code/images/notification.png b/code/images/notification.png new file mode 100644 index 00000000..81c73755 Binary files /dev/null and b/code/images/notification.png differ diff --git a/code/images/pin-map.png b/code/images/pin-map.png new file mode 100644 index 00000000..cd44c00f Binary files /dev/null and b/code/images/pin-map.png differ diff --git a/code/index.html b/code/index.html index 2fb5e0ae..edfc0326 100644 --- a/code/index.html +++ b/code/index.html @@ -1,21 +1,89 @@ - - - - - - - Project GitHub Tracker - - - -

GitHub Tracker

-

Projects:

-
- - - - - - - - \ No newline at end of file + + + + + + + Project GitHub Tracker + + + + + + + + +
+ +
+ + +
+

My Project Repositories with Technigo

+
+
+
+ + +
+ + + + + + + diff --git a/code/script.js b/code/script.js index e69de29b..0fe87d5f 100644 --- a/code/script.js +++ b/code/script.js @@ -0,0 +1,199 @@ +const userContainer = document.getElementById('userInfo'); +const reposContainer = document.getElementById('projects'); +const reposSubContainer = document.getElementById('project-box'); +const navSub = document.getElementById('nav-sub'); +const input = document.getElementById('navInput'); +const inputMobile = document.getElementById('navInputMobile'); +const githubImg = document.getElementById('nav-github-img'); +const turnLightMode = document.getElementById('btn-light'); +const turnLightModeMobile = document.getElementById('btn-light-nav'); + +// for removing previous chart +let chartDrawn = false; + +// shows my profile as default profile upon loading the website +showMyProfileOnLoad = () => { + let userName = 'loulunds'; + getUserData(userName); + fetchRepos(userName); +}; + +window.onload = showMyProfileOnLoad; + +// for getting user data +const getUserData = (user) => { + fetch(`https://api.github.com/users/${user}`) + .then((response) => response.json()) + .then((data) => { + userContainer.innerHTML = ``; + + if (data.login !== undefined) { + userContainer.innerHTML = ` +
+
+ +

${ + data.login + }

+ +

${ + data.name + }

+ +

pin${ + data.location + }

+ +

Member since: ${new Date(data.created_at) + .toDateString() + .slice(4)}

+
+
+ + + +
+ `; + } else { + userContainer.innerHTML = ` +

API rate limit exceeded. Failed to Load. Come back later.

+ `; + } + }) + .catch(() => { + userContainer.innerHTML = `

Sorry, we could not find the information

`; + }); +}; + +// for fetching the repos of the user +const fetchRepos = (user) => { + fetch(`https://api.github.com/users/${user}/repos`) + .then((response) => response.json()) + .then((data) => { + reposSubContainer.innerHTML = ``; + + // filters the repos that are only from Technigo + const forkedRepos = data.filter( + (repo) => repo.fork && repo.name.startsWith('project-') + ); + + // sorts the repos from oldest to newest + forkedRepos.sort((a, b) => { + return new Date(a.pushed_at) - new Date(b.pushed_at); + }); + + forkedRepos.forEach( + (repo) => + (reposSubContainer.innerHTML += ` +
+ +

book + ${repo.name}

+
+ +

Default branch ${ + repo.default_branch + }

+ +

Language: ${repo.language}

+ +

Recent push: ${new Date( + repo.pushed_at + ).toDateString()}

+ +

Commits:

+ +
+ `) + ); + + // renders the chart + if (!chartDrawn) { + drawChart(forkedRepos.length); + chartDrawn = true; + } + getPullRequests(forkedRepos); + }); +}; + +//Get all the PRs for each project. +const getPullRequests = (repos) => { + repos.forEach((repo) => { + fetch( + `https://api.github.com/repos/technigo/${repo.name}/pulls?per_page=100` + ) + .then((res) => res.json()) + .then((data) => { + // filters user's pull requests + const filteredPull = data.find( + (pull) => pull.user.login === repo.owner.login + ); + + if (filteredPull) { + showCommits(filteredPull.commits_url, repo.name); + } else { + document.getElementById(`commit-${repo.name}`).innerHTML = + ' No pull request from me'; + } + }); + }); +}; + +// shows number of commits +const showCommits = (url, myRepoName) => { + fetch(url) + .then((res) => res.json()) + .then((data) => { + document.getElementById(`commit-${myRepoName}`).innerHTML += data.length; + }); +}; + +// event listener +input.addEventListener('keypress', (event) => { + if (event.key === 'Enter' && input.value) { + let userName = ''; + userName = input.value; + getUserData(userName); + fetchRepos(userName); + } +}); + +// for mobile input +inputMobile.addEventListener('keypress', (event) => { + if (event.key === 'Enter' && inputMobile.value) { + let userName = ''; + userName = inputMobile.value; + getUserData(userName); + fetchRepos(userName); + toggleNav(); + } +}); + +// turns the light mode on +const toLightMode = () => { + document.body.classList.toggle('light'); + document.getElementById('userSpan').classList.toggle('user-span-light'); + document.getElementById('userSpanSub').classList.toggle('user-span-light'); +}; + +turnLightMode.addEventListener('click', (e) => { + toLightMode(); +}); + +turnLightModeMobile.addEventListener('click', (e) => { + toLightMode(); +}); + +// toggles the mobile-nav menu + +const toggleNav = () => { + navSub.classList.toggle('active'); +}; + +navSub.addEventListener('click', (e) => { + toggleNav(); +}); diff --git a/code/style.css b/code/style.css index 7c8ad447..f69931c0 100644 --- a/code/style.css +++ b/code/style.css @@ -1,3 +1,364 @@ -body { - background: #FFECE9; -} \ No newline at end of file +@import url('https://fonts.googleapis.com/css2?family=Montserrat:wght@300;400;500&family=Roboto&display=swap'); + +/* resets the default stylings on all elements */ +* { + margin: 0; + padding: 0; + font-family: 'Montserrat', sans-serif; + text-decoration: none; +} + +body { + background-color: rgb(29, 27, 27); + color: rgb(248, 239, 239); + font-weight: 500; +} + +/* light mode */ +.light { + background-color: rgb(248, 239, 239); + color: rgb(29, 27, 27); +} + +/* bec of mobile-first approach */ +.nav-desktop { + display: none; +} + +.nav-links { + display: none; + position: absolute; + top: 0; + width: 70vw; + background-color: rgb(189, 219, 227); + padding: 5rem; +} + +.nav-links > * { + padding: 2vh; + display: flex; + flex-direction: column; + align-items: center; + color: rgb(0, 0, 0, 0.88); + position: relative; +} + +.nav-input { + width: 80%; + margin: 0 auto; +} + +.nav-mobile { + display: grid; + grid-template-columns: 3rem auto 3rem; + grid-template-rows: 3rem; + grid-template-areas: 'menu icon bell'; + grid-gap: 3px; + justify-items: center; + align-items: center; + background-color: rgb(37, 35, 35); +} + +.nav-menu { + grid-area: menu; + height: 2rem; + z-index: 10; +} + +.nav-menu.active { + transform: rotate(90deg); +} + +.nav-menu.active + .nav-links { + display: block; +} + +.nav-icon { + grid-area: icon; + height: 2rem; +} + +.nav-notif { + grid-area: bell; + height: 2rem; +} + +.user-profile-box { + display: grid; + padding: 2rem 0 1rem 0; + align-items: center; + grid-template-columns: 10rem auto; + grid-template-rows: 11rem auto; + grid-template-areas: + 'pic info' + 'pic info' + 'pic info'; +} + +.user-info-box { + color: rgb(46, 107, 129); + grid-area: info; + align-self: end; +} + +/* !important overrules the #userSpan styling */ +/* for toggle */ +.user-span-light { + color: rgb(29, 27, 27) !important; +} + +#userSpan { + color: rgb(248, 239, 239); +} + +.user-img-box { + grid-area: pic; + justify-content: center; + align-items: center; +} + +.user-username { + font-size: 1.5rem; +} + +.user-fullname { + font-size: 1rem; +} + +.user-location { + font-size: 0.8rem; +} + +.user-pin-img { + height: 1rem !important; + padding-right: 0.5rem; +} + +.user-join { + font-size: 1rem; + padding-top: 0.2rem; +} + +/* rainbow border 😍 */ +.user-img { + margin-left: 0.7rem; + height: 8rem !important; + justify-self: center; + border: double 0.4em transparent; + border-radius: 50%; + background-image: linear-gradient(white, white), + linear-gradient( + 0deg, + rgba(251, 38, 38, 1) 0%, + rgba(252, 157, 51, 1) 14%, + rgba(253, 253, 66, 1) 30%, + rgba(165, 253, 78, 1) 41%, + rgba(84, 238, 230, 1) 49%, + rgba(111, 125, 221, 1) 61%, + rgba(180, 126, 206, 1) 71%, + rgba(208, 127, 204, 1) 89%, + rgba(255, 130, 130, 1) 100% + ); + background-origin: border-box; + background-clip: content-box, border-box; +} + +#projects { + padding: 1rem 0 0.8rem 0; +} + +.project-title { + font-size: 1.3rem; + padding-left: 1rem; +} + +.project-box { + display: grid; + grid-template-columns: 1fr; + grid-template-rows: auto; +} + +.repo-box { + border: 1px solid rgb(97, 97, 97); + border-radius: 0.5rem; + align-items: center; + margin: 1rem 1rem; + padding: 0.3rem 1.3rem; +} + +/* sets padding to all children of .repo-box */ +.repo-box > * { + padding: 0.2rem 0; +} + +.repo-book-img { + height: 1rem !important; + padding-right: 0.5rem; +} + +.repo-name { + text-transform: uppercase; + padding: 0.3rem; + color: rgb(54, 162, 255); +} + +.repo-name:hover { + color: rgb(127, 208, 145); +} + +.repo-branch { + color: rgb(46, 107, 129); + font-weight: 500; +} + +.repo-language { + color: rgba(180, 126, 206, 1); +} + +.repo-date { + color: rgb(66, 128, 179); +} + +.repo-commit { + color: rgb(65 147 142); + padding-right: 0.5rem; +} + +footer { + height: 8rem; + background-color: rgb(189, 219, 227); + display: flex; + justify-content: center; + width: 100%; +} + +footer img { + height: 8rem; +} + +.canvas-box { + padding-bottom: 2rem; +} + +#btn-light-nav { + background-color: rgb(37, 35, 35); +} + +#btn-light-nav:hover { + background-color: rgb(175, 170, 170); +} + +.error-message { + text-align: center; + font-size: 2rem; + margin: 2rem; +} + +@media (min-width: 768px) { + .nav-mobile { + display: none; + } + + .nav-desktop { + display: grid; + align-items: center; + background-color: rgb(37, 35, 35); + grid-template-columns: 3rem 16rem auto 3rem; + grid-template-rows: 3rem; + grid-template-areas: 'icon input a bell'; + padding: 0 1rem 0 1rem; + } + + .nav-icon { + grid-area: icon; + } + + .nav-input { + grid-area: input; + width: 14rem; + padding-left: 0.5rem; + } + + .nav-a { + grid-area: a; + display: flex; + justify-content: space-around; + } + + .nav-a > * { + color: rgb(161, 118, 231); + } + + .nav-a > *:hover { + color: rgb(54, 162, 255); + } + + .nav-notif { + grid-area: bell; + } + + #btn-light { + background-color: rgb(37, 35, 35); + } + + #btn-light:hover { + background-color: rgb(175, 170, 170); + } + + /* sets two major columns for the contents */ + main { + display: grid; + justify-items: center; + grid-template-columns: 15rem auto; + grid-template-rows: auto; + grid-template-areas: 'info projects'; + } + + #userInfo { + grid-area: info; + } + + #projects { + grid-area: projects; + } + + .project-title { + padding: 2rem 0 2rem 1rem; + } + + .user-profile-box { + display: grid; + justify-items: center; + padding: 5rem 0 1rem 1rem; + align-items: center; + grid-template-columns: 1fr; + grid-template-rows: 2.5fr 1fr; + grid-template-areas: + 'pic' + 'info'; + } + + .user-info-box { + padding-left: 2rem; + } + + #project-box { + display: grid; + grid-template-columns: 1fr 1fr; + grid-template-rows: auto; + padding-bottom: 2rem; + } +} + +@media (min-width: 1281px) { + body { + max-width: 60vw; + margin: 0 auto; + } + + .canvas-box { + max-width: 40vw; + margin: 0 auto; + padding-bottom: 2rem; + } +}