├── m1 ├── js │ └── boilerplate.js ├── html │ └── boilerplate.html ├── project.md ├── project-readme.md ├── oo │ └── example.js ├── css │ └── boilerplate.css ├── advanced.md ├── resources.md └── README.md ├── README.md ├── m3 ├── angular-routing │ ├── app.component.html │ ├── app.module.ts │ ├── restaurant-list.component.html │ ├── restaurant-create.component.ts │ └── restaurant-detail.component.ts ├── angular-forms │ ├── app.module.ts │ ├── styles.css │ ├── my-form.component.html │ └── my-form.component.ts ├── express-cors │ └── app.js ├── angular-http │ ├── app.module.ts │ ├── restaurant-list.component.html │ ├── restaurant-list.component.ts │ └── restaurant.service.ts ├── express-api-errors │ └── app.js ├── angular-app-layout │ └── app.component.html ├── project.md ├── typescript │ ├── types.ts │ └── interfaces.ts ├── angular-auth │ ├── app.component.html │ ├── guards │ │ ├── init-auth.guard.ts │ │ ├── require-anon.guard.ts │ │ └── require-user.guard.ts │ ├── app.component.ts │ ├── app.module.ts │ └── auth.service.ts ├── deployment │ ├── app.js │ └── readme.md ├── resources.md ├── angular-scss │ └── README.md ├── advanced.md ├── express-auth │ ├── auth.js │ └── rest-auth.postman_collection.json ├── project-readme.md └── README.md ├── extras ├── trends.md └── agile.md ├── m2 ├── express-apps │ ├── make-passport-user-available-for-templates.js │ ├── hbs-views-and-layouts.js │ ├── ejs-views-and-layouts.js │ ├── mongoose-connect.js │ ├── passport.js │ ├── bcrypt.js │ ├── flash.js │ ├── session.js │ ├── app.js │ └── helpers-passport.js ├── mongoose-models │ ├── review-as-subschema.js │ ├── home-with-owner.js │ ├── user-with-auto-timestamps.js │ ├── event-with-attendees.js │ ├── product-with-subschema.js │ └── restaurant-with-location.js ├── forms-css │ ├── form.html │ └── forms.css ├── project.md ├── es6 │ └── es6.js ├── mongoose-querys │ └── with-promises.js ├── resources.md ├── deployment.md ├── advanced.md ├── project-readme.md └── README.md ├── tools ├── eslint │ ├── README.MD │ └── .eslintrc.json ├── git │ ├── .gitignore │ └── README.md ├── shortcuts │ ├── chrome.md │ ├── terminal.md │ └── vscode.md └── vscode │ └── README.md └── .gitignore /m1/js/boilerplate.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | debugger; 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Cheat Sheet 2 | 3 | - [module 1](m1/) 4 | - [module 2](m2/) 5 | - [module 3](m3/) 6 | - [tools](tools/) 7 | -------------------------------------------------------------------------------- /m3/angular-routing/app.component.html: -------------------------------------------------------------------------------- 1 | ... 2 | 3 |
4 | 5 |
6 | 7 | ... 8 | -------------------------------------------------------------------------------- /extras/trends.md: -------------------------------------------------------------------------------- 1 | # Trends 2 | 3 | - [Business 2018](http://trendwatching.com/quarterly/2017-11/5-trends-2018/) 4 | 5 | - [Trend Radar](https://www.thoughtworks.com/radar) 6 | -------------------------------------------------------------------------------- /m2/express-apps/make-passport-user-available-for-templates.js: -------------------------------------------------------------------------------- 1 | // -- middleware after passport init, before routes 2 | 3 | app.use((req, res, next) => { 4 | app.locals.user = req.user; 5 | next(); 6 | }); 7 | -------------------------------------------------------------------------------- /m3/angular-forms/app.module.ts: -------------------------------------------------------------------------------- 1 | import { FormsModule } from '@angular/forms'; 2 | 3 | ... 4 | 5 | @NgModule({ 6 | ... 7 | imports: [ 8 | ..., 9 | FormsModule, 10 | ... 11 | ], 12 | ... 13 | }) 14 | -------------------------------------------------------------------------------- /m3/express-cors/app.js: -------------------------------------------------------------------------------- 1 | // npm install --save cors 2 | 3 | const cors = require('cors'); 4 | 5 | // -- middlewares 6 | 7 | app.use(cors({ 8 | credentials: true, 9 | origin: ['http://localhost:4200'] 10 | })); 11 | -------------------------------------------------------------------------------- /tools/eslint/README.MD: -------------------------------------------------------------------------------- 1 | # 2 | - disable all the linters / beautify / prettier 3 | - `eslint --init` 4 | - use popular style guide 5 | - standard 6 | - json 7 | - replace `.eslintrc.json` with [this](.eslintrc.json) 8 | -------------------------------------------------------------------------------- /m2/express-apps/hbs-views-and-layouts.js: -------------------------------------------------------------------------------- 1 | const hbs = require('hbs'); 2 | 3 | // -- 4 | 5 | app.set('view engine', 'hbs'); 6 | app.set('views', path.join(__dirname, '/views')); 7 | hbs.registerPartials(path.join(__dirname, '/views/partials')); 8 | -------------------------------------------------------------------------------- /m3/angular-http/app.module.ts: -------------------------------------------------------------------------------- 1 | import { HttpClientModule } from '@angular/common/http'; 2 | 3 | ... 4 | 5 | @NgModule({ 6 | ... 7 | imports: [ 8 | ..., 9 | HttpClientModule, 10 | ... 11 | ], 12 | ... 13 | }) 14 | -------------------------------------------------------------------------------- /m2/mongoose-models/review-as-subschema.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const mongoose = require('mongoose'); 4 | const Schema = mongoose.Schema; 5 | 6 | const reviewSchema = new Schema({ 7 | content: String, 8 | stars: Number, 9 | author: String 10 | }); 11 | 12 | const Review = mongoose.model('Review', reviewSchema); 13 | 14 | module.exports = Review; 15 | -------------------------------------------------------------------------------- /m1/html/boilerplate.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Hello, world! 6 | 7 | 8 | 9 | 10 | 11 | 12 |

Hello World

13 | 14 | 15 | -------------------------------------------------------------------------------- /tools/git/.gitignore: -------------------------------------------------------------------------------- 1 | # artefacts 2 | .eslintcache 3 | .npm 4 | .nyc_output 5 | *.log 6 | logs/ 7 | node_modules/ 8 | coverage/ 9 | build/ 10 | dist/ 11 | 12 | # ide 13 | .bak 14 | *.swp 15 | *~ 16 | *# 17 | 18 | # spam 19 | .DS_Store 20 | .DS_Store? 21 | ._* 22 | .Spotlight-V100 23 | .Trashes 24 | ehthumbs.db 25 | Thumbs.db 26 | desktop.ini 27 | 28 | 29 | # dotenv 30 | .env 31 | -------------------------------------------------------------------------------- /tools/eslint/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "standard", 3 | "env": { 4 | "es6": true, 5 | "node": true 6 | }, 7 | "globals": { 8 | "document": false, 9 | "window": false, 10 | "console": false 11 | }, 12 | "rules": { 13 | "indent": [ 14 | 2, 15 | 2 16 | ], 17 | "semi": [ 18 | "error", 19 | "always" 20 | ] 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /tools/shortcuts/chrome.md: -------------------------------------------------------------------------------- 1 | ### Chrome (MAC) 2 | 3 | **Function** | **Shortcut** 4 | -------- | -------- 5 | change between tabs |`⌘` + `⌥` + `arrow` 6 | open inspector |`⌘` + `⇧` + `i` 7 | reload page |`⌘` + `r` 8 | focus on navigation bar |`⌘` + `l` 9 | open new window |`⌘` + `n` 10 | open new tab |`⌘` + `t` 11 | close current tab |`⌘` + `w` 12 | open closed tab |`⌘` + `⇧` + `t` 13 | close chrome |`⌘` + `q` 14 | -------------------------------------------------------------------------------- /m2/forms-css/form.html: -------------------------------------------------------------------------------- 1 |

Create movie

2 | 3 |
4 | 5 |
6 | 7 | 8 |
9 | 10 |
11 | 12 | 13 |
14 | 15 |
16 | 17 |
18 |
19 | -------------------------------------------------------------------------------- /m2/mongoose-models/home-with-owner.js: -------------------------------------------------------------------------------- 1 | // 1..1 Relationships 2 | 'use strict'; 3 | 4 | const mongoose = require('mongoose'); 5 | const Schema = mongoose.Schema; 6 | const ObjectId = Schema.Types.ObjectId; 7 | 8 | const homeSchema = new Schema({ 9 | name: String, 10 | owner: { 11 | type: ObjectId, 12 | ref: 'User' 13 | } 14 | }); 15 | 16 | const Home = mongoose.model('Home', homeSchema); 17 | 18 | module.exports = Home; 19 | -------------------------------------------------------------------------------- /m2/project.md: -------------------------------------------------------------------------------- 1 | # Project 2 | 3 | ## Reference project 4 | 5 | - 2 models 6 | - login/signup 7 | - create something 8 | - add something to something 9 | 10 | ## Planing 11 | 12 | - MVC: views (path + layout) 13 | - MVC: routes (method + path + access control) 14 | - MVC: models 15 | 16 | ## Extra Features 17 | 18 | - 2 roles / types of users 19 | - location and maps 20 | - OAuths 21 | 22 | ## Ideas 23 | 24 | - projects of students 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # IDEs and editors 3 | /.idea 4 | .project 5 | .classpath 6 | .c9/ 7 | *.launch 8 | .settings/ 9 | *.sublime-workspace 10 | 11 | # IDE - VSCode 12 | .vscode/* 13 | !.vscode/settings.json 14 | !.vscode/tasks.json 15 | !.vscode/launch.json 16 | !.vscode/extensions.json 17 | 18 | # System Files 19 | .DS_Store 20 | .AppleDouble 21 | .LSOverride 22 | Icon 23 | Thumbs.db 24 | *~ 25 | ._* 26 | *.swp 27 | .Spotlight* 28 | .Trashes 29 | 30 | -------------------------------------------------------------------------------- /m2/mongoose-models/user-with-auto-timestamps.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const mongoose = require("mongoose"); 4 | const Schema = mongoose.Schema; 5 | 6 | const userSchema = new Schema({ 7 | username: { 8 | type: String, 9 | required: true 10 | }, 11 | password: { 12 | type: String, 13 | required: true 14 | } 15 | }, { 16 | timestamps: true 17 | }); 18 | 19 | const User = mongoose.model('User', userSchema); 20 | 21 | module.exports = User; 22 | 23 | -------------------------------------------------------------------------------- /m3/express-api-errors/app.js: -------------------------------------------------------------------------------- 1 | 2 | // catch 404 and forward to error handler 3 | app.use((req, res, next) => { 4 | res.status(404).json({code: 'not found'}); 5 | }); 6 | 7 | app.use((err, req, res, next) => { 8 | // always log the error 9 | console.error('ERROR', req.method, req.path, err); 10 | 11 | // only render if the error ocurred before sending the response 12 | if (!res.headersSent) { 13 | res.status(500).json({code: 'unexpected'}); 14 | } 15 | }); 16 | -------------------------------------------------------------------------------- /m2/express-apps/ejs-views-and-layouts.js: -------------------------------------------------------------------------------- 1 | // EJS 2 | // npm install ejs 3 | 4 | app.set('views', path.join(__dirname, 'views')); 5 | app.set('view engine', 'ejs'); 6 | 7 | 8 | // Layouts 9 | // npm install --save express-ejs-layouts 10 | 11 | const expressLayouts = require('express-ejs-layouts'); 12 | 13 | // -- 14 | 15 | app.use(expressLayouts); 16 | app.set('views', path.join(__dirname, 'views')); 17 | app.set('view engine', 'ejs'); 18 | app.set('layout', 'layouts/main'); 19 | -------------------------------------------------------------------------------- /m3/angular-app-layout/app.component.html: -------------------------------------------------------------------------------- 1 | 12 | 13 |
14 | 15 |
16 | 17 | 22 | -------------------------------------------------------------------------------- /m3/angular-routing/app.module.ts: -------------------------------------------------------------------------------- 1 | import { RouterModule, Routes } from '@angular/router'; 2 | 3 | ... 4 | 5 | const routes: Routes = [ 6 | { path: '', redirectTo: '/movies', pathMatch: 'full' }, 7 | { path: 'movies', component: MovieListComponent }, 8 | { path: 'movies/:id', component: MovieDetailComponent } 9 | ]; 10 | 11 | ... 12 | 13 | @NgModule({ 14 | ... 15 | imports: [ 16 | ..., 17 | RouterModule.forRoot(routes) 18 | ... 19 | ], 20 | ... 21 | }) 22 | -------------------------------------------------------------------------------- /m3/project.md: -------------------------------------------------------------------------------- 1 | # Project 2 | 3 | ## Reference project 4 | 5 | - 2 models 6 | - login/signup 7 | - create something 8 | - list something 9 | - add something to something 10 | 11 | ## Planing 12 | 13 | - Frontend: Pages (path + layout) 14 | - Frontend: Components iInput + output) 15 | - Frontend: Services (methods) 16 | - Backend: routes (method + path + access control) 17 | - Backend: models 18 | 19 | ## Extra Features 20 | 21 | 22 | ## Ideas 23 | 24 | - projects of students 25 | -------------------------------------------------------------------------------- /m2/express-apps/mongoose-connect.js: -------------------------------------------------------------------------------- 1 | // npm install mongoose 2 | 3 | const mongoose = require('mongoose'); 4 | 5 | // -- 6 | 7 | mongoose.connect('mongodb://localhost/database-name', { 8 | keepAlive: true, 9 | useNewUrlParser: true, 10 | reconnectTries: Number.MAX_VALUE 11 | }); 12 | 13 | // OR when using provess.env to get ready for deploy 14 | 15 | mongoose.connect(process.env.MONGODB_URI, { 16 | keepAlive: true, 17 | useNewUrlParser: true, 18 | reconnectTries: Number.MAX_VALUE 19 | }); 20 | -------------------------------------------------------------------------------- /m2/express-apps/passport.js: -------------------------------------------------------------------------------- 1 | // npm install --save passport passport-local 2 | 3 | const passport = require('passport'); 4 | const flash = require('connect-flash'); 5 | 6 | // NOTE: the following file should export a function that does the passport setup (serialize, unserialize, strategies) 7 | 8 | const configurePassport = require('./helpers/passport'); 9 | 10 | // - passport 11 | 12 | configurePassport(); 13 | app.use(flash()); 14 | app.use(passport.initialize()); 15 | app.use(passport.session()); 16 | -------------------------------------------------------------------------------- /m2/mongoose-models/event-with-attendees.js: -------------------------------------------------------------------------------- 1 | // 1..N or N..M 2 | 'use strict'; 3 | 4 | const mongoose = require('mongoose'); 5 | const Schema = mongoose.Schema; 6 | const ObjectId = Schema.Types.ObjectId; 7 | 8 | const eventSchema = new Schema({ 9 | name: { 10 | type: String 11 | }, 12 | date: { 13 | type: Date 14 | }, 15 | attendees: [{ 16 | type: ObjectId, 17 | ref: 'User' 18 | }] 19 | }); 20 | 21 | const Event = mongoose.model('Event', eventSchema); 22 | 23 | module.exports = Event; 24 | -------------------------------------------------------------------------------- /m2/mongoose-models/product-with-subschema.js: -------------------------------------------------------------------------------- 1 | // 1..N with Subdocuments 2 | 'use strict'; 3 | 4 | const mongoose = require('mongoose'); 5 | const Review = require('./review'); 6 | const Schema = mongoose.Schema; 7 | 8 | const productSchema = new Schema({ 9 | name : String, 10 | price : Number, 11 | imageUrl : String, 12 | description: String, 13 | reviews : [Review.schema] 14 | }); 15 | 16 | const Product = mongoose.model('Product', productSchema); 17 | 18 | module.exports = Product; 19 | -------------------------------------------------------------------------------- /m3/angular-routing/restaurant-list.component.html: -------------------------------------------------------------------------------- 1 | ... 2 | 3 |
4 | create a restaurant 5 |
6 | 7 | ... 8 | 9 |
10 | 16 |
17 | 18 | ... 19 | -------------------------------------------------------------------------------- /m3/typescript/types.ts: -------------------------------------------------------------------------------- 1 | // types in varible declarations 2 | const myNumber: number = 1; 3 | const myBoolean: boolean = false; 4 | const myString: string = "typescript"; 5 | const myWhatever: any = {}; 6 | const myArray: Array = ['a', 'b', 'c']; 7 | 8 | // with let we can set value later 9 | let timeoutId: number; 10 | 11 | // types in functions 12 | function myFunction(): void { 13 | console.log('this function "does not return"'); 14 | } 15 | 16 | function sum(a: number, b: number): number { 17 | return a + b; 18 | } 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /m2/express-apps/bcrypt.js: -------------------------------------------------------------------------------- 1 | // npm install bcrypt 2 | 3 | const bcrypt = require('bcrypt'); 4 | const saltRounds = 10; 5 | 6 | // Signup user 7 | 8 | const salt = bcrypt.genSaltSync(saltRounds); 9 | const hashedPassword = bcrypt.hashSync(plainPassword, salt); 10 | 11 | // Login user 12 | 13 | if (bcrypt.compareSync(password /* provided password */, user.password/* hashed password */)) { 14 | // Save the login in the session! 15 | req.session.currentUser = user; 16 | res.redirect('/'); 17 | } else { 18 | res.redirect('/auth/login'); 19 | } 20 | -------------------------------------------------------------------------------- /m2/mongoose-models/restaurant-with-location.js: -------------------------------------------------------------------------------- 1 | // model with locations 2 | 3 | 'use strict'; 4 | 5 | const mongoose = require('mongoose'); 6 | const Schema = mongoose.Schema; 7 | 8 | const restaurantSchema = new Schema({ 9 | name: String, 10 | description: String, 11 | location: { 12 | type: { 13 | type: String 14 | }, 15 | coordinates: [Number] 16 | } 17 | }); 18 | 19 | restaurantSchema.index({ location: '2dsphere' }); 20 | 21 | const Restaurant = mongoose.model("Restaurant", restaurantSchema); 22 | 23 | module.exports = Restaurant; 24 | -------------------------------------------------------------------------------- /m3/angular-http/restaurant-list.component.html: -------------------------------------------------------------------------------- 1 |
2 | is loading... 3 |
4 | 5 |
6 |

