diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 000000000..75d0b1e09 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,12 @@ +{ + // See https://go.microsoft.com/fwlink/?LinkId=733558 + // for the documentation about the tasks.json format + "version": "2.0.0", + "tasks": [ + { + "type": "npm", + "script": "install", + "problemMatcher": [] + } + ] +} \ No newline at end of file diff --git a/Week1/.vscode/settings.json b/Week1/.vscode/settings.json new file mode 100644 index 000000000..aef844305 --- /dev/null +++ b/Week1/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "liveServer.settings.port": 5501 +} \ No newline at end of file diff --git a/Week1/index.html b/Week1/index.html new file mode 100644 index 000000000..10de9623b --- /dev/null +++ b/Week1/index.html @@ -0,0 +1,23 @@ + + + + + + + + + + + + + HYF-GITHUB + + + + + +
+ + + + \ No newline at end of file diff --git a/Week1/index.js b/Week1/index.js new file mode 100644 index 000000000..a8b71e1f1 --- /dev/null +++ b/Week1/index.js @@ -0,0 +1,134 @@ +'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 createAndAppend(name, parent, options = {}) { + const elem = document.createElement(name); + parent.appendChild(elem); + Object.keys(options).forEach(key => { + const value = options[key]; + if (key === 'text') { + elem.textContent = value; + } else { + elem.setAttribute(key, value); + } + }); + return elem; + } + + // Header + function selectOptions(nameOptions) { + const repoSelect = document.getElementById('repoSelect'); + for (let i = 0; i < nameOptions.length; i++) { + createAndAppend('option', repoSelect, { value: i, text: nameOptions[i].name }); + } + } + + // Create table on left within main div + function displayInfo(element) { + const container = document.getElementById('container'); + const divInfo = createAndAppend('div', container, { + id: 'leftSide', + class: 'left-div whiteframe', + }); + // Table info + createAndAppend('table', divInfo, { id: 'table' }); + const table = document.getElementById('table'); + createAndAppend('tbody', table, { id: 'tbody' }); + function createTableRow(label, description) { + const tableR = createAndAppend('tr', table); + createAndAppend('td', tableR, { text: label, class: 'label' }); + createAndAppend('td', tableR, { text: description }); + } + + createTableRow('Repository: ', element.name); + createTableRow('Description: ', element.description); + createTableRow('Forks : ', element.forks); + const newDate = new Date(element.updated_at).toLocaleString(); + createTableRow('Updated: ', newDate); + } + + // Contributors + function contributorsList(element) { + fetchJSON(element.contributors_url, (err, data) => { + const container = document.getElementById('container'); + createAndAppend('div', container, { + id: 'rightSide', + class: 'right-div whiteframe', + }); + const rightSide = document.getElementById('rightSide'); + createAndAppend('h7', rightSide, { + text: 'Contributions', + class: 'contributor-header', + }); + createAndAppend('ul', rightSide, { + id: 'list', + class: 'contributor-list', + }); + + const list = document.getElementById('list'); + for (let i = 0; i < data.length; i++) { + const contributorURL = createAndAppend('a', list, { href: data[i].html_url, target: '_blank' }); + const contributorItem = createAndAppend('li', contributorURL, { class: 'contributor-item' }); + createAndAppend('img', contributorItem, { + src: data[i].avatar_url, + class: 'contributor-avatar', + }); + const contributorData = createAndAppend('div', contributorItem, { class: 'contributor-data' }); + createAndAppend('div', contributorData, { text: data[i].login }); + createAndAppend('div', contributorData, { + text: data[i].contributions, + class: 'contributor-badge', + }); + } + }); + } + + function main(url) { + fetchJSON(url, (err, data) => { + const root = document.getElementById('root'); + if (err) { + createAndAppend('div', root, { text: err.message, class: 'alert-error' }); + } else { + createAndAppend('header', root, { id: 'top', class: 'header' }); + const top = document.getElementById('top'); + createAndAppend('h7', top, { id: 'title', text: 'HYF Repositories' }); + createAndAppend('select', top, { id: 'repoSelect', class: 'repo-selector' }); + createAndAppend('div', root, { id: 'container' }); + data.sort((a, b) => a.name.localeCompare(b.name)); + selectOptions(data); + displayInfo(data[0]); + contributorsList(data[0]); + + document.getElementById('repoSelect').onchange = function startListener() { + const selectedItem = this.options[this.selectedIndex].value; + const leftSideInfo = document.getElementById('leftSide'); + leftSideInfo.parentNode.removeChild(leftSideInfo); + const contributors = document.getElementById('rightSide'); + contributors.parentNode.removeChild(contributors); + + displayInfo(data[selectedItem]); + contributorsList(data[selectedItem]); + }; + } + }); + } + + const HYF_REPOS_URL = 'https://api.github.com/orgs/HackYourFuture/repos?per_page=100'; + + window.onload = () => main(HYF_REPOS_URL); +} diff --git a/Week1/style.css b/Week1/style.css new file mode 100644 index 000000000..487cfe943 --- /dev/null +++ b/Week1/style.css @@ -0,0 +1,150 @@ +.alert-error { + color: red; +} +body { + width: 768px; + margin-left: auto; + margin-right: auto; + background-color: #f8f8f8; + font-family: 'Roboto', sans-serif; + color: rgb(0, 0, 0, 87%); + margin-top: 0; +} + +#container { + display: flex; + flex-direction: row; + align-items: flex-start; +} + +@media (max-width: 767px) { + body { + width: 100%; + } + #container { + margin: 0; + flex-direction: column; + align-items: stretch; + } +} + +h1, +h2, +h3, +h4 { + color: rgb(0, 0, 0, 54%); +} + +.header { + color: white; + background-color: #3f51b5; + padding: 8px 16px; + margin-bottom: 16px; + display: flex; + flex-direction: row; + align-items: center; +} + +.repo-selector { + margin-left: 16px; + font-size: 14px; + width: 250px; + height: 32px; + padding: 2px; +} + +.left-div, +.right-div { + background-color: white; + flex: 1; +} + +.left-div { + padding: 16px; + margin-right: 16px; +} + +@media (max-width: 767px) { + .left-div { + margin: 0; + } +} + +.contributor-list { + list-style-type: none; + padding: 0; + margin: 0; +} + +.alert { + padding: 0.75rem 1.25rem; + margin-bottom: 1rem; + border-radius: 0.25rem; + flex: 1; +} + +.contributor-header { + font-size: 0.8rem; + color: rgb(0, 0, 0, 54%); + padding: 16px 16px 8px 16px; +} + +.contributor-item { + border-bottom: solid 1px rgb(0, 0, 0, 12%); + padding: 16px; + display: flex; + flex-direction: row; + align-items: center; + cursor: pointer; +} + +.contributor-avatar { + border-radius: 3px; + margin-right: 16px; + height: 48px; +} + +.contributor-data { + flex: 1; + display: flex; + flex-direction: row; + justify-content: space-between; + align-content: center; +} + +.contributor-badge { + font-size: 12px; + padding: 2px 8px; + line-height: 1rem; + background-color: gray; + color: white; + border-radius: 4px; +} + +table { + table-layout: fixed; + color: rgb(0, 0, 0, 81%); +} + +td { + vertical-align: top; +} + +td:first-child { + width: 100px; + min-width: 100px; + max-width: 100px; +} + +td.label { + font-weight: bold; +} + +.whiteframe { + margin-bottom: 8px; + border: none; + border-radius: 2px; + background-color: #fff; + box-shadow: 0 1px 8px 0 rgba(0, 0, 0, 0.2), 0 3px 4px 0 rgba(0, 0, 0, 0.14), + 0 3px 3px -2px rgba(0, 0, 0, 0.12); +} diff --git a/Week2/.vscode/settings.json b/Week2/.vscode/settings.json new file mode 100644 index 000000000..aef844305 --- /dev/null +++ b/Week2/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "liveServer.settings.port": 5501 +} \ No newline at end of file diff --git a/Week2/App.js b/Week2/App.js new file mode 100644 index 000000000..2cd7f83ae --- /dev/null +++ b/Week2/App.js @@ -0,0 +1,81 @@ +'use strict'; + +/* global Util, Repository, Contributor */ + +class App { + constructor(url) { + this.initialize(url); + } + + /** + * Initialization + * @param {string} url The GitHub URL for obtaining the organization's repositories. + */ + async initialize(url) { + // Add code here to initialize your app + // 1. Create the fixed HTML elements of your page + // 2. Make an initial XMLHttpRequest using Util.fetchJSON() to populate your