Skip to content
This repository was archived by the owner on May 14, 2024. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
144 changes: 117 additions & 27 deletions homework/src/index.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,123 @@
'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}`));
const root = document.getElementById('root');
const startupContainer = createAndAppend('div', root, { id: 'startup' });
const headerStartupContainer = createAndAppend('h1', startupContainer, { html: 'HackYourFuture' });
const descriptionFirstContainer = createAndAppend('h5', startupContainer, { html: '"Refugee code school in Amsterdam"' });
const instructionsFirstContainer = createAndAppend('h4', startupContainer, { html: 'Select a repository to display information:' });
const repositoryContainer = createAndAppend('div', root);
const contributorsContainer = createAndAppend('div', root);

function fetchJSON(url) {
return new Promise(function (resolve, reject) {
const xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.send();
xhr.onreadystatechange = () => {
if (xhr.readyState === 4) {
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'));
});
}

function handleErrorStart(error) {

createAndAppend('div', startupContainer, { html: error.message, class: 'alert-error' });
}

function handleErrorRepository(error) {

const repositoryContainer2 = createAndAppend('div', repositoryContainer, { id: 'information' });
const headerRepositoryContainer = createAndAppend('h2', repositoryContainer2, { html: 'Repository Description' });
const innerRepositoryContainer = createAndAppend('div', repositoryContainer2);
createAndAppend('div', innerRepositoryContainer, { html: error.message, class: 'alert-error' });
}

function handleErrorContributors(error) {

const contributorsContainer2 = createAndAppend('div', contributorsContainer, { id: 'contributors' });
const headerContributorsContainer = createAndAppend('h2', contributorsContainer2, { html: 'Repository contributors' });
const innerContributorContainer = createAndAppend('div', contributorsContainer2, { id: 'inner-contributors' });
createAndAppend('div', innerContributorContainer, { html: error.message, class: 'alert-error' });
}

function startUpAndBuildSelectList(data) {

const arrayOfObjects = JSON.parse(data);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The 404 error is not being handled properly, the code throws an exception here

const newSelect = createAndAppend('select', startupContainer, { id: 'select-menu' });

arrayOfObjects.sort(function (a, b) {
const nameA = a.name.toUpperCase();
const nameB = b.name.toUpperCase();
if (nameA < nameB) {
return -1;
}
if (nameA > nameB) {
return 1;
}
};
xhr.onerror = () => cb(new Error('Network request failed'));
xhr.send();
return 0;
});

const optionItem = createAndAppend('option', newSelect, { html: 'Select' });

for (let i = 0; i < arrayOfObjects.length; i++) {
const optionItem = createAndAppend('option', newSelect, { html: arrayOfObjects[i].name, value: i });
}

newSelect.addEventListener('change', handleNewRepositoryRequest => {
const newUrl = 'https://api.github.com/repos/HackYourFuture/' + arrayOfObjects[event.target.value].name;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should try to avoid putting URLs in multiple places

repositoryContainer.innerHTML = '';
contributorsContainer.innerHTML = '';

fetchJSON(newUrl).then(buildRepositoryInfoSection, handleErrorRepository).then(buildContributorsSection, handleErrorContributors);
});
}

function buildRepositoryInfoSection(data) {

const repositoryContainer2 = createAndAppend('div', repositoryContainer, { id: 'information' });
const headerRepositoryContainer = createAndAppend('h2', repositoryContainer2, { html: 'Repository Description' });
const innerRepositoryContainer = createAndAppend('div', repositoryContainer2);
const repositoryObject = JSON.parse(data);
const table = createAndAppend('table', innerRepositoryContainer);
const tableRow1 = createAndAppend('tr', table);
const tableHeader1 = createAndAppend('th', tableRow1, { html: 'Repository' });
const tableData1 = createAndAppend('td', tableRow1);
const webpageLink = createAndAppend('a', tableData1, { html: repositoryObject.name, href: repositoryObject.svn_url, target: '_blank' });
const tableRow2 = createAndAppend('tr', table);
const tableHeader2 = createAndAppend('th', tableRow2, { html: 'Description:' });
const tableData2 = createAndAppend('td', tableRow2, { html: repositoryObject.description });
const tableRow3 = createAndAppend('tr', table);
const tableHeader3 = createAndAppend('th', tableRow3, { html: 'Forks:' });
const tableData3 = createAndAppend('td', tableRow3, { html: repositoryObject.forks });
const tableRow4 = createAndAppend('tr', table);
const tableHeader4 = createAndAppend('th', tableRow4, { html: 'Updated:' });
const tableData4 = createAndAppend('td', tableRow4, { html: repositoryObject.updated_at });
const contributorsUrl = repositoryObject.contributors_url;

return fetchJSON(contributorsUrl);
}

function buildContributorsSection(data) {

const contributorsContainer2 = createAndAppend('div', contributorsContainer, { id: 'contributors' });
const headerContributorsContainer = createAndAppend('h2', contributorsContainer2, { html: 'Repository contributors' });
const innerContributorContainer = createAndAppend('div', contributorsContainer2, { id: 'inner-contributors' });
const arrayOfContributors = JSON.parse(data);

for (const contributor of arrayOfContributors) {
const singleContributorContainer = createAndAppend('div', innerContributorContainer, { class: 'single-contributor' });
const contributorName = createAndAppend('h3', singleContributorContainer);
const contributorLink = createAndAppend('a', contributorName, { html: contributor.login, href: contributor.html_url, target: '_blank' });
const contributorImage = createAndAppend('img', singleContributorContainer, { src: contributor.avatar_url, alt: 'profile picture of ' + contributor.login, class: 'profile-pictures' });
}
}

function createAndAppend(name, parent, options = {}) {
Expand All @@ -29,19 +133,5 @@
});
return elem;
}

