diff --git a/homework/index.html b/homework/index.html index cc4b45bcb..858ec2287 100644 --- a/homework/index.html +++ b/homework/index.html @@ -18,7 +18,9 @@ -
+
+
+
diff --git a/homework/index.js b/homework/index.js index d8a04f271..1be88d6fa 100644 --- a/homework/index.js +++ b/homework/index.js @@ -1,19 +1,21 @@ 'use strict'; { - function fetchJSON(url, cb) { - const xhr = new XMLHttpRequest(); - xhr.open('GET', url); - xhr.responseType = 'json'; - xhr.onload = () => { - if (xhr.status < 400) { - cb(null, xhr.response); - } else { - cb(new Error(`Network error: ${xhr.status} - ${xhr.statusText}`)); - } - }; - xhr.onerror = () => cb(new Error('Network request failed')); - xhr.send(); + function fetchJSON(url) { + return new Promise((resolve, reject) => { + const xhr = new XMLHttpRequest(); + xhr.open('GET', url); + xhr.responseType = 'json'; + xhr.onload = () => { + if (xhr.status < 400) { + resolve(xhr.response); + } else { + reject(new Error(`Network error: ${xhr.status} - ${xhr.statusText}`)); + } + }; + xhr.onerror = () => reject(new Error('Network request failed')); + xhr.send(); + }); } function createAndAppend(name, parent, options = {}) { @@ -30,18 +32,103 @@ return elem; } - function main(url) { - fetchJSON(url, (err, data) => { - const root = document.getElementById('root'); - if (err) { + function renderContributors(contributors, contributorsContainer) { + createAndAppend('p', contributorsContainer, { text: 'Contributors', id: 'contributors' }); + contributors.forEach(contributor => { + const contributorsDetailsDiv = createAndAppend('div', contributorsContainer, { + class: 'contributor-details', + }); + createAndAppend('img', contributorsDetailsDiv, { + src: contributor.avatar_url, + alt: contributor.login, + class: 'image', + }); + createAndAppend('a', contributorsDetailsDiv, { + text: contributor.login, + href: contributor.html_url, + target: '_blank', + class: 'contributor-data', + }); + createAndAppend('p', contributorsDetailsDiv, { + text: contributor.contributions, + class: 'contributor-badge', + }); + }); + } + + function fetchAndRenderData(selectedRepo, repoContainer, contributorsContainer, root) { + repoContainer.innerHTML = ''; + contributorsContainer.innerHTML = ''; + + const updatedAt = new Date(selectedRepo.updated_at); + createAndAppend('span', repoContainer, { text: 'Repository: ', class: 'repo-child' }); + createAndAppend('a', repoContainer, { + text: `${selectedRepo.name}`, + href: selectedRepo.html_url, + target: '_blank', + class: 'repo-child right-cell', + }); + createAndAppend('p', repoContainer, { + text: `Description: ${selectedRepo.description}`, + class: 'repo-child', + }); + createAndAppend('p', repoContainer, { + text: `Fork: ${selectedRepo.forks}`, + class: 'repo-child', + }); + createAndAppend('p', repoContainer, { + text: `Updated: ${updatedAt.toLocaleString()}`, + class: 'repo-child', + }); + + fetchJSON(selectedRepo.contributors_url) + .then(contributors => { + renderContributors(contributors, contributorsContainer); + }) + .catch(err => { createAndAppend('div', root, { text: err.message, class: 'alert-error' }); - } else { - createAndAppend('pre', root, { text: JSON.stringify(data, null, 2) }); - } + }); + } + + function dropDown(root, repos) { + const header = createAndAppend('div', root, { id: 'header' }); + createAndAppend('p', header, { text: 'HYF Repositories', class: 'header' }); + const select = createAndAppend('select', header, { id: 'select' }); + + repos.sort((a, b) => a.name.localeCompare(b.name)); + + repos.forEach((repo, index) => { + createAndAppend('option', select, { + text: repo.name, + value: index, + }); + }); + + const mainContainer = createAndAppend('div', root, { id: 'main' }); + const repoContainer = createAndAppend('div', mainContainer, { id: 'repo-container' }); + const contributorsContainer = createAndAppend('div', mainContainer, { + id: 'contributor-container', }); + + select.addEventListener('change', () => { + const selectedRepo = repos[select.value]; + fetchAndRenderData(selectedRepo, repoContainer, contributorsContainer, root); + }); + fetchAndRenderData(repos[0], repoContainer, contributorsContainer, root); + } + + function main(url) { + const root = document.getElementById('root'); + fetchJSON(url) + .then(repos => { + dropDown(root, repos); + }) + .catch(err => { + createAndAppend('div', root, { text: err.message, class: 'alert-error' }); + }); } - const REPOS_URL = 'https://api.github.com/orgs/foocoding/repos?per_page=100'; + const HYF_REPOS_URL = 'https://api.github.com/orgs/HackYourFuture/repos?per_page=100'; - window.onload = () => main(REPOS_URL); + window.onload = () => main(HYF_REPOS_URL); } diff --git a/homework/style.css b/homework/style.css index a8985a8a5..d0bd96673 100644 --- a/homework/style.css +++ b/homework/style.css @@ -1,3 +1,64 @@ +#root { + display: flex; + flex-direction: column; + align-items: flex-start; + justify-content: center; +} +@media screen and (max-width: 768px) { + .h1.h1 { + width: 100%; + } + .right-div { + width: 100%; + } + .left-div { + width: 100%; + } +} .alert-error { - color: red; -} \ No newline at end of file + color: red; +} +.h1 { + text-align: center; +} +.container { + display: flex; + flex-direction: row; + align-items: flex-start; + margin: 10px; +} + +.right-div { + color: green; + display: flex; + flex-direction: row; + justify-content: space-between; + flex-wrap: wrap; + margin: 10px; + flex-grow: 1; + height: 200px; + width: 200px; +} + +.left-div { + color: brown; + display: flex; + flex-wrap: wrap; + flex-direction: column; + flex-grow: 1; + + align-items: right; + margin: 10px; +} +header { + width: 800px; + height: 70px; + background-color: purple; + text-emphasis-color: white; + text-align: left; +} +.info-container { + text-align: left; + width: 40; + height: 30; +}