All Restaurants

7 |

create a restaurant

8 |
9 | 17 |
18 | -------------------------------------------------------------------------------- /m1/project.md: -------------------------------------------------------------------------------- 1 | # Project 2 | 3 | ## Reference project 4 | 5 | - 3 states 6 | - main.js 7 | - game.js 8 | - restart 9 | 10 | ## Planning 11 | - [github repo readme](https://github.com/zapatran/template-project-game/blob/master/Project%20Template.md) with: 12 | - states 13 | - views 14 | - data structures 15 | - backlog 16 | 17 | ## Deploy 18 | - go to repository settings 19 | - look for Github Pages 20 | - choose master branch 21 | - click on save 22 | - url will be on top of the Github Pages section 23 | 24 | ## Extra Features 25 | 26 | 27 | ## Ideas 28 | 29 | - [retro 8bit](https://www.youtube.com/watch?v=Fugbn_PExSg) 30 | -------------------------------------------------------------------------------- /m3/angular-auth/app.component.html: -------------------------------------------------------------------------------- 1 | 20 | -------------------------------------------------------------------------------- /m3/angular-auth/guards/init-auth.guard.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { CanActivate } from '@angular/router'; 3 | 4 | import { AuthService } from '../services/auth.service'; 5 | 6 | @Injectable({ 7 | providedIn: 'root' 8 | }) 9 | 10 | export class InitAuthGuard implements CanActivate { 11 | 12 | constructor(private authService: AuthService) { } 13 | 14 | canActivate(): Promise { 15 | return this.authService.me() 16 | .then((user) => { 17 | return true; 18 | }) 19 | .catch((error) => { 20 | console.error(error); 21 | return false; 22 | }); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /m3/angular-http/restaurant-list.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | 3 | import { RestaurantService } from '../../services/restaurant.service'; 4 | 5 | @Component({ 6 | selector: 'app-restaurant-list', 7 | templateUrl: './restaurant-list.component.html', 8 | styleUrls: ['./restaurant-list.component.css'] 9 | }) 10 | export class RestaurantListComponent implements OnInit { 11 | 12 | restaurants: Array; 13 | 14 | constructor(private restaurantService: RestaurantService) { } 15 | 16 | ngOnInit() { 17 | this.restaurantService.getList() 18 | .then(data => this.restaurants = data); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /m3/angular-routing/restaurant-create.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { Router } from '@angular/router'; 3 | 4 | import { RestaurantService } from '../../services/restaurants.service'; 5 | 6 | @Component({ 7 | selector: 'app-restaurant-create', 8 | templateUrl: './restaurant-create.component.html', 9 | styleUrls: ['./restaurant-create.component.css'] 10 | }) 11 | export class RestaurantCreateComponent implements OnInit { 12 | 13 | constructor(private restaurantService: RestaurantService, private router: Router) { } 14 | 15 | ngOnInit() {} 16 | 17 | submit() { 18 | const data = { ... }; 19 | this.restaurantService.create(data) 20 | .then(() => this.router.navigate(['/restaurants'])); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /m2/forms-css/forms.css: -------------------------------------------------------------------------------- 1 | 2 | /* -- forms -- */ 3 | 4 | form.is-processing { 5 | opacity: 0.5; 6 | } 7 | 8 | form .field { 9 | margin-bottom: 20px; 10 | } 11 | 12 | form label { 13 | display: block; 14 | margin-bottom: 10px; 15 | font-style: bold; 16 | } 17 | 18 | form input { 19 | padding: 5px; 20 | font-size: 16px; 21 | } 22 | 23 | form .submit { 24 | padding-top: 20px; 25 | } 26 | 27 | form .submit button { 28 | padding: 5px 20px; 29 | text-align: center; 30 | font-size: 16px; 31 | background-color: #27afdc; 32 | cursor: pointer; 33 | } 34 | 35 | form .validation { 36 | margin: 5px 0 10px; 37 | color: red; 38 | } 39 | 40 | form .field.has-error label { 41 | color: red; 42 | } 43 | form .field.has-error input { 44 | border: 1px solid red; 45 | } 46 | -------------------------------------------------------------------------------- /m2/express-apps/flash.js: -------------------------------------------------------------------------------- 1 | // npm install --save connect-flash 2 | 3 | // -- app.js 4 | 5 | const flash = require('connect-flash'); 6 | 7 | // after the session middleware add the flash middleware 8 | 9 | app.use(flash()); 10 | 11 | // -- route that sends the message 12 | 13 | app.post('/form', (req, res, next) => { 14 | req.flash('message-name', 'The message content'); 15 | return res.redirect('/form'); 16 | }); 17 | 18 | // -- route that reads message 19 | 20 | app.get('/form', (req, res, next) => { 21 | const data = { 22 | messages: req.flash('message-name') 23 | }; 24 | res.render('template-name', data); 25 | }); 26 | 27 | // -- template-name.hbs 28 | 29 | {{#if messages.length}} 30 |
    31 | {{#each messages}}
  • {{this}}
  • {{/each}} 32 |
33 | {{/if}} 34 | -------------------------------------------------------------------------------- /m2/express-apps/session.js: -------------------------------------------------------------------------------- 1 | // npm install --save express-session connect-mongo 2 | 3 | const session = require('express-session'); 4 | const MongoStore = require('connect-mongo')(session); 5 | 6 | // -- 7 | 8 | app.use(session({ 9 | store: new MongoStore({ 10 | mongooseConnection: mongoose.connection, 11 | ttl: 24 * 60 * 60 // 1 day 12 | }), 13 | secret: 'some-string', 14 | resave: true, 15 | saveUninitialized: true, 16 | cookie: { 17 | maxAge: 24 * 60 * 60 * 1000 18 | } 19 | })); 20 | 21 | 22 | // Makes the currentUser available in every page 23 | // note1: currentUser needs to match whatever you use in login/signup/logout routes 24 | // note2: if using passport, req.user instead 25 | app.use((req, res, next) => { 26 | app.locals.currentUser = req.session.currentUser; 27 | next(); 28 | }); 29 | -------------------------------------------------------------------------------- /m3/angular-routing/restaurant-detail.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { ActivatedRoute } from '@angular/router'; 3 | 4 | import { RestaurantService } from '../../services/restaurant.service'; 5 | 6 | @Component({ 7 | selector: 'app-restaurant-detail', 8 | templateUrl: './restaurant-detail.component.html', 9 | styleUrls: ['./restaurant-detail.component.css'] 10 | }) 11 | export class RestaurantDetailComponent implements OnInit { 12 | 13 | restaurant: null; 14 | 15 | constructor(private restaurantService: RestaurantService, private route: ActivatedRoute) { } 16 | 17 | ngOnInit() { 18 | this.route.params 19 | .subscribe((params) => { 20 | this.restaurantService.getOne(params.id) 21 | .then(data => this.restaurant = data); 22 | }); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /m3/angular-forms/styles.css: -------------------------------------------------------------------------------- 1 | /* You can add global styles to this file, and also import other style files */ 2 | 3 | /* -- forms -- */ 4 | 5 | form.is-processing { 6 | opacity: 0.5; 7 | } 8 | 9 | form .field { 10 | margin-bottom: 20px; 11 | } 12 | 13 | form label { 14 | display: block; 15 | margin-bottom: 10px; 16 | font-style: bold; 17 | } 18 | 19 | form input { 20 | padding: 5px; 21 | font-size: 16px; 22 | } 23 | 24 | form .submit { 25 | padding-top: 20px; 26 | } 27 | 28 | form .submit button { 29 | padding: 5px 20px; 30 | text-align: center; 31 | font-size: 16px; 32 | background-color: cyan; 33 | cursor: pointer; 34 | } 35 | 36 | form .field.has-error label { 37 | color: red; 38 | } 39 | 40 | form .validation { 41 | margin: 5px 0 10px; 42 | color: red; 43 | } 44 | 45 | form .field.has-error input { 46 | border: 1px solid red; 47 | } 48 | -------------------------------------------------------------------------------- /m1/project-readme.md: -------------------------------------------------------------------------------- 1 | # Project's name 2 | 3 | ## Description 4 | Brief description of the project 5 | 6 | 7 | ## MVP (DOM - CANVAS) 8 | MVP definition, deliverables. 9 | 10 | 11 | ## Backlog 12 | 13 | 14 | ## Data structure 15 | Classes and methods definition. 16 | 17 | 18 | ## States y States Transitions 19 | Definition of the different states and their transition (transition functions) 20 | 21 | - splashScreen 22 | - gameScreen 23 | - gameoverScreen 24 | - winScreen 25 | 26 | 27 | ## Task 28 | Task definition in order of priority 29 | 30 | 31 | ## Links 32 | 33 | 34 | ### Trello 35 | [Link url](https://trello.com) 36 | 37 | 38 | ### Git 39 | URls for the project repo and deploy 40 | [Link Repo](http://github.com) 41 | [Link Deploy](http://github.com) 42 | 43 | 44 | ### Slides 45 | URls for the project presentation (slides) 46 | [Link Slides.com](http://slides.com) 47 | -------------------------------------------------------------------------------- /m3/angular-auth/guards/require-anon.guard.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { CanActivate } from '@angular/router'; 3 | import { Router } from '@angular/router'; 4 | 5 | import { AuthService } from '../services/auth.service'; 6 | 7 | @Injectable({ 8 | providedIn: 'root' 9 | }) 10 | export class RequireAnonGuard implements CanActivate { 11 | 12 | constructor( 13 | private authService: AuthService, 14 | private router: Router 15 | ) { } 16 | 17 | canActivate(): Promise { 18 | return this.authService.me() 19 | .then((user) => { 20 | if (!user) { 21 | return true; 22 | } else { 23 | this.router.navigate(['/']); 24 | return false; 25 | } 26 | }) 27 | .catch((error) => { 28 | console.error(error); 29 | return false; 30 | }); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /m3/angular-auth/guards/require-user.guard.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { CanActivate } from '@angular/router'; 3 | import { Router } from '@angular/router'; 4 | 5 | import { AuthService } from '../services/auth.service'; 6 | 7 | @Injectable({ 8 | providedIn: 'root' 9 | }) 10 | export class RequireUserGuard implements CanActivate { 11 | 12 | constructor( 13 | private authService: AuthService, 14 | private router: Router 15 | ) { } 16 | 17 | canActivate(): Promise { 18 | return this.authService.me() 19 | .then((user) => { 20 | if (user) { 21 | return true; 22 | } else { 23 | this.router.navigate(['/login']); 24 | return false; 25 | } 26 | }) 27 | .catch((error) => { 28 | console.error(error); 29 | return false; 30 | }); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /m3/angular-auth/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Router } from '@angular/router'; 2 | import { Component, OnInit } from '@angular/core'; 3 | 4 | import { AuthService } from './services/auth.service'; 5 | 6 | @Component({ 7 | selector: 'app-root', 8 | templateUrl: './app.component.html', 9 | styleUrls: ['./app.component.css'] 10 | }) 11 | export class AppComponent implements OnInit { 12 | title = 'app'; 13 | loading = true; 14 | anon: boolean; 15 | user: any; 16 | 17 | constructor( 18 | private authService: AuthService, 19 | private router: Router 20 | ) {} 21 | 22 | ngOnInit() { 23 | this.authService.userChange$.subscribe((user) => { 24 | this.loading = false; 25 | this.user = user; 26 | this.anon = !user; 27 | }); 28 | } 29 | 30 | logout() { 31 | this.authService.logout() 32 | .then(() => this.router.navigate(['/login'])); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /m3/typescript/interfaces.ts: -------------------------------------------------------------------------------- 1 | interface User { 2 | username: string; 3 | getRole(): string; 4 | } 5 | 6 | class Student implements User { 7 | private role: string = 'student'; 8 | private id: number; 9 | username: string; 10 | course: string; 11 | 12 | constructor(id: number, username: string) { // this code can be more compact, see next snippet 13 | this.username = username; 14 | } 15 | 16 | getRole(): string { 17 | return this.role; 18 | } 19 | 20 | setCourse(course: string): void { 21 | this.course = course; 22 | } 23 | } 24 | 25 | // example class with automatic public/private fields declared in constructor 26 | 27 | class Teacher implements User { 28 | private role: string = 'teacher'; 29 | course: string; 30 | 31 | constructor(private id: number, public username: string) { } 32 | 33 | getRole(): string { 34 | return this.role; 35 | } 36 | 37 | // ... etc 38 | } -------------------------------------------------------------------------------- /m3/deployment/app.js: -------------------------------------------------------------------------------- 1 | // https://medium.com/@ryanchenkie_40935/angular-cli-deployment-host-your-angular-2-app-on-heroku-3f266f13f352 2 | 3 | const express = require('express'); 4 | const path = require('path'); 5 | 6 | const pkg = require('./package.json'); 7 | const app = express(); 8 | 9 | const forceSSL = function () { 10 | return function (req, res, next) { 11 | if (req.headers['x-forwarded-proto'] !== 'https') { 12 | const path = 'https://' + req.get('Host') + req.url; 13 | return res.redirect(path); 14 | } 15 | next(); 16 | }; 17 | }; 18 | 19 | app.use(forceSSL()); 20 | 21 | app.use(express.static(path.join(__dirname, '/dist/client'))); 22 | 23 | app.get('/*', function (req, res) { 24 | res.sendFile(path.join(path.join(__dirname, '/dist/client/index.html'))); 25 | }); 26 | 27 | const port = process.env.PORT || 8080; 28 | 29 | app.listen(port, () => console.log(pkg.name + ' ' + pkg.version + ' listening on ' + port)); 30 | -------------------------------------------------------------------------------- /tools/git/README.md: -------------------------------------------------------------------------------- 1 | # git 2 | 3 | - [docs](https://services.github.com/on-demand/downloads/github-git-cheat-sheet.pdf) 4 | 5 | - git init 6 | - git status 7 | - git remote add origin https://..../name-repo.git 8 | - git remote -v 9 | - git status 10 | - git diff 11 | - git add . 12 | - git diff --cached 13 | - git status 14 | - git reset HEAD nameFile 15 | - git status 16 | - git add nameFile 17 | - git status 18 | - git commit -m "message" 19 | - git status 20 | - git pull 21 | - git push -u origin master 22 | - git push 23 | - git status 24 | - git checkout -b develop 25 | - git branch -a 26 | - git status 27 | - git checkout master 28 | - git merge develop 29 | - git status 30 | - git checkout fileName 31 | - git status 32 | - git reset --HARD (caution, dangerous!) 33 | - git status 34 | 35 | 36 | ## gource (visualise history) 37 | 38 | - [homepage](http://gource.io/) 39 | - [installing on osx](http://www.fullybaked.co.uk/articles/getting-gource-running-on-osx) 40 | -------------------------------------------------------------------------------- /m3/angular-forms/my-form.component.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | 5 | 6 |
7 |

username required

8 |

username is too short

9 |
10 |
11 | 12 |
13 | 14 |
15 |

there are errors in the form, please review the fields

16 |
17 |
18 |
19 | 20 | -------------------------------------------------------------------------------- /m1/oo/example.js: -------------------------------------------------------------------------------- 1 | // -- base constructor Vehicle 2 | 3 | function Vehicle (numberOfWheels) { 4 | this.running = false; 5 | this.wheels = numberOfWheels 6 | } 7 | 8 | // Vehicle methods 9 | 10 | Vehicle.prototype.start = function () { 11 | this.running = true; 12 | }; 13 | 14 | Vehicle.prototype.stop = function () { 15 | this.running = false; 16 | }; 17 | 18 | 19 | 20 | 21 | // -- Truck constructor extends (inherits from) Vehicle 22 | 23 | function Truck (capacity) { 24 | // inherited constructor 25 | Vehicle.call(this, 6); 26 | 27 | this.currentLoad = 0; 28 | this.capacity = capacity; 29 | } 30 | 31 | // inherit methods from base Vehicle 32 | Truck.prototype = Object.create(Vehicle.prototype); 33 | Truck.prototype.constructor = Truck; 34 | 35 | // Truck methods 36 | 37 | Truck.prototype.addLoad = function (kilos) { 38 | if (this.currentLoad + kilos > this.capacity) { 39 | throw new Error('Excess load!!'); 40 | } 41 | this.currentLoad += kilos; 42 | }; 43 | -------------------------------------------------------------------------------- /m3/angular-auth/app.module.ts: -------------------------------------------------------------------------------- 1 | // -- guards 2 | 3 | import { RequireAnonGuardService } from './guards/require-anon-guard.service'; 4 | import { RequireUserGuardService } from './guards/require-user-guard.service'; 5 | import { InitAuthGuardService } from './guards/init-auth-guard.service'; 6 | 7 | // -- routes 8 | 9 | const routes: Routes = [ 10 | { path: '', component: HomePageComponent, canActivate: [ InitAuthGuard ] }, 11 | { path: 'login', component: AuthLoginPageComponent, canActivate: [ RequireAnonGuard ] }, 12 | { path: 'signup', component: AuthSignupPageComponent, canActivate: [ RequireAnonGuard ] }, 13 | { path: 'page', component: ... , canActivate: [ RequireUserGuard ] }, 14 | { path: '**', redirectTo: '' } 15 | ]; 16 | 17 | // don't forget to register the guards in the providers 18 | 19 | @NgModule({ 20 | ... 21 | providers: [ 22 | ... 23 | InitAuthGuardService, 24 | RequireAnonGuardService, 25 | RequireUserGuardService, 26 | ... 27 | ], 28 | ... 29 | }); 30 | -------------------------------------------------------------------------------- /m3/resources.md: -------------------------------------------------------------------------------- 1 | # Resources 2 | 3 | 4 | ## Tools 5 | 6 | ### Angular 7 | 8 | - [Modules](https://ngx.tools) 9 | 10 | ### Frontend 11 | 12 | - [Webpack](https://webpack.js.org/) 13 | - [Sonarwhal](https://sonarwhal.com/scanner) 14 | 15 | ### UX 16 | 17 | - [Hot Jar](https://www.hotjar.com/tour) 18 | - [FullStory](https://www.fullstory.com/) 19 | - [Optimizely](https://www.optimizely.com) 20 | - [LiveChat](https://www.livechatinc.com/pricing/) 21 | - [Elevio](https://elev.io) 22 | 23 | ### Analytics 24 | 25 | - [MixPanel](https://mixpanel.com/) 26 | - [GA](https://www.google.com/analytics/#?modal_active=none) 27 | - [Adobe Analytics](https://www.adobe.com/data-analytics-cloud/analytics.html) 28 | 29 | 30 | 31 | ## Documentation 32 | 33 | 34 | ## Tutorials 35 | 36 | 37 | ## Libraries 38 | 39 | 40 | ## Websites 41 | 42 | - [Software Architecture Chronicles](https://medium.com/the-software-architecture-chronicles) 43 | 44 | 45 | ## Youtube Channels 46 | 47 | 48 | ## Podcasts 49 | 50 | 51 | ## Specifications 52 | -------------------------------------------------------------------------------- /m2/express-apps/app.js: -------------------------------------------------------------------------------- 1 | // require npm packages 2 | const path = require('path'); 3 | const express = require('express'); 4 | 5 | // require your own modules (router, models) 6 | 7 | // create app connect to db 8 | 9 | // -- setup the app 10 | 11 | // configure middlewares (static, session, cookies, body, ...) 12 | app.use(express.static('public')); 13 | app.use(express.json()); 14 | app.use(express.urlencoded({ extended: false })); 15 | 16 | // -- routes 17 | 18 | // -- 404 and error handler 19 | 20 | // NOTE: requires a views/not-found.ejs template 21 | app.use((req, res, next) => { 22 | res.status(404); 23 | res.render('not-found'); 24 | }); 25 | 26 | // NOTE: requires a views/error.ejs template 27 | app.use((err, req, res, next) => { 28 | // always log the error 29 | console.error('ERROR', req.method, req.path, err); 30 | 31 | // only render if the error ocurred before sending the response 32 | if (!res.headersSent) { 33 | res.status(500); 34 | res.render('error'); 35 | } 36 | }); 37 | 38 | module.exports = app; 39 | -------------------------------------------------------------------------------- /m2/es6/es6.js: -------------------------------------------------------------------------------- 1 | // -- arrow functions 2 | 3 | const doSomething = (param1, param2) => { 4 | return param1 + param2; 5 | }; 6 | 7 | const arr = [1, 2, 3, 4]; 8 | const newArr = arr.map((item) => item + 1); 9 | 10 | // -- classes and inheritance 11 | 12 | class Foo { 13 | constructor(param1) { 14 | this.prop1 = param1; 15 | } 16 | method1() { 17 | console.log('method 1'); 18 | } 19 | } 20 | 21 | class Bar extends Foo { 22 | constructor(param1, param2) { 23 | super(param1, param2) 24 | } 25 | method1() { 26 | console.log('method 1 redefined by Bar'); 27 | } 28 | method2() { 29 | console.log('method 2 added by Bar'); 30 | } 31 | } 32 | 33 | // -- object shorthand property names 34 | 35 | const name = "foo"; 36 | const obj = { name }; 37 | console.log(obj.name); // "foo" 38 | 39 | 40 | // -- template (and multiline) strings 41 | 42 | const name = "joe" 43 | const text = ` 44 |

hello ${name}

45 | `; 46 | 47 | 48 | // -- destructuring 49 | 50 | const person = {name: 'Joe', age: 33}; 51 | let {name, age} = person; 52 | console.log(name, age); // Joe 33 53 | 54 | 55 | -------------------------------------------------------------------------------- /m3/angular-forms/my-form.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-my-form', 5 | templateUrl: './my-form.component.html', 6 | styleUrls: ['./my-form.component.css'] 7 | }) 8 | export class MyFormComponent implements OnInit { 9 | 10 | feedbackEnabled = false; 11 | error = null; 12 | processing = false; 13 | // ... model (e,g. username: String) 14 | 15 | constructor(/* inject required services */) { } 16 | 17 | ngOnInit() { 18 | } 19 | 20 | submitForm(form) { 21 | this.error = ''; 22 | this.feedbackEnabled = true; 23 | if (form.valid) { 24 | this.processing = true; 25 | // this.someService.method(... data ...) 26 | // .then((result) => { 27 | // // ... handle result, reset form, etc... 28 | // // ... navigate with this.router.navigate(['...']) 29 | // // ... maybe turn this to false if your're staying on the page - this.processing = false; 30 | // }) 31 | // .catch((err) => { 32 | // this.error = err.error.error; // :-) 33 | // this.processing = false; 34 | // this.feedbackEnabled = false; 35 | // }); 36 | } 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /m2/express-apps/helpers-passport.js: -------------------------------------------------------------------------------- 1 | // note: use in conjunction with https://github.com/ByronGBP/ih-cheat-sheet/blob/master/snippets/express-apps/passport.js 2 | 3 | 'use strict'; 4 | 5 | const bcrypt = require('bcrypt'); 6 | const passport = require('passport'); 7 | const LocalStrategy = require('passport-local').Strategy; 8 | 9 | // NOTE: assumes that models/User exports an object with a "User" property 10 | const User = require('../models/user').User; 11 | 12 | function config () { 13 | passport.serializeUser((user, cb) => { 14 | cb(null, user._id); 15 | }); 16 | 17 | passport.deserializeUser((id, cb) => { 18 | User.findOne({ '_id': id }, (err, user) => { 19 | if (err) { return cb(err); } 20 | cb(null, user); 21 | }); 22 | }); 23 | 24 | passport.use(new LocalStrategy((username, password, next) => { 25 | User.findOne({ username }, (err, user) => { 26 | if (err) { 27 | return next(err); 28 | } 29 | if (!user) { 30 | return next(null, false, { message: 'Incorrect username' }); 31 | } 32 | if (!bcrypt.compareSync(password, user.password)) { 33 | return next(null, false, { message: 'Incorrect password' }); 34 | } 35 | 36 | return next(null, user); 37 | }); 38 | })); 39 | } 40 | 41 | module.exports = config; 42 | -------------------------------------------------------------------------------- /m2/mongoose-querys/with-promises.js: -------------------------------------------------------------------------------- 1 | const Place = require('../models/place'); 2 | 3 | // with promise variable 4 | router.get('/', (req, res, next) => { 5 | const promise = Place.find({ type: 'restaurant' }); 6 | promise.then((result) => { 7 | const data = { 8 | places: result; 9 | } 10 | res.render('place', data); 11 | }); 12 | promise.catch((error) => { 13 | next(error); 14 | }); 15 | }); 16 | 17 | router.post('/place', (req, res, next) => { 18 | const newPlace = { 19 | name: req.body.name, 20 | } 21 | const promise = Place.insertOne(newPlace); 22 | promise.then(() => { 23 | res.redirect('/'); 24 | }); 25 | promise.catch((error) => { 26 | next(error); 27 | }); 28 | }); 29 | 30 | 31 | // with chaining (no promise var) 32 | router.get('/', (req, res, next) => { 33 | Place.find({ type: 'restaurant' }) 34 | .then((result) => { 35 | const data = { 36 | places: result; 37 | } 38 | res.render('place', data); 39 | }); 40 | .catch((error) => { 41 | next(error); 42 | }); 43 | }); 44 | 45 | router.post('/place', (req, res, next) => { 46 | const newPlace = { 47 | name: req.body.name, 48 | } 49 | Place.insertOne(newPlace) 50 | .then(() => { 51 | res.redirect('/'); 52 | }) 53 | .catch((error) => { 54 | next(error); 55 | }); 56 | }); 57 | -------------------------------------------------------------------------------- /tools/vscode/README.md: -------------------------------------------------------------------------------- 1 | # chrome 2 | - `cmd + alt + arrow` (change between tabs) 3 | - `cmd + shift + i` (open inspector) 4 | - `cmd + r` (reload page) 5 | - `cmd + l` (focus on navigation bar) 6 | - `cmd + n` (open new window) 7 | - `cmd + t` (open new tab) 8 | - `cmd + w` (close current tab) 9 | - `cmd + shit + t` (open closed tab) 10 | - `cmd + q` (close chrome) 11 | 12 | # mac 13 | - `cmd + space + appName` (spotlight search) 14 | - `cmd + tab` (change between apps) 15 | 16 | # vs code (install extension Sublime Text Keymap) 17 | - `cmd + alt + arrow` (change between tabs) 18 | - `cmd + w` (close current tab) 19 | - `cmd + s` (save current file) 20 | - `cmd + atl + s` (save all open files) 21 | - `cmd + z` (undo) 22 | - `cmd + shift + z` (redo) 23 | - `cmd + c` (copy selected to clipboard) 24 | - `cmd + x` (cut selected to clipboard) 25 | - `cmd + v` (paste clipboard) 26 | - `cmd + d` (select the selected) 27 | - `cmd + backspace` (remove all to left) 28 | - `cmd + shift + d` (duplicate line) 29 | - `cmd + arrow` (go to arrow's direction) 30 | - `alt + arrow left/right` (move to next/previous word) 31 | - `alt + arrow up/down` (move line to) 32 | - `shift + arrow` (select) 33 | - `shift + alt + arrow` (select word) 34 | - `shift + cmd + arrow` (select from focus to arrow's direction) 35 | - `cmd + a` (select all) 36 | - `cmd + p` (search in project) 37 | - `cmd + /` (comment selected) -------------------------------------------------------------------------------- /m2/resources.md: -------------------------------------------------------------------------------- 1 | # Resources 2 | 3 | ## Tools 4 | 5 | - [ESLint](https://eslint.org/docs/rules/) 6 | - [Postman](https://www.getpostman.com/) 7 | 8 | ## Documentation 9 | 10 | ### ES6 11 | 12 | - [ES6](https://developer.mozilla.org/en-US/docs/Web/JavaScript/New_in_JavaScript/ECMAScript_2015_support_in_Mozilla) 13 | - [ES6 online book](http://exploringjs.com/es6/) 14 | 15 | ### Node 16 | 17 | - [Node.js](https://nodejs.org/en/docs/) 18 | - [NPM](https://docs.npmjs.com/) 19 | 20 | ### Express 21 | 22 | - [ExpressJs](https://expressjs.com/en/4x/api.html) 23 | 24 | ### MongoDB 25 | 26 | - [MongoDB](https://docs.mongodb.com/) 27 | - [Query Selectors](https://docs.mongodb.com/manual/reference/operator/query/#query-selectors) 28 | - [Update Operators](https://docs.mongodb.com/manual/reference/operator/update/#id1) 29 | - [Mongoose](http://mongoosejs.com/docs/guide.html) 30 | 31 | ## Libraries 32 | 33 | - [Lodash](https://lodash.com/docs) 34 | - [EJS](http://ejs.co/) 35 | - [Handlebars](http://tryhandlebarsjs.com/) 36 | - [Passport](http://www.passportjs.org/) 37 | 38 | ## Websites 39 | 40 | - [HackerNoon](https://hackernoon.com/) 41 | - [Webapp](https://webapplog.com/) 42 | - [StrongLoop](https://strongloop.com/strongblog/) 43 | - [IBM Javascript](https://developer.ibm.com/node/category/javascript-language/) 44 | 45 | ## Specifications 46 | 47 | - [Promises A+](https://promisesaplus.com/) 48 | -------------------------------------------------------------------------------- /m1/css/boilerplate.css: -------------------------------------------------------------------------------- 1 | 2 | /* ---- reset ---- */ 3 | 4 | html { 5 | box-sizing: border-box; 6 | } 7 | *, *:before, *:after { 8 | box-sizing: inherit; 9 | } 10 | 11 | body { 12 | margin: 0; 13 | padding: 0; 14 | } 15 | 16 | 17 | /* ---- typography ---- */ 18 | 19 | body { 20 | color: #111; 21 | font-family: Helvetica, Arial, sans-serif; 22 | font-size: 16px; 23 | line-height: 147%; 24 | } 25 | 26 | h1 {} 27 | 28 | h2 {} 29 | 30 | h3 {} 31 | 32 | p { 33 | margin: 0; 34 | } 35 | 36 | 37 | 38 | /* ---- layout ---- */ 39 | 40 | #site-header { 41 | padding: 30px 0; 42 | color: white; 43 | background: #111; 44 | } 45 | 46 | #site-footer { 47 | color: white; 48 | padding: 60px 0; 49 | background: #111; 50 | } 51 | 52 | #site-main { 53 | margin-bottom: 60px; 54 | } 55 | 56 | .container { 57 | margin: 0 20px; 58 | } 59 | 60 | .section { 61 | margin-bottom: 20px; 62 | padding-top: 20px; 63 | } 64 | 65 | @media (min-width: 768px) { 66 | .container { 67 | max-width: 728px; 68 | margin: 0 auto; 69 | } 70 | } 71 | 72 | 73 | 74 | 75 | /* ---- components ---- */ 76 | 77 | .button { 78 | width: 100%; 79 | background-color: blue; 80 | color: #fff; 81 | border: 1px solid #fff 82 | } 83 | 84 | .button-alt { 85 | color: blue; 86 | background-color: #fff; 87 | } 88 | 89 | /* ---- section ---- */ 90 | 91 | section.testimonials { 92 | // ... 93 | } 94 | 95 | section.testimonials .button { 96 | margin-bottom: 10px; 97 | } 98 | -------------------------------------------------------------------------------- /m3/angular-scss/README.md: -------------------------------------------------------------------------------- 1 | # if you start from scratch 2 | 3 | - https://scotch.io/tutorials/using-sass-with-the-angular-cli 4 | - ng new my-sassy-app --style=scss 5 | 6 | # if you want to convert an existing app 7 | 8 | ## update your angular-cli configuration (for ng serve, ng new, etc...) 9 | 10 | Don't forget to restart `ng-serve` after this. 11 | 12 | It will print some errors until you fix the following 13 | 14 | // .angular-cli.json 15 | 16 | 17 | "styles": [ 18 | "styles.scss" // - our main file converted to scss 19 | ], 20 | 21 | "defaults": { 22 | "styleExt": "scss", // - extension for components we generate next 23 | 24 | 25 | ## convert your main file to scss 26 | 27 | // styles.css > styles.scss 28 | 29 | @import './scss/variables.scss'; 30 | 31 | body { 32 | color: $color-body; 33 | } 34 | 35 | 36 | 37 | ## convert your existing components to scss 38 | 39 | // src/app/components/some.component.ts 40 | 41 | @Component({ 42 | selector: 'app-some', 43 | templateUrl: './some.component.html', 44 | styleUrls: ['./some.component.scss'] // <- changed the extension 45 | }) 46 | 47 | 48 | // src/app/components/some.component.css > src/app/components/some.component.scss 49 | 50 | @import '../../../scss/variables.scss'; 51 | 52 | h1 { 53 | color: $color-title; 54 | } 55 | 56 | ## create your global scss files in a separate folder 57 | 58 | 59 | // src/scss/variables.scss 60 | 61 | $color-body: black; 62 | $color-title: green; 63 | 64 | 65 | -------------------------------------------------------------------------------- /m3/angular-http/restaurant.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { HttpClient, HttpResponse } from '@angular/common/http'; 3 | 4 | // import { environment } from '../../environments/environment'; 5 | 6 | @Injectable({ 7 | providedIn: 'root' 8 | }) 9 | 10 | export class RestaurantService { 11 | 12 | private baseUrl = 'http://localhost:3000/restaurants'; 13 | 14 | constructor(private httpClient: HttpClient) { } 15 | 16 | // options.withCredentials is always required 17 | // without it, the HttpClient service does not send cookies in a CORS context 18 | // cookies are required to keep a session in the Rest API 19 | 20 | getList(): Promise { 21 | const options = { 22 | withCredentials: true 23 | }; 24 | return this.httpClient.get(`${this.baseUrl}`, options) 25 | .toPromise(); 26 | } 27 | 28 | // get() takes 2 arguments: url, options 29 | 30 | getOneById(id: string): Promise { 31 | const options = { 32 | withCredentials: true 33 | }; 34 | return this.httpClient.get(`${this.baseUrl}/${id}`, options) 35 | .toPromise(); 36 | } 37 | 38 | // post() and put() take 3 arguments: url, data, options 39 | 40 | create(data): Promise { 41 | const options = { 42 | withCredentials: true 43 | }; 44 | return this.httpClient.post(`${this.baseUrl}`, data, options) 45 | .toPromise(); 46 | } 47 | 48 | // how to gain access to the full response object (headers, status code, etc...) 49 | // and then still resolve with the resposne body (json) 50 | 51 | getFoobar(): Promise { 52 | const options = { 53 | withCredentials: true, 54 | observe: 'response' 55 | }; 56 | return this.httpClient.get(`${this.baseUrl}/foobar`, options) 57 | .toPromise() 58 | .then((res: HttpResponse) => res.body); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /m3/angular-auth/auth.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { HttpClient, HttpResponse } from '@angular/common/http'; 3 | import { Subject, Observable } from 'rxjs'; 4 | 5 | // import { environment } from '../../environments/environment'; 6 | 7 | @Injectable({ 8 | providedIn: 'root' 9 | }) 10 | 11 | export class AuthService { 12 | 13 | private user: any; 14 | private userChange: Subject = new Subject(); 15 | 16 | private API_URL = 'http://localhost:3000/auth'; 17 | 18 | userChange$: Observable = this.userChange.asObservable(); 19 | 20 | constructor(private httpClient: HttpClient) { } 21 | 22 | private setUser(user?: any) { 23 | this.user = user; 24 | this.userChange.next(user); 25 | return user; 26 | } 27 | 28 | me(): Promise { 29 | const options = { 30 | withCredentials: true 31 | }; 32 | return this.httpClient.get(`${this.API_URL}/me`, options) 33 | .toPromise() 34 | .then((user) => this.setUser(user)) 35 | .catch((err) => { 36 | if (err.status === 404) { 37 | this.setUser(); 38 | } 39 | }); 40 | } 41 | 42 | login(user: any): Promise { 43 | const options = { 44 | withCredentials: true 45 | }; 46 | return this.httpClient.post(`${this.API_URL}/login`, user, options) 47 | .toPromise() 48 | .then((data) => this.setUser(data)); 49 | } 50 | 51 | signup(user: any): Promise { 52 | const options = { 53 | withCredentials: true 54 | }; 55 | return this.httpClient.post(`${this.API_URL}/signup`, user, options) 56 | .toPromise() 57 | .then((data) => this.setUser(data)); 58 | } 59 | 60 | logout(): Promise { 61 | const options = { 62 | withCredentials: true 63 | }; 64 | return this.httpClient.post(`${this.API_URL}/logout`, null, options) 65 | .toPromise() 66 | .then(() => this.setUser()); 67 | } 68 | 69 | getUser(): any { 70 | return this.user; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /tools/shortcuts/terminal.md: -------------------------------------------------------------------------------- 1 | ### Terminal (MAC) 2 | 3 | #### Tabs and Windows 4 | **Function** | **Shortcut** 5 | -------- | -------- 6 | Fullscreen | `⌘`+ `Enter` 7 | Previous Tab | `⌘`+ `Left Arrow` 8 | Next Tab | `⌘`+ `Right Arrow` 9 | Go to Tab | `⌘` + `Number` 10 | Go to Window | `⌘` + `Option` + `Number` 11 | Go to Split Pane by Direction | `⌘` + `Option` + `Arrow` 12 | Go to Split Pane by Order of Use | `⌘` + `]` , `⌘` + `[` 13 | Split Window Horizontally (same profile) | `⌘` + `D` 14 | Split Window Vertically (same profile) | `⌘` + `d` 15 | Split Window Horizontally (new profile) | `Option` + `⌘` + `H` 16 | Split Window Vertically (new profile) | `Option` + `⌘` + `V` 17 | Set Mark | `⌘` + `M` 18 | Jump to Mark | `⌘` + `J` 19 | 20 | ### Basic Moves 21 | **Function** | **Shortcut** 22 | -------- | -------- 23 | Move back one character | `Ctrl` + `b` 24 | Move forward one character | `Ctrl` + `f` 25 | Delete current character | `Ctrl` + `d` 26 | Delete previous character | `Backspace` 27 | Undo | `Ctrl` + `-` 28 | 29 | ### Moving Faster 30 | **Function** | **Shortcut** 31 | -------- | -------- 32 | Move to the start of line | `Ctrl` + `a` 33 | Move to the end of line | `Ctrl` + `e` 34 | Move forward a word | `Option` + `f` 35 | Move backward a word | `Option` + `b` 36 | Clear the screen | `⌘` + `k` 37 | 38 | ### Copy and Paste 39 | **Function** | **Shortcut** 40 | -------- | -------- 41 | Copy from cursor to the end of line | `Ctrl` + `k` 42 | Copy from cursor to the end of word | `Option` + `d` 43 | Copy from cursor to the start of word | `Option` + `Backspace` 44 | Copy from cursor to previous whitespace | `Ctrl` + `w` 45 | Paste the last copied text | `Ctrl` + `w` 46 | Loop through and paste previously copy text | `Option` + `y` 47 | Loop through and paste the last argument of previous commands | `Option` + `.` 48 | 49 | ### Search the Command History 50 | **Function** | **Shortcut** 51 | -------- | -------- 52 | Search as you type | `Ctrl` + `r` and type the search term; Repeat `Ctrl` + `r` to loop through result 53 | Search the last remembered search term | `Ctrl` + `r` twice 54 | End the search at current history entry | `Ctrl` + `y` 55 | Cancel the search and restore original line | `Ctrl` + `g` 56 | -------------------------------------------------------------------------------- /m3/advanced.md: -------------------------------------------------------------------------------- 1 | # Advanced 2 | 3 | 4 | ## Typecript 5 | 6 | 7 | ## Angular 8 | 9 | 10 | ## Rest API 11 | 12 | 13 | ## Frontend/UI 14 | 15 | 16 | ### Testing 17 | 18 | - [Jasmine & Karma](https://codecraft.tv/courses/angular/unit-testing/jasmine-and-karma/) 19 | - [Karma](https://karma-runner.github.io/2.0/index.html) 20 | - [Jasmine](https://jasmine.github.io/) 21 | - [Protractor] 22 | - [BDD and Cucumber] 23 | 24 | ### Styleguide Driven Development 25 | 26 | - [Styleguide Driven Development](http://www.styleguidedrivendevelopment.com/) 27 | - [Atomic Design](http://bradfrost.com/blog/post/atomic-web-design/) 28 | - [Gallery](http://styleguides.io/) 29 | - [Graphic Design](https://www.canva.com/learn/50-meticulous-style-guides-every-startup-see-launching/) 30 | 31 | **Example living styleguides and component libraries:** 32 | - [Trello](https://design.trello.com/) 33 | - [Gov.UK](https://govuk-elements.herokuapp.com/) 34 | - [Schibsted](https://sui-components.now.sh/workbench/alert/basic/demo) 35 | - [Lonely Planet](http://rizzo.lonelyplanet.com/styleguide/design-elements/colours) 36 | - [S§lfesforce](https://www.lightningdesignsystem.com/components/accordion/) 37 | - [Auth0](https://github.com/auth0/styleguide) 38 | 39 | 40 | ### Living Styleguide tools 41 | 42 | - [Pattern Lab](http://patternlab.io/) 43 | - [Atomic Docs](http://atomicdocs.io/) 44 | - [Document CSS](https://documentcss.com/) 45 | - [SC5](http://styleguide.sc5.io/) 46 | - [Hologram](https://trulia.github.io/hologram/) 47 | - [Nucleus](https://holidaypirates.github.io/nucleus/) 48 | - [Zepplin](https://zeplin.io/) 49 | 50 | 51 | ### Web Components 52 | 53 | - [Web Components](https://www.webcomponents.org/) 54 | - [Polymer](https://medium.com/@oneeezy/frameworks-vs-web-components-9a7bd89da9d4) 55 | 56 | 57 | ## Cloud 58 | 59 | 60 | ### Containers 61 | 62 | 63 | ### Microservices 64 | 65 | - [MS at Scale - Mastering Chaos at Netflix](https://www.youtube.com/watch?v=CZ3wIuvmHeM) 66 | 67 | 68 | ### Serverless 69 | 70 | - [AWS + Lambda Video](https://www.manning.com/livevideo/production-ready-serverless?a_aid=aws-lambda-in-motion&a_bid=9318fc6f) 71 | 72 | 73 | 74 | ## Lean / Agile 75 | 76 | 77 | ### Systems Thinking 78 | 79 | - [Deming’s 14 Points](https://leanandkanban.wordpress.com/2011/07/15/demings-14-points/) 80 | -------------------------------------------------------------------------------- /m2/deployment.md: -------------------------------------------------------------------------------- 1 | # Deployment 2 | - http://learn.ironhack.com/#/learning_unit/3170 3 | - create heroku account 4 | - it's a cloud platform for hosting apps 5 | - https://signup.heroku.com/ 6 | - create application 7 | - provide a name (it will be the url https://app-name.herokuapp.com) 8 | - install [heroku CLI](https://devcenter.heroku.com/articles/heroku-cli) 9 | - download here: https://devcenter.heroku.com/articles/heroku-cli 10 | 11 | - prepare app inside the project 12 | - `$ heroku login` 13 | - `$ heroku git:remote -a app-name` 14 | - make sure package.json is in the root of the project 15 | - make sure package.json contains a start script 16 | - add [engines](https://devcenter.heroku.com/articles/nodejs-support#specifying-a-node-js-version) to package.json 17 | 18 | ``` 19 | "scripts": { 20 | "start": "node ./bin/www" 21 | }, 22 | "engines": { 23 | "node": "x.x.x", 24 | "npm": "x.x.x" 25 | } 26 | ``` 27 | 28 | - create database via shell 29 | - `$ heroku addons:create mongolab:sandbox` 30 | - `$ heroku addons:open mongolab` 31 | - `$ heroku config:get MONGODB_URI` 32 | 33 | - OR create database in [MLAB](https://mlab.com/) 34 | - sign up 35 | - create new MongoDB Deployment 36 | - cloud provider 37 | - free account 38 | - provide a name 39 | - submit 40 | - wait until the database is created 41 | - add "admin" user database 42 | - copy mongodb url to herokuapp settings config variables `MONGODB_URI` 43 | 44 | ``` 45 | mongodb://myuser:mypassword@ds255309.mlab.com:11309/ironhack-database 46 | ``` 47 | - configure app 48 | - REMOVE ALL API KEYS (e.g. facebook secret) FROM YOUR CODE 49 | - `$ npm install --save dotenv` 50 | - add `require('dotenv').config();` to app.js 51 | - create `.env` file (adds fake environment variables to `process.env`) 52 | - add `.env` to `.gitignore` 53 | - replace hardcoded mongodb URI with process env variable in app.js 54 | 55 | ``` 56 | # in .env file 57 | MONGODB_URI=mongodb://localhost/databaseName 58 | FACEBOOK_API_KEY=qwerqweoiov32414oih12p3ou12po12po3ihp1234 59 | ``` 60 | 61 | 62 | ```javascript 63 | // in app.js 64 | mongoose.connect(process.env.MONGODB_URI, ...); 65 | ``` 66 | 67 | - deploy 68 | - `$ git add` && `$ git commit` 69 | - `$ git push heroku master` 70 | - `$ heroku logs` 71 | - `$ heroku logs -t` 72 | -------------------------------------------------------------------------------- /m3/express-auth/auth.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const express = require('express'); 4 | const bcrypt = require('bcrypt'); 5 | const router = express.Router(); 6 | 7 | const User = require('../models/user'); 8 | 9 | router.get('/me', (req, res, next) => { 10 | if (req.session.currentUser) { 11 | res.status(200).json(req.session.currentUser); 12 | } else { 13 | res.status(404).json({code: 'not-found'}); 14 | } 15 | }); 16 | 17 | router.post('/login', (req, res, next) => { 18 | if (req.session.currentUser) { 19 | return res.status(401).json({code: 'unauthorized'}); 20 | } 21 | 22 | const username = req.body.username; 23 | const password = req.body.password; 24 | 25 | if (!username || !password) { 26 | return res.status(422).json({code: 'validation'}); 27 | } 28 | 29 | User.findOne({ username }) 30 | .then((user) => { 31 | if (!user) { 32 | return res.status(404).json({code: 'not-found'}); 33 | } 34 | if (bcrypt.compareSync(password, user.password)) { 35 | req.session.currentUser = user; 36 | return res.json(user); 37 | } else { 38 | return res.status(404).json({code: 'not-found'}); 39 | } 40 | }) 41 | .catch(next); 42 | }); 43 | 44 | router.post('/signup', (req, res, next) => { 45 | if (req.session.currentUser) { 46 | return res.status(401).json({code: 'unauthorized'}); 47 | } 48 | 49 | const username = req.body.username; 50 | const password = req.body.password; 51 | 52 | if (!username || !password) { 53 | return res.status(422).json({code: 'validation'}); 54 | } 55 | 56 | User.findOne({username}, 'username') 57 | .then((userExists) => { 58 | if (userExists) { 59 | return res.status(422).json({code: 'username-not-unique'}); 60 | } 61 | 62 | const salt = bcrypt.genSaltSync(10); 63 | const hashPass = bcrypt.hashSync(password, salt); 64 | 65 | const newUser = User({ 66 | username, 67 | password: hashPass 68 | }); 69 | 70 | return newUser.save() 71 | .then(() => { 72 | req.session.currentUser = newUser; 73 | res.json(newUser); 74 | }); 75 | }) 76 | .catch(next); 77 | }); 78 | 79 | router.post('/logout', (req, res) => { 80 | req.session.currentUser = null; 81 | return res.status(204).send(); 82 | }); 83 | 84 | module.exports = router; 85 | -------------------------------------------------------------------------------- /m2/advanced.md: -------------------------------------------------------------------------------- 1 | # Advanced 2 | 3 | 4 | ## HTTP 5 | 6 | - [CORS Intro](https://www.html5rocks.com/en/tutorials/cors/) 7 | - [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) 8 | 9 | 10 | ## Security 11 | 12 | - CSRF 13 | - XSS 14 | - Injection 15 | 16 | 17 | ### JWTf 18 | 19 | - [JWT Intro](https://jwt.io/introduction/) 20 | - [JWT for SPA](https://stormpath.com/blog/token-auth-spa) 21 | 22 | - [Node.js JWT](http://self-issued.info/docs/draft-ietf-oauth-json-web-token.html) 23 | 24 | 25 | ## Javascript 26 | 27 | 28 | ### Unit Testing 29 | 30 | - [Mocha & Chai](http://mherman.org/blog/2015/09/10/testing-node-js-with-mocha-and-chai) 31 | - [Mocha](https://mochajs.org/) 32 | - [Chai](http://www.chaijs.com/) 33 | - [Sinon](http://sinonjs.org/) 34 | 35 | 36 | ### ES6+ 37 | 38 | - [ES7 features](http://kangax.github.io/compat-table/es2016plus/) 39 | - [ES7, ES8](http://exploringjs.com/es2018-es2019/) 40 | 41 | 42 | ### Errors 43 | 44 | - [Node.js Error Handling Best Practices](http://goldbergyoni.com/checklist-best-practices-of-node-js-error-handling/) 45 | - [Error Handling in Node.js](https://www.joyent.com/node-js/production/design/errors) 46 | 47 | 48 | ### Async 49 | 50 | - [Best Practices](https://nemethgergely.com/async-function-best-practices/) 51 | 52 | 53 | ### Promises 54 | 55 | - [Best Practices][https://60devs.com/best-practices-for-using-promises-in-js.html] 56 | - [Anti-patterns](https://hackernoon.com/javascript-promises-best-practices-anti-patterns-b32309f65551) 57 | 58 | 59 | ## Node.js 60 | 61 | - [How the Event Loop REALLY Works](https://webapplog.com/event-loop/) 62 | 63 | 64 | ### Architecture 65 | 66 | - [Clean Code Javascript](https://github.com/ryanmcdermott/clean-code-javascript) 67 | - [Node.js Best Practices](https://blog.codeminer42.com/nodejs-and-good-practices-354e7d763626) 68 | - [Lean Architecture](https://herbertograca.com/category/development/book-notes/lean-architecture-by-james-coplien-and-gertrud-bjornvig/) 69 | - [Architecture 1st Step - Partitioning](https://herbertograca.com/2017/03/06/architecture-1st-design-step-partitioning/#more-7827) 70 | 71 | 72 | ### Templating 73 | 74 | - [Top Engines](https://colorlib.com/wp/top-templating-engines-for-javascript/) 75 | - [HBS](http://tryhandlebarsjs.com/) 76 | 77 | 78 | ## Databases 79 | 80 | 81 | ### Mongoose 82 | 83 | 84 | ## Devops 85 | 86 | 87 | ### Containers 88 | 89 | 90 | ### Deployment 91 | 92 | 93 | ### Configuration Management 94 | 95 | 96 | ### Secret Management 97 | 98 | - [Secret Management Tools](https://gist.github.com/maxvt/bb49a6c7243163b8120625fc8ae3f3cd) 99 | -------------------------------------------------------------------------------- /m3/deployment/readme.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # backend 4 | 5 | - create heroku app "foobar-server" 6 | 7 | - follow steps outlined [here](../../m2/deployment.md) 8 | 9 | ## backend app.js 10 | 11 | ``` 12 | app.use(cors({ 13 | credentials: true, 14 | origin: [process.env.CLIENT_URL] 15 | })); 16 | ``` 17 | 18 | ## backend .env 19 | 20 | ``` 21 | MONGODB_URI=mongodb://localhost:27017/foobar 22 | CLIENT_URL=http://localhost:4200 23 | ``` 24 | 25 | ## heroku app "foobar-api" settings 26 | 27 | ``` 28 | MONGODB_URI=... 29 | CLIENT_URL=https://foobar.herokuapp.com 30 | ``` 31 | 32 | 33 | 34 | 35 | # frontend 36 | 37 | - create heroku app "foobar" 38 | 39 | ## frontend ng build --aot --prod 40 | 41 | - fix all the errors 42 | 43 | - $ cd dist && ll 44 | - write down the name of the folder inside dist 45 | 46 | ## frontend package.json 47 | 48 | - add engines (run `node --version` and `npm --version` in your laptop first) 49 | 50 | ``` 51 | "engines": { 52 | "node": "9.0.0", 53 | "npm": "5.5.1" 54 | }, 55 | ``` 56 | 57 | - add the following entries to the `scripts` object 58 | 59 | ``` 60 | "heroku-prebuild": "rm -rf node_modules && npm cache clean --force", 61 | "postinstall": "ng build --aot --prod", 62 | "start": "node app.js" 63 | ``` 64 | 65 | - move the following entries from `devDependencies` to `dependencies`: 66 | 67 | ``` 68 | @angular/cli 69 | @angular/compiler-cli 70 | typescript 71 | ``` 72 | 73 | ## frontend add app.js file 74 | 75 | - this tiny node server will serve your angular app in heroku 76 | - copy `app.js` to the root of the repository 77 | - on both routes of app.js, change the folder name 'client' by the name you've noted before when doing ng build 78 | - `npm install --save express` 79 | 80 | ## frontend environemnts 81 | 82 | - add `apiUrl: 'http://localhost:3000'` to `src/app/environments/environment.ts` 83 | - add `apiUrl: 'http://foobar-server.herokuapp.com'` to `src/app/environments/environment.prod.ts` 84 | 85 | ## in all services 86 | 87 | - import envinroment and define the `baseUrl` for all ops in this service (e.g. ` + "/auth"`) 88 | 89 | ``` 90 | import { environment } from '../../environments/environment'; 91 | const apiUrl = environment.apiUrl + '/name-of-resource'; 92 | ``` 93 | 94 | - use that `apiUrl` in all methods 95 | 96 | 97 | ## testing against the heroku backend 98 | 99 | - go to heroku and change the "foobar-api" settings to allow testing from localhost (set `CLIENT_URL` temporarily to `http://localhost:4200`) 100 | - go to `src/app/environments/environment.ts` and temporarily change the `apiUrl` to be the heroku one 101 | - load a route that does a GET/POST to backend 102 | - test that there are no errors in the console 103 | - test you get the expected results from heroku (success, the seeded data or empty results) 104 | - after testing make sure you reset the settings 105 | -- in the heroku backend project settings, `CLIENT_URL` should be set to `https://foobar.herokuapp.com` 106 | -- in `environment.ts` the `apiUrl` key should be set to `http://localhost:3000` 107 | 108 | ## deploy 109 | 110 | - commit everything 111 | - merge to master 112 | - push to `origin master` AND `heroku master` 113 | 114 | 115 | -------------------------------------------------------------------------------- /m1/advanced.md: -------------------------------------------------------------------------------- 1 | # Advanced 2 | 3 | 4 | ## UX 5 | 6 | - [UX Basics](https://developers.google.com/web/fundamentals/design-and-ux/ux-basics/) 7 | 8 | 9 | ## CSS 10 | 11 | - [CSS Guidelines](https://cssguidelin.es) 12 | - [OOCSS](http://oocss.org/) 13 | - [SMACSS](https://smacss.com/) 14 | - [BEM](http://getbem.com/introduction/) 15 | - [Web Typography](http://webtypography.net/) 16 | - [Vertical Grid](https://24ways.org/2006/compose-to-a-vertical-rhythm/) 17 | - [Baseline Grid](http://joshnh.com/weblog/how-to-set-up-a-baseline-grid/) 18 | 19 | 20 | ## Flexbox & Grid 21 | 22 | - [Complete Flexbox Guide](https://css-tricks.com/snippets/css/a-guide-to-flexbox/) 23 | - [Flexbox Cheatsheet](http://jonibologna.com/content/images/flexboxsheet.pdf) 24 | - [Flexbox Game](http://flexboxfroggy.com/) 25 | - [Flexbox vs Grid](https://medium.com/@lauren.kroner/flexbox-vs-css-grid-6a94547b6c06) 26 | - [Grid Reference](https://cssreference.io/css-grid/) 27 | - [Advanced Grid Techniques](https://css-tricks.com/things-ive-learned-css-grid-layout/) 28 | 29 | ## Typography 30 | 31 | - [Web Typography 101](https://medium.com/@andreacrofts/web-typography-101-302af8a65be7) 32 | - [Balancing line-height and font-size](https://www.smashingmagazine.com/2014/09/balancing-line-length-font-size-responsive-web-design/) 33 | - [Responsive - REM global and EM local](https://css-tricks.com/rem-global-em-local/) 34 | - [16px, anything else too small](https://www.smashingmagazine.com/2011/10/16-pixels-body-copy-anything-less-costly-mistake/) 35 | - [Your body text is too small](https://blog.usejournal.com/your-body-text-is-too-small-5e02d36dc902) 36 | - [Responsive font-size](http://codeitdown.com/responsive-font-size-css/) 37 | - [Fluid Typography](https://css-tricks.com/snippets/css/fluid-typography/) 38 | 39 | 40 | ## Responsive Web Design 41 | 42 | - [Mobile first 2010](https://www.lukew.com/ff/entry.asp?1117) 43 | - [The many faces of mobile first 2012](http://bradfrost.com/blog/mobile/the-many-faces-of-mobile-first/) 44 | - [Media queries mobile first 2014](https://zellwk.com/blog/how-to-write-mobile-first-css/) 45 | - [Responsive Web Design Basics](https://developers.google.com/web/fundamentals/design-and-ux/responsive/) 46 | - [Media queries in 2018](https://www.smashingmagazine.com/2018/02/media-queries-responsive-design-2018/) 47 | - [Responsive Design Patterns](https://uxplanet.org/responsive-design-best-practices-c6d3f5fd163b) 48 | - [Responsive images](https://css-tricks.com/responsive-images-css/) 49 | - [Responsive Tables](https://dbushell.com/2012/01/05/responsive-tables-2/) 50 | 51 | 52 | ## Progressive Web Apps 53 | 54 | - [Google resources](https://developers.google.com/web/progressive-web-apps/) 55 | - [App Shel Pattern](https://developers.google.com/web/fundamentals/architecture/app-shell) 56 | 57 | 58 | ## OpenGraph (Facebook) 59 | 60 | - [Quick Tutorial](https://davidwalsh.name/facebook-meta-tags) 61 | - [Open Graph Protocol Specification](http://ogp.me/) 62 | - [Facebook Sharing 101](https://developers.facebook.com/docs/sharing/webmasters) 63 | - [Facebook Sharing Best Practices](https://developers.facebook.com/docs/sharing/best-practices/) 64 | 65 | 66 | ## Accessibility 67 | 68 | - [Intro](https://developers.google.com/web/fundamentals/accessibility/) 69 | - [ARIA](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA) 70 | 71 | 72 | ## Security 73 | 74 | - [no opnener](https://mathiasbynens.github.io/rel-noopener/) 75 | 76 | 77 | ## OpenGraph 78 | 79 | - [](https://developers.facebook.com/docs/sharing/webmasters/) 80 | -------------------------------------------------------------------------------- /m2/project-readme.md: -------------------------------------------------------------------------------- 1 | # Project Name 2 | 3 | ## Description 4 | 5 | Describe your project in one/two lines. 6 | 7 | ## User Stories 8 | 9 | - **404** - As a user I want to see a nice 404 page when I go to a page that doesn’t exist so that I know it was my fault 10 | - **500** - As a user I want to see a nice error page when the super team screws it up so that I know that is not my fault 11 | - **homepage** - As a user I want to be able to access the homepage so that I see what the app is about and login and signup 12 | - **sign up** - As a user I want to sign up on the webpage so that I can see all the events that I could attend 13 | - **login** - As a user I want to be able to log in on the webpage so that I can get back to my account 14 | - **logout** - As a user I want to be able to log out from the webpage so that I can make sure no one will access my account 15 | - **events list** - As a user I want to see all the events available so that I can choose which ones I want to attend 16 | - **events create** - As a user I want to create an event so that I can invite others to attend 17 | - **events detail** - As a user I want to see the event details and attendee list of one event so that I can decide if I want to attend 18 | - **event attend** - As a user I want to be able to attend to event so that the organizers can count me in 19 | 20 | ## Backlog 21 | 22 | List of other features outside of the MVPs scope 23 | 24 | User profile: 25 | - see my profile 26 | - upload my profile picture 27 | - see other users profile 28 | - list of events created by the user 29 | - list events the user is attending 30 | 31 | Geo Location: 32 | - add geolocation to events when creating 33 | - show event in a map in event detail page 34 | - show all events in a map in the event list page 35 | 36 | Homepage 37 | - ... 38 | 39 | 40 | ## ROUTES: 41 | 42 | - GET / 43 | - renders the homepage 44 | - GET /auth/signup 45 | - redirects to / if user logged in 46 | - renders the signup form (with flash msg) 47 | - POST /auth/signup 48 | - redirects to / if user logged in 49 | - body: 50 | - username 51 | - email 52 | - password 53 | - GET /auth/login 54 | - redirects to / if user logged in 55 | - renders the login form (with flash msg) 56 | - POST /auth/login 57 | - redirects to / if user logged in 58 | - body: 59 | - username 60 | - password 61 | - POST /auth/logout 62 | - body: (empty) 63 | 64 | - GET /events 65 | - renders the event list + the create form 66 | - POST /events/create 67 | - redirects to / if user is anonymous 68 | - body: 69 | - name 70 | - date 71 | - location 72 | - description 73 | - GET /events/:id 74 | - renders the event detail page 75 | - includes the list of attendees 76 | - attend button if user not attending yet 77 | - POST /events/:id/attend 78 | - redirects to / if user is anonymous 79 | - body: (empty - the user is already stored in the session) 80 | 81 | 82 | ## Models 83 | 84 | User model 85 | 86 | ``` 87 | username: String 88 | password: String 89 | ``` 90 | 91 | Event model 92 | 93 | ``` 94 | owner: ObjectId 95 | name: String 96 | description: String 97 | date: Date 98 | location: String 99 | attendees: [ObjectId] 100 | ``` 101 | 102 | ## Links 103 | 104 | ### Trello 105 | 106 | [Link to your trello board](https://trello.com) or picture of your physical board 107 | 108 | ### Git 109 | 110 | The url to your repository and to your deployed project 111 | 112 | [Repository Link](http://github.com) 113 | 114 | [Deploy Link](http://heroku.com) 115 | 116 | ### Slides 117 | 118 | The url to your presentation slides 119 | 120 | [Slides Link](http://slides.com) 121 | 122 | 123 | -------------------------------------------------------------------------------- /tools/shortcuts/vscode.md: -------------------------------------------------------------------------------- 1 | ### VSCode (Sublime Text Keymap - MAC) 2 | 3 | #### Text Editing Beginner 4 | **Function** | **Shortcut** 5 | -------- | -------- 6 | Move line/selection up | `⌃` + `⌘` + `Up Arrow` 7 | Cut line | `⌘` + `X` 8 | Insert line after | `⌘` + `↵` 9 | Insert line before | `⇧` + `⌘` + `↵` 10 | Move line/selection down | `⌃` + `⌘` + `Down Arrow` 11 | Select line - repeat to select next lines | `⌘` + `L` 12 | Select word - repeat select others occurrences | `⌘` + `D` 13 | Go to matching parentheses | `⌃` + `M` 14 | Select all contents of the current parentheses | `⇧` + `⌃` + `M` 15 | 16 | #### Text Editing Intermediate 17 | **Function** | **Shortcut** 18 | -------- | -------- 19 | Indent current line(s) | `⌘` + `]` 20 | Un-indent current line(s) | `⌘` + `[` 21 | Duplicate line(s) | `⇧` + `⌘` + `D` 22 | Comment/un-comment current line | `⌘` + `/` 23 | Block comment current selection | `⌥` + `⌘` + `/` 24 | Redo or repeat last keyboard shortcut command | `⌘` + `Y` 25 | 26 | #### Text Editing Advance 27 | **Function** | **Shortcut** 28 | -------- | -------- 29 | Delete from cursor to end of line | `⌘` + `K` + `⌘` + `K` 30 | Delete from cursor to start of line | `⌘` + `BACKSPACE` 31 | Paste and indent correctly | `⇧` + `⌘` + `V` 32 | Select next auto-complete suggestion | `⌃` + `SPACE` 33 | Soft undo | `⌘` + `U` 34 | Paste from history | `⌥` + `⌘` + `V` 35 | 36 | #### Text Navigation/Goto Anywhere 37 | **Function** | **Shortcut** 38 | -------- | -------- 39 | Quick-open files by name | `⌘` + `P` 40 | Goto symbol | `⌘` + `R` 41 | Goto line in current file | `⌃` + `G` 42 | Select current line | `⌘` + `L` 43 | Select between brackets | `⇧` + `⌃` + `M` 44 | Select current indentation | `⇧` + `⌘` + `J` 45 | Use selection for find | `⌘` + `E` 46 | Use selection for replace | `⇧` + `⌘` + `E` 47 | Expand selection to html tag | `⇧` + `⌘` + `A` 48 | 49 | #### Find/Replace 50 | **Function** | **Shortcut** 51 | -------- | -------- 52 | Find | `⌘` + `F` 53 | Find in files | `⇧` + `⌘` + `F` 54 | Find next | `⌘` + `G` 55 | Replace... | `⌥` + `⌘` + `F` 56 | Find previous | `⇧` + `⌘` + `G` 57 | Incremental find | `⌘` + `I` 58 | Replace next | `⌥` + `⌘` + `E` 59 | Quick find | `⌥` + `⌘` + `G` 60 | 61 | #### General 62 | **Function** | **Shortcut** 63 | -------- | -------- 64 | Hide sublime text 3 | `⌘` + `H` 65 | Hide all other windows | `⌥` + `⌘` + `H` 66 | Toggle side bar | `⌘` + `K` + `⌘` + `B` 67 | Command prompt | `⇧` + `⌘` + `P` 68 | Open file | `⌘` + `O` 69 | Zoom in | `⌘` + `=` 70 | User settings | `⌘` + `,` 71 | Zoom out | `⌘` + `-` 72 | Make a new sticky note | `⇧` + `⌘` + `Y` 73 | Save as... | `⇧` + `⌘` + `S` 74 | Save all | `⌥` + `⌘` + `S` 75 | Show console | `⌃` + `Back tick` 76 | Enter/exit full screen | `⌃` + `⌘` + `F` 77 | Enter distraction free mode | `⇧` + `⌃` + `⌘` + `F` 78 | Spell check | `F6` 79 | 80 | #### Text manipulation 81 | **Function** | **Shortcut** 82 | -------- | -------- 83 | Transform to uppercase | `⌘` + `K` + `⌘` + `U` 84 | Transform to lowercase | `⌘` + `K` + `⌘` + `L` 85 | Delete line | `⇧` + `⌃` + `K` 86 | Join lines | `⌘` + `J` 87 | Close html tag | `⌥` + `⌘` + `.` 88 | Sort lines | `F5` 89 | Sort lines (case sensitive) | `⌃` + `F5` 90 | 91 | #### Split Window 92 | **Function** | **Shortcut** 93 | -------- | -------- 94 | Split view into two columns | `⌥` + `⌘` + `2` 95 | Revert view to single column | `⌥` + `⌘` + `1` 96 | Set view to grid (4 groups) | `⌥` + `⌘` + `5` 97 | Jump to group 2 | `⌃` + `2` 98 | Move file to group 2 | `⇧` + `⌃` + `2` 99 | Split view into 3 columns | `⌥` + `⌘` + `3` 100 | Split view into 4 columns | `⌥` + `⌘` + `4` 101 | Split view into 2 rows | `⇧` + `⌥` + `⌘` + `2` 102 | Split view into 3 rows | `⇧` + `⌥` + `⌘` + `3` 103 | Jump to group 1 | `⌃` + `1` 104 | -------------------------------------------------------------------------------- /m3/project-readme.md: -------------------------------------------------------------------------------- 1 | # Project Name 2 | 3 | ## Description 4 | 5 | Describe your project in one/two lines. 6 | 7 | ## User Stories 8 | 9 | - **404:** As an anon/user I can see a 404 page if I try to reach a page that does not exist so that I know it's my fault 10 | - **Signup:** As an anon I can sign up in the platform so that I can start saving favorite restaurants 11 | - **Login:** As a user I can login to the platform so that I can see my favorite restaurants 12 | - **Logout:** As a user I can logout from the platform so no one else can use it 13 | - **Add Restaurants** As a user I can add a restaurant so that I can share it with the community 14 | - **List Restaurants** As a user I want to see the restaurants so that I can choose one to eat 15 | - **Search Restaurants** As a user I want to search restaurants by name so that I know if it´s already in the platform 16 | - **Add to favorites** As a user I want to add a restaurant to favorite so that I can save the restaurants that I liked the most 17 | - **See my favorites** As a user I want to see my favorite restaurantes so that I can see the ones I liked the most 18 | 19 | ## Backlog 20 | 21 | User profile: 22 | - see other users profile sand their favorites 23 | 24 | Geo Location: 25 | - see restaurants in a map 26 | 27 | # Client 28 | 29 | ## Routes 30 | 31 | - / - Homepage 32 | - /auth/signup - Signup form 33 | - /auth/login - Login form 34 | - /restaurants - restaurant list 35 | - /restaurants/create - create a restaurant 36 | - /restaurants/:id - restaurant detail 37 | - /profile/me - my details and favorite restaurants 38 | - 404 39 | 40 | ## Pages 41 | 42 | - Home Page (public) 43 | - Sign in Page (anon only) 44 | - Log in Page (anon only) 45 | - Restaurants List Page (public only) 46 | - Restaurant Create (user only) 47 | - Restaurant Detail Page (public only) 48 | - My Profile Page (user only) 49 | - 404 Page (public) 50 | 51 | ## Components 52 | 53 | - Restaurant Card component 54 | - Input: restaurant: any 55 | - Output: favorite(restaurantId: string, on: boolean) 56 | - Search component 57 | - Output: change(terms: string) 58 | 59 | ## IO 60 | 61 | 62 | ## Services 63 | 64 | - Auth Service 65 | - auth.login(user) 66 | - auth.signup(user) 67 | - auth.logout() 68 | - auth.me() 69 | - auth.getUser() // synchronous 70 | - Restaurant Service 71 | - restaurant.list() 72 | - restaurant.create(data) 73 | - restaurant.detail(id) 74 | - restaurant.addFavorite(id) 75 | - restaurant.removeFavorite(id) 76 | 77 | # Server 78 | 79 | ## Models 80 | 81 | User model 82 | 83 | ``` 84 | username - String // required 85 | email - String // required & unique 86 | password - String // required 87 | favorites - [ObjectID] 88 | ``` 89 | 90 | Restaurant model 91 | 92 | ``` 93 | owner - ObjectID // required 94 | name - String // required 95 | phone - String 96 | address - String 97 | ``` 98 | 99 | ## API Endpoints/Backend Routes 100 | 101 | - GET /auth/me 102 | - POST /auth/signup 103 | - body: 104 | - username 105 | - email 106 | - password 107 | - POST /auth/login 108 | - body: 109 | - username 110 | - password 111 | - POST /auth/logout 112 | - body: (empty) 113 | - POST /user/me/favorite 114 | - body: 115 | - restaurantId 116 | - DELETE /user/me/favorite/:restaurantId 117 | - body: (empty) 118 | - GET /restaurant 119 | - POST /restaurant 120 | - body: 121 | - name 122 | - phone 123 | - address 124 | - GET /restaurant/:id 125 | 126 | 127 | 128 | ## Links 129 | 130 | ### Trello/Kanban 131 | 132 | [Link to your trello board](https://trello.com) or picture of your physical board 133 | 134 | ### Git 135 | 136 | The url to your repository and to your deployed project 137 | 138 | [Client repository Link](http://github.com) 139 | [Server repository Link](http://github.com) 140 | 141 | [Deploy Link](http://heroku.com) 142 | 143 | ### Slides 144 | 145 | The url to your presentation slides 146 | 147 | [Slides Link](http://slides.com) 148 | -------------------------------------------------------------------------------- /m3/express-auth/rest-auth.postman_collection.json: -------------------------------------------------------------------------------- 1 | { 2 | "info": { 3 | "name": "REST API AUTH", 4 | "_postman_id": "2f256535-ff24-8d46-fe85-98983bd7a2ef", 5 | "description": "", 6 | "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" 7 | }, 8 | "item": [ 9 | { 10 | "name": "localhost:3000/auth/me", 11 | "request": { 12 | "method": "GET", 13 | "header": [], 14 | "body": {}, 15 | "url": { 16 | "raw": "localhost:3000/auth/me", 17 | "host": [ 18 | "localhost" 19 | ], 20 | "port": "3000", 21 | "path": [ 22 | "auth", 23 | "me" 24 | ] 25 | }, 26 | "description": "" 27 | }, 28 | "response": [] 29 | }, 30 | { 31 | "name": "localhost:3000/auth/login (unknown)", 32 | "request": { 33 | "method": "POST", 34 | "header": [ 35 | { 36 | "key": "Content-Type", 37 | "value": "application/json" 38 | } 39 | ], 40 | "body": { 41 | "mode": "raw", 42 | "raw": "{\n\t\"username\": \"!\",\n\t\"password\": \"!\"\n}" 43 | }, 44 | "url": { 45 | "raw": "localhost:3000/auth/login", 46 | "host": [ 47 | "localhost" 48 | ], 49 | "port": "3000", 50 | "path": [ 51 | "auth", 52 | "login" 53 | ] 54 | }, 55 | "description": "" 56 | }, 57 | "response": [] 58 | }, 59 | { 60 | "name": "localhost:3000/auth/login (validation)", 61 | "request": { 62 | "method": "POST", 63 | "header": [ 64 | { 65 | "key": "Content-Type", 66 | "value": "application/json" 67 | } 68 | ], 69 | "body": { 70 | "mode": "raw", 71 | "raw": "{\n\n}" 72 | }, 73 | "url": { 74 | "raw": "localhost:3000/auth/login", 75 | "host": [ 76 | "localhost" 77 | ], 78 | "port": "3000", 79 | "path": [ 80 | "auth", 81 | "login" 82 | ] 83 | }, 84 | "description": "" 85 | }, 86 | "response": [] 87 | }, 88 | { 89 | "name": "localhost:3000/auth/login (foobar:1234)", 90 | "request": { 91 | "method": "POST", 92 | "header": [ 93 | { 94 | "key": "Content-Type", 95 | "value": "application/json" 96 | } 97 | ], 98 | "body": { 99 | "mode": "raw", 100 | "raw": "{\n\t\"username\": \"foobar\",\n\t\"password\": \"1234444\"\n}" 101 | }, 102 | "url": { 103 | "raw": "localhost:3000/auth/login", 104 | "host": [ 105 | "localhost" 106 | ], 107 | "port": "3000", 108 | "path": [ 109 | "auth", 110 | "login" 111 | ] 112 | }, 113 | "description": "" 114 | }, 115 | "response": [] 116 | }, 117 | { 118 | "name": "localhost:3000/auth/signup (validation)", 119 | "request": { 120 | "method": "POST", 121 | "header": [ 122 | { 123 | "key": "Content-Type", 124 | "value": "application/json" 125 | } 126 | ], 127 | "body": { 128 | "mode": "raw", 129 | "raw": "{\n\n}" 130 | }, 131 | "url": { 132 | "raw": "localhost:3000/auth/signup", 133 | "host": [ 134 | "localhost" 135 | ], 136 | "port": "3000", 137 | "path": [ 138 | "auth", 139 | "signup" 140 | ] 141 | }, 142 | "description": "" 143 | }, 144 | "response": [] 145 | }, 146 | { 147 | "name": "localhost:3000/auth/signup (foobar:1234)", 148 | "request": { 149 | "method": "POST", 150 | "header": [ 151 | { 152 | "key": "Content-Type", 153 | "value": "application/json" 154 | } 155 | ], 156 | "body": { 157 | "mode": "raw", 158 | "raw": "{\n\t\"username\": \"foobar\",\n\t\"password\": \"1234\"\n}" 159 | }, 160 | "url": { 161 | "raw": "localhost:3000/auth/signup", 162 | "host": [ 163 | "localhost" 164 | ], 165 | "port": "3000", 166 | "path": [ 167 | "auth", 168 | "signup" 169 | ] 170 | }, 171 | "description": "" 172 | }, 173 | "response": [] 174 | }, 175 | { 176 | "name": "localhost:3000/auth/logout", 177 | "request": { 178 | "method": "POST", 179 | "header": [], 180 | "body": { 181 | "mode": "raw", 182 | "raw": "" 183 | }, 184 | "url": { 185 | "raw": "localhost:3000/auth/logout", 186 | "host": [ 187 | "localhost" 188 | ], 189 | "port": "3000", 190 | "path": [ 191 | "auth", 192 | "logout" 193 | ] 194 | }, 195 | "description": "" 196 | }, 197 | "response": [] 198 | } 199 | ] 200 | } -------------------------------------------------------------------------------- /extras/agile.md: -------------------------------------------------------------------------------- 1 | # Intro 2 | 3 | - [TALK - Alistair Cockburn - Agile is for Wimps: Software Development in the 21st Century](https://www.youtube.com/watch?v=dOg41YdZ_as) 4 | - [TALK - Pragmatic Dave Thomas - Agile is Dead](https://www.youtube.com/watch?v=a-BOSpxYJ9M) 5 | - [Glossary](https://www.agilealliance.org/agile101/agile-glossary/) 6 | 7 | 8 | # websites 9 | 10 | - [Agile Manifesto](http://agilemanifesto.org/) 11 | - [Agile Patterns](http://agilepatterns.org/) 12 | - [Agile Alliance](https://www.agilealliance.org/) 13 | - [Age of Product](https://age-of-product.com/) 14 | - [Growing Agile Blog](https://www.growingagile.co.za/blog/) 15 | - [Atlassian Blog](https://www.atlassian.com/blog/agile) 16 | - [Lean Kanban Blog](http://anderson.leankanban.com/blog/) 17 | - [Lean Agile Blog](https://www.leanagiletraining.com/blog/) 18 | - [Agile Code](https://www.agile-code.com/blog/) 19 | - [Luis Goncalves Blog](https://luis-goncalves.com) 20 | - [Agile Testing](http://lisacrispin.com/) 21 | - [Lynne Cazaly Blog](http://www.lynnecazaly.com.au/) 22 | - [Bob Marshall Blog](https://flowchainsensei.wordpress.com/) 23 | 24 | # People 25 | 26 | - Alistair Cockburn | Heart of Agile | CrystalClear 27 | - [videos](https://www.youtube.com/results?search_query=alistair+cockburn) 28 | - [about](https://en.wikipedia.org/wiki/Alistair_Cockburn) 29 | - [website](http://alistair.cockburn.us/) 30 | - Kent Beck | XP | TDD 31 | - [videos](https://www.youtube.com/results?search_query=Kent+Beck) 32 | - [about](https://en.wikipedia.org/wiki/Kent_Beck) 33 | - Martin Fowler | OOP | UML | XP 34 | - [videos](https://www.youtube.com/results?search_query=Martin+Folwer) 35 | - [about](https://en.wikipedia.org/wiki/Martin_Fowler) 36 | - [website](https://martinfowler.com/) 37 | - Robert C. Martin | SOLID | XP 38 | - [videos](https://www.youtube.com/watch?v=Tng6Fox8EfI&list=PLcr1-V2ySv4Tf_xSLj2MbQZr78fUVQAua) 39 | - [about](https://en.wikipedia.org/wiki/Robert_C._Martin) 40 | - Ron Jeffries | XP 41 | - [videos](https://www.youtube.com/results?search_query=ron+jeffries&page=&utm_source=opensearch) 42 | - [about](https://en.wikipedia.org/wiki/Ron_Jeffries) 43 | - [website](https://ronjeffries.com/) 44 | - Ward Cunningham | Design Patterns | XP 45 | - [videos](https://www.youtube.com/results?search_query=Ward+Cunningham) 46 | - [about](https://en.wikipedia.org/wiki/Ward_Cunningham) 47 | - Dave Thomas | XP | Kata 48 | - [videos](https://www.youtube.com/results?search_query=dave+thomas+agile) 49 | - [about](https://en.wikipedia.org/wiki/Dave_Thomas_(programmer)) 50 | - [website](https://pragdave.me/) 51 | - Andy Hunt | XP 52 | - [videos](https://www.youtube.com/results?search_query=andy+hunt) 53 | - [about](https://en.wikipedia.org/wiki/Andy_Hunt_(author)) 54 | - [website](https://toolshed.com/) 55 | - James Grenning | XP | TDD 56 | - [videos](https://www.youtube.com/results?search_query=James+Grenning) 57 | - [website](http://blog.wingman-sw.com/) 58 | - Lisa Crispin | Testing 59 | - [videos](https://www.youtube.com/results?search_query=lisa+crispin) 60 | - [about](http://lisacrispin.com/about) 61 | - [website](http://lisacrispin.com/) 62 | - Mike Beedle | Busniness Agility 63 | - [videos](https://www.youtube.com/results?search_query=mike+beedle) 64 | - [website](https://medium.com/@mikebeedle) 65 | - Jim Highsmith | Leadership 66 | - [videos](https://www.youtube.com/results?search_query=jim+highsmith) 67 | - [about](https://en.wikipedia.org/wiki/Jim_Highsmith) 68 | - [website](http://jimhighsmith.com/) 69 | - Ken Schwaber | Scrum 70 | - [videos](https://www.youtube.com/results?search_query=Ken+Schwaber) 71 | - [about](https://en.wikipedia.org/wiki/Ken_Schwaber) 72 | - [website](https://kenschwaber.wordpress.com/) 73 | - Jeff Sutherland | Scrum 74 | - [videos](https://www.youtube.com/results?search_query=Jeff+Sutherland) 75 | - [about](https://en.wikipedia.org/wiki/Jeff_Sutherland) 76 | - [website](http://scrum.jeffsutherland.com/) 77 | - Esther Derby | Coaching 78 | - [videos](https://www.youtube.com/results?search_query=esther+derby) 79 | - [website](http://www.estherderby.com/about-esther) 80 | - [about](http://www.estherderby.com/) 81 | - Diana Larsen | Coaching 82 | - [videos](https://www.youtube.com/results?search_query=diana+larsen) 83 | - [about](https://www.amazon.com/Diana-Larsen/e/B002BM7U7Q) 84 | - Lyssa Adkin | Coaching 85 | - [videos](https://www.youtube.com/results?search_query=Lyssa+Adkin) 86 | - [about](http://www.coachingagileteams.com/about/) 87 | - [website](http://www.coachingagileteams.com/about/) 88 | - Dave Snowden | Lean 89 | - [videos](https://www.youtube.com/results?search_query=Dave+Snowden) 90 | - [about](https://en.wikipedia.org/wiki/Dave_Snowden) 91 | - Chris Matts | Lean 92 | - [videos](https://www.youtube.com/results?search_query=Chris+Matts+lean) 93 | - [website](https://theitriskmanager.wordpress.com/) 94 | - Woody Zuil | XP | Mob Programming 95 | - [videos](https://www.youtube.com/results?search_query=Woody+Zuil) 96 | - [about](https://www.industriallogic.com/people/woody) 97 | - Bob Hartman | Coach | Scrum 98 | - [videos](https://www.youtube.com/results?search_query=Bob+Hartman+agile) 99 | - [about](https://www.scrumalliance.org/community/profile/rhartman) 100 | 101 | 102 | # Background 103 | 104 | - [Peter Drucker] 105 | - [Deming] 106 | - [Maslow] 107 | 108 | 109 | # Kanban 110 | 111 | - [Intro](http://agileupgrade.com/why-90-percent-gets-kanban-wrong-and-getting-it-right/) 112 | - values 113 | - transparency 114 | - agreement 115 | - respect 116 | - balance 117 | - understanding 118 | - colleboration 119 | - leadership 120 | - customer focus 121 | - flow 122 | - principles 123 | - start with what you do now 124 | - agree to pursue evolutionary change 125 | - respect current processes, roles, responsibilities and titles 126 | - encourage acts of leadership at all levels 127 | - practices 128 | - visualize, signal 129 | - limit work-in-progress 130 | - manage flow 131 | - make policies explicit 132 | - implement feedback loops 133 | - improve collaboratively, evolve experimentally 134 | - scientific method 135 | - ceremonies 136 | - replenishment meeting (strategy review) 137 | - kanban/daily meeting (operations review, service delivery review) 138 | - delivery planning meeting (risk review) 139 | - pull vs push 140 | - https://www.infoq.com/fr/presentations/ways-to-kickstart-agile-kanban-way 141 | 142 | 143 | # Scrum 144 | 145 | - [ORG](http://scrum.org/) 146 | - [Scrum guide](https://www.scrum.org/resources/scrum-guide) 147 | - [guides](https://www.scrumguides.org/) 148 | - values 149 | - [POST](https://guntherverheyen.com/2013/05/03/theres-value-in-the-scrum-values/) 150 | - commitment 151 | - focus 152 | - courage 153 | - openness 154 | - respect 155 | - roles 156 | - [Product Owner](http://agiletrail.com/2011/11/29/37-tasks-for-a-product-owner%E2%80%99s-job/) 157 | - [Scrum Master](http://agiletrail.com/2011/11/14/42-tasks-for-a-scrum-masters-job/) 158 | - [Scrum Team](https://www.scrum-institute.org/Scrum_Roles_The_Scrum_Team.php) 159 | - ceremonies 160 | - refinement (grooming) 161 | - planning 162 | - estimation 163 | - stand-up 164 | - sprint review 165 | - retrospective 166 | - tools 167 | - [user stories](https://www.thoughtworks.com/es/insights/blog/story-mapping-visual-way-building-product-backlog) 168 | - product backlog 169 | - sprint backlog 170 | - velocity 171 | - impediment boards 172 | 173 | 174 | # XP 175 | 176 | - [ORG](http://www.extremeprogramming.org/) 177 | - values 178 | - simplicity 179 | - communication 180 | - feedback 181 | - respect 182 | - courage 183 | - principles 184 | - all code tested 185 | - all code pair programmed 186 | - customer always available 187 | - integrate often 188 | - release often 189 | - refactor always 190 | - flow (plan, test, code, integrate, release) 191 | - practices 192 | - release planning 193 | - iteration planning 194 | - spike solutions 195 | - pair programming 196 | - tools 197 | - user stories 198 | - velocity 199 | - unit tests 200 | - test driven 201 | - pair programming 202 | - more 203 | - [Unit Tests](https://medium.com/javascript-scene/what-every-unit-test-needs-f6cd34d9836d) 204 | - [TDD](https://www.thoughtworks.com/insights/blog/effective-navigation-in-pair-programming) 205 | - [BDD](https://www.slideshare.net/thomaslundstrom/bdd-approaches-for-web-development-at-agile-testing-days-2009) 206 | - [Pair Programmning](https://medium.com/@jdxcode/how-to-pair-program-d6741077e513) 207 | 208 | 209 | # Retrospectives 210 | 211 | - [TOOL](https://plans-for-retrospectives.com/) 212 | - [TALK](https://www.youtube.com/watch?v=w8w-dFrmovQ) 213 | - 5 steps: 214 | - set the stage 215 | - gather data 216 | - generate insights 217 | - decide actions 218 | - close 219 | 220 | 221 | # More 222 | 223 | - [No Estimates](https://ronjeffries.com/xprog/articles/the-noestimates-movement/) 224 | - [Mob Programmning](https://www.agilealliance.org/resources/sessions/mob-programming-a-whole-team-approach-aatc2017/) 225 | - [Profound knowledge](https://www.youtube.com/watch?v=6nZYeZWBcbo) 226 | - [Theory of Constraints](https://www.youtube.com/watch?v=wTZcDXlAB2U) 227 | - [Kaizen](https://www.slideshare.net/proyectalis/agile-kaizen-continuous-improvement-far-beyond-retrospectives/) 228 | -------------------------------------------------------------------------------- /m1/resources.md: -------------------------------------------------------------------------------- 1 | # Resources 2 | 3 | 4 | ## Tools 5 | 6 | - [VSCode](https://code.visualstudio.com/docs) 7 | - [Chrome Dev Tools](https://developers.google.com/web/tools/chrome-devtools/) 8 | 9 | ### Terminal 10 | 11 | - [iTerm](https://www.iterm2.com/) and [Terminator](https://gnometerminator.blogspot.com.es/p/introduction.html) 12 | - [Bash](https://www.gnu.org/software/bash/manual/html_node/index.html) 13 | 14 | ### Git 15 | 16 | - [Git Reference](https://git-scm.com/doc) 17 | - [Git Cheatsheet](https://services.github.com/on-demand/downloads/github-git-cheat-sheet.pdf) 18 | - [GitHub](https://guides.github.com/) 19 | 20 | ### Accessibility 21 | 22 | - [Acessibility Checklist][https://a11yproject.com/checklist] 23 | - [Screen Reader](https://chrome.google.com/webstore/detail/chromevox/kgejglhpjiefppelpmljglcjbhoiplfn) 24 | - [Tota11y](http://khan.github.io/tota11y) 25 | - [No Coffee](https://chrome.google.com/webstore/detail/nocoffee/jjeeggmbnhckmgdhmgdckeigabjfbddl?hl=en-GB) Vision filter 26 | 27 | 28 | ## Documentation 29 | 30 | ### HTML 31 | 32 | - [MDN HTML guide](https://developer.mozilla.org/en-US/docs/Learn) 33 | - [MDN HTML reference](https://developer.mozilla.org/kab/docs/Web/HTML) 34 | - [W3C HTML Validator](https://validator.w3.org/#validate_by_input) 35 | 36 | ### CSS 37 | 38 | - [MDN CSS guide](https://developer.mozilla.org/en-US/docs/Learn/CSS/Introduction_to_CSS) 39 | - [MDN CSS reference](https://developer.mozilla.org/en-US/docs/Web/CSS) 40 | - [W3C CSS Validator](https://jigsaw.w3.org/css-validator/#validate_by_input) 41 | 42 | ### SASS 43 | 44 | - [SASS](https://sass-lang.com/guide) 45 | 46 | ### Javascript 47 | 48 | - [MDN Javascript guide](https://developer.mozilla.org/bm/docs/Web/JavaScript) 49 | - [MDN Javascript reference](https://developer.mozilla.org/bm/docs/Web/JavaScript) 50 | 51 | ### Accessibility 52 | 53 | - [The a11y project][https://a11yproject.com/] 54 | - [WRC ARIA LAndmarks][https://www.w3.org/TR/wai-aria-practices-1.1/examples/landmarks/index.html] 55 | - [MDN WAI-ARIA Basics][https://developer.mozilla.org/en-US/docs/Learn/Accessibility/WAI-ARIA_basics] 56 | - [The W3C WAI Tutorials][https://www.w3.org/WAI/tutorials/] 57 | 58 | ### Dom 59 | 60 | - [MDN DOM guide](https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model) 61 | - [MDN DOM reference](https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model) 62 | 63 | ### Canvas 64 | 65 | - [MDN Canvas guide](https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model) 66 | - [MDN Canvas reference](https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model) 67 | 68 | - [Can I Use](https://caniuse.com/) 69 | 70 | ### Testing 71 | 72 | - [Frontend Checklist](https://frontendchecklist.io/) 73 | 74 | ### Building 75 | 76 | - [Intro to webpack](https://medium.com/@kimberleycook/intro-to-webpack-1d035a47028d) 77 | 78 | ### Deploying 79 | 80 | - [Github Pages](https://pages.github.com/) 81 | 82 | ### And many more docs... 83 | 84 | - [DEV DOCS](http://devdocs.io/) 85 | 86 | ## Libraries 87 | 88 | - [Bootstrap](https://getbootstrap.com/docs/4.1/getting-started/introduction/) - toolkit for developing with HTML, CSS, and JS to quickly prototype your ideas or build your entire app 89 | - [jQuery](https://api.jquery.com/) - fast, small, and feature-rich JavaScript library with manipulation, event handling, and animation features 90 | - [MomentJS](https://momentjs.com/) - library to parse, validate, manipulate, and display dates and times in JavaScript 91 | - [ScrollMagic](http://scrollmagic.io/) - library that tracks user's current scroll position 92 | - [GSAP](https://greensock.com/gsap) - the GreenSock Animation Platform animates anything JavaScript can touch 93 | 94 | 95 | ## Online tools 96 | 97 | ### JS Tools 98 | 99 | - [Plunkr](https://plnkr.co/) 100 | - [JSBin](https://jsbin.com/?html,output) 101 | - [Repl.it](https://codepen.io/) 102 | 103 | ### Design 104 | 105 | - [Google Fonts](https://fonts.google.com/) 106 | - [Colorzilla](http://www.colorzilla.com/chrome/) 107 | - [Colors](https://coolors.co/) 108 | - [Colors](http://paletton.com/) 109 | - [SVG Icons](https://www.flaticon.com/) 110 | - [Icons](https://icomoon.io/) 111 | - [Font awesome](https://fontawesome.com/) - font icons 112 | - [Thenounproject](https://thenounproject.com/) - comunity with Catalogs of Symbols. 113 | - [Photos](https://unsplash.com/) 114 | - [Photos](https://www.pexels.com/) 115 | - [Photos](https://pixabay.com/) 116 | - [Photos](https://www.freeimages.com/) 117 | 118 | ### Prototyping 119 | 120 | - [Origami](https://origami.design/) 121 | - [Balsamiq](https://balsamiq.com/) 122 | - [Invision](https://www.invisionapp.com/) 123 | - [Pop](https://marvelapp.com/pop/) 124 | - [UXPin](https://www.uxpin.com/) 125 | - [MockPlus](https://www.mockplus.com/) 126 | 127 | ### Lorem Ipsum 128 | 129 | - [Lorem Ipsum](https://www.lipsum.com/) 130 | - [Bacon Ipsum](https://baconipsum.com/) 131 | - [Cat Ipsum](http://www.catipsum.com/) 132 | - [Zombie Ipsum](http://www.zombieipsum.com/) 133 | 134 | ### Lorem Images 135 | 136 | - [Lorem Pixel](https://lorempixel.com/) 137 | - [Lorem Flikr](https://loremflickr.com/) 138 | - [Placeholder](https://placeholder.com/) 139 | - [PlaceImg](https://placeimg.com/) 140 | - [...and more](https://www.crazyegg.com/blog/image-text-placeholders-web-design/) 141 | 142 | ### CSS tools 143 | 144 | - [UIgradients](https://uigradients.com/) - background Linear Gradient Generator. You can generate the css for gradient with a usefull preview 145 | - [Colorzilla Gradient Generator](http://www.colorzilla.com/gradient-editor/) - background Linear Gradient Generator. You can generate the css for gradient with a usefull preview 146 | - [Clippy](https://bennettfeely.com/clippy/) - clip-path generator - you can generate the css for clip-path polygon with a usefull preview 147 | - [The Ultimate CSS Generator](https://webcode.tools/css-generator) - a very complete CSS generator when you can generate code for animations, box-shadows, filters, etc. 148 | 149 | ## Tutorials 150 | 151 | - [Web Design](https://webdesign.tutsplus.com/tutorials/) 152 | - [Modern Javascript Tutorial](https://javascript.info/) 153 | - [CSS Tricks](https://css-tricks.com/) 154 | - [Github HelloWorld](https://guides.github.com/activities/hello-world/) 155 | 156 | ## Libraries 157 | 158 | - [Bootstrap](https://getbootstrap.com/) 159 | - [jQuery](https://jquery.com/) 160 | - [MomentJS](https://momentjs.com/) 161 | - [ToneJS](https://tonejs.github.io/) 162 | - [Miligram](https://milligram.io/) 163 | 164 | ## People 165 | 166 | - [Brendan Eich](https://brendaneich.com/) 167 | - [Douglas Crockford](http://www.crockford.com/) 168 | - [John Resig](http://ejohn.org/) 169 | - [Jeffrey Zeldman](http://www.zeldman.com/) 170 | - [Martin Fowler](https://martinfowler.com/) 171 | - [Jason Santa Maria](http://jasonsantamaria.com/) 172 | - [Eric Meyer](http://meyerweb.com/) 173 | - [Remy Sharp](https://remysharp.com/) 174 | - [Andy Clarke](http://www.stuffandnonsense.co.uk](http://www.forabeautifulweb.com) 175 | - [Jeremy Keith](https://adactio.com/) 176 | - [Christian Heilmann](https://www.christianheilmann.com/) 177 | - [Mike Monteiro](http://muledesign.com/) 178 | - [Jason Santa Maria](http://jasonsantamaria.com) 179 | - [Nicole Sullivan](http://www.stubbornella.org/) 180 | - [Robert C. Martin](https://cleancoders.com/developers) 181 | - [Tim Pope](http://tbaggery.com/) 182 | - [Peter Paul Koch](http://quirksmode.org/) 183 | - [David Shea](http://www.csszengarden.com](http://mezzoblue.com) 184 | - [Rebecca Murphey](http://rmurphey.com/ ) 185 | - [Jason Kotke](http://kottke.org/) 186 | - [Lea Verou](http://lea.verou.me/) 187 | - [Susan Robertson](http://alistapart.com/author/susanrobertson) 188 | - [Tom Preston Werner](http://tom.preston-werner.com/) 189 | - [Laura Kalbag](https://laurakalbag.com/) 190 | - [Rachel Andrew](https://rachelandrew.co.uk/) 191 | - [Addy Osmani](https://www.addyosmani.com) 192 | - [Sarah Dresner](http://sarahdrasnerdesign.com/) 193 | - [Jakob Nielsen](http://www.useit.com) 194 | - [Sarah Parmenter](http://www.sazzy.co.uk/) 195 | - [Scott Hanselman](http://www.hanselman.com/) 196 | - [Sara Soueidan](https://sarasoueidan.com/) 197 | - [Chris Lea](https://chrislea.com/about/) 198 | - [Lara Hogan](http://larahogan.me/) 199 | - [Mike Bostock](http://bost.ocks.org) 200 | - [Tim Bray](https://www.tbray.org/) 201 | - [Luke Wroblewski](http://www.lukew.com/) 202 | - [Mark Otto](http://mdo.fm/) 203 | - [Chris Wanstrath](http://chriswanstrath.com/) 204 | - [Shane Hudson](https://shanehudson.net/) 205 | - [Sindre Sothus](https://twitter.com/sindresorhus) 206 | - [Briant Ford](http://briantford.com/) 207 | - [Jessica Lord](http://jlord.us/) 208 | - [James Halliday](http://substack.net/) 209 | - [Eric Elliot](https://medium.com/@_ericelliott) 210 | - [Andrea Giammarchi](https://medium.com/@WebReflection) 211 | 212 | 213 | ## Websites 214 | 215 | - [Smashing Magazine](https://www.smashingmagazine.com/) 216 | - [A List Apart](http://alistapart.com/) 217 | - [Age Of Product](https://age-of-product.com/) 218 | - [Mountain Goat](https://www.mountaingoatsoftware.com/blog) 219 | - [Apiumhub](https://apiumhub.com/tech-blog-barcelona/) 220 | 221 | 222 | ## Podcasts 223 | 224 | - [Agile for Humans](https://ryanripley.com/agile-for-humans/) 225 | - [Scrum Master Toobox](http://scrum-master-toolbox.org/) 226 | 227 | 228 | ## Specifications 229 | 230 | - [Javascript](http://www.ecma-international.org/ecma-262/6.0/) 231 | - [HTML5](https://www.w3.org/TR/2010/WD-html5-20100624/) 232 | - [CSS](https://www.w3.org/Style/CSS/specs.en.html) 233 | -------------------------------------------------------------------------------- /m2/README.md: -------------------------------------------------------------------------------- 1 | 2 | # concepts 3 | 4 | - HTTP request/response cycle 5 | - Backend rendering 6 | - Templates + Layouts + Partials 7 | - Cookies + Session + Auth 8 | - CommonJS Modules 9 | - NPM Packages 10 | - MVC Pattern 11 | - CRUD 12 | - Document DBs + Data modelling 13 | 14 | # es6 15 | 16 | - [LU - ES6 | Basics](http://learn.ironhack.com/#/learning_unit/3976) 17 | - [LU - ES6 | Advanced](http://learn.ironhack.com/#/learning_unit/3977) 18 | 19 | - let and const 20 | - [MDN let](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let) 21 | - [MDN const](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const) 22 | - [MDN temporal dead zone](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let#Temporal_Dead_Zone) 23 | - block scoped 24 | - no leaking vars from for loops, including the the iterator var(s) 25 | - shadowing now also happens with blocks 26 | - const 27 | - value can't change 28 | - `const num = 42; num++ // ERROR` 29 | - if object can be mofiied (just no reassigned) 30 | - `const person = {name: 'Joe'}; person.name = 'Joan'; // OK` 31 | - `const person = {name: 'Joe'}; person = {name: 'Joan'}; // ERROR` 32 | - same for arrays (remeber: arrays are objects) or any other object 33 | - `const names = ['Joe']; names.push('Joan') // OK` 34 | - `const names = ['Joe']; names = []; // ERROR` 35 | 36 | 37 | - arrow functions 38 | - [MDN Arrow Functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions) 39 | - have no context 40 | - no more self = this; 41 | - arrow functions everywhere, especially as callbacks 42 | - single line arrow functions (no brackets, implicit return) 43 | - `const addNumbers = (n1, n2) => n1 + n2;` 44 | - multi line, require return statement 45 | ``` 46 | const addRandom = (num) => { 47 | const random = Math.random(); 48 | return num + random; 49 | } 50 | ``` 51 | - returning an object from single line arrow function: use () 52 | - `const makePerson = (name, age) => ({name: name, age: age});` 53 | 54 | - classes 55 | - [MDN Classes](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes) 56 | - `class` and `constructor()` 57 | - methods 58 | - inheritance with `class Foo extends Bar` and `super()` 59 | 60 | - spread syntax 61 | - [MDN Spread Syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax) 62 | - spread operator ...arr 63 | - inserting elements into an array 64 | - `var parts = ['shoulders', 'knees'];` 65 | - `var lyrics = ['head', ...parts, 'and', 'toes'];` 66 | - concatenating 67 | - `arr1 = [...arr1, ...arr2];` 68 | - copy an array 69 | - `arr1 = [...arr2];` 70 | 71 | - others 72 | - object shortcuts (implicit value) 73 | - template (and multiline) strings 74 | - default values for function parameters 75 | - array method examples `arr.findIndex()`, `arr.fill()`, `Array.from()` 76 | - string method examples `str.includes()`, `str.startsWidth()`, `str.repeat()` 77 | 78 | ## promises 79 | 80 | - [LU](http://learn.ironhack.com/#/learning_unit/3979) 81 | - [MDN Promises guide](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises) 82 | - [MDN Promises reference](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) 83 | 84 | - syntax 85 | - instead of `do((err, result) => {});` 86 | - `do().then(result => { ... handle result ... }).catch(err => { ... handle error ... })` 87 | 88 | - promise as a variable 89 | - `const promiseToDoSomething = doSomething()` 90 | - can be passed around 91 | - can be stored, useful for accessing unresolved/cached results with only one (async) syntax 92 | 93 | - late binding 94 | - binding after the promise has been resolved/rejected still possible 95 | - then/catch will still be invoked 96 | 97 | - multiple binding 98 | - `promiseToDoSomething.then(result => { ...do things... })` 99 | - `promiseToDoSomething.then(result => { ...do more things... })` 100 | 101 | - chaining results 102 | - return value of `.then()` callback is given as argument to the chained `.then()` callback 103 | - `do1().then(resultOfDo1 => do2(resultOfDo1)).then(resultOfDo2 => { ... })` 104 | 105 | - synchronizing parallel work 106 | - given array of promises 107 | - wait for all to resolve `Promise.all(promises).then(results => { /* array with resolve values of all promises, in same order */ })` 108 | - wait for the first to resolve `Promise.race(promises).then(result => { /* result is the resolve value of the first promise to resolve */ })` 109 | 110 | - DRY error handling 111 | - `do1().then(result1 => do2()).then(result2 => do3()).catch(err => /* { err is from do1(), do2() OR do3() */ });` 112 | 113 | - creating a function that returns a promise 114 | ```javascript 115 | const doSomething = function () { 116 | return new Promise((resolve, reject) => { 117 | // call resolve(value) when you have the result 118 | // call reject(error) or throw new Error('error') 119 | }); 120 | }; 121 | ``` 122 | 123 | - creating pre-resolved/pre-rejected promises 124 | - `const resolved = Promise.resolve(value);` 125 | - `const rejected = Promise.reject(error);` 126 | 127 | 128 | 129 | ## es6 best practices 130 | 131 | - [LU](http://learn.ironhack.com/#/learning_unit/3979) 132 | - [refactoring](https://refactoring.guru/) 133 | - short lines 134 | - small functions 135 | - use arrow functions 136 | - variables and functions 137 | - use const always 138 | - use let when const not possible 139 | - don't use var anymore 140 | - OO 141 | - small classes 142 | - small methods 143 | _ this._privateData 144 | - _doPricateThing() 145 | - Promises 146 | - always use when available 147 | - always catch 148 | 149 | # nodejs 150 | 151 | - [LU](http://learn.ironhack.com/#/learning_unit/3985) 152 | - [Node.js docs](https://nodejs.org/dist/latest-v10.x/docs/api/) 153 | 154 | - **IT'S NOT A FRAMEWORK!** 155 | - runtime environment for running javascript in the backend (v8 engine) 156 | - app can be an http server (runs "forever") 157 | - runs javascript, same as browser (but no window, no DOM) 158 | - start apps with "node app.js" 159 | - node callbacks convection (err, result) => { ... } 160 | - has some built-in modules like `fs`, `process`, `path` and `http` 161 | 162 | ## node modules 163 | - every js file is a module 164 | - every file has it's own scope (no global scope) 165 | - npm packages are also modules 166 | - for our files: 167 | - in `folder/mymodule.js`, to define what it exports 168 | - `module.exports = ...` 169 | - in another file use relative path to require it 170 | - `const mymodule = require('./folder/mymodule')` 171 | - for npm packages: 172 | - const express = require('express') 173 | 174 | ## npm 175 | - http://npmjs.org 176 | - npm init (new projects only) 177 | - npm install (after cloning existing project) 178 | - npm install --save package-name 179 | - npm install --save-dev package-name 180 | - npm install -g package-name (may require sudo) 181 | - package.json (every node project needs one) 182 | - always add "node_modules" to .gitignore 183 | 184 | ## package.json 185 | - "scripts" are shortcuts 186 | - "dependencies" are the packages the project needs to be executed 187 | - "devDependencies" are the packages the developers need to work on the project 188 | 189 | ```json 190 | "scripts": { 191 | "start": "node app.js", 192 | "start-dev": "nodemon --inspect app.js" 193 | } 194 | ``` 195 | 196 | ## nodemon 197 | - npm install -g nodemon 198 | - nodemon --inspect app.js 199 | - in package.json scripts 200 | - "start": "nodemon app.js" 201 | - "start-dev": "nodemon --inspect app.js" 202 | 203 | 204 | # http 205 | 206 | - [LU](http://learn.ironhack.com/#/learning_unit/3986) 207 | - request + response = request/response cycle 208 | - request = headers + body (optional) 209 | - response = status + headers + body (optional) 210 | - cookies 211 | - httponly 212 | - secure 213 | - url 214 | - `https://localhost:3000/homepage?foo=bar&baz=123#fragment` 215 | - `scheme://hostname:port/path?querystring` 216 | - fragment is never sent to the server 217 | - method: GET, POST, PUT, DELETE [and others](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods) 218 | - [status codes](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status): 219 | - 2xx - success (e.g. 200 OK, 204 No Content) 220 | - 3xx - redirection (e.g. 301 moved permanently) 221 | - used with response header `Location: http://....` indicating where it moved too 222 | - 4xx - user error (e.g.: 404 not found, 401 not authorized) 223 | - 5xx - server error (e.g.: 500 internal error, 504 timeout) 224 | 225 | 226 | # express 227 | - http server framework 228 | - pipeline of middlewares, followed by routes 229 | 230 | ## express generator 231 | - [docs](https://expressjs.com/en/starter/generator.html) 232 | - npm install -g express-generator 233 | - express my-project --view=hbs --git 234 | - add start-dev to package.json scripts 235 | - add launcher.json 236 | - add .eslintrc.json (eslint --init) 237 | - git init 238 | - add .gitignore with node_modules 239 | - add our [error handling snippets](./express-apps/app.js) to app.js 240 | 241 | ## express route 242 | 243 | - `router.get('/foo/bar/baz', (req, res, next) => { .... });` 244 | - authorize, validate, perform actions, render/redirect 245 | - GET routes: render or redirect 246 | - POST routes: always redirect 247 | - req 248 | - `req.method` - GET/POST 249 | - `req.path` - `/foo/bar/baz` 250 | - `req.headers` - key/values of all headers sent from browser 251 | - `req.body` key/values of all data from POST body 252 | - `req.params` key/values of path placeholders (`/product/:productId/reviews/:reviewId`) 253 | - `req.query` key/values of query string (`/products/search?page=2&sort=price`) 254 | - res 255 | - `res.status(404)` - set the status ccode of the response 256 | - `res.send('

some text

')` - just responde with a string 257 | - `res.redirect('/some/path')` - send a 302 response with a location (start with `/` to make it an absolute path) 258 | - `res.render('template-name', data)` - if data contains `.events`, you can use `{{#each events}}` in the template 259 | - `res.json(data)` - send JSON data, will also set the header `Content-type: application/json` 260 | - `res.set('Content-Type', 'text/plain')` - set custom headers 261 | - next 262 | - call `next()` to serve a 404 263 | - call `next(err)` to serve a 500 and log the error 264 | 265 | 266 | ## session & auth 267 | - use expression session (see snippet) 268 | - 2x routes for login (get & post) 269 | - 2x routes for signup (get & post) 270 | - use post for logout 271 | - signup: `req.session.currentUser = newUser` 272 | - login: `req.session.currentUser = user` 273 | - logout: `delete req.session.currentUser` 274 | - user in views: `req.locals.user = req.session.currentUser` 275 | 276 | ## passport 277 | - config (see snippet) 278 | - serialize 279 | - deserialize 280 | - use(new Strategy) 281 | - app.use(...); 282 | - app.use(...); 283 | - req.login(newUser) 284 | - req.logout() 285 | - if (!req.user) { ... } 286 | - if (!req.isAuthenticated()) { ... } 287 | 288 | ## best practices 289 | 290 | - order matters, middlewares before routes, 404 at the end 291 | - separate your routes by prefix (e.g. '/auth', '/beers', ...) 292 | - POST routes 293 | - check for authorization (e.g. `if (req.session.currentUser) ... ` 294 | - always validate the POST body (e.g. `if (!req.body.username) ....` 295 | - always `res.redirect()` never `res.render()` 296 | - GET routes 297 | - check for authorization (e.g. `if (req.session.currentUser) ... ` 298 | - when loading items by id, check if DB returns a doc, and if it doesn't `return next()` to send to 404 middleware 299 | - use a `const data` object to send to `res.render('template', data)` 300 | - always `.catch(next)` 301 | 302 | # mongodb 303 | 304 | - document database (as opposedd to relational database) 305 | - stores data as documents, schema free, but relationships still exist 306 | - data modelling 307 | - [query operators](https://docs.mongodb.com/manual/reference/operator/query/) 308 | - [update operators](https://docs.mongodb.com/manual/reference/operator/update/) 309 | 310 | ## mongo shell 311 | - $ mongo 312 | - show dbs 313 | - use database-name 314 | - db.help() 315 | - db.createCollection("animals") 316 | - show collections 317 | - db.animals.help() 318 | - db.animals.find().pretty() 319 | - db.animals.insert({}) 320 | - [read operations](https://docs.mongodb.com/manual/crud/#read-operations) 321 | 322 | ## mongo import 323 | - mongoimport --db database-name --collection collection-name --file fileName 324 | 325 | ## mongoose 326 | - npm install --save mongoose 327 | - object document mapper 328 | - bring schemas into our use of mongodb 329 | - see example schemas in `./snippets` 330 | - types: String, Number, Date, Boolean, Array, Mixed, Objectid 331 | -------------------------------------------------------------------------------- /m3/README.md: -------------------------------------------------------------------------------- 1 | # concepts 2 | 3 | - SPA 4 | - Build 5 | - Components 6 | - Injection + Services + Singleton 7 | - REST API 8 | 9 | # typescript 10 | 11 | - [DOCS](https://www.typescriptlang.org/) 12 | - [LU](http://learn.ironhack.com/#/learning_unit/2960) 13 | - made by microsoft 14 | - superset of javascript 15 | - all ES5 and ES6 code is valid in typescript 16 | - browser can NOT understand typescript 17 | - transpiled down to es6 or es5 by tools 18 | - types 19 | - [DOCS](https://www.typescriptlang.org/docs/handbook/basic-types.html) 20 | - type safety vs javascript dynamic types 21 | - can (should) be applied to: 22 | - constants and variables 23 | - function parameters 24 | - function return values 25 | - class properties 26 | - interfaces 27 | - [DOCS](https://www.typescriptlang.org/docs/handbook/interfaces.html) 28 | - small reusables "contracts" 29 | - define what will be "public" 30 | - interfaces are also types (advanced) 31 | - classes 32 | - [DOCS](https://www.typescriptlang.org/docs/handbook/classes.html) 33 | - concept of public vs private 34 | - properties documented before the constructor 35 | - class properties have types 36 | - class method arguments and return values have types 37 | - can implement more than one interface 38 | - all methods and fields are public by default 39 | - methods and fields can be declared as private 40 | - private, public shortcut on constructors 41 | - decorators 42 | - [DOCS](https://www.typescriptlang.org/docs/handbook/decorators.html) 43 | - can be applied to class, class property, class method, function param, getters/setters 44 | - DO: 45 | - add types everywhere 46 | - function parameters 47 | - function return values 48 | - class properties 49 | - use lower case for primitives 50 | - string 51 | - boolean 52 | - number 53 | - upper case for objects 54 | - Object 55 | - Array 56 | - Date 57 | - K.I.S.S. objects and arrays (prevents errors like `username is not a known property of newUser`) 58 | - `newEvent: any` 59 | - `events: Array` 60 | - DON'T 61 | - add `:void` to functions that return undefined 62 | - forget to initialize arrays `events: Array = []` 63 | - prevents error when later doing `this.events.push(...)` 64 | - add the type declaration to primitives that are immediately initialized 65 | - e.g.: `category: string = 'default'` 66 | - prevents tslint complaining `Type string trivially inferred from a string literal, remove type annotation (no-inferrable-types)` 67 | 68 | 69 | # angular 70 | 71 | - [DOCS](https://angular.io/) 72 | - made by google 73 | - written in typescript 74 | - single page application framework, including: 75 | - views 76 | - components 77 | - form management 78 | - routing 79 | - dependency injection 80 | 81 | 82 | ## angular CLI 83 | 84 | - [DOCS](https://github.com/angular/angular-cli/wiki) 85 | - `$ ng new name-of-app` 86 | - `$ ng serve` 87 | - `$ ng serve --aot` 88 | - `$ ng g c components/name-of-component` 89 | - `$ ng g c pages/name-of-page` 90 | - `$ ng g s services/name-of-service` 91 | - `$ ng g g guards/name-of-guard` 92 | - `$ ng g p pipes/name-of-pipe` 93 | - `$ ng g class models/name-of-model` 94 | - `$ ng build` 95 | 96 | 97 | ## app structure 98 | 99 | - [DOCS](https://angular.io/guide/setup-systemjs-anatomy) 100 | - `index.html` 101 | - is static 102 | - contains `` 103 | - can contain extra script and style tags 104 | - app/app.module.ts (a.k.a. THE app) 105 | - [DOCS](https://angular.io/guide/bootstrapping) 106 | - declares all the angular modules used in the app 107 | - declares the routing 108 | - declares all the components created by us 109 | - declares all the services, pipes, etc... create by us 110 | - app/app.component.* (a.k.a. main component or layout component) 111 | - layout of the app (header, footer) 112 | - where the ``goes 113 | - app/pages 114 | - where we should store our page components 115 | - `ng g c pages/login-page` 116 | - app/components 117 | - where we should store our smaller components 118 | - `ng g c components/auth-login-form` 119 | 120 | ## templates & binding 121 | 122 | - [DOCS](https://angular.io/guide/template-syntax) 123 | - interpolation `{{ expression }}` 124 | - property binding `