function main(url) {
fetchJSON(url, (err, data) => {
const root = document.getElementById('root');
if (err) {
createAndAppend('div', root, { html: err.message, class: 'alert-error' });
} else {
createAndAppend('pre', root, { html: JSON.stringify(data, null, 2) });
}
});
}

const HYF_REPOS_URL = 'https://api.github.com/orgs/HackYourFuture/repos?per_page=100';

window.onload = () => main(HYF_REPOS_URL);
fetchJSON("https://api.github.com/orgs/HackYourFuture/repos?per_page=100").then(startUpAndBuildSelectList, handleErrorStart);
}
238 changes: 237 additions & 1 deletion homework/src/style.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,239 @@

body {
font-family: 'Raleway', sans-serif;
background-color:rgb(237,237,237);
color:rgb(92,83,74);
}

* {box-sizing: border-box;}

h1 {
font-size: 2.5vw;
color: rgb(0,118,163);
margin-bottom: 0px;
}

h3 {
text-align: center;
font-size: 0.9vw;
color: rgb(85,85,85);
}

h2 {
text-align: center;
padding: 1vw;
font-size: 1.8vw;
color: rgb(0,118,163);
}

h4 {
font-size: 1vw;
font-weight: normal;
color: rgb(51,51,51);
margin-top: 1.5vw;
margin-bottom: 0.5vw;
}

h5 {
font-size: 0.8vw;
font-weight: normal;
font-style: italic;
color: rgb(2, 98, 136);
margin-top: 0.8vw;
}

#select-menu {
font-size: 1vw;
border-radius: 0.8vw;
padding: 0.3vw;
}

table {
margin: 0 auto;
font-size: 1.2vw;
padding: 1vw;
}

th {padding: 1vw;}

td {padding: 1vw;}

#startup {
position: fixed;
top:14vw;
left: 3.5%;
width: 23%;
padding: 1%;
}

#information {
position: fixed;
background-color: white;
top:11vw;
left: 30%;
width: 40%;
padding: 1%;
border-radius:2vw;
}

#contributors {
position: absolute;
top:3vw;
right: 3%;
width: 24%;
padding: 1%;
}

#inner-contributors {
display: flex;
flex-wrap:wrap;
justify-content:space-around;
}

.single-contributor {
width: 38%;
border-radius:1.5vw;
height: 9vw;
margin: 6%;
}

.profile-pictures {
width: 50%;
margin-left: 25%;
border-radius: 1vw;
}

.alert-error {
color: red;
color: red;
background-color: rgb(250, 198, 198);
padding: 1vw;
border-radius:1.3vw;
}

@media screen and (min-width:416px) and (max-width:1024px) {

h1 {font-size: 3vw;}

h3 {font-size: 1.6vw;}

h2 {font-size: 2.5vw;}

h4 {font-size: 1.3vw;}

h5 {font-size: 1.2vw;}

#select-menu {
font-size: 1.3vw;
border-radius:1vw;
}

table {
font-size: 1.7vw;
}

#startup {
position: absolute;
top: 8.5vw;
left: 3%;
width: 28%;
}

#information {
position: absolute;
background-color: white;
top:4vw;
left: 37%;
width: 60%;
border-radius:3vw;
}

#contributors {
position: relative;
top:37vw;
right: 0vw;
width: 100%;
}

#inner-contributors {
display: flex;
flex-wrap:wrap;
justify-content:space-around;
}

.single-contributor {
width: 15%;
border-radius:3vw;
height: 16vw;
margin: 2%;
}

.profile-pictures {
width: 50%;
border-radius:2vw;
}
.alert-error {border-radius:1.5vw;}

}

@media screen and (max-width:415px) {

h1 {font-size: 6vw;}

h3 {font-size: 3.2vw;}

h2 {font-size: 4.5vw;}

h4 {font-size: 2.5vw;}

h5 {font-size: 2vw;}

#select-menu {
font-size: 2.5vw;
border-radius:1.5vw;
}

table {font-size: 3vw;}

#startup {
position: absolute;
top: 6vw;
left: 6.5%;
width: 92%;
}

#information {
position: absolute;
background-color: white;
top:45vw;
left: 6.5%;
width: 86%;
padding: 3%;
border-radius:5vw;
}

#contributors {
position: relative;
top:95vw;
right: 0vw;
width: 100%;
}

#inner-contributors {
display: flex;
flex-wrap:wrap;
justify-content:space-around;
}

.single-contributor {
width: 26%;
border-radius:3vw;
height: 28vw;
margin: 3%;
}
.single-contributor h3 {padding: 3%;}
.profile-pictures {
width: 50%;
border-radius:3.5vw;
}
.alert-error {border-radius:2.5vw;}
}