Skip to content

Instantly share code, notes, and snippets.

@Theartbug
Last active April 23, 2018 19:38
Show Gist options
  • Save Theartbug/eb670f062d8a85fcceed59e09671662c to your computer and use it in GitHub Desktop.
Save Theartbug/eb670f062d8a85fcceed59e09671662c to your computer and use it in GitHub Desktop.
RWD 11/20/17

12/11/2017 RESTful APIs

Random Notes

-Stack of our dev environment: - Client: localhost:8080 - Makes HTTP requests - API_url points toward server - Server: NodeJS, Express - Makes queries to DB - Sends response back to client - Environmental variable point towards database location (database_url) - Database: postgres - Sends data as result -Stack of our production environment: - Client: orgName.github.io/repoName - Makes HTTP requests - API_url points toward server - Server: NodeJS, Express - Makes queries to DB - Sends response back to client - Environmental variable point towards database location (database_url) - Database: heroku - Sends data as result

  • Operate local dev environment while working on projects! Must create a database on each computer.
  • pg:push can send a local database to heroku on macs.

REST / API

REpresentational State Transfer - A design pattern used to form an API - Rules for transferring data with HTTP requests - Constraints: - URL paths are based on resources: - One path for one resource - GET /comments/:id - GET /comments - POST /comments - PUT /comments/:id - DELETE /comments/:id - HTTP methods are used appropriately (GET for getting, PUT for updating, DELETE to remove, POST to send) - Data is sent as JSON or XML - Server is stateless (server has no idea what is happening on client side)

- Non RESTful examples:
    - ``GET /comments/:id/update``
    - ``GET /comments?id=d&method=update``
- Stateless server does not track the apps Stateless
    - All necessary info to update a resource is in every request or response
    - Able to have one server and multiple clients
    - States: loged in, stuff in shopping cart, etc

Application Program Interface - Collection of functions / classes / objects to use in code - Just like a library! - How the library and code interact - Web APIs can provide services or data. - RESTful APIs follow REST constraints.

PostMan

  • Used to query / manage APIs.
  • Insert url into request bar, will get data from database according to request.
  • Can make a POST request using key:value pairs in the app under the body tab
  • Can have multiple tabs open
  • When making a POST request, use form-urlencoded in the body tab.

console.developers.google.com/apis

  • Create API, credentials, create API key
  • dashboard, enable APIs and services, google books, click enable
    • key will be in all API credentials.
    • append query parameter &key=yourAPIkey to all requested URLs.
  • Preforming a search:
q - Search for volumes that contain this text string. There are special keywords you can specify in the search terms to search in particular fields, such as:
intitle: Returns results where the text following this keyword is found in the title.
inauthor: Returns results where the text following this keyword is found in the author.
inpublisher: Returns results where the text following this keyword is found in the publisher.
subject: Returns results where the text following this keyword is listed in the category list of the volume.
isbn: Returns results where the text following this keyword is the ISBN number.
lccn: Returns results where the text following this keyword is the Library of Congress Control Number.
oclc: Returns results where the text following this keyword is the Online Computer Library Center number.

Demo

  • Don't make queries from client side as the key will not be secret.
  • Node module called superAgent: https://visionmedia.github.io/superagent/
  • Query parameters are preceeded by a '?' in a url. Allows access with the body.query in routes.

terminal:

npm i -s superagent

server.js:

const superagent = require('superagent');

const googleUrl = 'https://www.googleapis.com/books/v1/volumes?q=';
const gAPIKey = proccess.env.key;

