diff --git a/Week1/homework/HackYourRepo/index.js b/Week1/homework/HackYourRepo/index.js index 826dff669..46be930c6 100644 --- a/Week1/homework/HackYourRepo/index.js +++ b/Week1/homework/HackYourRepo/index.js @@ -12,7 +12,7 @@ cb(new Error(`Network error: ${xhr.status} - ${xhr.statusText}`)); } }; - xhr.onerror = () => cb(new Error('Network request failed')); + xhr.onerror = () => cb(new Error('Network request faileddddd')); xhr.send(); } diff --git a/Week2/homework/HackYourRepo2/index.js b/Week2/homework/HackYourRepo2/index.js index 42c45c3dc..3e609ddbe 100644 --- a/Week2/homework/HackYourRepo2/index.js +++ b/Week2/homework/HackYourRepo2/index.js @@ -21,7 +21,12 @@ 'Content-Type': 'application/json', } }) - .then((response) => response.json()) + .then((response) => { + if (!response.ok) { + throw response + } + return response.json() + }) .then((data) => { cb(null, data); }) @@ -212,4 +217,4 @@ const HYF_REPOS_URL = 'https://api.github.com/orgs/HackYourFuture/repos?per_page=100'; window.onload = () => main(HYF_REPOS_URL); -} \ No newline at end of file +} diff --git a/Week3/homework/HackYourRepo2/hyf.png b/Week3/homework/HackYourRepo2/hyf.png new file mode 100644 index 000000000..76bc5a13b Binary files /dev/null and b/Week3/homework/HackYourRepo2/hyf.png differ diff --git a/Week3/homework/HackYourRepo2/index.html b/Week3/homework/HackYourRepo2/index.html new file mode 100644 index 000000000..ded633180 --- /dev/null +++ b/Week3/homework/HackYourRepo2/index.html @@ -0,0 +1,24 @@ + + + + + + + + + + + + + HYF-GITHUB + + + + + +
+ + + + + \ No newline at end of file diff --git a/Week3/homework/HackYourRepo2/index.js b/Week3/homework/HackYourRepo2/index.js new file mode 100644 index 000000000..b54a0d265 --- /dev/null +++ b/Week3/homework/HackYourRepo2/index.js @@ -0,0 +1,250 @@ +'use strict'; + +{ + async function fetchJSON(url, cb) { + // const xhr = new XMLHttpRequest(); + // xhr.open('GET', url); + // xhr.responseType = 'json'; + // xhr.onload = () => { + // if (xhr.status >= 200 && xhr.status <= 299) { + // cb(null, xhr.response); + // } else { + // cb(new Error(`Network error: ${xhr.status} - ${xhr.statusText}`)); + // } + // }; + // xhr.onerror = () => cb(new Error('Network request failed')); + // xhr.send(); + + // With fetch() + // fetch(url, { + // method: 'GET', + // headers: { + // 'Content-Type': 'application/json', + // } + // }) + // .then((response) => { + // if (!response.ok) { + // throw response + // } + // return response.json() + // }) + // .then((data) => { + // cb(null, data); + // }) + // .catch((err) => { + // cb(new Error('Network request failed')); + // }); + + /// With Axios + // const axios = require('axios'); + // axios.get(url) + // .then(function (response) { + // if (response.status !== 200) { + // throw response + // } + // return response.data + // }) + // .then(function (data) { + // cb(null, data); + // }) + // .catch(function (error) { + // cb(new Error('Network request failed')); + // }); + + + // With axios async await + try { + const response = await axios.get(url) + if (response.status !== 200) { + throw response + } + const data = response.data; + cb(null, data); + } catch (error) { + cb(new Error('Network request failed')); + } + } + + function createAndAppend(name, parent, options = {}) { + const elem = document.createElement(name); + parent.appendChild(elem); + Object.entries(options).forEach(([key, value]) => { + if (key === 'text') { + elem.innerHTML = value; + } else { + elem.setAttribute(key, value); + } + }); + return elem; + } + + // Fix the format of the date + const fixFormatDate = (myDate) => { + let [date, time] = myDate.split('T'); + let [year, month, day] = date.split('-'); + let [timeClean] = time.split('Z'); + let [hour, minutes, seconds] = timeClean.split(':'); + if (hour > 12) { + hour = hour - 12; + var time_ind = 'PM'; + } else { + var time_ind = 'AM'; + } + let fixedDate = `${day}/${month}/${year}, ${hour}:${minutes}:${seconds} ${time_ind}`; + + return fixedDate; + } + + + function renderRepoDetails(repo, ul) { + + createAndAppend('li', ul, { + text: `Repository: ${repo.name}
Description: ${repo.description}
Forks: ${repo.forks}
Updated: ${fixFormatDate(repo.updated_at)}`, + style: `padding: 1.5rem` + }); + } + + + // Sort the arrays, eg. repos + const sortArrayAlpha = (array) => { + let sortedArray = array.sort(function (a, b) { + let textA = a.name.toUpperCase(); + let textB = b.name.toUpperCase(); + return (textA < textB) ? -1 : (textA > textB) ? 1 : 0; + }); + return sortedArray; + } + + // Load the contributors container + const loadContributors = (url) => { + fetchJSON(url, (err, contributors) => { + contributors_container.innerHTML = ''; + + createAndAppend('h3', contributors_container, { + id: 'contributors__title', + text: 'Contributions' + }); + var contributorsList = createAndAppend('ul', contributors_container, { + id: 'contributors__list' + }); + + if (contributors) { + contributors.forEach(contributor => { + const contributorElem = createAndAppend('li', contributorsList, { + class: 'contributor__element' + }); + const nameImgElem = createAndAppend('div', contributorElem, { + class: 'contributor__name-container' + }) + createAndAppend('img', nameImgElem, { + class: 'contributor__image', + src: contributor.avatar_url, + style: 'height: 50px; width:50px' + }); + createAndAppend('a', nameImgElem, { + text: contributor.login, + href: contributor.html_url + }); + createAndAppend('div', contributorElem, { + text: contributor.contributions, + class: 'contributions__count' + }) + }); + } + + + if (err) { + createAndAppend('li', contributorsList, { + text: `Network Request Failed`, + class: 'alert-error', + }); + return; + } + }); + } + + + function main(url) { + + fetchJSON(url, (err, repos) => { + const root = document.getElementById('root'); + + // CREATE THE HEADER + const hyfElem = createAndAppend('div', root, { + text: `HYF Repositories`, + style: `padding: 1.5rem; color: white; background-color: #4567d8`, + id: 'hyf__header' + }); + + const data_container = createAndAppend('div', root, { + id: 'data__container' + }) + + const list_container = createAndAppend('div', data_container, { + id: 'list__container' + }); + const ul = createAndAppend('ul', list_container); + + if (repos) { + // Sort the repos array + let sortRepos = sortArrayAlpha(repos); + + // Create the SELECT item + const selectElem = createAndAppend('select', hyfElem, { + name: 'repos', + id: 'repos__select' + }) + + sortRepos.forEach(repo => { + createAndAppend('option', selectElem, { + text: repo.name, + value: repo.name + }); + }); + + + renderRepoDetails(sortRepos[0], ul); + + const contributors_container = createAndAppend('div', data_container, { + id: 'contributors_container' + }) + + loadContributors(sortRepos[0].contributors_url); + + // Make the repos have only specific number of items eg. 10 + const sizeRepos = (num) => { + const reposSized = []; + for (let i = 0; i < num; i++) { + reposSized.push(sortRepos[i]); + } + return reposSized; + } + + selectElem.addEventListener('change', e => { + ul.innerHTML = ''; + sortRepos.forEach(repo => { + if (repo.name === e.target.value) { + renderRepoDetails(repo, ul); + loadContributors(repo.contributors_url); + } + }); + }) + } + + + if (err) { + createAndAppend('li', ul, { + text: `Network Request Failed`, + class: 'alert-error', + }); + return; + } + + // sizeRepos(10).forEach(repo => renderRepoDetails(repo, ul)); + }); + } + + const HYF_REPOS_URL = + 'https://api.github.com/orgs/HackYourFuture/repos?per_page=100'; + window.onload = () => main(HYF_REPOS_URL); +} \ No newline at end of file diff --git a/Week3/homework/HackYourRepo2/style.css b/Week3/homework/HackYourRepo2/style.css new file mode 100644 index 000000000..c5c071148 --- /dev/null +++ b/Week3/homework/HackYourRepo2/style.css @@ -0,0 +1,99 @@ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +.alert-error { + color: #A62C23; + background-color: #FADADD; + border-radius: 5px; + padding: 1rem; + font-size: 1.25rem; +} + +ul { + list-style: none; +} + +li { + margin: 0.2rem; + line-height: 2rem; + font-size: 1.25rem; + border-radius: 3px; + box-shadow: 10px 5px 5px gray; +} + +#hyf__header { + margin: 0.5rem; + line-height: 2rem; + font-size: 1.25rem; + border-radius: 3px; + box-shadow: 10px 5px 5px gray; +} + +#repos__select { + margin: 1rem; + font-size: 1rem; + border-radius: 3px; +} + +#list__container { + display: inline-block; + width: 49%; +} + +#contributors_container { + display: inline-block; + width: 49%; +} + +#contributors__title { + text-align: center; + margin: 1.5rem 0 0.5rem 0; +} + +.contributor__image { + margin: 0.5rem; + border-radius: 2px; +} + +#data__container { + width: 100%; + display: flex; + align-items: flex-start; +} + +.contributor__element { + padding: 2rem; + width: 100%; + display: flex; + align-items: center; + justify-content: space-between; +} + +.contributions__count { + justify-self: flex-end; + text-align: center; + width: 2rem; + color: white; + background: #4567d8; + border-radius: 5px; +} + +.contributor__name-container { + display: flex; + align-items: center; +} + +@media (max-width: 200px) { + .updated { + display: none; + } +} + +@media (max-width: 400px) { + .description { + display: none; + } +} \ No newline at end of file diff --git a/homework-classes/.vscode/settings.json b/homework-classes/.vscode/settings.json new file mode 100644 index 000000000..1889d99ba --- /dev/null +++ b/homework-classes/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "cSpell.ignoreWords": [ + "repos" + ] +} \ No newline at end of file diff --git a/homework-classes/App.js b/homework-classes/App.js index 8788f8b85..4c43dce6f 100755 --- a/homework-classes/App.js +++ b/homework-classes/App.js @@ -21,7 +21,7 @@ class App { constructor(account) { - const containers = App.renderContainers(); + const containers = App.renderContainers(account); const model = new Model(account); const fetchData = model.fetchData.bind(model); @@ -34,14 +34,14 @@ fetchData(); } - static renderContainers() { + static renderContainers(account) { const root = document.getElementById('root'); - const header = createAndAppend('header', root, { class: 'header' }); + const header = createAndAppend('div', root, { class: 'header', text: account.name, id: 'hyf__header' }); const error = createAndAppend('div', root); - const main = createAndAppend('main', root, { + const main = createAndAppend('div', root, { class: 'main-container', }); - const repo = createAndAppend('section', main, { + const repo = createAndAppend('ul', main, { class: 'repo-container whiteframe', }); const contributors = createAndAppend('section', main, { diff --git a/homework-classes/ContributorsView.js b/homework-classes/ContributorsView.js index 58cb2b984..f58278c08 100755 --- a/homework-classes/ContributorsView.js +++ b/homework-classes/ContributorsView.js @@ -20,7 +20,39 @@ */ render(contributors) { // TODO: replace this comment and the console.log with your own code - console.log('ContributorsView', contributors); + this.container.innerHTML = ''; + + createAndAppend('h3', this.container, { + id: 'contributors__title', + text: 'Contributions' + }); + + const contributorsList = createAndAppend('ul', this.container, { + id: 'contributors__list' + }); + + contributors.forEach(contributor => { + const contributorElem = createAndAppend('li', contributorsList, { + class: 'contributor__element' + }); + const nameImgElem = createAndAppend('div', contributorElem, { + class: 'contributor__name-container' + }) + createAndAppend('img', nameImgElem, { + class: 'contributor__image', + src: contributor.avatar_url, + style: 'height: 50px; width:50px' + }); + createAndAppend('a', nameImgElem, { + text: contributor.login, + href: contributor.html_url + }); + createAndAppend('div', contributorElem, { + text: contributor.contributions, + class: 'contributions__count' + }) + }); + // console.log('ContributorsView', contributors); } } diff --git a/homework-classes/HeaderView.js b/homework-classes/HeaderView.js index 11f9c8971..767f918a5 100755 --- a/homework-classes/HeaderView.js +++ b/homework-classes/HeaderView.js @@ -23,7 +23,7 @@ * @param {Object[]} repos An array of repository objects. */ render(repos) { - createAndAppend('div', this.header, { text: this.account.name }); + // createAndAppend('div', this.header, { text: this.account.name, id: 'hyf__header' }); this.select = createAndAppend('select', this.header, { class: 'repo-select', autofocus: 'autofocus', diff --git a/homework-classes/Model.js b/homework-classes/Model.js index 25884a133..036a4c87b 100755 --- a/homework-classes/Model.js +++ b/homework-classes/Model.js @@ -21,6 +21,7 @@ async fetchData(id) { const repoId = parseInt(id, 10); this.state.error = null; + try { if (this.state.repos.length === 0) { const repos = await Model.fetchJSON(makeUrl(this.account)); diff --git a/homework-classes/RepoView.js b/homework-classes/RepoView.js index 073166fea..cc00a245a 100755 --- a/homework-classes/RepoView.js +++ b/homework-classes/RepoView.js @@ -20,7 +20,56 @@ */ render(repo) { // TODO: replace this comment and the console.log with your own code - console.log('RepoView', repo); + this.container.innerHTML = ''; + + // Fix the format of the date + const fixFormatDate = (myDate) => { + let [date, time] = myDate.split('T'); + let [year, month, day] = date.split('-'); + let [timeClean] = time.split('Z'); + let [hour, minutes, seconds] = timeClean.split(':'); + if (hour > 12) { + hour = hour - 12; + var time_ind = 'PM'; + } else { + var time_ind = 'AM'; + } + let fixedDate = `${day}/${month}/${year}, ${hour}:${minutes}:${seconds} ${time_ind}`; + + return fixedDate; + } + + + function renderRepoDetails(repo, ul) { + + createAndAppend('li', ul, { + text: `Repository: ${repo.name}
Description: ${repo.description}
Forks: ${repo.forks}
Updated: ${fixFormatDate(repo.updated_at)}`, + style: `padding: 1.5rem` + }); + } + + // const data_container = createAndAppend('div', root, { + // id: 'data__container' + // }) + + const list_container = createAndAppend('div', this.container, { + id: 'list__container' + }); + const ul = createAndAppend('ul', list_container); + + + renderRepoDetails(repo, ul); + + // selectElem.addEventListener('change', e => { + // ul.innerHTML = ''; + // sortRepos.forEach(repo => { + // if (repo.name === e.target.value) { + // renderRepoDetails(repo, ul); + // loadContributors(repo.contributors_url); + // } + // }); + // }) + // console.log('RepoView', repo); } } diff --git a/homework-classes/Util.js b/homework-classes/Util.js index dc5d79a87..5833ad081 100755 --- a/homework-classes/Util.js +++ b/homework-classes/Util.js @@ -14,7 +14,7 @@ parent.appendChild(elem); Object.entries(options).forEach(([key, value]) => { if (key === 'text') { - elem.textContent = value; + elem.innerHTML = value; } else { elem.setAttribute(key, value); } diff --git a/homework-classes/style.css b/homework-classes/style.css index 90d106051..03518d057 100755 --- a/homework-classes/style.css +++ b/homework-classes/style.css @@ -1,3 +1,124 @@ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + .alert-error { - color: red; + color: #A62C23; + background-color: #FADADD; + border-radius: 5px; + padding: 1rem; + font-size: 1.25rem; +} + +ul { + list-style: none; +} + +li { + margin: 0.2rem; + line-height: 2rem; + font-size: 1.25rem; + border-radius: 3px; + box-shadow: 10px 5px 5px gray; +} + +#hyf__header { + /* display: inline-block; */ + font-size: 1.25rem; + padding: 1.5rem; + line-height: 2rem; + color: white; + background-color: #4567d8; + margin: 0.5rem; + border-radius: 3px; + box-shadow: 10px 5px 5px gray; +} + +#root { + display: flex; + flex-direction: column; +} + +.header { + /* display: flex; + color: white; + background-color: #842BD7; + margin: 0.5rem; + border-radius: 3px; + box-shadow: 10px 5px 5px gray; */ +} + +.repo-select { + /* display: inline-block; */ + margin: 1rem; + font-size: 1rem; + border-radius: 3px; +} + +.repo-container { + display: inline-block; + width: 49%; +} + +.contributors-container { + display: inline-block; + width: 49%; +} + +#contributors__title { + text-align: center; + margin: 1.5rem 0 0.5rem 0; +} + +.contributor__image { + margin: 0.5rem; + border-radius: 2px; +} + +#data__container { + width: 100%; + display: flex; + align-items: flex-start; +} + +.main-container { + width: 100%; + display: flex; + align-items: flex-start; +} + +.contributor__element { + padding: 2rem; + width: 100%; + display: flex; + align-items: center; + justify-content: space-between; +} + +.contributions__count { + justify-self: flex-end; + text-align: center; + width: 2rem; + color: white; + background: #4567d8; + border-radius: 5px; +} + +.contributor__name-container { + display: flex; + align-items: center; +} + +@media (max-width: 200px) { + .updated { + display: none; + } } + +@media (max-width: 400px) { + .description { + display: none; + } +} \ No newline at end of file