diff --git a/homework/src/index.js b/homework/src/index.js index f0a3a2f06..6dcd9dcc1 100644 --- a/homework/src/index.js +++ b/homework/src/index.js @@ -1,47 +1,111 @@ -'use strict'; +"use strict"; + +function main(url) { + + const root = document.getElementById("root"); + const header = createEl("header", root); + const article = createEl("article", root); + createEl("label", header, { txt: "HYF Repositories" }); + const select = createEl("select", header); -{ function fetchJSON(url, cb) { const xhr = new XMLHttpRequest(); xhr.open('GET', url); xhr.responseType = 'json'; xhr.onload = () => { - if (xhr.status < 400) { + if (xhr.status === 200) { cb(null, xhr.response); } else { - cb(new Error(`Network error: ${xhr.status} - ${xhr.statusText}`)); + cb(new Error(`Network Error: ${xhr.status} - ${xhr.statusText}`)); } }; - xhr.onerror = () => cb(new Error('Network request failed')); + xhr.onerror = () => { + cb(new Error(`Network request failed`)); + }; xhr.send(); } - function createAndAppend(name, parent, options = {}) { + function createEl(name, parent, options = {}) { const elem = document.createElement(name); parent.appendChild(elem); - Object.keys(options).forEach((key) => { - const value = options[key]; - if (key === 'text') { - elem.innerText = value; + for (let key in options) { + if (key === "txt") { + elem.innerText = options.txt; } else { - elem.setAttribute(key, value); + elem.setAttribute(key, options[key]); } - }); + } return elem; } - function main(url) { - fetchJSON(url, (err, data) => { - const root = document.getElementById('root'); - if (err) { - createAndAppend('div', root, { text: err.message, class: 'alert-error' }); + fetchJSON(url, (err, repos) => { + if (err === null) { + repos.sort((a, b) => a.name.localeCompare(b.name)) + .forEach((repo, i) => { + let nm = repo.name.charAt(0).toUpperCase() + repo.name.slice(1); + createEl("option", select, { txt: nm, value: i }); + }); + renderRepo(repos, select.value); + } else { + root.innerHTML = ""; + createEl("div", root, { txt: err.message, id: "error" }); + } + }); + + function renderRepo(repos, index) { + article.innerHTML = ""; + repoDetails(repos[index]); + contributors(repos[index].contributors_url); + + select.addEventListener("change", () => { + article.innerHTML = ""; + repoDetails(repos[select.value]); + contributors(repos[select.value].contributors_url); + }); + + } + + function repoDetails(details) { + + const table = createEl("table", article); + let tr = createEl("tr", table); + createEl("th", tr, { txt: "Repository:" }); + let td = createEl("td", tr); + createEl("a", td, { + txt: details.name, href: details.html_url, target: "_blank" + }); + + if (details.description) { + createEl("tr", table).innerHTML = + `Description:${details.description}`; + } + createEl("tr", table).innerHTML = + `Forks:${details.forks_count}`; + createEl("tr", table).innerHTML = + `Updated:${details.updated_at}`; + } + + function contributors(url) { + fetchJSON(url, (err, infos) => { + if (err === null) { + const ul = createEl("ul", article); + infos.forEach(info => { + let li = createEl("li", ul); + let a = createEl("a", li, { + href: info.html_url, target: "_blank" + }); + createEl("img", a, { src: info.avatar_url }); + createEl("p", a, { txt: info.login }); + createEl("span", a, { txt: info.contributions }); + }); } else { - createAndAppend('pre', root, { text: JSON.stringify(data, null, 2) }); + article.innerHTML = ""; + createEl("div", article, { txt: err.message, id: "error" }); } }); } - const HYF_REPOS_URL = 'https://api.github.com/orgs/HackYourFuture/repos?per_page=100'; - - window.onload = () => main(HYF_REPOS_URL); } + +const HYF_REPOS_URL = 'https://api.github.com/orgs/HackYourFuture/repos?per_page=100'; +window.onload = () => main(HYF_REPOS_URL); diff --git a/homework/src/style.css b/homework/src/style.css index a8985a8a5..a00bb8b57 100644 --- a/homework/src/style.css +++ b/homework/src/style.css @@ -1,3 +1,99 @@ -.alert-error { - color: red; -} \ No newline at end of file +@import url('https://fonts.googleapis.com/css?family=Roboto'); +body { + margin: 0; +} +#error { + background-color: #f8d7da; + color: #7b1c2a; + width: 100%; + padding: 12px 20px; + border-radius: 6px; +} +#root { + max-width: 70%; + margin: auto; + font-family: 'Roboto', Arial, sans-serif; +} +header { + width: 100%; + background-color: #3f51b5; +} +header label { + display: inline-block; + margin: 17px; + font-size: 20px; + color: #fff; +} +header select { + display: inline-block; + padding: 6px; +} + +article { + display: flex; + flex-flow: wrap; + padding: 15px 0; + font-size: 15px; +} +article table { + flex: 5; + padding: 20px; + margin: 0 5px 0 0; + box-shadow: 0px 0px 8px rgb(148, 148, 148); +} +article table tr th { + text-align: left; +} +article table tr td { + padding: 0 0 0 8px; +} +article ul { + flex: 5; + list-style-type: none; + padding: 0; + margin: 0 0 0 5px; + box-shadow: 0px 0px 8px rgb(148, 148, 148); +} +article ul p { + margin: 0; + padding: 15px; + font-size: 14px; + color: rgb(95, 94, 94); +} +article ul li a { + display: flex; + align-items: center; + text-decoration: none; + margin: 0; + padding: 15px; +} +article ul li a img { + width: 45px; + height: 45px; + border-radius: 6px; +} +article ul li a p { + flex: 8; + margin: 0; + padding: 0 0 0 15px; +} +article ul li a span { + margin: 0; + padding: 1px 6px; + background-color: #808080; + border-radius: 4px; + font-size: 14px; + color: #fff; +} + +@media screen and (max-width: 750px) { + #root { + max-width: 100%; + } + + article table, article ul { + flex: 100%; + width: 100%; + margin: 0 0 10px 0; + } +}