app.get('/books/search', (req, res) => {
    const query = req.query.search;
    superagent //will make another HTTP request to outside API
    .get(`${googleUrl}${query}&key=${key}`)
    .end((err, data) => {
        //res.body is the response obj from google's server.
        //res.body.items = an array of books
        //TODO: only get a certain number of books
        // arr.slice() to shorten array
        // arr.map() shortened array to go through each book and shrink its data to what is needed
        // GOAL: send back an array of objects to call .toHtml().
        const bookReturn = resp.body.items.slice(0,10).map( book => {
            return {
                title: book.volumeInfo.title,
                isbn: book.industryIdentifiers[0].identifier,
                author: book.authors[0],
                book.imageLinks.thumbnail,
                description: volumeInfo.description
            }
        })
        res.send(bookReturn); 
    }
});

.env:

const key = 'AIzaSyCYn6mCA1f7vYcprRhxdpJ-TEdA77o4EBk';

12/11/2017 Middleware

Random Notes

  • Additional users to edit database:

    1. Heroku.com
    2. Access -> new collaborator
    3. Check email and accept
    4. Obtain heroku Git URL
    5. type "git remote add heroku herokuURL"
    6. type "heroku git:psql" to access the database
  • Update Heroku

    1. git push heroku master
    2. git push heroku branch:master
    3. Look at the Deploy tab to see when the last commit was made. Can easily roll back to previous version.
  • Make gh-pages branch

    1. git checkout gh-pages
    2. Or go into settings and set gh pages to master.
  • Root issue on gh-pages

    1. Routes are incorrect with '/' due to name of repository
    2. Set page.base('repoName') right before page.start();
    3. Add '.' prior to all links in html.

Middleware Functions

  • Functions that take data and then call the next provided function.
  • With that data they can manipulate, obtain more, etc.
  • Examples are body-parser and ExpressJS.use()
  • app.use(req, res, next) will add a method to each route to run every time prior to request fulfillment.
  • body parser will expose data from request as request.body.

Steps for UPDATE feature

  1. Add update button to book template in the detailed book view.
  2. Event listener will capture books current info, redirect to update form page /book/:id/update
  3. Add a route listening for the Update button. Show only the update form and hide everything else.
  4. Form with inputs of book information. Set "value" of inputs to book information. Add event listener to submission.
  5. Create a function to send a PUT request to server in Models.js with form submission.
  6. Create a route to accept the PUT request to 'api/v1/books/:id'. RESTFUL design means the route URI does not need create on it.
  7. Add function to query database in route to update data. UPDATE SET WHERE
  8. Redirect the page after recieving updated book info, and reappend all the books to the page.

Demo

html:

// in template for detailed book
// if it was placed in the regular book template, would have to hide somehow.
<button data-method="update">UPDATE</button>

booView:

bookView = (ctx) => {
    $(button[data-method="update"]).on('click', function () {
        page(`/ClientSide/cards/${ctx.book.id}/update`);
    });
}

bookView.initUpdatePage = (ctx, cb) => {
    const book = ctx.book;
    $('main section').hide();
        $('.tab-book').hide();
        $(`section[data-method="update"]`).show();
        

        event.preventDefault();
        const updatedData = {
            isbn: $('#update input[name="isbn"]').val(book.isbn),
            description: $('#update input[name="description"]').val(book.description),
            author: $('#update input[name="author"]').val(book.author),
            title: $('#update input[name="title"]').val(book.title),
            image_url: $('#update input[name="image_url"]').val(book.image_url)
        }

        $('#update-book').on('submit', app.Book.update(book.id, updatedData))
}

models.js:

Book.update = (id, data) => {
    $.ajax({
        url: `${API_URL}/api/v1/books/${id}`,
        method: 'PUT',
        data: data
    })
    .done(data=> {
        page(`/books/${id});
    })
}

routes.js:

page('/cards/:id/update', app.Book.fetchOne,app.bookView.initUpdatePage)
// could do a server request or use the local data of Book.all. Server request is better in cases where multiple people may be updating information and local stuff may be outdated.

server.js:

app.put('/api/v1/books/:id', (req, res) => {
    client.query('UPDATE books SET author=$1, isbn=$2, description=$3, title=$4, image_url=$5;', [req.body.author, req.body.isbn, req.body.description, req.body.title, req.body.image_url])
    .then(data => res.status(200).send('Book updated'))
    .catch(console.error);
})

12/08/2017 Single Page Applications & Client-Side Routing

Random Notes

  • Create cleaner code by returns when chaining expressions or long arrays.
  • Place app.Card.fetchAll(app.cardView.initIndexPage) at the bottom of the html Page
  • use var to declare a variable multiple times when there is ambiguity about what script may come first. Alternatively, declare the variable in html prior to all the scripts that will use it.
  • Having api within the route for a HTTP request will help alert that it will serve data instead of a file.
  • Console.table() will create a table of object properties if given an object.
  • Don't concat strings with objects:
console.log('object:', {...}); // will work
console.log('object' + {...}); // will break

Multiple Servers

  • Live-server is in local clientside environment. Start the server with nodemon server.js. This server can only serve files.
$.get('http://localhost:3000/api/v1/books)
// pings the node server

$.get('http://localhost:8080/api/v1/books)
// pings the live-server
  • In production, only github pages is pinged for files and heroku is pinged for database data.

page.js

  • Clientside router library that listens for requests to certain routes and deliver views to those routes.
  • CDN: <script src="https://cdn.rawgit.com/visionmedia/page.js/master/page.js"></script>
//page('routeToListenFor', (context object, anotherCallback) => {}, anotherCallback);

page('/', app.Book.loadAll(app.Book.initIndexPage)); //runs initially as a function on load, but does not work as a callback. Instead:

page('/', () => {
    app.Book.loadAll(app.Book.initIndexPage)    
}) //will work unlike above due to callback syntax. Will continually run after each call. May post multiple items to the page. Be sure to empty out the section in the function each time.

page('/about', app.aboutView.initAboutPage); //function reference to be called later

page('*', (ctx, next) => {console.log('nothing to see here!')});

page.start(); // starts listening

Demo

  • Single page app has one index.html file and is dynamically changed depending on what is requested through HTTP requests and routes.
  • Hide / show things depending on request
    • Was initially done with event listeners, but with empty href=#. Had to prevent default. The address bar did not update with changes. Unable to go backwards / forwards.
  • Routers send files / API sends data.
  • For showing a single book at a time using page.js:
// in handlebars template
<section href='/books/{{id}}'>{{image_url}}</section>

// in routes.js
page('books/:id', app.Book.fetchOne, app.cardView.initDetailPage);
    // will call a function that will query our database server in heroku for one specific card based on the id given.
    // This function will be created on the Book class
    // Will then call another callback after the first finished.

1. user clicks a link
2. pagejs will run app.Book.fetchOne
    - and pass it two things: ctx (object) and next (function = app.bookView.initDetailPage);
    - fetchOne will get data from database then call next function (initDetail)
    - initDetail will append to DOM

In book.js:

Book.fetchOne = (ctx, cb) => {
    $.get('https://lab11books.herokuapp.com/api/v1/books/:id')
    .then(data => {
        // data is an array, need 1st object in it, then will transform it into a card instance to use .toHtml method
        ctx.book = new Book(data[0]);
        cb();
        })
    .fail(console.log);
}; // change the requested server to the live-server when in a dev environment.

In server.js:

app.get('/api/v1/:id', (req, res) => {
    client.query('SELECT * FROM books WHERE id = $1', [req.params.id])
    .then(data => res.send(data.rows))
    .catch(cosole.error);
})

In bookView.js:

bookView.initDetailPage = (ctx) => {
    $('main section').hide();
    $('#cards').empty().show();
    $('#books).append(ctx.book.toHtml());
}
  • Create a variable for the heroku app API and localhost. Will need to use template literal. Comment out to switch between them.
const API_URL = 'https://lab11books.herokuapp.com';
const API_URL = 'https://localhost:3000';

12/07/2017 Production & Deployment

Demo

  • github -> new organization in dropdown (call it anything) -> create two repos -> label each repo by server and client -> add pair as collaborator -> git clone repositories and create aliases
  • Can create aliases for repositories
  • All public folder will be on client side, server.js will be in server side.

get clone REPOSITRY_LINK alias

  • Write readMe.md with tasks

    • Create an Express app:
    • That connects to PG database
      • Create a database with a cards table and seed stuff in it
      • Design schema with cards
        • id, recipient, sender, content
    • Create routes
      • GET api/v1/cards
      • GET api/v1/cards:recipient
  • npm init, fill in fields

  • npm i -s express (saves express to package.json)

  • npm i -s pg (interfaces with database)

  • create a .gitignore to ignore node_modules/

  • create eslintrc.json and reference a file in the class examples. Remove globals. Remove "env" browser and jquery.

  • commit frequently during set up.

In server.js:

require('dovenv').config();
const express = require('express');
const app = express();
const pg = require('pg');


const PORT = 3000;
const conString = 'postgres://@localhost:5432/custom_cards';
//5432 is the default port postgres will serve on 
const client = new pg.Client(constring);
client.connect();


app.get('/api/v1/cards', (req,res) => {
    client.query('SELECT * FROM cards;')
        .then(data => res.send(data.rows)); //will send the data as an object to the browser
});

app.get('/api/v1/:recipient', (req,res) => {
    client.query('SELECT * FROM cards WHERE recipient = $1', [:reipient])
        .then((data) => res.send(data.rows)); //will send the message from the selected recipient
});

app.get('*', (req,res) => {
    res.text.send('ERROR path does not exist')
})

app.listen(PORT, () => (console.log('listening for api requests to ${PORT}')));

In psql:

psql -U postgres

CREATE DATABASE custom_cards;

\c custom_cards; //switches to new db

CREATE TABLE cards (id SERIAL PRIMARY KEY, recipient VARCHAR(50), sender VARCHAR(50), content VARCHAR(250));

\dt // lists tables in database

\d cards // gives schema of table

INSERT INTO cards (recipient, sender, content) VALUES ('mom', 'grace', 'Merry Christmas!');

INSERT INTO cards (recipient, sender, content) VALUES ('dad', 'grace', 'You are a great dad!');

INSERT INTO cards (recipient, sender, content) VALUES ('Hazel', 'grace', 'MEOW MEOW');

SELECT * FROM cards; //displays the entire table to show changes

Environment Variables

  • Dev environment is run on our local computer with the purpose of editing / viewing changes without modifying live production environment.
  • Production environment is your app deployed for the public to use. The nodeJS file is taken from our local server and is instead run by a different server that the public can access. The same will happen with the database. Heroku manages both the database and server.
  • Staging environment is accessable by all team members and is tested for bugs. After tests can be pushed to Production or back to Dev.
  • Add .env file for environment variables to be able to still use local environment. Ignore it in .gitignore. Save as a dependency. Require in server.js.

in server.js:

const PORT = process.env.PORT;

const client = new pg.Client(process.eng.DATABASE_URL);

.env file:

PORT=3000;
DATABASE_URL=postgres://@localhost:5432

in terminal after creation of .env file:

npm i -s dotenv

Heroku

  • Allows the deployment of an app and manages hosting / eases deployment.
  • Heroku will give back a constring to link server/database to Heroku, use a placeholder for constring and PORT

In terminal:

heroku create demo //must be unique to heroku

git push heroku master //deploys heroku to project
  • To configure the database url of heroku place the following in terminal to connect to database:
 $ heroku addons:create heroku-postgresql:hobby-dev
  $ heroku config
  $ heroku ps:restart

  heroku pg:psql //opens database created with heroku

  heroku pg:copy //to push a database that already exists up to Heroku on a mac
  • Frontend tasks:
    • index.html that displays books
    • create an about view for displaying content on app
    • use AJAX to render books dynamically
    • Style using mobile-only approach
    • Book objects, fetchAll, loadAll scripts

Server Debugger

  • click debugger. Click on gear on top. Will launch a launch.json file. Will contain server.js under "program".
  • Will allow breakpoint placement in code.
  • A bar will appear at the top of the code with play, pause, step-over, step-into.
  • Add a breakpoint by clicking the line number on the left side of the bar.
  • Can see what variables are in the terminal by typing them in during a breakpoint pause.
  • Do not run the server in the terminal, go to the debugger and press play.
  • Must be added to every project.

12/06/2017 Functional Programming

Random Notes

  • Client Technologies
    1. jQuery / AJAX
    2. handlebars.js, chart.js, highlight.js, etc.
    3. DOM (HTML + CSS)
  • Server Technologies
    1. SQL
    2. Express
    3. pg
    4. fs
    5. body-parser
  • Database Technologies
    1. postgres (Database management system)

Body-Parser in the Server

  • NodeJS module. When a user submits data with a form, the AJAX call sends that request in a POST method, the body of the request holds the data from the form.
  • Body-parser makes the body part of the POST request easier for the server to understand.
  • Access the body information with request.body.objectKeyName
  • Will appear as an object / string that was sent.
    • If a string is sent, the string will be the key name, and an empty string for the value in an object.
  • Without body-parser will not be able to access the object in the body from the request.

Scope

  • Const and let are block scoped (inside of {}).
  • var is functional scoped
  • Closure allows functions inside of other functions to have access to variables of their parent functions. The inner function is then exposed by being returned.
function superSecretPassword() {
    // has access to its variables, and any global variables
    const password = 'standing desk';
    console.log( 'I know the hidden word', password === 'standing desk' ); // true

    function spillIt () {
        // has access to its variables, its parent variables, and any global variables
        const pin = '2221';
        console.log( `don't tell anyone but the secret password is ${password}!` );
        console.log(`or you can use the pin: ${pin}`);
    }

    // we can expose enclosed variables or functions by returning them.
    return spillIt;
}
  • spillIt() is not in the global scope.
  • When it is returned from superSecretPassword, it can be invoked in two ways
// 1st way: save it in a variable to invoke later
const spillIt = superSecretPassword();
spillIt();

// 2nd way: immediate invokation of spillIt
superSecretPassword()();
  • This allows the global scope to have access to stpillIt()

IIFE

  • Immediately invoked function expression
  • Wrap a function in parenthesis and then invoke it with the invoke parenthesis after being wrapped.
(function (x) => (stuff))(argument);
  • Can be used to create closure
(function() {

    const passwordManager = {};
    passwordManager.password = 'monkeys';

    passwordManager.spill = function () {
        console.log( `don't tell anyone but the secret password is ${this.password}!` );
    };

    passwordManager.secure = function (newPW) {
        this.password = newPW;
    };

    passwordManager.spill();
})();
  • passwordManager.spill() is no longer available in the global scope
  • In order to access it in the global scope, add it as a method to an object
const app = {};

(function(app) {

    const passwordManager = {};
    passwordManager.password = 'monkeys';

    passwordManager.spill = function () {
        console.log( `don't tell anyone but the secret password is ${this.password}!` );
    };

    passwordManager.secure = function (newPW) {
        this.password = newPW;
    };

    app.passwordManager = passwordManager;
})(app);

app.passwordManager.spill();
  • Can now be called in the global scope and used elsewhere.
  • The reasoning is to not pollute the global scope, and to only expose methods purposefully.

Functional Programming

  • Characteristics
    • Immutable
    • Declarative
    • Pure functions (given same inpute will always have same output, no side effects)
    • Higher order functions

Array methods that create declarative programming and solidify immutability:

  • These methods can be chained on each other!

.forEach(): takes a callback function and applies that function to each item in the array. Does not return a new array.

// `.forEach()` => does something once per item in the array
const drinks = [];
meals.forEach( meal => {
  drinks.push( meal.drink );
}); // does not mutate the original array or return a new array

.map(): loops through the array and applies something to each item, then returns all mutated items in a new array. Must have a return statement if the mutating function is longer than one line.

// `.map()` => alters each item in the array and returns a new array with those values
const desserts = meals.map( mel => mel.dessert);

.filter(): checks each item in the array against a condition, if true, those items are returned as a new array.

// `.filter()` => checks each item in an array against a condition, items that satisfy it are returned
const sodaMeals = meals.filter((meal) => return (meal.drink === 'milk'));

.reduce(callback(accumulator, currentvalue), [initialvalue]): collapses the array to a single item and returns that as a value. The accumulator keeps track of the combined items. Can take an optional initial value

const array1 = [1, 2, 3, 4];
const reducer = (accumulator, currentValue) => accumulator + currentValue;

// 1 + 2 + 3 + 4
console.log(array1.reduce(reducer));
// expected output: 10

// 5 + 1 + 2 + 3 + 4
console.log(array1.reduce(reducer, 5));
// expected output: 15
// Initial value is optional. Will be used as initial value.

12/04/2017 SQL: JOIN & Relations

Random Notes

  • In terminal, npm *scriptName* will run a script from package.json
  • add the script to package.json
"scripts": {
    "keyWord":"code to run"
}
  • SQL is strictly typed.
  • pg is the npm module that allows us to send a query from our server to our database.
  • fs is the npm module that allows us to interface with the server's files
  • process.env.PORT will be used during production
  • Backticks will allow multi-line strings. Best used for SQL queries in nodeJS!

SQL

  • Placeholders are noted with ':' preceeding a node route statement.
  • Inside the body of the query, use '$number' and give an array that denotes what that variable will receieve, the number is the number in the array. $1 denotes place 0 in the array.
app.get('/tasks/:category)', function(request, response) {
    client.query(`SELECT * FROM tasks WHERE category = $1`, [request.params.caegory]) //request.params is an object that the placeholder :category has access to
    .then(function(data) {
        response.send(data.rows);
    }) // always give a catch error statement when giving a variable to a get request
    .catch(function(err)) {
        console.error(`request /task/:category --- ${err}`);
    } 
}
  • request.params An object containing properties mapped to the named route “parameters”. For example, if you have the route /user/:name, then the "name" property is available as req.params.name. This object defaults to {}.

  • CREATE TABLE IF NOT EXISTS table will only create a new table if none exists by the name you give it.

  • SELECT COUNT(*) ALL FROM table will give us the number of rows

  • Schema: What the table's cloumns and values will be (data types)

JOIN & Relations

  • Redundancy is error-prone
  • Normalization decomposes a table into smaller, less redundant tables without information loss.
  • Use Foreign keys in old table to reference Primary key in new table.
  • DROP TABLE table Kills a table.
CREATE TABLE authors (
    id INTEGER PRIMARY KEY,
    name VARCHAR(50) UNIQUE NOT NULL,
    url VARCHAR(225)
);
  • Primary key creates a unique non-repeating link
CREATE TABLE articles (
    id INTEGER PRIMARY KEY,
    title VARCHAR(50) NOT NULL,
    arthorId INTEGER NOT NULL REFERENCES authors(id),
    markdown TEXT NOT NULL,
    publishedOn DATETIME
);
  • REFERENCES table(primaryKey) takes a primary key from another table to reference
  • Database Relationships
    1. 1:1 (one article to one author)
    2. 1:many (one article to many authors)/ Many:1 (many articles to one author)
    3. Many / many (multiple authors to multiple articles)
SELECT articles.id, title,  authors.name AS author, authors.url AS authorUrl, markdown, publishedOn
FROM articles
INNER JOIN authors
    ON articles.authorId = authors.id
ORDER BY publishedOn DESC;
  • INNER JOIN This query will return all of the records in the left table (table A) that have a matching record in the right table (table B)
  • AS creates aliases for columns in new table
SELECT content, user.name AS person, categories.name AS category, tasks
INNER JOIN users
    ON tasks.user_id = users.user_id
INNER JOIN categories
    ON tasks.category_id = categories.category_id

OR

SELECT content, categories.name AS category, users.name as person
FROM tasks, users, categories
WHERE tasks.user_id = users.user_id AND tasks.category_id = categories.category_id;
  • Double INNER JOIN can join multiple tables, in this case 3 tables to create a new one.
  • Can use a WHERE clause instead of INNER JOIN for inner joins - much more readable and shorter!

DEMO

  • INSERT INTO table (column, column2, ...) VALUES (value, value2, ...);*
INSERT INTO tasks (content, user_id, category_id) VALUES ('hanging out', 2, 1);

12/04/2017 SQL & POSTGRES

Random Notes

  • WRRC (without DB):

    1. Send Request from client ($.post / $.get)
    2. Recieve Request to server (app.post / app.get)
    3. Send Request from server (client.query())
    4. ??? DB stuff
    5. ??? DB stuff
    6. Recieve Request to server (.then(), .catch())
    7. Send Request from server(response.sendFile)
    8. Receive Request to client (Promises: .then(), .done(), .error(), .success())
  • Callbacks run inside of other functions

    • Can be defined within the function call, or written elsewhere.
function singAnd (lyrics, callback) {
    console.log (lyrics);
    callback(); //The passed in function is invoked here
}
  • Can run javasctript files in the terminal using node.
node callback.js
// code prints here if any console.log()s

SQL

  • Better way to store persistence than localStorage.

  • Database Management Systems (DBMS) typically composed of tables of data

  • Documents is an alternative form of data storage, similar to JSON objects

  • SQL is a languaged used to work with the DBMS.

  • SQL statements are made up of clauses, expressions, and predicates

UPDATE country 
SET population = population + 1 //expression
WHERE name = 'USA'; // predicate
  • UPDATE, SET, and WHERE are clauses.
  • population = population + 1 is an expression
  • name = 'USA' is a predicate
  • When creating a table with CREATE TABLE, columns are defined with data types

SQL Template

SELECT column
FROM tables
WHERE conditional
  • In terms of Model, View, Controller for databases

    1. Model: tables in database (models are simplified version of a real world object. Columns are properties of objects. Rows are instances of that object)
    2. View: terminal / client computer
    3. Controller: server
  • PSQL is a direct link between the client and the database, another part to the DBMS. Appears within the terminal / shell

  • Postgress is the DBMS we are working with

  • pg runs within the server and connects the server to the database

Running DBMS

  • Type psql in terminal
  • Quit with \q
newdb=# CREATE TABLE dogs (name VARCHAR(50), color VARCHAR(50), age INGETER);

INSERT INTO dogs (name, color, age) VALUES ('Lewis', 'brown', 12);

UPDATE dogs SET age = 13 WHERE name = 'Lewis';
  • semicolon is very important! Will not run query without it.

pg

  • install: npm i -save pg
    • Make sure actually in project folder with server.js
  • Must set up to connect to database
    • In server.js: const pg = require('pg');
    • Different on Macs vs PC

Inside of server.js:

const pg = require('pg');
const client = new pg.client('postgres://@localhost:5432/kilovolt'); //port specific to each user
clinet.connect(); // now server is connected to database
  • client.query(queryStatement) sends requests from server to database.
  • .then() will run once a response is received from previous request statement.

CRUD

  • CRUD: Create, Read, Update, Destory

    • What can be done with a database
    • Each respond to HTTP methods
  • Create: POST request -> CREATE TABLE / INSERT INTO

  • Read: GET request -> SELECT FROM WHERE

  • Update: PUT request -> UPDATE SET WHERE

  • Delete: DELETE request -> DELETE FROM WHERE

12/01/2017 NPM && Node.js

NodeJS

  • Node is not a library or frameworks.
  • Node is a runtime environment that uses the same engine as the browser version of javascript (Chrome V8) that allows us to write javascript in a server.
  • Node works with NPM (package manager) and modules / packages (express, body-parser, live-server, eslint).
  • NPM works in the commandline.

Express

  • An NPM package that is a framework that helps create a server

EX:

app.get('/', function(request,response){
    response.sendFile('./public/index.html');
});
  • Similar appearence to a HTTP request. This request is referencing the root directory.
  • / refers to the root directory of the server.
  • . refers to the current directory (greater specificity than public/index.html).

Install for Existing Node

  • Existing node projects have package.json file. This file will give a name, description, etc.
    1. cd into the directory that holds the package.json
    2. npm install will find the dependencies in the package.json and install them
    3. After packages are installed they will be held in a node_modules
    4. Add node_modules folder into .gitignore
  • server.js is to servers as index.html is to browsers. This file handles any HTTP request received and serve files requested.
  • routes within a server handle different kinds of requests
  • .listen will run the code in a server.
  • server.js will never exist on client.
  • broswer files will never execute in the server.
  • to load a framework / dependency:
// Load Express
const express = require( 'express' );

// Instantiate Express so that we can use its functionality
// Method that will handle our HTTP requests
const app = express();

// Designate a port to serve our app on. Mostly anything goes.
const PORT = 4567;

// Define which directory we will serve files from
// Tells our app to use these files for serving data
// This exposes the files. Without this, requested files would not be able to be given
app.use( express.static( './public' ) );

/* creating routes for our server to respond to   */
// each will run depending on the kind of request made (request listener), similar to event listeners
// Here is how to set up a GET route for the root of our website (eg when a user visits acl.com/)
// This is listening for a GET request on the root (when a client types root website url or website.com/index.html)
app.get( '/', function ( request, response ) {
    console.log( 'I CONSOLE IN THE SERVER (aka terminal) AHH' );
    response.sendFile( '/index.html', { root: './public' });
});

// Here is how to set up a GET route for the path acl.com/bat of our website
app.get( '/bat', function ( request, response ) {
    response.sendFile( '/public/bat-country.html', { root: '.'} );
});

// Let's 404 everything except for our routes and index.html
// Since the server runs this file from the top down, requests to '/' and '/bat' will be reached first.
// .status('404') is not required but should be used as it will change how it appears in dev tools.
app.get( '*', function ( request, response ) {
    console.log( 'they made a request to something??' );
    response.status('404').sendFile( '/public/404.html', { root: '.' } );
});

// Now let's tell the app to listen so that it can do its thing
// console.log() will print to the terminal, not the browser.
app.listen( PORT, function () {
    console.log( `listening on ${PORT}` );
});
  • Will not automatically refresh when something is changed in the server. Must restart with node: node server.js.
  • response.sendFile() is similar to a return statement, will not run code after the statement.
  • Cannot debug code in the browser from server files.

Install from Scratch

  1. Start with NPM init in the correct folder. Go through prompts. Will create a package.json
  2. Run NPM install --save express (will install the framework package express). Will then be listed in package.json as a dependency. Will install express automatically the next time someone runs npm install. Also adds node_modules folder and package-lock.json file.
// requires express and creates the express method in app variable
const express = require('express');
const app = express();
const PORT = 4567;
// can be found at http://localhost:4567

// exposes files to give to clients
app.use( express.static('./public'));

//routes are declared so client does not have to know direct filepath for files
//route declares the type of request and the url to listen on
// request must be a parameter in the function callback, even if it is not needed
// request object has a large amount of data about the request made including: permissions, headers, etc.
app.get('/dogs', (request, response) => {
    response.sendFile('/public/cats4life.html', {root: '.'});
});

app.get('/', (request, response) => {
    response.sendFile('/public/index.html', {root:'.'});
});


// sets up a listener for requests on particular port number. Can have a callback function.
app.listen( PORT, () => {
    console.log(`listening on ${PORT}`)
});

AJAX server requests

// Broswer side

// AJAX request, using 'humans' as an alias. Obscuring the data
$.getJSON('humans', (resp) => {
    console.log(resp);
});

// Server side

// request is coming from the alias 'humans'
// {root: '.'} is required in .sendFile, or full path
app.get('/humans', (response, response) => {
    response.sendFile('public/humans.json', {root:'.'})
});

11/30/2017 AJAX & JSON

Random Notes

  • isup.me will check a whether a website is down for just you or everyone.
  • You can add variables to eslint to be considered globals, which can resolve an error where eslint does not recognize a variable defined in a separate file.
  • control+shift+k: vscode shortcut to delete current selected line.
  • control+k+f: format js/json code.

WRRC - Web Request Response Cycle

  • How your website is sent to the client in the browser. Your website is a collection of files (.js, .png, .html, .css, .svg).

  • A server is another computer elsewhere that holds many files needed to see websites. A server allows multiple people to use those files at their personal computers (client).

  • When the client moves through and interacts with a website in a browser, requests are made to the server to access files needed.

  • The client in the browser will send an HTTP request to a server for files needed:

    1. What files are needed? URI file path
    2. What action is to be done? HTTP method (GET / POST)
    3. Include headers for metadata (tell the server who we are)
    4. Include a body to send data to the server (form submission)
  • The server responds with an HTTP protocol:

    1. Status of request sent (success, failure)
    2. Headers for metadata
    3. Body is the file requested
  • In Chrome Dev Tools on the Network tab, requests are found with the header and response.

HTTP Methods

  • GET: will retrieve data from server (very first request is made from the browser for index.html file, all following is from html / js files)
  • POST: will send data to server to create /update a file
  • PUT: updates an existing file
  • DELETE: deletes an existing file

JSON - JavaScript Object Notation

  • Is plain text with the appearance of a js object literal.
  • Serializes objects (dehydrates them for rehydration later) for transfer between client and server.
  • Keys and strings require double quotes.

{"key":value}

AJAX - Asynchronous JavaScript and XML

  • Allows us to make an HTTP request from javascript. Greater control of when/how things happen. Eliminates the need for the browser to make another url request, smaller requests instead (refresh part of the page).
  • Asynchronous, allows js script to continue running until response returns instead of waiting for response.
  • Callback function is triggered when response is given.

With jQuery:

  • $.ajax(object): passed an object with settings
$.ajax({
    method: 'GET',
    url: 'data.json',
    success: (data) => data,
    error: (res,status,err) => {
        console.error(status, err)
    }
});
  • $.get('filename'): shortcut for GET. Can have callback functions chained depending on server response.
$.get('data.json')
    .done((res)=> {console.log(res)})
    .fail((res,status,err) => {console.log(status, err)})
  • $.getJSON('filename')
$.getJSON('data.json')
    .done((res)=> {console.log(res)})
    .fail((res,status,err) => {console.log(status, err)})

11/29/2017 Forms & Typography

Typography

  • How to present text with intention of user experience.
  • Typography: website as Audio: movie. It is noticable when something is off / wrong, removes user from experience.
  • Important vocab: typeface, font, cap-height, x-height, baseline, descender, ascender, serif, sans serif, color, weight.
  • Typeface is the characteristics that make it unique.
  • Font is the collection of the typface in italic, bold, etc.
  • Serif fonts have tails / decoration to the typeface. Better in print?
  • Sans-serif fonts without serif tails. Better in web media?
  • Can host fonts locally and through google fonts CDN.
  • Fonts can be sized with pixels, rems, and ems.
  • Font Scale the ratios between different areas with fonts in your media.
  • em relative in size to parent.
  • rem relative in size to base font-size for page.
  • pixels do not ever change. Are not responsive.
  • Type-scale.com will show different sizes and ratios for fonts.

Deep Dive :nth-of-type()

  • CSS pseudo-class selector
  • Will match all of the selected elements of a given type.
  • The parenthesis () can accept a n term which designates a pattern for matching.
  • n + 1 is equivalent to n, as it will cycle through 0 first.
  • You can place key words 'even' and 'odd' into ().
  • You can place a specific number to select directly (3).
  • How it works: https://css-tricks.com/how-nth-child-works/

EX: /* Odd paragraphs */ p:nth-of-type(2n+1) { color: red; }

/* Even paragraphs */ p:nth-of-type(2n) { color: blue; }

/* First paragraph */ p:nth-of-type(1) { font-weight: bold; }

Forms

    <fieldset>
        <input type='text' placeholder='Title'>
        <textarea placeholder='What to say?'>
        <input type='text' placeholder='Author Name'>
        <input type='text' placeholder='Author Website'>
        <input type='text' placeholder='Category'>
        <input type='checkbox'><label>Published</label>
    </fieldset>
</form>

11/27/2017 Templates

Attribute selector: Element[attributeName='value']

CSS :not() will filter out the selector given from the selector the not is attached to.

  • EX: artile:not(.template)

Arrow Functions: drop the function keyword for =>.

  • Can dispose of {} if the expression is single line
  • Can dispose of parameter () if there is only one parameter
  • Does not need return statement if expression is single line
  • Lexically binds 'this'. Does not change, is whatever 'this' was outside of the function call (context). Will often refer to the window. EX: Sunshine = x => x+7;

Handlebars.js

  • Templating system in html.
  • Compiles code from html into javasctript. That javasctript will fill in the placeholders and return a string to append to the DOM.
  • Handlebars.compile(input, options) will compile the template and return a string.
  • Placed in the section between script tags. Type = 'text/handlebars-template'.
  • Placeholders are inside {{}}. Does not render html.
  • {{{}}} will render html.
  • Use CDN of handlebars.js
  • Steps:
    1. Get template from html
    2. Compile template in JS function
    3. Use that function to create a filled template
    4. Append filled template to DOM

11/27/2017 jQuery and Events

Ternary operator: is a way to compactly evaluate conditional statements that only have two possible results.

condition ? true expression : false expression

  • Commonly used to determine what a value of a variable should be.

EX: let isWorthIt = weight > 20 ? true : false

$('').clone() is a powerful way to clone DOM elements and their children. Can be used in conjunction with a template class so these elements do not have to be created new each time!

Template Literals are used to more easily concat strings with variables. Backticks (``) are required instead of quotes. When expresions are inserted, use ${} around the expression. That expression can be anything evaluate-able!

EX: let variable = 'cool'!; This is a template literal, so very ${variable}!

Event Listeners will execute a callback function when a certain event is triggered on a certain element. The event listener designates the triggering event and the element it is listening on.

  • Can use 'this' to designate the element listened in the callback function.
  • $('').click(callback) will create a listener for a click. When .click() is empty it will create a click on the jQuery object element.
  • $('').on(trigger, optional filter, callback) behaves like the .addEventListener(). The filter is an added condition to the listener so that those with the added filter are the only elements the event is fired on.
  • Have the event listener with a filter listen on a parent element of dynamically created elements so the event listener fires to those dynamically created elements.

EX: $('parent').on('click', '.child', callback)

  • The callback will only fire when the elements with .child are clicked. No other elements within .parent will fire unless they have .child class.

Class exercise:

cakeView.handleFlavor = function () { const $cakeLayers = $('#actual-cake div'); $('input[name="flavor"]').change( function () { console.log('this is the element listening for the event:', this); console.log('$(this) is that same element as a jQuery object!:', $(this));

    $cakeLayers.css('background-color', $(this).val());
});

}; 0. What is the overall purpose or goal of your function? To change the background-color of the

elements of the cake to match the color the selected colors. 1. If there are event listeners in your function, answer the following questions about them: A. What element is the event listener being attached to? What line in index.html is it on? The input fields on lines 38, 41, and 44. B. What event is the element listening for? A change in the input element value (checked or not). C. What happens in the callback function? The background color of the div element is changed to the color value of the input element. 2. Where is your function's call site? In cakeView.init function on line 55.

11/21/17 Agile, MVC, jQuery

Lab time is to try things and make a complete project, even if that project is janky.

Agile - A way to manage a team to culture flexibility. Transparent, client is involved, small incremental changes, adaptable to chaning circumstances. Like mini waterfalls that happen repeatedly. Can be managed with: - Kanban (sticky notes: todo, in action, QA, Done). - Scrum. 2-4 weeks of highly focused sprints on task goals. Implemented in ACL for daily sprints. - Lean. Minimal viable product. What is the least we can do to create the product that is asked for.

Waterfall - Linear design, production, testing process. Challenging due to time length and does not allow for flexibility.

MVC - Model, View, Controller. Design pattern for JS and more vaguely architecture for an app. - Model: JS object representation of the idea that needs to be worked with in the app (Ex: a school would have a teacher object, student object, homework object, classes object). - View: The DOM, what the user sees and experiences in the UI. - Controller: The interactivity of the application. Includes JS and CSS. - Ex: Ice cream ordering. Controller would be the worker who takes order. Model are the items ordered (icecream, cone, toppings), view is the final product (icream cone with toppings). - Ex: Database is model, front-end is view, server is controller.

JS / jQuery

array.forEach(...,[thisArg]) - will run a loop and preform the code given to each item in the array. Optional second argument for value of 'this'. - Has preset variables for index and array.

To include jQuery, two methods: CDN (content delivery network) or local. - CDN: <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha256-k2WSCIexGzOj3Euiig+TlR8gA0EmPjuc79OEeY5L45g=" crossorigin="anonymous"></script> - When CDN, browsers will cache files, will not have to download again. Do not have to maintain. - When local, can work offline.

(HTML ASIDE) data-* - Allows the creation of a personalized attribute in HTML. - can be called from the element with element.dataset.* in JS.

jQuery variables - should have '$' in front of them to designate they are jQuery objects. - Can have methods chained as jQuery returns on object.

.find(...) - jQuery method that will look for all selected within a jQuery object. Requires a selector. Can use * to select all children.

.clone() - will create a deep copy (all children, id, classes) of the selected element.

.attr() - Sets attribute values of elements. Can set more than one value at once.

jQuery cheat sheet: https://oscarotero.com/jquery/

Evaluation (proccess of object creation):

function Ship (data) { this.name = data.name; this.owner = data.owner; }

Ship.prototype.sink = function () { this.name = 'SUNKEN ' + this.name.toUpperCase(); }

const shipData = [ {name: 'sweet Creature', owner: 'Owen'}, {name: 'Hot Stuff', owner: 'Gina'} ];

const ship = new Ship (shipData[0]); // evaluate this line ship.name;

shipData[0] = {name: 'sweet Creature', owner: 'Owen'}; ship = { this.name = 'sweet Creature'; this.owner = 'Owen'; } ship.name = 'sweet Creature'; ship.sink = 'SUNKEN SWEET CREATURE';

11/20/17 - Responsive Web Design.

Live-server will automatically update the project so no need to refresh. To open do 'Live-server folder_name'.

Different browsers have different default syling. We use normalize.css to conqure these problems.

Will be implementing SMACSS to organize CSS. There are five categories: Base, Layout, Module, State, and Theme. There is another method called BEM, which is a naming convetion for elements.

Base - Only use element selectors. Default values.

Layout - Containers / sections for content. Use Id tags as there should only be one of each kind of content holder. Ex - #header, #main, #secondary, #tertiary.

Modules - Style individual components. Class tags are used to identify. Ex - .feat, .feat-name, .feat-span.

State - Modifies the behavior of a module or layout with class selectors.

Theme - The images, colors, fonts are designated.

Adaptive web design will have multiple style sheets in the server. Depending on the origin request for the website, a stylesheet will be given.

Media queries are used to create responsive design. Note: When zoomed in, values will be off for media queries in Chrome. @media ___ and (min-width: ___ px) {___};

icomoon.io has icon fonts. Easier to style with color and size. Each icon has a character code that is usable in css.

Mobile-first design: Start with mobile in mind when creating an app, use media queries to scale up.

gitignore file will ignore and not tract stated files.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment