From 0d02620284af5556141467e9d731576423a99bc5 Mon Sep 17 00:00:00 2001 From: Mohammad Fakhera <58679279+nlmohdnl@users.noreply.github.com> Date: Mon, 16 Mar 2020 07:56:22 +0100 Subject: [PATCH 1/5] js3w1homeworks --- .../homework/js-exercises/dogPhotoGallary.js | 42 ++++++++++++++++ .../js-exercises/dogPhotoGallery.html | 48 +++++++++++++++++++ .../js-exercises/programmerHumor.html | 13 +++++ .../homework/js-exercises/programmerHumor.js | 48 +++++++++++++++++++ Week1/homework/js-exercises/whoDo.html | 39 +++++++++++++++ Week1/homework/project.js | 0 6 files changed, 190 insertions(+) create mode 100644 Week1/homework/js-exercises/dogPhotoGallary.js create mode 100644 Week1/homework/js-exercises/dogPhotoGallery.html create mode 100644 Week1/homework/js-exercises/programmerHumor.html create mode 100644 Week1/homework/js-exercises/programmerHumor.js create mode 100644 Week1/homework/js-exercises/whoDo.html create mode 100644 Week1/homework/project.js diff --git a/Week1/homework/js-exercises/dogPhotoGallary.js b/Week1/homework/js-exercises/dogPhotoGallary.js new file mode 100644 index 000000000..61bb2fd02 --- /dev/null +++ b/Week1/homework/js-exercises/dogPhotoGallary.js @@ -0,0 +1,42 @@ +'use strict' +//add event listener + +const xhrBtn = document.getElementById('xhr'); +const axiosBtn = document.getElementById('axi'); + +xhrBtn.addEventListener('click', imageXHR); +axiosBtn.addEventListener('click', imageAxios); + +//XHR function +function imageXHR() { + const xhr = new XMLHttpRequest(); + xhr.open('GET', 'https://dog.ceo/api/breeds/image/random'); + xhr.responseType = 'json'; + xhr.onload = () => { + createImage(xhr.response.message); + }; + xhr.send(); +} +//Axios function +function imageAxios() { + axios + .get('https://dog.ceo/api/breeds/image/random') + .then(res => { + createImage(res.data.message); + }) + .catch(err => console.error(err)); +} + +//Manupolating DOM function +function createImage(dogImg) { + + const imgUl = document.getElementById('imgUl'); + const img = document.createElement('img'); + const li = document.createElement('li'); + + img.setAttribute('src', dogImg); + img.style = 'width:200px; height:200px'; + + li.appendChild(img); + imgUl.appendChild(li); +} \ No newline at end of file diff --git a/Week1/homework/js-exercises/dogPhotoGallery.html b/Week1/homework/js-exercises/dogPhotoGallery.html new file mode 100644 index 000000000..9143fd811 --- /dev/null +++ b/Week1/homework/js-exercises/dogPhotoGallery.html @@ -0,0 +1,48 @@ + + + + + + + + + + + Dog Photos + + + + +
+ + +
+ +
+ +
+ + + + + diff --git a/Week1/homework/js-exercises/programmerHumor.html b/Week1/homework/js-exercises/programmerHumor.html new file mode 100644 index 000000000..1edcfc706 --- /dev/null +++ b/Week1/homework/js-exercises/programmerHumor.html @@ -0,0 +1,13 @@ + + + + + + + Programmer Humor + + + + + + \ No newline at end of file diff --git a/Week1/homework/js-exercises/programmerHumor.js b/Week1/homework/js-exercises/programmerHumor.js new file mode 100644 index 000000000..f7edc350d --- /dev/null +++ b/Week1/homework/js-exercises/programmerHumor.js @@ -0,0 +1,48 @@ + +//XHR function +function apiWithXhr(url, callback) { + const xhr = new XMLHttpRequest(); + xhr.open('GET', url); + xhr.responseType = 'json'; + xhr.onload = () => { + callback(null, { + response: xhr.response, + status: xhr.status, + readyState: xhr.readyState, + }); + } + xhr.onerror = () => callback('Error!'); + xhr.send(); +} + +const url = 'https://xkcd.now.sh/?comic=614'; +//error handeler +apiWithXhr(url, (err, data) => { + if (err) { + console.error(err); + return; + }else if (data.status == 200 && data.readyState == 4) { + renderImg(data.response, 'Images with XHR'); + }else { + console.error('Error(load: ', data.response, 'Status: ', data.status); + } +}); + +//axios function +axios +.get('https://xkcd.now.sh/?comic=614') +.then(res => { + renderImg(res.data, 'Images with AXIOS'); +}) +.catch(err => console.error(err)); + +function renderImg(data, text) { + + console.log(data); + const h1 = document.createElement('h1'); + h1.textContent = text; + const img = document.createElement('img'); + img.setAttribute('src', data.img); + document.body.appendChild(h1); + document.body.appendChild(img); +} \ No newline at end of file diff --git a/Week1/homework/js-exercises/whoDo.html b/Week1/homework/js-exercises/whoDo.html new file mode 100644 index 000000000..2990181d5 --- /dev/null +++ b/Week1/homework/js-exercises/whoDo.html @@ -0,0 +1,39 @@ + + + + + + Who Do we have here? + + + + + + + + + \ No newline at end of file diff --git a/Week1/homework/project.js b/Week1/homework/project.js new file mode 100644 index 000000000..e69de29bb From 5a584ce62b11896d54933712841e1a84df7f0ae5 Mon Sep 17 00:00:00 2001 From: Mohammad Fakhera <58679279+nlmohdnl@users.noreply.github.com> Date: Wed, 25 Mar 2020 13:25:45 +0100 Subject: [PATCH 2/5] js3w2hw --- Week2/homework/index.html | 33 +++++++++ Week2/homework/index.js | 141 ++++++++++++++++++++++++++++++++++++++ Week2/homework/style.css | 84 +++++++++++++++++++++++ 3 files changed, 258 insertions(+) create mode 100644 Week2/homework/index.html create mode 100644 Week2/homework/index.js create mode 100644 Week2/homework/style.css diff --git a/Week2/homework/index.html b/Week2/homework/index.html new file mode 100644 index 000000000..d71898f8f --- /dev/null +++ b/Week2/homework/index.html @@ -0,0 +1,33 @@ + + + + + + + + + + + + + HYF Version-2 + + + + + +
+
+

HYF Repositories

+ +
+
+
+
+
+
+ + + + \ No newline at end of file diff --git a/Week2/homework/index.js b/Week2/homework/index.js new file mode 100644 index 000000000..dc309f91a --- /dev/null +++ b/Week2/homework/index.js @@ -0,0 +1,141 @@ +/* eslint-disable no-console */ +/* eslint-disable no-use-before-define */ +/* eslint-disable no-unused-vars */ +const createAndAppend = (name, parent, options = {}) => { + const elem = document.createElement(name); + parent.appendChild(elem); + Object.entries(options).forEach(([key, value]) => { + if (key === 'innerHTML') { + elem.innerHTML = value; + } else if (key === 'text') { + elem.textContent = value; + } else { + elem.setAttribute(key, value); + } + }); + return elem; + }; + const errorHandler = err => { + const root = document.getElementById('root'); + createAndAppend('div', root, { + text: err.message, + class: 'alert-error', + }); + }; + + const optionLoading = items => { + const selectEl = document.querySelector('#reposName'); + items + .sort((current, next) => current.name.localeCompare(next.name)) + .forEach(repo => { + createAndAppend('option', selectEl, { + text: repo.name, + value: repo.name, + }); + }); + }; + + const renderRepoContainer = repo => { + const { selectedIndex } = document.querySelector('select'); + const convertedDate = new Date( + repo[selectedIndex].updated_at, + ).toLocaleString(); + const repoContainer = document.querySelector('.repo-container'); + + createAndAppend('ul', repoContainer, { class: 'repoDetails' }); + const cardUl = document.querySelector('.repoDetails'); + + createAndAppend('li', cardUl, { + innerHTML: `Repository :${repo[selectedIndex].name}`, + }); + createAndAppend('li', cardUl, { + innerHTML: `Description: ${repo[selectedIndex].description}`, + }); + createAndAppend('li', cardUl, { + innerHTML: `Forks: ${repo[selectedIndex].forks_count}`, + }); + createAndAppend('li', cardUl, { + innerHTML: `Updated: ${convertedDate}`, + }); + + return repo; + }; + + const renderRepoContributors = repo => { + const { selectedIndex } = document.querySelector('select'); + const selectedRepo = repo[selectedIndex]; + + const repoContributors = document.querySelector('.contributors-container'); + createAndAppend('ul', repoContributors, { class: 'repoContributors' }); + const ulContributors = document.querySelector('.repoContributors'); + + createAndAppend('h5', ulContributors, { + text: 'Contributions', + style: 'margin:0 0 5px 0; font-size: 15px; ', + }); + + fetchJSON(selectedRepo.contributors_url) + .then(data => + data.forEach(dataSelected => { + const li = createAndAppend('li', ulContributors, { + style: + 'display: flex;text-align: center; justify-content: space-between; border-bottom: 2px solid #687466;', + }); + const imgAvatar = createAndAppend('img', li, { + src: dataSelected.avatar_url, + class: 'avatar', + }); + const contInfo = createAndAppend('a', li, { + text: dataSelected.login, + href: dataSelected.html_url, + target: '_blank', + style: 'margin: 20px auto 0 5px; text-decoration: none;', + }); + const contCount = createAndAppend('span', li, { + text: dataSelected.contributions, + class: 'contributions-count', + }); + }), + ) + .catch(err => console.error(err)); + }; + + const renderSelectedOptionChange = repo => { + const selectRepo = document.querySelector('select'); + selectRepo.addEventListener('change', () => { + document.querySelector('section.repo-container ul').remove(); + document.querySelector('.repoContributors').remove(); + + renderRepoContainer(repo); + renderRepoContributors(repo); + }); + }; + + const fetchJSON = url => { + const repos = fetch(url) + .then(res => { + if (!res.ok) { + throw new Error('Network response was not ok'); + } + return res.json(); + }) + .then(data => data) + .catch(err => errorHandler(err)); + return repos; + }; + + const main = url => { + fetchJSON(url) + .then(data => { + optionLoading(data); + renderRepoContainer(data); + renderRepoContributors(data); + renderSelectedOptionChange(data); + }) + .catch(err => errorHandler(err)); + }; + + const HYF_REPOS_URL = + 'https://api.github.com/orgs/HackYourFuture/repos?per_page=30'; + + main(HYF_REPOS_URL); \ No newline at end of file diff --git a/Week2/homework/style.css b/Week2/homework/style.css new file mode 100644 index 000000000..fbae9cdfa --- /dev/null +++ b/Week2/homework/style.css @@ -0,0 +1,84 @@ + +body { + font-family: italic 20px Serif; +} +.CardHeader { + background-color:palevioletred; + color: white; + justify-content: left; + padding:10px; + margin-bottom: 5px; + border: 1px solid aqua; + width: auto; +} + +.repoDetails { + display: inline-block; + background-color: white; + padding: 15px; + line-height: 20px; + border: 1px solid black; + list-style-type: none; +} + +.repoDetails li span { + font-size: 15px; + white-space: normal; +} +.firstText { + display: inline-block; + margin-right: 5px; + font-weight: bolder; + width: 85px; +} +.main-container { + display: flex; +} +.repoContributors { + display: inline-block; + width: 90%; + background-color: white; + padding: 15px; + line-height: 20px; + border: 1px solid black; + list-style-type: none; +} + +.repo-container { + width: 100%; + margin-left: 15px; +} +.contributors-container { + width: 100%; +} +.avatar { + margin-bottom: 3px; + margin-top: 3px; + width: 65px; + border-radius: 50%; +} +.contributions-count { + background-color: cadetblue; + border: 2px solid rgba(0, 0, 0, 0.17); + font-weight: bold; + border-radius: 5px; + padding: 7px; + margin: 15px 5px 25px 0; +} +.alert-error { + width: 72%; + margin: 2px 0; + padding: 10px; + border-radius: 3px 3px 3px 3px; + color: #d8000c; + background-color: #ffbaba; +} +@media screen and (max-width: 700px) { + .repo-container, + .contributors-container { + width: 100%; + } + .main-container { + display: block; + } +} \ No newline at end of file From a37cbe8c71e7b31825b09c4a2ad92459ff27c9a4 Mon Sep 17 00:00:00 2001 From: Mohammad Fakhera <58679279+nlmohdnl@users.noreply.github.com> Date: Wed, 25 Mar 2020 13:34:41 +0100 Subject: [PATCH 3/5] js3w1hw --- Week1/homework/project.js | 0 Week1/homework/project/index.html | 23 ++++++++ Week1/homework/project/index.js | 91 +++++++++++++++++++++++++++++++ Week1/homework/project/style.css | 57 +++++++++++++++++++ 4 files changed, 171 insertions(+) delete mode 100644 Week1/homework/project.js create mode 100644 Week1/homework/project/index.html create mode 100644 Week1/homework/project/index.js create mode 100644 Week1/homework/project/style.css diff --git a/Week1/homework/project.js b/Week1/homework/project.js deleted file mode 100644 index e69de29bb..000000000 diff --git a/Week1/homework/project/index.html b/Week1/homework/project/index.html new file mode 100644 index 000000000..ebbfb1120 --- /dev/null +++ b/Week1/homework/project/index.html @@ -0,0 +1,23 @@ + + + + + + + + + + + + + HYF-GITHUB + + + + + +
+ + + + \ No newline at end of file diff --git a/Week1/homework/project/index.js b/Week1/homework/project/index.js new file mode 100644 index 000000000..874014316 --- /dev/null +++ b/Week1/homework/project/index.js @@ -0,0 +1,91 @@ +'use strict'; + +{ + 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(); + } + + function createAndAppend(name, parent, options = {}) { + const elem = document.createElement(name); + parent.appendChild(elem); + Object.entries(options).forEach(([key, value]) => { + if (key === 'text') { + elem.textContent = value; + } else { + elem.setAttribute(key, value); + } + }); + return elem; + } + + function renderRepoDetails(repo, ul) { + // create repositories list + const li = createAndAppend('li', ul, { class: 'repoList' }); + const div = createAndAppend('div', li, { class: 'repository' }); + // create Repository table + const table = createAndAppend('table', div); + + // create Repository title row + const tr1 = createAndAppend('tr', table); + createAndAppend('td', tr1, { text: 'Repository:', class: 'title' }); + const td = createAndAppend('td', tr1); + createAndAppend('a', td, { + href: repo.html_url, + text: repo.name, + target: '_blank' + }); + + // create Description row + const tr2 = createAndAppend('tr', table); + createAndAppend('td', tr2, { text: 'Description:', class: 'title' }); + createAndAppend('td', tr2, { text: repo.description }); + + // create Fork row + const tr3 = createAndAppend('tr', table); + createAndAppend('td', tr3, { text: 'Forks:', class: 'title' }); + createAndAppend('td', tr3, { text: repo.forks }); + + // create Updated row + const tr4 = createAndAppend('tr', table); + createAndAppend('td', tr4, { text: 'Updated:', class: 'title' }); + createAndAppend('td', tr4, { text: repo.updated_at }); + } + + function main(url) { + fetchJSON(url, (err, repos) => { + const root = document.getElementById('root'); + // create the page header + createAndAppend('div', root, { + text: 'HYF Repositories', + class: 'head', + }); + + if (err) { + createAndAppend('div', root, { + text: err.message, + class: 'alert-error', + }); + return; + } + const ul = createAndAppend('ul', root, {class: 'repoUl'}); + // sorting the repositories form A to Z + repos.sort((currentRepo, nextRepo) => currentRepo.name.localeCompare(nextRepo.name)); + repos.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/Week1/homework/project/style.css b/Week1/homework/project/style.css new file mode 100644 index 000000000..734ee9180 --- /dev/null +++ b/Week1/homework/project/style.css @@ -0,0 +1,57 @@ +body { + font-family: italic 20px Serif; +} + + #root { + width: 80%; + margin: auto; + } + + .alert-error { + color: #9D1C24; + background-color: #F8D7DA; + height: 50px; + padding: 20px 0 0 10px; + margin-top: 5px; + } + + .head { + background-color: purple; + color: #ffffff; + height: 50px; + padding: 20px 0 0 10px; + margin-top: 5px;; + font-size: 1.5rem; + } + + .title { + font-weight: bold; + padding: 5px 0 5px 5px; + } + + .repoUl { + margin: 0; + padding: 0; + } + + .repoList { + list-style: none; + margin: 0; + padding: 0; + } + + .repository { + box-shadow: 2px 2px 15px -2px rgba(133,126,133,1); + margin: 7px 0 7px 0; + } + + @media only screen and (max-width: 600px) { + #root { + width: 100%; + font-size: 14px; + } + + .head { + text-align: center; + } + } \ No newline at end of file From a699fe872eb895588da0b02d7d9ae8996ecbabc4 Mon Sep 17 00:00:00 2001 From: Mohammad Fakhera <58679279+nlmohdnl@users.noreply.github.com> Date: Sat, 28 Mar 2020 10:39:21 +0100 Subject: [PATCH 4/5] js3w3hw --- Week3/homework/part1/hyf.png | Bin 0 -> 9116 bytes Week3/homework/part1/index.html | 34 +++++ Week3/homework/part1/index.js | 175 +++++++++++++++++++++++ Week3/homework/part1/style.css | 146 +++++++++++++++++++ Week3/homework/part2/App.js | 56 ++++++++ Week3/homework/part2/ContributorsView.js | 62 ++++++++ Week3/homework/part2/ErrorView.js | 31 ++++ Week3/homework/part2/HeaderView.js | 46 ++++++ Week3/homework/part2/Model.js | 53 +++++++ Week3/homework/part2/Observable.js | 20 +++ Week3/homework/part2/RepoView.js | 58 ++++++++ Week3/homework/part2/Util.js | 27 ++++ Week3/homework/part2/index.html | 33 +++++ Week3/homework/part2/style.css | 148 +++++++++++++++++++ 14 files changed, 889 insertions(+) create mode 100644 Week3/homework/part1/hyf.png create mode 100644 Week3/homework/part1/index.html create mode 100644 Week3/homework/part1/index.js create mode 100644 Week3/homework/part1/style.css create mode 100644 Week3/homework/part2/App.js create mode 100644 Week3/homework/part2/ContributorsView.js create mode 100644 Week3/homework/part2/ErrorView.js create mode 100644 Week3/homework/part2/HeaderView.js create mode 100644 Week3/homework/part2/Model.js create mode 100644 Week3/homework/part2/Observable.js create mode 100644 Week3/homework/part2/RepoView.js create mode 100644 Week3/homework/part2/Util.js create mode 100644 Week3/homework/part2/index.html create mode 100644 Week3/homework/part2/style.css diff --git a/Week3/homework/part1/hyf.png b/Week3/homework/part1/hyf.png new file mode 100644 index 0000000000000000000000000000000000000000..76bc5a13b4a53ea97a6c09ca5fe399f40ab20e4e GIT binary patch literal 9116 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 GkN*WepL25n literal 0 HcmV?d00001 diff --git a/Week3/homework/part1/index.html b/Week3/homework/part1/index.html new file mode 100644 index 000000000..f9cc7119e --- /dev/null +++ b/Week3/homework/part1/index.html @@ -0,0 +1,34 @@ + + + + + + + + + + + + + HYF-GITHUB + + + + + + +
+
+

HYF Repositories

+ +
+
+
+
+
+
+ + + + \ No newline at end of file diff --git a/Week3/homework/part1/index.js b/Week3/homework/part1/index.js new file mode 100644 index 000000000..4e4cbc7e9 --- /dev/null +++ b/Week3/homework/part1/index.js @@ -0,0 +1,175 @@ +'use strict'; + +{ + // root div declaration + const root = document.getElementById('root'); + + // this function will fetch JSON data using async/await and axios + async function fetchJSON(url) { + + try { + + const response = await axios.get(url); + // throw the error if exists + if (!response.statusText) { + throw new Error(`Network error: ${response.status},${response.statusText}`); + } + const resData = await response.data; + // return the fetched data + return resData; + + } + catch (error) { + // catch the error if exists + printError(error); + + } + } + + // this function create and append elements + function createAndAppend(name, parent, options = {}) { + const elem = document.createElement(name); + parent.appendChild(elem); + Object.entries(options).forEach(([key, value]) => { + if (key === 'text') { + elem.textContent = value; + } else { + elem.setAttribute(key, value); + } + }); + return elem; + } + + // this function render the selected Repository details + function renderRepoDetails(repo, repoContainer) { + // create Repository table + const table = createAndAppend('table', repoContainer); + + // create Repository title row + const titleTr = createAndAppend('tr', table); + createAndAppend('td', titleTr, { text: 'Repository:', class: 'title' }); + const td = createAndAppend('td', titleTr); + createAndAppend('a', td, { + href: repo.html_url, + text: repo.name, + target: '_blank' + }); + + // create Description row + const descriptionTr = createAndAppend('tr', table); + createAndAppend('td', descriptionTr, { text: 'Description:', class: 'title' }); + createAndAppend('td', descriptionTr, { text: repo.description }); + + // create Fork row + const forksTr = createAndAppend('tr', table); + createAndAppend('td', forksTr, { text: 'Forks:', class: 'title' }); + createAndAppend('td', forksTr, { text: repo.forks }); + + // create Updated row + const updatedTr = createAndAppend('tr', table); + createAndAppend('td', updatedTr, { text: 'Updated:', class: 'title' }); + createAndAppend('td', updatedTr, { text: repo.updated_at }); + } + + // this function render the Contributions details + async function renderContributorsDetails(repo, contributorsContainer) { + // create section title + const ul = createAndAppend('ul', contributorsContainer, { + text: 'Contributions', + class: 'contributors-ul' + }); + + // fetch contributors data + try { + const contributors = await fetchJSON(repo.contributors_url); + // create contributors list + contributors.forEach( Contributor => { + const li = createAndAppend('li', ul, { class: 'Contributor-li' }); + const ContributorDiv = createAndAppend('div', li, { class: 'Contributor-div' }); + + // create contributor image + createAndAppend('img', ContributorDiv, { + class: 'contributors-img', + src: Contributor.avatar_url, + }); + + // create contributor name + createAndAppend('a', ContributorDiv, { + class: 'contributors-a', + text: Contributor.login, + href: Contributor.html_url, + target: '_blank', + }); + + // create contributors number + createAndAppend('span', ContributorDiv, { + class: 'contributors-span', + text: Contributor.contributions, + }); + }); + } + catch(err) { + // catch the error if exists + printError(err); + } + } + + // this function removes all childs of passed element + function removeElems(elem) { + while (elem.lastElementChild) { + elem.removeChild(elem.lastElementChild); + } + } + + // this function print the catched error to window + function printError(err) { + createAndAppend('div', root, { + text: err.message, + class: 'alert-error', + }); + } + + // this is the main function + async function main(url) { + // fetch Repositories data + try { + const repos = await fetchJSON(url); + // declare the DOM elements for list and containers + const reposList = document.getElementById('repos-List'); + const repoContainer = document.querySelector('.repo-container'); + const contributorsContainer = document.querySelector('.contributors-container'); + + // sorting the repositories form A to Z + repos.sort((currentRepo, nextRepo) => currentRepo.name.localeCompare(nextRepo.name)); + + // filling the dropdown list with sorted repositories titles + repos.forEach(repo => { + createAndAppend('option', reposList, { text: repo.name, value: repo.name }); + }); + + // display information about the first repository + renderRepoDetails(repos[0], repoContainer); + renderContributorsDetails(repos[0], contributorsContainer); + + // refreshed for the newly selected repository when the user changes the selection + reposList.addEventListener('change', () => { + // empty the containers from old data when the user changes the selection + removeElems(repoContainer); + removeElems(contributorsContainer); + // find the selected repository and render the details + let currentRepo = repos.filter( repo => repo.name == reposList.value ); + renderRepoDetails(currentRepo[0], repoContainer); + renderContributorsDetails(currentRepo[0], contributorsContainer); + }); + + } + catch(err) { + // catch the error if exists + printError(err); + } + } + + 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/part1/style.css b/Week3/homework/part1/style.css new file mode 100644 index 000000000..9913dba3f --- /dev/null +++ b/Week3/homework/part1/style.css @@ -0,0 +1,146 @@ +body { + margin: 0; + padding: 0; + font-size: 16px; + font-family: Arial, Helvetica, sans-serif; + } + + #root { + width: 80%; + margin: auto; + } + + .alert-error { + color: #9D1C24; + background-color: #F8D7DA; + height: 50px; + padding: 20px 0 0 10px; + margin-top: 5px; + } + + .head { + background-color: #3F51B5; + color: #ffffff; + height: 100px; + padding: 0px; + margin-top: 5px; + display: flex; + } + + .head > h1 { + padding: 0.5rem 0 0 1rem; + } + + #repos-List { + height: auto; + width: 20rem; + margin: auto 1rem ; + font-size: large; + } + + .title { + font-weight: bold; + padding: 5px 0 5px 5px; + } + + .main-container { + display: flex; + } + + .repo-container, .contributors-container { + box-shadow: 2px 2px 15px -2px rgba(133,126,133,1); + margin: 7px 0 7px 0; + width: 50%; + } + + .repo-container { + height: 8rem; + margin-right: 0.5rem; + } + + .contributors-ul { + font-weight: bold; + padding: 5px 0 5px 5px; + list-style: none; + } + + .Contributor-li { + margin: 1rem 0 1rem 0; + border-bottom: 1px solid #dfdcdc; + } + + .Contributor-div { + height: 4.5rem; + } + + .contributors-img { + width: 50px; + margin-left: 1rem; + } + + .contributors-a { + margin: auto 1rem; + font-weight: normal; + position: relative; + bottom: 1.5rem; + } + + .contributors-span { + margin: 1rem 1rem 0 0; + float: right; + font-weight: normal; + font-size: small; + text-align: center; + width: 2rem; + color: #ffffff; + background-color: #5f5d5d; + border-radius: 0.2rem; + } + + /* Change style to be responsive to ---Mobile devices--- */ + + @media (max-width: 600px) { + #root { + width: 100%; + font-size: 14px; + } + + .head > h1 { + font-size: 1rem; + padding: 2rem 0 0 1rem; + } + + #repos-List { + width: 5rem; + margin: auto 1rem ; + font-size: small; + position: relative; + + } + + #repos-List option{ + width: 5rem; + + } + + .main-container { + display: block; + } + .repo-container, .contributors-container { + width: 100%; + } + } + + /* Change style to be responsive to --Tablets devices--*/ + + @media (min-width: 600px) and (max-width: 1024px) { + #root { + width: 95%; + font-size: 14px; + } + + .head > h1 { + font-size: 1.5rem; + padding: 1rem 0 0 1rem; + } + } \ No newline at end of file diff --git a/Week3/homework/part2/App.js b/Week3/homework/part2/App.js new file mode 100644 index 000000000..316fb93a7 --- /dev/null +++ b/Week3/homework/part2/App.js @@ -0,0 +1,56 @@ +use strict'; + +{ + const accounts = { + hyf: { + name: 'HackYourFuture', + type: 'org', + }, + microsoft: { + name: 'Microsoft', + type: 'org', + }, + jim: { + name: 'remarcmij', + type: 'user', + }, + }; + + const { Model, HeaderView, RepoView, ContributorsView, ErrorView } = window; + const { createAndAppend } = window.Util; + + class App { + constructor(account) { + const containers = App.renderContainers(); + + const model = new Model(account); + const fetchData = model.fetchData.bind(model); + + model.subscribe(new HeaderView(account, containers.header, fetchData)); + model.subscribe(new RepoView(containers.repo)); + model.subscribe(new ContributorsView(containers.contributors)); + model.subscribe(new ErrorView(containers.error)); + + fetchData(); + } + + static renderContainers() { + const root = document.getElementById('root'); + const header = createAndAppend('header', root, { class: 'header' }); + const error = createAndAppend('div', root); + const main = createAndAppend('main', root, { + class: 'main-container', + }); + const repo = createAndAppend('section', main, { + class: 'repo-container whiteframe', + }); + const contributors = createAndAppend('section', main, { + class: 'contributors-container whiteframe', + }); + return { header, error, main, repo, contributors }; + } + } + + const ACCOUNT_KEY = 'hyf'; + window.onload = () => new App(accounts[ACCOUNT_KEY]); +} \ No newline at end of file diff --git a/Week3/homework/part2/ContributorsView.js b/Week3/homework/part2/ContributorsView.js new file mode 100644 index 000000000..9161a3ddb --- /dev/null +++ b/Week3/homework/part2/ContributorsView.js @@ -0,0 +1,62 @@ +'use strict'; + +{ + const { createAndAppend } = window.Util; + + class ContributorsView { + constructor(container) { + this.container = container; + } + + update(state) { + if (!state.error) { + this.render(state.contributors); + } + } + + /** + * Renders the list of contributors + * @param {Object[]} contributors An array of contributor objects + */ + render(contributors) { + // TODO: replace this comment and the console.log with your own code + + // empty the conatainer from its old data + this.container.textContent = ''; + + // create section title + const ul = createAndAppend('ul', this.container, { + text: 'Contributions', + class: 'contributors-ul' + }); + + // create the contributors list + contributors.forEach( Contributor => { + const li = createAndAppend('li', ul, { class: 'Contributor-li' }); + const ContributorDiv = createAndAppend('div', li, { class: 'Contributor-div' }); + + // create contributor image + createAndAppend('img', ContributorDiv, { + class: 'contributors-img', + src: Contributor.avatar_url, + }); + + // create contributor name + createAndAppend('a', ContributorDiv, { + class: 'contributors-a', + text: Contributor.login, + href: Contributor.html_url, + target: '_blank', + }); + + // create contributors number + createAndAppend('span', ContributorDiv, { + class: 'contributors-span', + text: Contributor.contributions, + }); + }); + } + } + + window.ContributorsView = ContributorsView; +} \ No newline at end of file diff --git a/Week3/homework/part2/ErrorView.js b/Week3/homework/part2/ErrorView.js new file mode 100644 index 000000000..d71aec290 --- /dev/null +++ b/Week3/homework/part2/ErrorView.js @@ -0,0 +1,31 @@ +use strict'; + +{ + const { createAndAppend } = window.Util; + + class ErrorView { + constructor(container) { + this.container = container; + } + + update(state) { + this.render(state.error); + } + + /** + * Renders an error for the 'error' message type. + * @param {Error} error An Error object + */ + render(error) { + this.container.innerHTML = ''; + if (error) { + createAndAppend('div', this.container, { + text: error.message, + class: 'alert alert-error', + }); + } + } + } + + window.ErrorView = ErrorView; +} \ No newline at end of file diff --git a/Week3/homework/part2/HeaderView.js b/Week3/homework/part2/HeaderView.js new file mode 100644 index 000000000..f49c3e77e --- /dev/null +++ b/Week3/homework/part2/HeaderView.js @@ -0,0 +1,46 @@ +'use strict'; + +{ + const { createAndAppend } = window.Util; + + class HeaderView { + constructor(account, header, fetchData) { + this.account = account; + this.header = header; + this.fetchData = fetchData; + this.select = null; + } + + update(state) { + if (!this.select && !state.error) { + this.render(state.repos); + } + } + + /** + * Renders the data for the 'select' message type. Create a