├── .gitignore ├── 02-hello-vue ├── app.js └── index.html ├── 03-v-for ├── app.css ├── app.js ├── data.json └── index.html ├── 04-computed-properties ├── app.css ├── app.js ├── data.json └── index.html ├── 05-components-refactor ├── app.css ├── app.js ├── data.json └── index.html ├── 05-components-simple ├── app.js └── index.html ├── 07-giphyapi-app ├── .babelrc ├── .gitignore ├── README.md ├── index.html ├── package.json ├── src │ ├── App.vue │ ├── components │ │ ├── Preview.vue │ │ └── Search.vue │ └── main.js └── webpack.config.js ├── 08-router-simple ├── .babelrc ├── .gitignore ├── README.md ├── index.html ├── package.json ├── src │ ├── App.vue │ ├── components │ │ ├── Bar.vue │ │ ├── Foo.vue │ │ └── Home.vue │ └── main.js └── webpack.config.js ├── 08-router ├── .babelrc ├── .gitignore ├── README.md ├── index.html ├── package.json ├── src │ ├── App.vue │ ├── components │ │ ├── Home.vue │ │ ├── UserItem.vue │ │ ├── UserPosts.vue │ │ └── UserProfile.vue │ └── main.js └── webpack.config.js ├── 09-vue-goodies ├── app.js └── index.html ├── 10-vue-testing ├── .babelrc ├── .editorconfig ├── .gitignore ├── README.md ├── build │ ├── build.js │ ├── check-versions.js │ ├── dev-client.js │ ├── dev-server.js │ ├── utils.js │ ├── webpack.base.conf.js │ ├── webpack.dev.conf.js │ └── webpack.prod.conf.js ├── config │ ├── dev.env.js │ ├── index.js │ ├── prod.env.js │ └── test.env.js ├── index.html ├── package.json ├── src │ ├── App.vue │ ├── components │ │ ├── Preview.vue │ │ └── Search.vue │ └── main.js ├── static │ └── .gitkeep └── test │ ├── e2e │ ├── custom-assertions │ │ └── elementCount.js │ ├── nightwatch.conf.js │ ├── runner.js │ └── specs │ │ └── test.js │ └── unit │ ├── .eslintrc │ ├── index.js │ ├── karma.conf.js │ └── specs │ ├── Preview.spec.js │ └── Search.spec.js ├── 11-vue-form └── server │ ├── README.md │ ├── api │ └── swagger.yaml │ ├── controllers │ ├── Default.js │ └── DefaultService.js │ ├── index.js │ └── package.json ├── 12-vue-spa ├── .babelrc ├── .gitlab-ci.yml ├── 200.html ├── CNAME ├── README.md ├── index.html ├── package-lock.json ├── package.json ├── src │ ├── App.vue │ ├── assets │ │ ├── halls.json │ │ ├── movieDetails.json │ │ ├── movieTimes.json │ │ ├── movies.json │ │ ├── soldTickets.json │ │ └── ticketPrices.json │ ├── components │ │ ├── AppHeader.vue │ │ ├── Confirmation.vue │ │ ├── Home.vue │ │ ├── Loader.vue │ │ ├── Movie.vue │ │ ├── MovieDetails.vue │ │ ├── SeatSelection.vue │ │ └── TicketSelection.vue │ ├── main.js │ ├── router │ │ └── routerOptions.js │ ├── services │ │ └── service.js │ └── stores │ │ └── store.js ├── webpack.config.js └── yarn.lock └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | -------------------------------------------------------------------------------- /02-hello-vue/app.js: -------------------------------------------------------------------------------- 1 | window.addEventListener('load', () => { 2 | 3 | window.vue = new Vue({ 4 | el: '#app', 5 | data: { 6 | message: 'Hello World!', 7 | isLoggedIn: true, 8 | username: 'Fatih' 9 | } 10 | }) 11 | 12 | }) 13 | -------------------------------------------------------------------------------- /02-hello-vue/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Vue 5 | 6 | 7 | 8 | 9 | 10 |
11 |

{{message}} {{username}}

12 |

Anon user

13 |
14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /03-v-for/app.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-size: 13px; 3 | line-height: 19px; 4 | color: #111; 5 | font-family: Arial, sans-serif; 6 | background: #FFF; 7 | } 8 | 9 | h4, p { 10 | padding: 0; 11 | margin: 0; 12 | } 13 | 14 | .item { 15 | border-bottom: 1px solid #DDD; 16 | padding: 15px 0; 17 | overflow: hidden; 18 | } 19 | 20 | .item:first-child { 21 | border-top: 1px solid #DDD; 22 | } 23 | 24 | .item img { 25 | width: 100px; 26 | height: 100px; 27 | } 28 | 29 | h4 { 30 | color: #0066c0; 31 | font-size: 16px; 32 | line-height: 1.255; 33 | } 34 | 35 | .image, .info { 36 | float: left; 37 | } 38 | 39 | .image { 40 | margin-right: 20px; 41 | } 42 | 43 | .seller { 44 | font-size: 13px; 45 | line-height: 19px; 46 | } 47 | 48 | .status.available { 49 | color: #008a00; 50 | font-size: 12px; 51 | line-height: 1.5; 52 | } 53 | 54 | .shipping { 55 | color: #555; 56 | font-size: 12px; 57 | line-height: 1.5; 58 | } 59 | 60 | .info a { 61 | color: #0066c0; 62 | font-size: 12px; 63 | text-decoration: none; 64 | line-height: 24px; 65 | } 66 | 67 | .saved-header { 68 | margin-top: 50px; 69 | } 70 | 71 | a.secondary { 72 | padding-left: 5px; 73 | margin-left: 3px; 74 | border-left: 1px solid #CCC; 75 | } 76 | -------------------------------------------------------------------------------- /03-v-for/app.js: -------------------------------------------------------------------------------- 1 | window.addEventListener('load', () => { 2 | 3 | window.vue = new Vue({ 4 | el: '#app', 5 | name: 'Cart', 6 | data: { 7 | isLoading: true, 8 | cart: [], 9 | saved: [] 10 | }, 11 | methods: { 12 | removeFromCart(index) { 13 | this.cart.splice(index, 1); 14 | }, 15 | saveForLater(index) { 16 | const item = this.cart.splice(index, 1); 17 | this.saved.push(item[0]); 18 | }, 19 | removeFromSavedList(index) { 20 | this.saved.splice(index); 21 | }, 22 | moveToCart(index) { 23 | const item = this.saved.splice(index, 1); 24 | this.cart.push(item[0]); 25 | } 26 | }, 27 | created() { 28 | fetch('./data.json') 29 | .then((res) => { return res.json() }) 30 | .then((res) => { 31 | this.isLoading = false; 32 | this.cart = res.cart; 33 | this.saved = res.saved; 34 | }) 35 | } 36 | }) 37 | 38 | }); 39 | -------------------------------------------------------------------------------- /03-v-for/data.json: -------------------------------------------------------------------------------- 1 | { 2 | "cart": [ 3 | { 4 | "url": "https://www.amazon.com/gp/product/B00BKQT6F8/ref=ox_sc_act_image_1?ie=UTF8&psc=1&smid=A3UH27URU5GI5Q", 5 | "image": "https://images-na.ssl-images-amazon.com/images/I/41UJuETOtuL._SS100_.jpg", 6 | "name": "Daniel Wellington Stainless Steel Watch with Brown Strap", 7 | "seller": "Daniel Wellington", 8 | "isAvailable": true, 9 | "isEligible": true 10 | }, 11 | { 12 | "url": "https://www.amazon.com/gp/product/B00JP6FP6E/ref=ox_sc_act_title_1?ie=UTF8&psc=1&smid=A2VT4H683M5NNA", 13 | "image": "https://images-na.ssl-images-amazon.com/images/I/51t0LVOv0QL._SS100_.jpg", 14 | "name": "Apple Watch Band Milanese Loop", 15 | "seller": "MoKo", 16 | "isAvailable": true, 17 | "isEligible": false 18 | } 19 | ], 20 | "saved": [ 21 | { 22 | "url": "https://www.amazon.com/gp/product/B0142CCDT2/ref=ox_sc_act_image_1?ie=UTF8&psc=1&smid=A2VT4H683M5NNA", 23 | "image": "https://images-na.ssl-images-amazon.com/images/I/31yjqkf3PAL._SS100_.jpg", 24 | "name": "Apple Watch Band Soft Silicone Replacement Sport Band for 38mm Apple Watch", 25 | "seller": "MoKo", 26 | "isAvailable": true, 27 | "isEligible": true 28 | } 29 | ] 30 | } 31 | -------------------------------------------------------------------------------- /03-v-for/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | VueJS Demo 7 | 8 | 9 | 10 | 11 | 12 |
13 |

Loading

14 |

Shopping Cart

15 |

No item in cart.

16 |
17 |
18 |
19 | 20 | 21 | 22 |
23 |
24 |

{{item.name}}

25 |

by {{item.seller}}

26 |

In Stock

27 |

Eligible for FREE Shipping & FREE Returns

28 | Delete 29 | Save for later 30 |
31 |
32 |
33 | 34 |

Saved for later ({{saved.length}} item)

35 |
36 |
37 |
38 | 39 | 40 | 41 |
42 |
43 |

{{item.name}}

44 |

by {{item.seller}}

45 |

In Stock

46 |

Eligible for FREE Shipping & FREE Returns

47 | Delete 48 | Move to cart 49 |
50 |
51 |
52 |
53 | 54 | 55 | -------------------------------------------------------------------------------- /04-computed-properties/app.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-size: 13px; 3 | line-height: 19px; 4 | color: #111; 5 | font-family: Arial, sans-serif; 6 | background: #FFF; 7 | } 8 | 9 | h4, p { 10 | padding: 0; 11 | margin: 0; 12 | } 13 | 14 | .item { 15 | border-bottom: 1px solid #DDD; 16 | padding: 15px 0; 17 | overflow: hidden; 18 | } 19 | 20 | .item:first-child { 21 | border-top: 1px solid #DDD; 22 | } 23 | 24 | .item img { 25 | width: 100px; 26 | height: 100px; 27 | } 28 | 29 | h4 { 30 | color: #0066c0; 31 | font-size: 16px; 32 | line-height: 1.255; 33 | } 34 | 35 | .image, .info { 36 | float: left; 37 | } 38 | 39 | .image { 40 | margin-right: 20px; 41 | } 42 | 43 | .seller { 44 | font-size: 13px; 45 | line-height: 19px; 46 | } 47 | 48 | .status.available { 49 | color: #008a00; 50 | font-size: 12px; 51 | line-height: 1.5; 52 | } 53 | 54 | .shipping { 55 | color: #555; 56 | font-size: 12px; 57 | line-height: 1.5; 58 | } 59 | 60 | .info a { 61 | color: #0066c0; 62 | font-size: 12px; 63 | text-decoration: none; 64 | line-height: 24px; 65 | } 66 | 67 | .saved-header { 68 | margin-top: 50px; 69 | } 70 | 71 | a.secondary { 72 | padding-left: 5px; 73 | margin-left: 3px; 74 | border-left: 1px solid #CCC; 75 | } 76 | 77 | .price { 78 | color: #b12704; 79 | font-size: 17px; 80 | } 81 | 82 | p.price { 83 | float: left; 84 | margin-left: 20px; 85 | } 86 | 87 | .subtotal { 88 | font-size: 17px; 89 | font-weight: bold; 90 | line-height: 60px; 91 | text-align: right; 92 | margin-right: 40px; 93 | } 94 | -------------------------------------------------------------------------------- /04-computed-properties/app.js: -------------------------------------------------------------------------------- 1 | window.addEventListener('load', () => { 2 | 3 | window.vue = new Vue({ 4 | el: '#app', 5 | name: 'Cart', 6 | data: { 7 | isLoading: true, 8 | cart: [], 9 | saved: [] 10 | }, 11 | methods: { 12 | removeFromCart(index) { 13 | this.cart.splice(index, 1); 14 | }, 15 | saveForLater(index) { 16 | const item = this.cart.splice(index, 1); 17 | this.saved.push(item[0]); 18 | }, 19 | removeFromSavedList(index) { 20 | this.saved.splice(index); 21 | }, 22 | moveToCart(index) { 23 | const item = this.saved.splice(index, 1); 24 | this.cart.push(item[0]); 25 | } 26 | }, 27 | computed: { 28 | cartTotal() { 29 | let total = 0; 30 | this.cart.forEach((item) => { 31 | total += parseFloat(item.price, 10); 32 | }); 33 | return total.toFixed(2); 34 | } 35 | }, 36 | created() { 37 | fetch('./data.json') 38 | .then((res) => { return res.json() }) 39 | .then((res) => { 40 | this.isLoading = false; 41 | this.cart = res.cart; 42 | this.saved = res.saved; 43 | }) 44 | } 45 | }) 46 | 47 | }); 48 | -------------------------------------------------------------------------------- /04-computed-properties/data.json: -------------------------------------------------------------------------------- 1 | { 2 | "cart": [ 3 | { 4 | "url": "https://www.amazon.com/gp/product/B00BKQT6F8/ref=ox_sc_act_image_1?ie=UTF8&psc=1&smid=A3UH27URU5GI5Q", 5 | "image": "https://images-na.ssl-images-amazon.com/images/I/41UJuETOtuL._SS100_.jpg", 6 | "name": "Daniel Wellington Stainless Steel Watch with Brown Strap", 7 | "seller": "Daniel Wellington", 8 | "isAvailable": true, 9 | "isEligible": true, 10 | "price": "99.90" 11 | }, 12 | { 13 | "url": "https://www.amazon.com/gp/product/B00JP6FP6E/ref=ox_sc_act_title_1?ie=UTF8&psc=1&smid=A2VT4H683M5NNA", 14 | "image": "https://images-na.ssl-images-amazon.com/images/I/51t0LVOv0QL._SS100_.jpg", 15 | "name": "Apple Watch Band Milanese Loop", 16 | "seller": "MoKo", 17 | "isAvailable": true, 18 | "isEligible": false, 19 | "price": "16.90" 20 | } 21 | ], 22 | "saved": [ 23 | { 24 | "url": "https://www.amazon.com/gp/product/B0142CCDT2/ref=ox_sc_act_image_1?ie=UTF8&psc=1&smid=A2VT4H683M5NNA", 25 | "image": "https://images-na.ssl-images-amazon.com/images/I/31yjqkf3PAL._SS100_.jpg", 26 | "name": "Apple Watch Band Soft Silicone Replacement Sport Band for 38mm Apple Watch", 27 | "seller": "MoKo", 28 | "isAvailable": true, 29 | "isEligible": true, 30 | "price": "28.76" 31 | } 32 | ] 33 | } 34 | -------------------------------------------------------------------------------- /04-computed-properties/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | VueJS Demo 7 | 8 | 9 | 10 | 11 | 12 |
13 |

Loading

14 |

Shopping Cart

15 |

No item in cart.

16 |
17 |
18 |
19 | 20 | 21 | 22 |
23 |
24 |

{{item.name}}

25 |

by {{item.seller}}

26 |

In Stock

27 |

Eligible for FREE Shipping & FREE Returns

28 | Delete 29 | Save for later 30 |
31 |

${{item.price}}

32 |
33 |
34 | Subtotal ({{cart.length}} items): ${{cartTotal}} 35 |
36 |
37 | 38 |

Saved for later ({{saved.length}} item)

39 |
40 |
41 |
42 | 43 | 44 | 45 |
46 |
47 |

{{item.name}}

48 |

by {{item.seller}}

49 |

In Stock

50 |

Eligible for FREE Shipping & FREE Returns

51 | Delete 52 | Move to cart 53 |
54 |
55 |
56 |
57 | 58 | 59 | -------------------------------------------------------------------------------- /05-components-refactor/app.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-size: 13px; 3 | line-height: 19px; 4 | color: #111; 5 | font-family: Arial, sans-serif; 6 | background: #FFF; 7 | } 8 | 9 | h4, p { 10 | padding: 0; 11 | margin: 0; 12 | } 13 | 14 | .item { 15 | border-bottom: 1px solid #DDD; 16 | padding: 15px 0; 17 | overflow: hidden; 18 | } 19 | 20 | .item:first-child { 21 | border-top: 1px solid #DDD; 22 | } 23 | 24 | .item img { 25 | width: 100px; 26 | height: 100px; 27 | } 28 | 29 | h4 { 30 | color: #0066c0; 31 | font-size: 16px; 32 | line-height: 1.255; 33 | } 34 | 35 | .image, .info { 36 | float: left; 37 | } 38 | 39 | .image { 40 | margin-right: 20px; 41 | } 42 | 43 | .seller { 44 | font-size: 13px; 45 | line-height: 19px; 46 | } 47 | 48 | .status.available { 49 | color: #008a00; 50 | font-size: 12px; 51 | line-height: 1.5; 52 | } 53 | 54 | .shipping { 55 | color: #555; 56 | font-size: 12px; 57 | line-height: 1.5; 58 | } 59 | 60 | .info a { 61 | color: #0066c0; 62 | font-size: 12px; 63 | text-decoration: none; 64 | line-height: 24px; 65 | } 66 | 67 | .saved-header { 68 | margin-top: 50px; 69 | } 70 | 71 | a.secondary { 72 | padding-left: 5px; 73 | margin-left: 3px; 74 | border-left: 1px solid #CCC; 75 | } 76 | 77 | .price { 78 | color: #b12704; 79 | font-size: 17px; 80 | } 81 | 82 | p.price { 83 | float: left; 84 | margin-left: 20px; 85 | } 86 | 87 | .subtotal { 88 | font-size: 17px; 89 | font-weight: bold; 90 | line-height: 60px; 91 | text-align: right; 92 | margin-right: 40px; 93 | } 94 | -------------------------------------------------------------------------------- /05-components-refactor/app.js: -------------------------------------------------------------------------------- 1 | Vue.component('VueCart', { 2 | props: { 3 | cart: { type: Array, required: true }, 4 | title: { type: String, required: true }, 5 | type: { type: String, required: true } 6 | }, 7 | methods: { 8 | removeFromCart(index) { 9 | return this.cart.splice(index, 1); 10 | }, 11 | changeCart(index) { 12 | const item = this.removeFromCart(index); 13 | this.$emit('itemchangedoncart', item[0], this.type); 14 | } 15 | }, 16 | computed: { 17 | cartTotal() { 18 | let total = 0; 19 | this.cart.forEach((item) => { 20 | total += parseFloat(item.price, 10); 21 | }); 22 | return total.toFixed(2); 23 | }, 24 | isShoppingCart() { 25 | return this.type == 'shoppingCart' 26 | }, 27 | isSavedCart() { 28 | return this.type == 'savedCart' 29 | } 30 | }, 31 | template: ` 32 |
33 |

{{title}}

34 |

No item in cart.

35 |
36 |
37 |
38 | 39 | 40 | 41 |
42 |
43 |

{{item.name}}

44 |

by {{item.seller}}

45 |

In Stock

46 |

Eligible for FREE Shipping & FREE Returns

47 | Delete 48 | Save for later 49 | Move to cart 50 |
51 |

\${{item.price}}

52 |
53 |
54 |
55 | Subtotal ({{cart.length}} items): \${{cartTotal}} 56 |
57 |
58 | ` 59 | }); 60 | 61 | window.addEventListener('load', () => { 62 | 63 | window.vue = new Vue({ 64 | el: '#app', 65 | name: 'Cart', 66 | data: { 67 | isLoading: true, 68 | cart: [], 69 | saved: [] 70 | }, 71 | methods: { 72 | handleItemChange(item, cartType) { 73 | if (cartType === 'shoppingCart') { 74 | this.saved.push(item); 75 | } 76 | else { 77 | this.cart.push(item); 78 | } 79 | } 80 | }, 81 | created() { 82 | fetch('./data.json') 83 | .then((res) => { return res.json() }) 84 | .then((res) => { 85 | this.isLoading = false; 86 | this.cart = res.cart; 87 | this.saved = res.saved; 88 | }) 89 | } 90 | }) 91 | 92 | }); 93 | -------------------------------------------------------------------------------- /05-components-refactor/data.json: -------------------------------------------------------------------------------- 1 | { 2 | "cart": [ 3 | { 4 | "url": "https://www.amazon.com/gp/product/B00BKQT6F8/ref=ox_sc_act_image_1?ie=UTF8&psc=1&smid=A3UH27URU5GI5Q", 5 | "image": "https://images-na.ssl-images-amazon.com/images/I/41UJuETOtuL._SS100_.jpg", 6 | "name": "Daniel Wellington Stainless Steel Watch with Brown Strap", 7 | "seller": "Daniel Wellington", 8 | "isAvailable": true, 9 | "isEligible": true, 10 | "price": "99.90" 11 | }, 12 | { 13 | "url": "https://www.amazon.com/gp/product/B00JP6FP6E/ref=ox_sc_act_title_1?ie=UTF8&psc=1&smid=A2VT4H683M5NNA", 14 | "image": "https://images-na.ssl-images-amazon.com/images/I/51t0LVOv0QL._SS100_.jpg", 15 | "name": "Apple Watch Band Milanese Loop", 16 | "seller": "MoKo", 17 | "isAvailable": true, 18 | "isEligible": false, 19 | "price": "16.90" 20 | } 21 | ], 22 | "saved": [ 23 | { 24 | "url": "https://www.amazon.com/gp/product/B0142CCDT2/ref=ox_sc_act_image_1?ie=UTF8&psc=1&smid=A2VT4H683M5NNA", 25 | "image": "https://images-na.ssl-images-amazon.com/images/I/31yjqkf3PAL._SS100_.jpg", 26 | "name": "Apple Watch Band Soft Silicone Replacement Sport Band for 38mm Apple Watch", 27 | "seller": "MoKo", 28 | "isAvailable": true, 29 | "isEligible": true, 30 | "price": "28.76" 31 | } 32 | ] 33 | } 34 | -------------------------------------------------------------------------------- /05-components-refactor/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | VueJS Demo 7 | 8 | 9 | 10 | 11 | 12 |
13 |

Loading

14 | 15 | 21 | 22 | 28 | 29 |
30 | 31 | 32 | -------------------------------------------------------------------------------- /05-components-simple/app.js: -------------------------------------------------------------------------------- 1 | window.addEventListener('load', () => { 2 | 3 | Vue.component('hello', { 4 | template: ` 5 |

Hello Component

6 | `, 7 | methods: { 8 | sayHello() { 9 | console.log('Hello World!'); 10 | } 11 | } 12 | }); 13 | 14 | window.vue = new Vue({ 15 | el: '#app' 16 | }) 17 | 18 | }); 19 | -------------------------------------------------------------------------------- /05-components-simple/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | VueJS Demo 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 |
16 | 17 | 18 | -------------------------------------------------------------------------------- /07-giphyapi-app/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | ["es2015", { "modules": false }] 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /07-giphyapi-app/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | dist/ 4 | npm-debug.log 5 | -------------------------------------------------------------------------------- /07-giphyapi-app/README.md: -------------------------------------------------------------------------------- 1 | # giphyapi 2 | 3 | > VueJS demo project for my YT VueJS video serie 4 | 5 | ## Build Setup 6 | 7 | ``` bash 8 | # install dependencies 9 | npm install 10 | 11 | # serve with hot reload at localhost:8080 12 | npm run dev 13 | 14 | # build for production with minification 15 | npm run build 16 | ``` 17 | 18 | For detailed explanation on how things work, consult the [docs for vue-loader](http://vuejs.github.io/vue-loader). 19 | -------------------------------------------------------------------------------- /07-giphyapi-app/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | VueJS Giphy App 6 | 7 | 8 |
9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /07-giphyapi-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "giphyapi", 3 | "description": "VueJS demo project for my YT VueJS video serie", 4 | "version": "1.0.0", 5 | "author": "Fatih Acet ", 6 | "private": true, 7 | "scripts": { 8 | "dev": "cross-env NODE_ENV=development webpack-dev-server --open --inline --hot", 9 | "build": "cross-env NODE_ENV=production webpack --progress --hide-modules" 10 | }, 11 | "dependencies": { 12 | "vue": "^2.1.0" 13 | }, 14 | "devDependencies": { 15 | "babel-core": "^6.0.0", 16 | "babel-loader": "^6.0.0", 17 | "babel-preset-es2015": "^6.0.0", 18 | "cross-env": "^3.0.0", 19 | "css-loader": "^0.25.0", 20 | "file-loader": "^0.9.0", 21 | "vue-loader": "^10.0.0", 22 | "vue-template-compiler": "^2.1.0", 23 | "webpack": "^2.1.0-beta.25", 24 | "webpack-dev-server": "^2.1.0-beta.9" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /07-giphyapi-app/src/App.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 44 | 45 | 52 | -------------------------------------------------------------------------------- /07-giphyapi-app/src/components/Preview.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 16 | 17 | 24 | -------------------------------------------------------------------------------- /07-giphyapi-app/src/components/Search.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 22 | 23 | 24 | 40 | -------------------------------------------------------------------------------- /07-giphyapi-app/src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './App.vue' 3 | 4 | new Vue({ 5 | el: '#app', 6 | render: h => h(App) 7 | }) 8 | -------------------------------------------------------------------------------- /07-giphyapi-app/webpack.config.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var webpack = require('webpack') 3 | 4 | module.exports = { 5 | entry: './src/main.js', 6 | output: { 7 | path: path.resolve(__dirname, './dist'), 8 | publicPath: '/dist/', 9 | filename: 'build.js' 10 | }, 11 | module: { 12 | rules: [ 13 | { 14 | test: /\.vue$/, 15 | loader: 'vue-loader', 16 | options: { 17 | loaders: { 18 | // Since sass-loader (weirdly) has SCSS as its default parse mode, we map 19 | // the "scss" and "sass" values for the lang attribute to the right configs here. 20 | // other preprocessors should work out of the box, no loader config like this nessessary. 21 | 'scss': 'vue-style-loader!css-loader!sass-loader', 22 | 'sass': 'vue-style-loader!css-loader!sass-loader?indentedSyntax' 23 | } 24 | // other vue-loader options go here 25 | } 26 | }, 27 | { 28 | test: /\.js$/, 29 | loader: 'babel-loader', 30 | exclude: /node_modules/ 31 | }, 32 | { 33 | test: /\.(png|jpg|gif|svg)$/, 34 | loader: 'file-loader', 35 | options: { 36 | name: '[name].[ext]?[hash]' 37 | } 38 | } 39 | ] 40 | }, 41 | resolve: { 42 | alias: { 43 | 'vue$': 'vue/dist/vue.common.js' 44 | } 45 | }, 46 | devServer: { 47 | historyApiFallback: true, 48 | noInfo: true 49 | }, 50 | performance: { 51 | hints: false 52 | }, 53 | devtool: '#eval-source-map' 54 | } 55 | 56 | if (process.env.NODE_ENV === 'production') { 57 | module.exports.devtool = '#source-map' 58 | // http://vue-loader.vuejs.org/en/workflow/production.html 59 | module.exports.plugins = (module.exports.plugins || []).concat([ 60 | new webpack.DefinePlugin({ 61 | 'process.env': { 62 | NODE_ENV: '"production"' 63 | } 64 | }), 65 | new webpack.optimize.UglifyJsPlugin({ 66 | sourceMap: true, 67 | compress: { 68 | warnings: false 69 | } 70 | }), 71 | new webpack.LoaderOptionsPlugin({ 72 | minimize: true 73 | }) 74 | ]) 75 | } 76 | -------------------------------------------------------------------------------- /08-router-simple/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | ["es2015", { "modules": false }] 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /08-router-simple/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | dist/ 4 | npm-debug.log 5 | -------------------------------------------------------------------------------- /08-router-simple/README.md: -------------------------------------------------------------------------------- 1 | # 08-router-simple 2 | 3 | > A Vue.js project 4 | 5 | ## Build Setup 6 | 7 | ``` bash 8 | # install dependencies 9 | npm install 10 | 11 | # serve with hot reload at localhost:8080 12 | npm run dev 13 | 14 | # build for production with minification 15 | npm run build 16 | ``` 17 | 18 | For detailed explanation on how things work, consult the [docs for vue-loader](http://vuejs.github.io/vue-loader). 19 | -------------------------------------------------------------------------------- /08-router-simple/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 08-router-simple 6 | 7 | 8 |
9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /08-router-simple/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "08-router-simple", 3 | "description": "A Vue.js project", 4 | "version": "1.0.0", 5 | "author": "Fatih Acet ", 6 | "private": true, 7 | "scripts": { 8 | "dev": "cross-env NODE_ENV=development webpack-dev-server --open --inline --hot", 9 | "build": "cross-env NODE_ENV=production webpack --progress --hide-modules" 10 | }, 11 | "dependencies": { 12 | "vue": "^2.1.0", 13 | "vue-router": "^2.1.1" 14 | }, 15 | "devDependencies": { 16 | "babel-core": "^6.0.0", 17 | "babel-loader": "^6.0.0", 18 | "babel-preset-es2015": "^6.0.0", 19 | "cross-env": "^3.0.0", 20 | "css-loader": "^0.25.0", 21 | "file-loader": "^0.9.0", 22 | "vue-loader": "^10.0.0", 23 | "vue-template-compiler": "^2.1.0", 24 | "webpack": "^2.1.0-beta.25", 25 | "webpack-dev-server": "^2.1.0-beta.9" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /08-router-simple/src/App.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 12 | 17 | 18 | 34 | -------------------------------------------------------------------------------- /08-router-simple/src/components/Bar.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 11 | -------------------------------------------------------------------------------- /08-router-simple/src/components/Foo.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 11 | -------------------------------------------------------------------------------- /08-router-simple/src/components/Home.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 11 | -------------------------------------------------------------------------------- /08-router-simple/src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import VueRouter from 'vue-router' 3 | 4 | Vue.use(VueRouter); 5 | 6 | import App from './App.vue' 7 | import Home from './components/Home.vue' 8 | import Foo from './components/Foo.vue' 9 | import Bar from './components/Bar.vue' 10 | 11 | const router = new VueRouter({ 12 | routes: [ 13 | { path: '/', component: Home }, 14 | { path: '/foo', component: Foo }, 15 | { path: '/bar', component: Bar } 16 | ], 17 | mode: 'history' 18 | }) 19 | 20 | new Vue({ 21 | el: '#app', 22 | render: h => h(App), 23 | router 24 | }) 25 | -------------------------------------------------------------------------------- /08-router-simple/webpack.config.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var webpack = require('webpack') 3 | 4 | module.exports = { 5 | entry: './src/main.js', 6 | output: { 7 | path: path.resolve(__dirname, './dist'), 8 | publicPath: '/dist/', 9 | filename: 'build.js' 10 | }, 11 | module: { 12 | rules: [ 13 | { 14 | test: /\.vue$/, 15 | loader: 'vue-loader', 16 | options: { 17 | loaders: { 18 | // Since sass-loader (weirdly) has SCSS as its default parse mode, we map 19 | // the "scss" and "sass" values for the lang attribute to the right configs here. 20 | // other preprocessors should work out of the box, no loader config like this nessessary. 21 | 'scss': 'vue-style-loader!css-loader!sass-loader', 22 | 'sass': 'vue-style-loader!css-loader!sass-loader?indentedSyntax' 23 | } 24 | // other vue-loader options go here 25 | } 26 | }, 27 | { 28 | test: /\.js$/, 29 | loader: 'babel-loader', 30 | exclude: /node_modules/ 31 | }, 32 | { 33 | test: /\.(png|jpg|gif|svg)$/, 34 | loader: 'file-loader', 35 | options: { 36 | name: '[name].[ext]?[hash]' 37 | } 38 | } 39 | ] 40 | }, 41 | resolve: { 42 | alias: { 43 | 'vue$': 'vue/dist/vue.common.js' 44 | } 45 | }, 46 | devServer: { 47 | historyApiFallback: true, 48 | noInfo: true 49 | }, 50 | performance: { 51 | hints: false 52 | }, 53 | devtool: '#eval-source-map' 54 | } 55 | 56 | if (process.env.NODE_ENV === 'production') { 57 | module.exports.devtool = '#source-map' 58 | // http://vue-loader.vuejs.org/en/workflow/production.html 59 | module.exports.plugins = (module.exports.plugins || []).concat([ 60 | new webpack.DefinePlugin({ 61 | 'process.env': { 62 | NODE_ENV: '"production"' 63 | } 64 | }), 65 | new webpack.optimize.UglifyJsPlugin({ 66 | sourceMap: true, 67 | compress: { 68 | warnings: false 69 | } 70 | }), 71 | new webpack.LoaderOptionsPlugin({ 72 | minimize: true 73 | }) 74 | ]) 75 | } 76 | -------------------------------------------------------------------------------- /08-router/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | ["es2015", { "modules": false }] 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /08-router/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | dist/ 4 | npm-debug.log 5 | -------------------------------------------------------------------------------- /08-router/README.md: -------------------------------------------------------------------------------- 1 | # 08-router 2 | 3 | > A Vue.js project 4 | 5 | ## Build Setup 6 | 7 | ``` bash 8 | # install dependencies 9 | npm install 10 | 11 | # serve with hot reload at localhost:8080 12 | npm run dev 13 | 14 | # build for production with minification 15 | npm run build 16 | ``` 17 | 18 | For detailed explanation on how things work, consult the [docs for vue-loader](http://vuejs.github.io/vue-loader). 19 | -------------------------------------------------------------------------------- /08-router/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 08-router 6 | 7 | 8 |
9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /08-router/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "08-router", 3 | "description": "A Vue.js project", 4 | "version": "1.0.0", 5 | "author": "Fatih Acet ", 6 | "private": true, 7 | "scripts": { 8 | "dev": "cross-env NODE_ENV=development webpack-dev-server --open --inline --hot", 9 | "build": "cross-env NODE_ENV=production webpack --progress --hide-modules" 10 | }, 11 | "dependencies": { 12 | "vue": "^2.1.0", 13 | "vue-router": "^2.1.1" 14 | }, 15 | "devDependencies": { 16 | "babel-core": "^6.0.0", 17 | "babel-loader": "^6.0.0", 18 | "babel-preset-es2015": "^6.0.0", 19 | "cross-env": "^3.0.0", 20 | "css-loader": "^0.25.0", 21 | "file-loader": "^0.9.0", 22 | "vue-loader": "^10.0.0", 23 | "vue-template-compiler": "^2.1.0", 24 | "webpack": "^2.1.0-beta.25", 25 | "webpack-dev-server": "^2.1.0-beta.9" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /08-router/src/App.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | 13 | 38 | -------------------------------------------------------------------------------- /08-router/src/components/Home.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 27 | -------------------------------------------------------------------------------- /08-router/src/components/UserItem.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 24 | -------------------------------------------------------------------------------- /08-router/src/components/UserPosts.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 32 | -------------------------------------------------------------------------------- /08-router/src/components/UserProfile.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 49 | -------------------------------------------------------------------------------- /08-router/src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import VueRouter from 'vue-router' 3 | 4 | Vue.use(VueRouter); 5 | 6 | import App from './App.vue' 7 | import Home from './components/Home.vue' 8 | import UserProfile from './components/UserProfile.vue' 9 | import UserPosts from './components/UserPosts.vue' 10 | 11 | const router = new VueRouter({ 12 | routes: [ 13 | { path: '/', component: Home, name: 'home' }, 14 | { path: '/user/:id', component: UserProfile, name: 'userProfile' }, 15 | { path: '/user/:userId/posts', component: UserPosts } 16 | ], 17 | mode: 'history' 18 | }) 19 | 20 | new Vue({ 21 | el: '#app', 22 | render: h => h(App), 23 | router 24 | }) 25 | -------------------------------------------------------------------------------- /08-router/webpack.config.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var webpack = require('webpack') 3 | 4 | module.exports = { 5 | entry: './src/main.js', 6 | output: { 7 | path: path.resolve(__dirname, './dist'), 8 | publicPath: '/dist/', 9 | filename: 'build.js' 10 | }, 11 | module: { 12 | rules: [ 13 | { 14 | test: /\.vue$/, 15 | loader: 'vue-loader', 16 | options: { 17 | loaders: { 18 | // Since sass-loader (weirdly) has SCSS as its default parse mode, we map 19 | // the "scss" and "sass" values for the lang attribute to the right configs here. 20 | // other preprocessors should work out of the box, no loader config like this nessessary. 21 | 'scss': 'vue-style-loader!css-loader!sass-loader', 22 | 'sass': 'vue-style-loader!css-loader!sass-loader?indentedSyntax' 23 | } 24 | // other vue-loader options go here 25 | } 26 | }, 27 | { 28 | test: /\.js$/, 29 | loader: 'babel-loader', 30 | exclude: /node_modules/ 31 | }, 32 | { 33 | test: /\.(png|jpg|gif|svg)$/, 34 | loader: 'file-loader', 35 | options: { 36 | name: '[name].[ext]?[hash]' 37 | } 38 | } 39 | ] 40 | }, 41 | resolve: { 42 | alias: { 43 | 'vue$': 'vue/dist/vue.common.js' 44 | } 45 | }, 46 | devServer: { 47 | historyApiFallback: true, 48 | noInfo: true 49 | }, 50 | performance: { 51 | hints: false 52 | }, 53 | devtool: '#eval-source-map' 54 | } 55 | 56 | if (process.env.NODE_ENV === 'production') { 57 | module.exports.devtool = '#source-map' 58 | // http://vue-loader.vuejs.org/en/workflow/production.html 59 | module.exports.plugins = (module.exports.plugins || []).concat([ 60 | new webpack.DefinePlugin({ 61 | 'process.env': { 62 | NODE_ENV: '"production"' 63 | } 64 | }), 65 | new webpack.optimize.UglifyJsPlugin({ 66 | sourceMap: true, 67 | compress: { 68 | warnings: false 69 | } 70 | }), 71 | new webpack.LoaderOptionsPlugin({ 72 | minimize: true 73 | }) 74 | ]) 75 | } 76 | -------------------------------------------------------------------------------- /09-vue-goodies/app.js: -------------------------------------------------------------------------------- 1 | window.addEventListener('load', () => { 2 | 3 | new Vue({ 4 | el: '#vmodel', 5 | data: { 6 | message: 'Hello World', 7 | selectedVal: 'foo', 8 | isSelected: true 9 | }, 10 | methods: { 11 | log() { 12 | console.log(`"${this.message}"`); 13 | }, 14 | setValue() { 15 | this.selectedVal = 'baz'; 16 | } 17 | } 18 | }) 19 | 20 | setTimeout(() => { 21 | new Vue({ 22 | el: '#vcloak', 23 | data: { 24 | users: [ { name: 'Fatih' }, { name: 'Didem'} ] 25 | } 26 | }) 27 | }, 3000) 28 | 29 | Vue.component('v-select', { 30 | template: ` 31 | 34 | ` 35 | }) 36 | 37 | Vue.component('v-option', { 38 | props: [ 'value' ], 39 | template: `` 40 | }); 41 | 42 | new Vue({ el: '#slots' }); 43 | 44 | 45 | new Vue({ 46 | el: '#nextTick', 47 | data: { 48 | message: 'Hello!' 49 | }, 50 | methods: { 51 | change() { 52 | this.message = 'Hello World!'; 53 | console.log(document.querySelector('#nextTick').innerText); 54 | 55 | this.$nextTick(() => { 56 | console.log(document.querySelector('#nextTick').innerText); 57 | }) 58 | } 59 | } 60 | }) 61 | 62 | Vue.config.keyCodes.a = 65; 63 | new Vue({ 64 | el: '#modifiers', 65 | methods: { 66 | log() { 67 | console.log('Fooooooo'); 68 | } 69 | } 70 | }) 71 | 72 | Vue.filter('withTax', (price) => { 73 | return `${(price * 1.18).toFixed(2)} tl`; 74 | }) 75 | 76 | new Vue({ 77 | el: '#filters', 78 | data: { 79 | name: 'logitech camera', 80 | price: 25 81 | }, 82 | filters: { 83 | uppercase(text) { 84 | return text.toUpperCase(); 85 | } 86 | } 87 | }) 88 | 89 | 90 | }); 91 | -------------------------------------------------------------------------------- /09-vue-goodies/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | VueJS Demo 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 21 | 22 | 23 |
24 | 25 | 26 |
27 |
    28 |
  • {{user.name}}
  • 29 |
30 |
31 | 32 |
33 | 34 | 35 | 36 | 37 | 38 |
39 | 40 |
41 | {{message}} 42 | 43 |
44 | 45 |
46 | Go to Foo 47 | 48 | 49 | 50 | 51 |
52 | 53 |
54 |

{{name | uppercase}}

55 |

{{price | withTax | uppercase }}

56 |
57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /10-vue-testing/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015", "stage-2"], 3 | "plugins": ["transform-runtime"], 4 | "comments": false, 5 | "env": { 6 | "test": { 7 | "plugins": [ "istanbul" ] 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /10-vue-testing/.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /10-vue-testing/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | dist/ 4 | npm-debug.log 5 | test/unit/coverage 6 | test/e2e/reports 7 | selenium-debug.log 8 | -------------------------------------------------------------------------------- /10-vue-testing/README.md: -------------------------------------------------------------------------------- 1 | # 10-vue-testing 2 | 3 | > A Vue.js project 4 | 5 | ## Build Setup 6 | 7 | ``` bash 8 | # install dependencies 9 | npm install 10 | 11 | # serve with hot reload at localhost:8080 12 | npm run dev 13 | 14 | # build for production with minification 15 | npm run build 16 | 17 | # run unit tests 18 | npm run unit 19 | 20 | # run e2e tests 21 | npm run e2e 22 | 23 | # run all tests 24 | npm test 25 | ``` 26 | 27 | For detailed explanation on how things work, checkout the [guide](http://vuejs-templates.github.io/webpack/) and [docs for vue-loader](http://vuejs.github.io/vue-loader). 28 | -------------------------------------------------------------------------------- /10-vue-testing/build/build.js: -------------------------------------------------------------------------------- 1 | // https://github.com/shelljs/shelljs 2 | require('./check-versions')() 3 | require('shelljs/global') 4 | env.NODE_ENV = 'production' 5 | 6 | var path = require('path') 7 | var config = require('../config') 8 | var ora = require('ora') 9 | var webpack = require('webpack') 10 | var webpackConfig = require('./webpack.prod.conf') 11 | 12 | console.log( 13 | ' Tip:\n' + 14 | ' Built files are meant to be served over an HTTP server.\n' + 15 | ' Opening index.html over file:// won\'t work.\n' 16 | ) 17 | 18 | var spinner = ora('building for production...') 19 | spinner.start() 20 | 21 | var assetsPath = path.join(config.build.assetsRoot, config.build.assetsSubDirectory) 22 | rm('-rf', assetsPath) 23 | mkdir('-p', assetsPath) 24 | cp('-R', 'static/*', assetsPath) 25 | 26 | webpack(webpackConfig, function (err, stats) { 27 | spinner.stop() 28 | if (err) throw err 29 | process.stdout.write(stats.toString({ 30 | colors: true, 31 | modules: false, 32 | children: false, 33 | chunks: false, 34 | chunkModules: false 35 | }) + '\n') 36 | }) 37 | -------------------------------------------------------------------------------- /10-vue-testing/build/check-versions.js: -------------------------------------------------------------------------------- 1 | var semver = require('semver') 2 | var chalk = require('chalk') 3 | var packageConfig = require('../package.json') 4 | var exec = function (cmd) { 5 | return require('child_process') 6 | .execSync(cmd).toString().trim() 7 | } 8 | 9 | var versionRequirements = [ 10 | { 11 | name: 'node', 12 | currentVersion: semver.clean(process.version), 13 | versionRequirement: packageConfig.engines.node 14 | }, 15 | { 16 | name: 'npm', 17 | currentVersion: exec('npm --version'), 18 | versionRequirement: packageConfig.engines.npm 19 | } 20 | ] 21 | 22 | module.exports = function () { 23 | var warnings = [] 24 | for (var i = 0; i < versionRequirements.length; i++) { 25 | var mod = versionRequirements[i] 26 | if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) { 27 | warnings.push(mod.name + ': ' + 28 | chalk.red(mod.currentVersion) + ' should be ' + 29 | chalk.green(mod.versionRequirement) 30 | ) 31 | } 32 | } 33 | 34 | if (warnings.length) { 35 | console.log('') 36 | console.log(chalk.yellow('To use this template, you must update following to modules:')) 37 | console.log() 38 | for (var i = 0; i < warnings.length; i++) { 39 | var warning = warnings[i] 40 | console.log(' ' + warning) 41 | } 42 | console.log() 43 | process.exit(1) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /10-vue-testing/build/dev-client.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | require('eventsource-polyfill') 3 | var hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true') 4 | 5 | hotClient.subscribe(function (event) { 6 | if (event.action === 'reload') { 7 | window.location.reload() 8 | } 9 | }) 10 | -------------------------------------------------------------------------------- /10-vue-testing/build/dev-server.js: -------------------------------------------------------------------------------- 1 | require('./check-versions')() 2 | var config = require('../config') 3 | if (!process.env.NODE_ENV) process.env.NODE_ENV = JSON.parse(config.dev.env.NODE_ENV) 4 | var path = require('path') 5 | var express = require('express') 6 | var webpack = require('webpack') 7 | var opn = require('opn') 8 | var proxyMiddleware = require('http-proxy-middleware') 9 | var webpackConfig = process.env.NODE_ENV === 'testing' 10 | ? require('./webpack.prod.conf') 11 | : require('./webpack.dev.conf') 12 | 13 | // default port where dev server listens for incoming traffic 14 | var port = process.env.PORT || config.dev.port 15 | // Define HTTP proxies to your custom API backend 16 | // https://github.com/chimurai/http-proxy-middleware 17 | var proxyTable = config.dev.proxyTable 18 | 19 | var app = express() 20 | var compiler = webpack(webpackConfig) 21 | 22 | var devMiddleware = require('webpack-dev-middleware')(compiler, { 23 | publicPath: webpackConfig.output.publicPath, 24 | quiet: true 25 | }) 26 | 27 | var hotMiddleware = require('webpack-hot-middleware')(compiler, { 28 | log: () => {} 29 | }) 30 | // force page reload when html-webpack-plugin template changes 31 | compiler.plugin('compilation', function (compilation) { 32 | compilation.plugin('html-webpack-plugin-after-emit', function (data, cb) { 33 | hotMiddleware.publish({ action: 'reload' }) 34 | cb() 35 | }) 36 | }) 37 | 38 | // proxy api requests 39 | Object.keys(proxyTable).forEach(function (context) { 40 | var options = proxyTable[context] 41 | if (typeof options === 'string') { 42 | options = { target: options } 43 | } 44 | app.use(proxyMiddleware(context, options)) 45 | }) 46 | 47 | // handle fallback for HTML5 history API 48 | app.use(require('connect-history-api-fallback')()) 49 | 50 | // serve webpack bundle output 51 | app.use(devMiddleware) 52 | 53 | // enable hot-reload and state-preserving 54 | // compilation error display 55 | app.use(hotMiddleware) 56 | 57 | // serve pure static assets 58 | var staticPath = path.posix.join(config.dev.assetsPublicPath, config.dev.assetsSubDirectory) 59 | app.use(staticPath, express.static('./static')) 60 | 61 | var uri = 'http://localhost:' + port 62 | 63 | devMiddleware.waitUntilValid(function () { 64 | console.log('> Listening at ' + uri + '\n') 65 | }) 66 | 67 | module.exports = app.listen(port, function (err) { 68 | if (err) { 69 | console.log(err) 70 | return 71 | } 72 | 73 | // when env is testing, don't need open it 74 | if (process.env.NODE_ENV !== 'testing') { 75 | opn(uri) 76 | } 77 | }) 78 | -------------------------------------------------------------------------------- /10-vue-testing/build/utils.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var config = require('../config') 3 | var ExtractTextPlugin = require('extract-text-webpack-plugin') 4 | 5 | exports.assetsPath = function (_path) { 6 | var assetsSubDirectory = process.env.NODE_ENV === 'production' 7 | ? config.build.assetsSubDirectory 8 | : config.dev.assetsSubDirectory 9 | return path.posix.join(assetsSubDirectory, _path) 10 | } 11 | 12 | exports.cssLoaders = function (options) { 13 | options = options || {} 14 | // generate loader string to be used with extract text plugin 15 | function generateLoaders (loaders) { 16 | var sourceLoader = loaders.map(function (loader) { 17 | var extraParamChar 18 | if (/\?/.test(loader)) { 19 | loader = loader.replace(/\?/, '-loader?') 20 | extraParamChar = '&' 21 | } else { 22 | loader = loader + '-loader' 23 | extraParamChar = '?' 24 | } 25 | return loader + (options.sourceMap ? extraParamChar + 'sourceMap' : '') 26 | }).join('!') 27 | 28 | // Extract CSS when that option is specified 29 | // (which is the case during production build) 30 | if (options.extract) { 31 | return ExtractTextPlugin.extract('vue-style-loader', sourceLoader) 32 | } else { 33 | return ['vue-style-loader', sourceLoader].join('!') 34 | } 35 | } 36 | 37 | // http://vuejs.github.io/vue-loader/en/configurations/extract-css.html 38 | return { 39 | css: generateLoaders(['css']), 40 | postcss: generateLoaders(['css']), 41 | less: generateLoaders(['css', 'less']), 42 | sass: generateLoaders(['css', 'sass?indentedSyntax']), 43 | scss: generateLoaders(['css', 'sass']), 44 | stylus: generateLoaders(['css', 'stylus']), 45 | styl: generateLoaders(['css', 'stylus']) 46 | } 47 | } 48 | 49 | // Generate loaders for standalone style files (outside of .vue) 50 | exports.styleLoaders = function (options) { 51 | var output = [] 52 | var loaders = exports.cssLoaders(options) 53 | for (var extension in loaders) { 54 | var loader = loaders[extension] 55 | output.push({ 56 | test: new RegExp('\\.' + extension + '$'), 57 | loader: loader 58 | }) 59 | } 60 | return output 61 | } 62 | -------------------------------------------------------------------------------- /10-vue-testing/build/webpack.base.conf.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var config = require('../config') 3 | var utils = require('./utils') 4 | var projectRoot = path.resolve(__dirname, '../') 5 | 6 | var env = process.env.NODE_ENV 7 | // check env & config/index.js to decide whether to enable CSS source maps for the 8 | // various preprocessor loaders added to vue-loader at the end of this file 9 | var cssSourceMapDev = (env === 'development' && config.dev.cssSourceMap) 10 | var cssSourceMapProd = (env === 'production' && config.build.productionSourceMap) 11 | var useCssSourceMap = cssSourceMapDev || cssSourceMapProd 12 | 13 | module.exports = { 14 | entry: { 15 | app: './src/main.js' 16 | }, 17 | output: { 18 | path: config.build.assetsRoot, 19 | publicPath: process.env.NODE_ENV === 'production' ? config.build.assetsPublicPath : config.dev.assetsPublicPath, 20 | filename: '[name].js' 21 | }, 22 | resolve: { 23 | extensions: ['', '.js', '.vue', '.json'], 24 | fallback: [path.join(__dirname, '../node_modules')], 25 | alias: { 26 | 'vue$': 'vue/dist/vue.common.js', 27 | 'src': path.resolve(__dirname, '../src'), 28 | 'assets': path.resolve(__dirname, '../src/assets'), 29 | 'components': path.resolve(__dirname, '../src/components') 30 | } 31 | }, 32 | resolveLoader: { 33 | fallback: [path.join(__dirname, '../node_modules')] 34 | }, 35 | module: { 36 | loaders: [ 37 | { 38 | test: /\.vue$/, 39 | loader: 'vue' 40 | }, 41 | { 42 | test: /\.js$/, 43 | loader: 'babel', 44 | include: [ 45 | path.join(projectRoot, 'src') 46 | ], 47 | exclude: /node_modules/ 48 | }, 49 | { 50 | test: /\.json$/, 51 | loader: 'json' 52 | }, 53 | { 54 | test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, 55 | loader: 'url', 56 | query: { 57 | limit: 10000, 58 | name: utils.assetsPath('img/[name].[hash:7].[ext]') 59 | } 60 | }, 61 | { 62 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, 63 | loader: 'url', 64 | query: { 65 | limit: 10000, 66 | name: utils.assetsPath('fonts/[name].[hash:7].[ext]') 67 | } 68 | } 69 | ] 70 | }, 71 | vue: { 72 | loaders: utils.cssLoaders({ sourceMap: useCssSourceMap }), 73 | postcss: [ 74 | require('autoprefixer')({ 75 | browsers: ['last 2 versions'] 76 | }) 77 | ] 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /10-vue-testing/build/webpack.dev.conf.js: -------------------------------------------------------------------------------- 1 | var config = require('../config') 2 | var webpack = require('webpack') 3 | var merge = require('webpack-merge') 4 | var utils = require('./utils') 5 | var baseWebpackConfig = require('./webpack.base.conf') 6 | var HtmlWebpackPlugin = require('html-webpack-plugin') 7 | var FriendlyErrors = require('friendly-errors-webpack-plugin') 8 | 9 | // add hot-reload related code to entry chunks 10 | Object.keys(baseWebpackConfig.entry).forEach(function (name) { 11 | baseWebpackConfig.entry[name] = ['./build/dev-client'].concat(baseWebpackConfig.entry[name]) 12 | }) 13 | 14 | module.exports = merge(baseWebpackConfig, { 15 | module: { 16 | loaders: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap }) 17 | }, 18 | // eval-source-map is faster for development 19 | devtool: '#eval-source-map', 20 | plugins: [ 21 | new webpack.DefinePlugin({ 22 | 'process.env': config.dev.env 23 | }), 24 | // https://github.com/glenjamin/webpack-hot-middleware#installation--usage 25 | new webpack.optimize.OccurrenceOrderPlugin(), 26 | new webpack.HotModuleReplacementPlugin(), 27 | new webpack.NoErrorsPlugin(), 28 | // https://github.com/ampedandwired/html-webpack-plugin 29 | new HtmlWebpackPlugin({ 30 | filename: 'index.html', 31 | template: 'index.html', 32 | inject: true 33 | }), 34 | new FriendlyErrors() 35 | ] 36 | }) 37 | -------------------------------------------------------------------------------- /10-vue-testing/build/webpack.prod.conf.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var config = require('../config') 3 | var utils = require('./utils') 4 | var webpack = require('webpack') 5 | var merge = require('webpack-merge') 6 | var baseWebpackConfig = require('./webpack.base.conf') 7 | var ExtractTextPlugin = require('extract-text-webpack-plugin') 8 | var HtmlWebpackPlugin = require('html-webpack-plugin') 9 | var env = process.env.NODE_ENV === 'testing' 10 | ? require('../config/test.env') 11 | : config.build.env 12 | 13 | var webpackConfig = merge(baseWebpackConfig, { 14 | module: { 15 | loaders: utils.styleLoaders({ sourceMap: config.build.productionSourceMap, extract: true }) 16 | }, 17 | devtool: config.build.productionSourceMap ? '#source-map' : false, 18 | output: { 19 | path: config.build.assetsRoot, 20 | filename: utils.assetsPath('js/[name].[chunkhash].js'), 21 | chunkFilename: utils.assetsPath('js/[id].[chunkhash].js') 22 | }, 23 | vue: { 24 | loaders: utils.cssLoaders({ 25 | sourceMap: config.build.productionSourceMap, 26 | extract: true 27 | }) 28 | }, 29 | plugins: [ 30 | // http://vuejs.github.io/vue-loader/en/workflow/production.html 31 | new webpack.DefinePlugin({ 32 | 'process.env': env 33 | }), 34 | new webpack.optimize.UglifyJsPlugin({ 35 | compress: { 36 | warnings: false 37 | } 38 | }), 39 | new webpack.optimize.OccurrenceOrderPlugin(), 40 | // extract css into its own file 41 | new ExtractTextPlugin(utils.assetsPath('css/[name].[contenthash].css')), 42 | // generate dist index.html with correct asset hash for caching. 43 | // you can customize output by editing /index.html 44 | // see https://github.com/ampedandwired/html-webpack-plugin 45 | new HtmlWebpackPlugin({ 46 | filename: process.env.NODE_ENV === 'testing' 47 | ? 'index.html' 48 | : config.build.index, 49 | template: 'index.html', 50 | inject: true, 51 | minify: { 52 | removeComments: true, 53 | collapseWhitespace: true, 54 | removeAttributeQuotes: true 55 | // more options: 56 | // https://github.com/kangax/html-minifier#options-quick-reference 57 | }, 58 | // necessary to consistently work with multiple chunks via CommonsChunkPlugin 59 | chunksSortMode: 'dependency' 60 | }), 61 | // split vendor js into its own file 62 | new webpack.optimize.CommonsChunkPlugin({ 63 | name: 'vendor', 64 | minChunks: function (module, count) { 65 | // any required modules inside node_modules are extracted to vendor 66 | return ( 67 | module.resource && 68 | /\.js$/.test(module.resource) && 69 | module.resource.indexOf( 70 | path.join(__dirname, '../node_modules') 71 | ) === 0 72 | ) 73 | } 74 | }), 75 | // extract webpack runtime and module manifest to its own file in order to 76 | // prevent vendor hash from being updated whenever app bundle is updated 77 | new webpack.optimize.CommonsChunkPlugin({ 78 | name: 'manifest', 79 | chunks: ['vendor'] 80 | }) 81 | ] 82 | }) 83 | 84 | if (config.build.productionGzip) { 85 | var CompressionWebpackPlugin = require('compression-webpack-plugin') 86 | 87 | webpackConfig.plugins.push( 88 | new CompressionWebpackPlugin({ 89 | asset: '[path].gz[query]', 90 | algorithm: 'gzip', 91 | test: new RegExp( 92 | '\\.(' + 93 | config.build.productionGzipExtensions.join('|') + 94 | ')$' 95 | ), 96 | threshold: 10240, 97 | minRatio: 0.8 98 | }) 99 | ) 100 | } 101 | 102 | module.exports = webpackConfig 103 | -------------------------------------------------------------------------------- /10-vue-testing/config/dev.env.js: -------------------------------------------------------------------------------- 1 | var merge = require('webpack-merge') 2 | var prodEnv = require('./prod.env') 3 | 4 | module.exports = merge(prodEnv, { 5 | NODE_ENV: '"development"' 6 | }) 7 | -------------------------------------------------------------------------------- /10-vue-testing/config/index.js: -------------------------------------------------------------------------------- 1 | // see http://vuejs-templates.github.io/webpack for documentation. 2 | var path = require('path') 3 | 4 | module.exports = { 5 | build: { 6 | env: require('./prod.env'), 7 | index: path.resolve(__dirname, '../dist/index.html'), 8 | assetsRoot: path.resolve(__dirname, '../dist'), 9 | assetsSubDirectory: 'static', 10 | assetsPublicPath: '/', 11 | productionSourceMap: true, 12 | // Gzip off by default as many popular static hosts such as 13 | // Surge or Netlify already gzip all static assets for you. 14 | // Before setting to `true`, make sure to: 15 | // npm install --save-dev compression-webpack-plugin 16 | productionGzip: false, 17 | productionGzipExtensions: ['js', 'css'] 18 | }, 19 | dev: { 20 | env: require('./dev.env'), 21 | port: 8080, 22 | assetsSubDirectory: 'static', 23 | assetsPublicPath: '/', 24 | proxyTable: {}, 25 | // CSS Sourcemaps off by default because relative paths are "buggy" 26 | // with this option, according to the CSS-Loader README 27 | // (https://github.com/webpack/css-loader#sourcemaps) 28 | // In our experience, they generally work as expected, 29 | // just be aware of this issue when enabling this option. 30 | cssSourceMap: false 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /10-vue-testing/config/prod.env.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | NODE_ENV: '"production"' 3 | } 4 | -------------------------------------------------------------------------------- /10-vue-testing/config/test.env.js: -------------------------------------------------------------------------------- 1 | var merge = require('webpack-merge') 2 | var devEnv = require('./dev.env') 3 | 4 | module.exports = merge(devEnv, { 5 | NODE_ENV: '"testing"' 6 | }) 7 | -------------------------------------------------------------------------------- /10-vue-testing/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 10-vue-testing 6 | 7 | 8 |
9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /10-vue-testing/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "10-vue-testing", 3 | "version": "1.0.0", 4 | "description": "A Vue.js project", 5 | "author": "Fatih Acet ", 6 | "private": true, 7 | "scripts": { 8 | "dev": "node build/dev-server.js", 9 | "build": "node build/build.js", 10 | "unit": "cross-env BABEL_ENV=test karma start test/unit/karma.conf.js", 11 | "e2e": "node test/e2e/runner.js", 12 | "test": "npm run unit && npm run e2e" 13 | }, 14 | "dependencies": { 15 | "vue": "^2.1.0" 16 | }, 17 | "devDependencies": { 18 | "autoprefixer": "^6.4.0", 19 | "babel-core": "^6.0.0", 20 | "babel-loader": "^6.0.0", 21 | "babel-plugin-transform-runtime": "^6.0.0", 22 | "babel-preset-es2015": "^6.0.0", 23 | "babel-preset-stage-2": "^6.0.0", 24 | "babel-register": "^6.0.0", 25 | "chalk": "^1.1.3", 26 | "connect-history-api-fallback": "^1.1.0", 27 | "css-loader": "^0.25.0", 28 | "eventsource-polyfill": "^0.9.6", 29 | "express": "^4.13.3", 30 | "extract-text-webpack-plugin": "^1.0.1", 31 | "file-loader": "^0.9.0", 32 | "friendly-errors-webpack-plugin": "^1.1.2", 33 | "function-bind": "^1.0.2", 34 | "html-webpack-plugin": "^2.8.1", 35 | "http-proxy-middleware": "^0.17.2", 36 | "json-loader": "^0.5.4", 37 | "cross-env": "^3.1.3", 38 | "karma": "^1.3.0", 39 | "karma-coverage": "^1.1.1", 40 | "karma-mocha": "^1.2.0", 41 | "karma-phantomjs-launcher": "^1.0.0", 42 | "karma-sinon-chai": "^1.2.0", 43 | "karma-sourcemap-loader": "^0.3.7", 44 | "karma-spec-reporter": "0.0.26", 45 | "karma-webpack": "^1.7.0", 46 | "lolex": "^1.4.0", 47 | "mocha": "^3.1.0", 48 | "chai": "^3.5.0", 49 | "sinon": "^1.17.3", 50 | "sinon-chai": "^2.8.0", 51 | "inject-loader": "^2.0.1", 52 | "babel-plugin-istanbul": "^3.0.0", 53 | "phantomjs-prebuilt": "^2.1.3", 54 | "chromedriver": "^2.21.2", 55 | "cross-spawn": "^4.0.2", 56 | "nightwatch": "^0.9.8", 57 | "selenium-server": "2.53.1", 58 | "semver": "^5.3.0", 59 | "opn": "^4.0.2", 60 | "ora": "^0.3.0", 61 | "shelljs": "^0.7.4", 62 | "url-loader": "^0.5.7", 63 | "vue-loader": "^10.0.0", 64 | "vue-style-loader": "^1.0.0", 65 | "vue-template-compiler": "^2.1.0", 66 | "webpack": "^1.13.2", 67 | "webpack-dev-middleware": "^1.8.3", 68 | "webpack-hot-middleware": "^2.12.2", 69 | "webpack-merge": "^0.14.1" 70 | }, 71 | "engines": { 72 | "node": ">= 4.0.0", 73 | "npm": ">= 3.0.0" 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /10-vue-testing/src/App.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 44 | 45 | 52 | -------------------------------------------------------------------------------- /10-vue-testing/src/components/Preview.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 17 | 18 | 25 | -------------------------------------------------------------------------------- /10-vue-testing/src/components/Search.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 22 | 23 | 24 | 40 | -------------------------------------------------------------------------------- /10-vue-testing/src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './App.vue' 3 | 4 | new Vue({ 5 | el: '#app', 6 | render: h => h(App) 7 | }) 8 | -------------------------------------------------------------------------------- /10-vue-testing/static/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fatihacet/vuejs-videolari/94f9f38a3a69727be38aa1a7b727dec771d714cb/10-vue-testing/static/.gitkeep -------------------------------------------------------------------------------- /10-vue-testing/test/e2e/custom-assertions/elementCount.js: -------------------------------------------------------------------------------- 1 | // A custom Nightwatch assertion. 2 | // the name of the method is the filename. 3 | // can be used in tests like this: 4 | // 5 | // browser.assert.elementCount(selector, count) 6 | // 7 | // for how to write custom assertions see 8 | // http://nightwatchjs.org/guide#writing-custom-assertions 9 | exports.assertion = function (selector, count) { 10 | this.message = 'Testing if element <' + selector + '> has count: ' + count 11 | this.expected = count 12 | this.pass = function (val) { 13 | return val === this.expected 14 | } 15 | this.value = function (res) { 16 | return res.value 17 | } 18 | this.command = function (cb) { 19 | var self = this 20 | return this.api.execute(function (selector) { 21 | return document.querySelectorAll(selector).length 22 | }, [selector], function (res) { 23 | cb.call(self, res) 24 | }) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /10-vue-testing/test/e2e/nightwatch.conf.js: -------------------------------------------------------------------------------- 1 | require('babel-register') 2 | var config = require('../../config') 3 | 4 | // http://nightwatchjs.org/guide#settings-file 5 | module.exports = { 6 | src_folders: ['test/e2e/specs'], 7 | output_folder: 'test/e2e/reports', 8 | custom_assertions_path: ['test/e2e/custom-assertions'], 9 | 10 | selenium: { 11 | start_process: true, 12 | server_path: 'node_modules/selenium-server/lib/runner/selenium-server-standalone-2.53.1.jar', 13 | host: '127.0.0.1', 14 | port: 4444, 15 | cli_args: { 16 | 'webdriver.chrome.driver': require('chromedriver').path 17 | } 18 | }, 19 | 20 | test_settings: { 21 | default: { 22 | selenium_port: 4444, 23 | selenium_host: 'localhost', 24 | silent: true, 25 | globals: { 26 | devServerURL: 'http://localhost:' + (process.env.PORT || config.dev.port) 27 | } 28 | }, 29 | 30 | chrome: { 31 | desiredCapabilities: { 32 | browserName: 'chrome', 33 | javascriptEnabled: true, 34 | acceptSslCerts: true 35 | } 36 | }, 37 | 38 | firefox: { 39 | desiredCapabilities: { 40 | browserName: 'firefox', 41 | javascriptEnabled: true, 42 | acceptSslCerts: true 43 | } 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /10-vue-testing/test/e2e/runner.js: -------------------------------------------------------------------------------- 1 | // 1. start the dev server using production config 2 | process.env.NODE_ENV = 'testing' 3 | var server = require('../../build/dev-server.js') 4 | 5 | // 2. run the nightwatch test suite against it 6 | // to run in additional browsers: 7 | // 1. add an entry in test/e2e/nightwatch.conf.json under "test_settings" 8 | // 2. add it to the --env flag below 9 | // or override the environment flag, for example: `npm run e2e -- --env chrome,firefox` 10 | // For more information on Nightwatch's config file, see 11 | // http://nightwatchjs.org/guide#settings-file 12 | var opts = process.argv.slice(2) 13 | if (opts.indexOf('--config') === -1) { 14 | opts = opts.concat(['--config', 'test/e2e/nightwatch.conf.js']) 15 | } 16 | if (opts.indexOf('--env') === -1) { 17 | opts = opts.concat(['--env', 'chrome']) 18 | } 19 | 20 | var spawn = require('cross-spawn') 21 | var runner = spawn('./node_modules/.bin/nightwatch', opts, { stdio: 'inherit' }) 22 | 23 | runner.on('exit', function (code) { 24 | server.close() 25 | process.exit(code) 26 | }) 27 | 28 | runner.on('error', function (err) { 29 | server.close() 30 | throw err 31 | }) 32 | -------------------------------------------------------------------------------- /10-vue-testing/test/e2e/specs/test.js: -------------------------------------------------------------------------------- 1 | // For authoring Nightwatch tests, see 2 | // http://nightwatchjs.org/guide#usage 3 | 4 | module.exports = { 5 | 'app should work': function (browser) { 6 | const devServer = browser.globals.devServerURL; 7 | 8 | browser 9 | .url(devServer) 10 | .waitForElementVisible('#app', 5000) 11 | .waitForElementVisible('p.loading', 5000) 12 | .waitForElementNotPresent('p.loading', 5000) 13 | .waitForElementVisible('#app .search-input', 5000) 14 | .waitForElementVisible('#app .search-button', 5000) 15 | .waitForElementVisible('#app li', 5000) 16 | .waitForElementVisible('#app li img', 5000) 17 | .setValue('#app .search-input', 'Star Wars') 18 | .click('#app .search-button') 19 | .waitForElementVisible('p.loading', 5000) 20 | .waitForElementNotPresent('p.loading', 10000) 21 | .assert.containsText('#app', 'star') 22 | .end() 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /10-vue-testing/test/unit/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "mocha": true 4 | }, 5 | "globals": { 6 | "expect": true, 7 | "sinon": true 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /10-vue-testing/test/unit/index.js: -------------------------------------------------------------------------------- 1 | // Polyfill fn.bind() for PhantomJS 2 | /* eslint-disable no-extend-native */ 3 | Function.prototype.bind = require('function-bind') 4 | 5 | // require all test files (files that ends with .spec.js) 6 | const testsContext = require.context('./specs', true, /\.spec$/) 7 | testsContext.keys().forEach(testsContext) 8 | 9 | // require all src files except main.js for coverage. 10 | // you can also change this to match only the subset of files that 11 | // you want coverage for. 12 | const srcContext = require.context('src', true, /^\.\/(?!main(\.js)?$)/) 13 | srcContext.keys().forEach(srcContext) 14 | -------------------------------------------------------------------------------- /10-vue-testing/test/unit/karma.conf.js: -------------------------------------------------------------------------------- 1 | // This is a karma config file. For more details see 2 | // http://karma-runner.github.io/0.13/config/configuration-file.html 3 | // we are also using it with karma-webpack 4 | // https://github.com/webpack/karma-webpack 5 | 6 | var path = require('path') 7 | var merge = require('webpack-merge') 8 | var baseConfig = require('../../build/webpack.base.conf') 9 | var utils = require('../../build/utils') 10 | var webpack = require('webpack') 11 | var projectRoot = path.resolve(__dirname, '../../') 12 | 13 | var webpackConfig = merge(baseConfig, { 14 | // use inline sourcemap for karma-sourcemap-loader 15 | module: { 16 | loaders: utils.styleLoaders() 17 | }, 18 | devtool: '#inline-source-map', 19 | vue: { 20 | loaders: { 21 | js: 'babel-loader' 22 | } 23 | }, 24 | plugins: [ 25 | new webpack.DefinePlugin({ 26 | 'process.env': require('../../config/test.env') 27 | }) 28 | ] 29 | }) 30 | 31 | // no need for app entry during tests 32 | delete webpackConfig.entry 33 | 34 | // Use babel for test files too 35 | webpackConfig.module.loaders.some(function (loader, i) { 36 | if (/^babel(-loader)?$/.test(loader.loader)) { 37 | loader.include.push(path.resolve(projectRoot, 'test/unit')) 38 | return true 39 | } 40 | }) 41 | 42 | module.exports = function (config) { 43 | config.set({ 44 | // to run in additional browsers: 45 | // 1. install corresponding karma launcher 46 | // http://karma-runner.github.io/0.13/config/browsers.html 47 | // 2. add it to the `browsers` array below. 48 | browsers: ['PhantomJS'], 49 | frameworks: ['mocha', 'sinon-chai'], 50 | reporters: ['spec', 'coverage'], 51 | files: ['./index.js'], 52 | preprocessors: { 53 | './index.js': ['webpack', 'sourcemap'] 54 | }, 55 | webpack: webpackConfig, 56 | webpackMiddleware: { 57 | noInfo: true 58 | }, 59 | coverageReporter: { 60 | dir: './coverage', 61 | reporters: [ 62 | { type: 'lcov', subdir: '.' }, 63 | { type: 'text-summary' } 64 | ] 65 | } 66 | }) 67 | } 68 | -------------------------------------------------------------------------------- /10-vue-testing/test/unit/specs/Preview.spec.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Preview from 'src/components/Preview' 3 | 4 | describe('Preview.vue', () => { 5 | 6 | it('should list gifs', () => { 7 | 8 | const container = document.createElement('div'); 9 | const PreviewComponent = Vue.extend(Preview); 10 | const vm = new PreviewComponent({ 11 | propsData: { 12 | gifs: [ 13 | { images: { fixed_height: { url: 'foo.gif' } } }, 14 | { images: { fixed_height: { url: 'bar.gif' } } } 15 | ] 16 | } 17 | }); 18 | 19 | vm.$mount(container); 20 | 21 | expect(vm.gifs.length).to.equal(2); 22 | expect(vm.$el.querySelectorAll('li').length).to.equal(2); 23 | expect(vm.$el.querySelector('li').firstChild.tagName).to.equal('IMG'); 24 | expect(vm.$el.querySelector('li').firstChild.src).to.contain('foo.gif'); 25 | 26 | }) 27 | 28 | }) 29 | -------------------------------------------------------------------------------- /10-vue-testing/test/unit/specs/Search.spec.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Search from 'src/components/Search' 3 | 4 | describe('Search.vue', () => { 5 | 6 | let vm = null; 7 | 8 | beforeEach(() => { 9 | const container = document.createElement('div'); 10 | const SearchComponent = Vue.extend(Search); 11 | vm = new SearchComponent(); 12 | 13 | vm.$mount(container); 14 | }); 15 | 16 | it('should be instantiated', () => { 17 | expect(vm.query).to.equal(''); 18 | expect(vm.$el.firstChild.tagName).to.equal('INPUT'); 19 | expect(vm.$el.lastChild.tagName).to.equal('BUTTON'); 20 | }); 21 | 22 | it('should emit event when button is clicked', () => { 23 | const spy = sinon.spy(vm, '$emit'); 24 | vm.$el.lastChild.click(); 25 | 26 | expect(spy.called).to.be.true; 27 | 28 | const [ eventName, query ] = spy.args[0]; 29 | expect(eventName).to.equal('SearchRequested'); 30 | expect(query).to.equal(''); 31 | }); 32 | 33 | it('should update query when input value changed', () => { 34 | const input = vm.$el.firstChild; 35 | input.value = 'Hello'; 36 | input.dispatchEvent(new Event('input')); 37 | expect(vm.query).to.equal('Hello'); 38 | }); 39 | 40 | }); 41 | -------------------------------------------------------------------------------- /11-vue-form/server/README.md: -------------------------------------------------------------------------------- 1 | # Swagger generated server 2 | 3 | ## Overview 4 | This server was generated by the [swagger-codegen](https://github.com/swagger-api/swagger-codegen) project. By using the [OpenAPI-Spec](https://github.com/OAI/OpenAPI-Specification) from a remote server, you can easily generate a server stub. 5 | 6 | ### Running the server 7 | To run the server, run: 8 | 9 | ``` 10 | npm start 11 | ``` 12 | 13 | To view the Swagger UI interface: 14 | 15 | ``` 16 | open http://localhost:8090/docs 17 | ``` 18 | 19 | This project leverages the mega-awesome [swagger-tools](https://github.com/apigee-127/swagger-tools) middleware which does most all the work. 20 | -------------------------------------------------------------------------------- /11-vue-form/server/api/swagger.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | swagger: "2.0" 3 | info: 4 | description: "#### A simple API for a VueJS demo app\n" 5 | version: "1.0.0" 6 | title: "VueJS Demo API" 7 | host: "localhost:8090" 8 | basePath: "/" 9 | schemes: 10 | - "http" 11 | paths: 12 | /labels: 13 | get: 14 | operationId: "labelsGet" 15 | parameters: [] 16 | responses: 17 | 200: 18 | description: "Return all labels" 19 | x-swagger-router-controller: "Default" 20 | /labels/add: 21 | post: 22 | operationId: "labelsAdd" 23 | parameters: 24 | - name: "title" 25 | in: "formData" 26 | required: true 27 | type: "string" 28 | - name: "description" 29 | in: "formData" 30 | required: false 31 | type: "string" 32 | - name: "color" 33 | in: "formData" 34 | required: true 35 | type: "string" 36 | responses: 37 | 200: 38 | description: "Return created label" 39 | x-swagger-router-controller: "Default" 40 | /labels/remove/{id}: 41 | delete: 42 | operationId: "labelsRemove" 43 | parameters: 44 | - name: "id" 45 | in: "path" 46 | required: true 47 | type: "string" 48 | responses: 49 | 200: 50 | description: "Remove a label" 51 | x-swagger-router-controller: "Default" 52 | definitions: {} 53 | -------------------------------------------------------------------------------- /11-vue-form/server/controllers/Default.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var url = require('url'); 4 | 5 | var Default = require('./DefaultService'); 6 | 7 | module.exports.labelsAdd = function labelsAdd (req, res, next) { 8 | Default.labelsAdd(req.swagger.params, res, next); 9 | }; 10 | 11 | module.exports.labelsGet = function labelsGet (req, res, next) { 12 | Default.labelsGet(req.swagger.params, res, next); 13 | }; 14 | 15 | module.exports.labelsRemove = function labelsRemove (req, res, next) { 16 | Default.labelsRemove(req.swagger.params, res, next); 17 | }; 18 | -------------------------------------------------------------------------------- /11-vue-form/server/controllers/DefaultService.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | let labelId = 1; 4 | let labels = []; 5 | 6 | 7 | exports.labelsGet = function(args, res, next) { 8 | /** 9 | * 10 | * no response value expected for this operation 11 | **/ 12 | res.end(JSON.stringify(labels)); 13 | } 14 | 15 | 16 | exports.labelsAdd = function(args, res, next) { 17 | /** 18 | * 19 | * title String 20 | * color String 21 | * description String (optional) 22 | * no response value expected for this operation 23 | **/ 24 | const { title, description, color } = args; 25 | const label = { 26 | id: labelId++, 27 | title: title.value, 28 | description: description.value || '', 29 | color: color.value 30 | }; 31 | 32 | labels.push(label); 33 | 34 | res.end(JSON.stringify(label)); 35 | } 36 | 37 | 38 | exports.labelsRemove = function(args, res, next) { 39 | /** 40 | * 41 | * id String 42 | * no response value expected for this operation 43 | **/ 44 | let id = args.id.value; 45 | 46 | labels = labels.filter((label) => { 47 | return label.id != parseInt(id, 10); 48 | }); 49 | 50 | res.end(JSON.stringify({ result: true })); 51 | } 52 | -------------------------------------------------------------------------------- /11-vue-form/server/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var app = require('connect')(); 4 | var http = require('http'); 5 | var swaggerTools = require('swagger-tools'); 6 | var jsyaml = require('js-yaml'); 7 | var fs = require('fs'); 8 | var serverPort = 8090; 9 | 10 | // swaggerRouter configuration 11 | var options = { 12 | swaggerUi: '/swagger.json', 13 | controllers: './controllers', 14 | useStubs: process.env.NODE_ENV === 'development' ? true : false // Conditionally turn on stubs (mock mode) 15 | }; 16 | 17 | // The Swagger document (require it, build it programmatically, fetch it from a URL, ...) 18 | var spec = fs.readFileSync('./api/swagger.yaml', 'utf8'); 19 | var swaggerDoc = jsyaml.safeLoad(spec); 20 | 21 | // Initialize the Swagger middleware 22 | swaggerTools.initializeMiddleware(swaggerDoc, function (middleware) { 23 | // Interpret Swagger resources and attach metadata to request - must be first in swagger-tools middleware chain 24 | app.use(middleware.swaggerMetadata()); 25 | 26 | // Validate Swagger requests 27 | app.use(middleware.swaggerValidator()); 28 | 29 | // Route validated requests to appropriate controller 30 | app.use(middleware.swaggerRouter(options)); 31 | 32 | // Serve the Swagger documents and Swagger UI 33 | app.use(middleware.swaggerUi()); 34 | 35 | // Start the server 36 | http.createServer(app).listen(serverPort, function () { 37 | console.log('Your server is listening on port %d (http://localhost:%d)', serverPort, serverPort); 38 | console.log('Swagger-ui is available on http://localhost:%d/docs', serverPort); 39 | }); 40 | }); 41 | -------------------------------------------------------------------------------- /11-vue-form/server/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-js-demo-api", 3 | "version": "1.0.0", 4 | "description": "#### A simple API for a VueJS demo app ", 5 | "main": "index.js", 6 | "scripts": { 7 | "prestart": "npm install", 8 | "start": "node index.js" 9 | }, 10 | "keywords": [ 11 | "swagger" 12 | ], 13 | "license": "Unlicense", 14 | "private": true, 15 | "dependencies": { 16 | "connect": "^3.2.0", 17 | "js-yaml": "^3.3.0", 18 | "swagger-tools": "0.10.1" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /12-vue-spa/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | ["latest", { 4 | "es2015": { "modules": false } 5 | }] 6 | ], 7 | "plugins": ["transform-object-rest-spread"] 8 | } 9 | -------------------------------------------------------------------------------- /12-vue-spa/.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | image: node:latest 2 | 3 | cache: 4 | paths: 5 | - node_modules/ 6 | 7 | before_script: 8 | - apt-get update -qq && apt-get install -y -qq sshpass 9 | 10 | deploy: 11 | only: 12 | - master 13 | script: 14 | - rm ./package-lock.json 15 | - npm install 16 | - npm run build 17 | - rm -rf .git 18 | - rm -rf node_modules 19 | - sshpass -V 20 | - export SSHPASS=$PASSWD 21 | - sshpass -e scp -o stricthostkeychecking=no -r . root@178.128.240.68:/var/www/html 22 | -------------------------------------------------------------------------------- /12-vue-spa/200.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 12-vue-spa 6 | 7 | 8 | 9 |
10 | 11 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /12-vue-spa/CNAME: -------------------------------------------------------------------------------- 1 | vue-spa-demo.surge.sh 2 | -------------------------------------------------------------------------------- /12-vue-spa/README.md: -------------------------------------------------------------------------------- 1 | # 12-vue-spa 2 | 3 | > Vue JS Single Page Application demo for movie ticketing website 4 | 5 | ## Build Setup 6 | 7 | ``` bash 8 | # install dependencies 9 | npm install 10 | 11 | # serve with hot reload at localhost:8080 12 | npm run dev 13 | 14 | # build for production with minification 15 | npm run build 16 | ``` 17 | 18 | For detailed explanation on how things work, consult the [docs for vue-loader](http://vuejs.github.io/vue-loader). 19 | -------------------------------------------------------------------------------- /12-vue-spa/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 12-vue-spa 6 | 7 | 8 | 9 |
10 | 11 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /12-vue-spa/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "12-vue-spa", 3 | "description": "Vue JS Single Page Application demo for movie ticketing website", 4 | "version": "1.0.0", 5 | "author": "Fatih Acet ", 6 | "private": true, 7 | "scripts": { 8 | "dev": "cross-env NODE_ENV=development webpack-dev-server --open --hot", 9 | "build": "cross-env NODE_ENV=production webpack --progress --hide-modules" 10 | }, 11 | "dependencies": { 12 | "vue": "^2.2.1", 13 | "vue-router": "^2.5.2", 14 | "vuex": "^2.3.1" 15 | }, 16 | "devDependencies": { 17 | "babel-core": "^6.0.0", 18 | "babel-loader": "^6.0.0", 19 | "babel-plugin-transform-object-rest-spread": "^6.23.0", 20 | "babel-preset-latest": "^6.0.0", 21 | "cross-env": "^3.0.0", 22 | "css-loader": "^0.25.0", 23 | "file-loader": "^0.9.0", 24 | "vue-loader": "^11.1.4", 25 | "vue-template-compiler": "^2.2.1", 26 | "webpack": "^2.2.0", 27 | "webpack-dev-server": "^2.2.0" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /12-vue-spa/src/App.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 15 | 16 | 23 | -------------------------------------------------------------------------------- /12-vue-spa/src/assets/halls.json: -------------------------------------------------------------------------------- 1 | { 2 | "H1": { 3 | "name": "Salon 1", 4 | "seating": { 5 | "A": [ "", "", "", "", "", 1, 2, 3, 4, 5, 6, "", "", "", "" ], 6 | "B": [ "", "", "", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, "", "" ], 7 | "C": [ "", "", "", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, "", "" ], 8 | "D": [ "", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, "" ], 9 | "E": [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ], 10 | "F": [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ], 11 | "G": [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ], 12 | "I": [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ], 13 | "J": [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ], 14 | "K": [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ], 15 | "L": [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ], 16 | "M": [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ] 17 | } 18 | }, 19 | "H2": { 20 | "name": "Salon 2", 21 | "seating": { 22 | "A": [ "", "", "", "", "", 1, 2, 3, 4, 5, 6, "", "", "", "" ], 23 | "B": [ "", "", "", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, "", "" ], 24 | "C": [ "", "", "", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, "", "" ], 25 | "D": [ "", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, "" ], 26 | "E": [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ], 27 | "F": [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ], 28 | "G": [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ], 29 | "I": [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ], 30 | "J": [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ], 31 | "K": [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ], 32 | "L": [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ], 33 | "M": [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ] 34 | } 35 | }, 36 | "H3": { 37 | "name": "Salon 3", 38 | "seating": { 39 | "A": [ "", "", "", "", "", 1, 2, 3, 4, 5, 6, "", "", "", "" ], 40 | "B": [ "", "", "", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, "", "" ], 41 | "C": [ "", "", "", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, "", "" ], 42 | "D": [ "", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, "" ], 43 | "E": [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ], 44 | "F": [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ], 45 | "G": [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ], 46 | "I": [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ], 47 | "J": [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ], 48 | "K": [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ], 49 | "L": [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ], 50 | "M": [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ] 51 | } 52 | }, 53 | "H4": { 54 | "name": "Salon 4", 55 | "seating": { 56 | "A": [ "", "", "", "", "", 1, 2, 3, 4, 5, 6, "", "", "", "" ], 57 | "B": [ "", "", "", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, "", "" ], 58 | "C": [ "", "", "", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, "", "" ], 59 | "D": [ "", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, "" ], 60 | "E": [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ], 61 | "F": [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ], 62 | "G": [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ], 63 | "I": [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ], 64 | "J": [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ], 65 | "K": [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ], 66 | "L": [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ], 67 | "M": [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ] 68 | } 69 | }, 70 | "H5": { 71 | "name": "Salon 5", 72 | "seating": { 73 | "A": [ "", "", "", "", "", 1, 2, 3, 4, 5, 6, "", "", "", "" ], 74 | "B": [ "", "", "", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, "", "" ], 75 | "C": [ "", "", "", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, "", "" ], 76 | "D": [ "", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, "" ], 77 | "E": [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ], 78 | "F": [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ], 79 | "G": [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ], 80 | "I": [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ], 81 | "J": [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ], 82 | "K": [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ], 83 | "L": [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ], 84 | "M": [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ] 85 | } 86 | }, 87 | "H6": { 88 | "name": "Salon 6", 89 | "seating": { 90 | "A": [ "", "", "", "", "", 1, 2, 3, 4, 5, 6, "", "", "", "" ], 91 | "B": [ "", "", "", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, "", "" ], 92 | "C": [ "", "", "", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, "", "" ], 93 | "D": [ "", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, "" ], 94 | "E": [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ], 95 | "F": [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ], 96 | "G": [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ], 97 | "I": [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ], 98 | "J": [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ], 99 | "K": [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ], 100 | "L": [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ], 101 | "M": [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ] 102 | } 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /12-vue-spa/src/assets/movieDetails.json: -------------------------------------------------------------------------------- 1 | { 2 | "337339": { 3 | "adult": false, 4 | "backdrop_path": "/jzdnhRhG0dsuYorwvSqPqqnM1cV.jpg", 5 | "belongs_to_collection": { 6 | "id": 9485, 7 | "name": "The Fast and the Furious Collection", 8 | "poster_path": "/mCkqJf4ijbNoBWvJ0RTWZJuhJUA.jpg", 9 | "backdrop_path": "/z5A5W3WYJc3UVEWljSGwdjDgQ0j.jpg" 10 | }, 11 | "budget": 250000000, 12 | "genres": [ 13 | { 14 | "id": 28, 15 | "name": "Action" 16 | }, 17 | { 18 | "id": 80, 19 | "name": "Crime" 20 | }, 21 | { 22 | "id": 53, 23 | "name": "Thriller" 24 | } 25 | ], 26 | "homepage": "http://www.fastandfurious.com/", 27 | "id": 337339, 28 | "imdb_id": "tt4630562", 29 | "original_language": "en", 30 | "original_title": "The Fate of the Furious", 31 | "overview": "When a mysterious woman seduces Dom into the world of crime and a betrayal of those closest to him, the crew face trials that will test them as never before.", 32 | "popularity": 75.8251, 33 | "poster_path": "/iNpz2DgTsTMPaDRZq2tnbqjL2vF.jpg", 34 | "production_companies": [ 35 | { 36 | "name": "Universal Pictures", 37 | "id": 33 38 | }, 39 | { 40 | "name": "Original Film", 41 | "id": 333 42 | }, 43 | { 44 | "name": "One Race Films", 45 | "id": 7154 46 | } 47 | ], 48 | "production_countries": [ 49 | { 50 | "iso_3166_1": "US", 51 | "name": "United States of America" 52 | } 53 | ], 54 | "release_date": "2017-04-12", 55 | "revenue": 0, 56 | "runtime": 136, 57 | "spoken_languages": [ 58 | { 59 | "iso_639_1": "en", 60 | "name": "English" 61 | } 62 | ], 63 | "status": "Released", 64 | "tagline": "Family no more", 65 | "title": "The Fate of the Furious", 66 | "video": false, 67 | "vote_average": 6.9, 68 | "vote_count": 1114, 69 | "videos": { 70 | "results": [ 71 | { 72 | "id": "58f33203c3a368086700ede3", 73 | "iso_639_1": "en", 74 | "iso_3166_1": "US", 75 | "key": "vve9TtFg9wM", 76 | "name": "Official Trailer Tease", 77 | "site": "YouTube", 78 | "size": 1080, 79 | "type": "Teaser" 80 | }, 81 | { 82 | "id": "58f33221c3a368086700edf5", 83 | "iso_639_1": "en", 84 | "iso_3166_1": "US", 85 | "key": "JwMKRevYa_M", 86 | "name": "Official Trailer", 87 | "site": "YouTube", 88 | "size": 1080, 89 | "type": "Trailer" 90 | }, 91 | { 92 | "id": "58f3323e9251413d9500e7c7", 93 | "iso_639_1": "en", 94 | "iso_3166_1": "US", 95 | "key": "-9FU7Ia-BKg", 96 | "name": "Big Game Spot (Super Bowl)", 97 | "site": "YouTube", 98 | "size": 1080, 99 | "type": "Teaser" 100 | }, 101 | { 102 | "id": "58f332559251413d8400e760", 103 | "iso_639_1": "en", 104 | "iso_3166_1": "US", 105 | "key": "jeKBMdYaM3U", 106 | "name": "Official Trailer 2", 107 | "site": "YouTube", 108 | "size": 1080, 109 | "type": "Trailer" 110 | } 111 | ] 112 | }, 113 | "cast": [ 114 | { 115 | "cast_id": 0, 116 | "character": "Dominic Toretto", 117 | "credit_id": "553bb629c3a368784500aacb", 118 | "id": 12835, 119 | "name": "Vin Diesel", 120 | "order": 0, 121 | "profile_path": "/3RdYMTLoL1X16djGF52cFtJovDT.jpg" 122 | }, 123 | { 124 | "cast_id": 25, 125 | "character": "Letty Ortiz", 126 | "credit_id": "57a2a7a4c3a36832b80025c6", 127 | "id": 17647, 128 | "name": "Michelle Rodriguez", 129 | "order": 1, 130 | "profile_path": "/v37VK0MNuRuJOCKPKJcZAJXRA5r.jpg" 131 | }, 132 | { 133 | "cast_id": 1, 134 | "character": "Luke Hobbs", 135 | "credit_id": "553bb63fc3a368746200017c", 136 | "id": 18918, 137 | "name": "Dwayne Johnson", 138 | "order": 2, 139 | "profile_path": "/akweMz59qsSoPUJYe7QpjAc2rQp.jpg" 140 | }, 141 | { 142 | "cast_id": 12, 143 | "character": "Deckard Shaw", 144 | "credit_id": "5595cbda9251414e06000173", 145 | "id": 976, 146 | "name": "Jason Statham", 147 | "order": 3, 148 | "profile_path": "/PhWiWgasncGWD9LdbsGcmxkV4r.jpg" 149 | }, 150 | { 151 | "cast_id": 15, 152 | "character": "Cipher", 153 | "credit_id": "573fcbd3c3a36807400004f2", 154 | "id": 6885, 155 | "name": "Charlize Theron", 156 | "order": 4, 157 | "profile_path": "/4PLynhfkAa0WFUXd3frSpKtaG1V.jpg" 158 | }, 159 | { 160 | "cast_id": 21, 161 | "character": "Frank Petty / Mr. Nobody", 162 | "credit_id": "57a2a780c3a3686c1a00186d", 163 | "id": 6856, 164 | "name": "Kurt Russell", 165 | "order": 5, 166 | "profile_path": "/rlnFuNkisPpuypARI7QaGCmOY6V.jpg" 167 | } 168 | ] 169 | }, 170 | "315837": { 171 | "adult": false, 172 | "backdrop_path": "/lsRhmB7m36pEX0UHpkpJSE48BW5.jpg", 173 | "belongs_to_collection": null, 174 | "budget": 110000000, 175 | "genres": [ 176 | { 177 | "id": 28, 178 | "name": "Action" 179 | }, 180 | { 181 | "id": 18, 182 | "name": "Drama" 183 | }, 184 | { 185 | "id": 878, 186 | "name": "Science Fiction" 187 | } 188 | ], 189 | "homepage": "http://www.ghostintheshellmovie.com/", 190 | "id": 315837, 191 | "imdb_id": "tt1219827", 192 | "original_language": "en", 193 | "original_title": "Ghost in the Shell", 194 | "overview": "In the near future, Major is the first of her kind: a human saved from a terrible crash, who is cyber-enhanced to be a perfect soldier devoted to stopping the world's most dangerous criminals.", 195 | "popularity": 38.31906, 196 | "poster_path": "/myRzRzCxdfUWjkJWgpHHZ1oGkJd.jpg", 197 | "production_companies": [ 198 | { 199 | "name": "Paramount Pictures", 200 | "id": 4 201 | }, 202 | { 203 | "name": "DreamWorks SKG", 204 | "id": 27 205 | }, 206 | { 207 | "name": "Shanghai Film Group", 208 | "id": 3407 209 | }, 210 | { 211 | "name": "Reliance Entertainment", 212 | "id": 7294 213 | }, 214 | { 215 | "name": "Arad Productions", 216 | "id": 14439 217 | }, 218 | { 219 | "name": "Grosvenor Park Productions", 220 | "id": 17449 221 | }, 222 | { 223 | "name": "Steven Paul Production", 224 | "id": 44311 225 | }, 226 | { 227 | "name": "Huahua Media", 228 | "id": 83645 229 | }, 230 | { 231 | "name": "Seaside Entertainment", 232 | "id": 88981 233 | } 234 | ], 235 | "production_countries": [ 236 | { 237 | "iso_3166_1": "NZ", 238 | "name": "New Zealand" 239 | }, 240 | { 241 | "iso_3166_1": "US", 242 | "name": "United States of America" 243 | }, 244 | { 245 | "iso_3166_1": "GB", 246 | "name": "United Kingdom" 247 | }, 248 | { 249 | "iso_3166_1": "IN", 250 | "name": "India" 251 | }, 252 | { 253 | "iso_3166_1": "CN", 254 | "name": "China" 255 | }, 256 | { 257 | "iso_3166_1": "CA", 258 | "name": "Canada" 259 | } 260 | ], 261 | "release_date": "2017-03-29", 262 | "revenue": 163631454, 263 | "runtime": 106, 264 | "spoken_languages": [ 265 | { 266 | "iso_639_1": "ja", 267 | "name": "日本語" 268 | }, 269 | { 270 | "iso_639_1": "en", 271 | "name": "English" 272 | } 273 | ], 274 | "status": "Released", 275 | "tagline": "", 276 | "title": "Ghost in the Shell", 277 | "video": false, 278 | "vote_average": 6.0, 279 | "vote_count": 777, 280 | "videos": { 281 | "results": [ 282 | { 283 | "id": "58af6e06c3a3682d1000164c", 284 | "iso_639_1": "en", 285 | "iso_3166_1": "US", 286 | "key": "xTPvnQ2wDlI", 287 | "name": "Official Trailer #1", 288 | "site": "YouTube", 289 | "size": 1080, 290 | "type": "Trailer" 291 | }, 292 | { 293 | "id": "58af6eac9251411a71001717", 294 | "iso_639_1": "en", 295 | "iso_3166_1": "US", 296 | "key": "5XnptKCeaJE", 297 | "name": "Official Trailer #2", 298 | "site": "YouTube", 299 | "size": 1080, 300 | "type": "Trailer" 301 | }, 302 | { 303 | "id": "58af6f4b9251411a640017ad", 304 | "iso_639_1": "en", 305 | "iso_3166_1": "US", 306 | "key": "E9Tlz8DKyNM", 307 | "name": "Featurette: \"Mamoru Oshii\"", 308 | "site": "YouTube", 309 | "size": 1080, 310 | "type": "Featurette" 311 | }, 312 | { 313 | "id": "58375b9ec3a36836a9017e13", 314 | "iso_639_1": "en", 315 | "iso_3166_1": "US", 316 | "key": "q7Tm73m0VZs", 317 | "name": "Ghost In The Shell (2017) - #2", 318 | "site": "YouTube", 319 | "size": 1080, 320 | "type": "Teaser" 321 | }, 322 | { 323 | "id": "58375bb5c3a36836a30171c3", 324 | "iso_639_1": "en", 325 | "iso_3166_1": "US", 326 | "key": "_6NJJ6pMKVY", 327 | "name": "Ghost In The Shell (2017) - #3", 328 | "site": "YouTube", 329 | "size": 1080, 330 | "type": "Teaser" 331 | }, 332 | { 333 | "id": "58375be8925141318f0183ac", 334 | "iso_639_1": "en", 335 | "iso_3166_1": "US", 336 | "key": "xziBGsIaWh8", 337 | "name": "Ghost In The Shell (2017) - #4", 338 | "site": "YouTube", 339 | "size": 1080, 340 | "type": "Teaser" 341 | }, 342 | { 343 | "id": "58375bff925141318f0183bc", 344 | "iso_639_1": "en", 345 | "iso_3166_1": "US", 346 | "key": "vWDBpTB6T0Q", 347 | "name": "Ghost In The Shell (2017) - #5", 348 | "site": "YouTube", 349 | "size": 1080, 350 | "type": "Teaser" 351 | }, 352 | { 353 | "id": "58375c3fc3a36836a301722c", 354 | "iso_639_1": "en", 355 | "iso_3166_1": "US", 356 | "key": "5uR2BA3MFQE", 357 | "name": "Ghost In The Shell (2017) - Tokyo", 358 | "site": "YouTube", 359 | "size": 1080, 360 | "type": "Teaser" 361 | }, 362 | { 363 | "id": "58375b74c3a36836a9017dea", 364 | "iso_639_1": "en", 365 | "iso_3166_1": "US", 366 | "key": "HapT0SKcyfY", 367 | "name": "Ghost In The Shell (2017) - #1", 368 | "site": "YouTube", 369 | "size": 1080, 370 | "type": "Teaser" 371 | } 372 | ] 373 | }, 374 | "cast": [ 375 | { 376 | "cast_id": 0, 377 | "character": "Major", 378 | "credit_id": "54db4267c3a3681237001701", 379 | "id": 1245, 380 | "name": "Scarlett Johansson", 381 | "order": 0, 382 | "profile_path": "/yDYpYy09nfyXIWHC6mbsaRdLiDV.jpg" 383 | }, 384 | { 385 | "cast_id": 2, 386 | "character": "Batou", 387 | "credit_id": "56c331059251414a0e001a04", 388 | "id": 90060, 389 | "name": "Pilou Asbæk", 390 | "order": 1, 391 | "profile_path": "/wcQRF5ZOBY8NX7xrjXE2pOBmwyZ.jpg" 392 | }, 393 | { 394 | "cast_id": 4, 395 | "character": "Daisuke Aramaki", 396 | "credit_id": "56da2456c3a3680c8900016d", 397 | "id": 3317, 398 | "name": "Takeshi Kitano", 399 | "order": 2, 400 | "profile_path": "/xkXZ7HC8uyhu5MtNnbdP8mhdiFN.jpg" 401 | }, 402 | { 403 | "cast_id": 6, 404 | "character": "Dr. Ouélet", 405 | "credit_id": "57bec5809251414e360007f7", 406 | "id": 1137, 407 | "name": "Juliette Binoche", 408 | "order": 3, 409 | "profile_path": "/rkW6eE75Tt1i3J1s2fsIDZBW0kd.jpg" 410 | }, 411 | { 412 | "cast_id": 3, 413 | "character": "Hideo Kuze", 414 | "credit_id": "56c331179251414a860027ce", 415 | "id": 10692, 416 | "name": "Michael Pitt", 417 | "order": 4, 418 | "profile_path": "/e0UbPlJX4zC205Dfvi7w4ubGR5.jpg" 419 | } 420 | ] 421 | }, 422 | "283995": { 423 | "adult": false, 424 | "backdrop_path": "/8sFWWIolWPm2FQLNt9cSKpNZJcz.jpg", 425 | "belongs_to_collection": { 426 | "id": 284433, 427 | "name": "Guardians of the Galaxy Collection", 428 | "poster_path": "/kFWLxUwcSpiLzszZbxUIZT9g6WR.jpg", 429 | "backdrop_path": "/b09vRh5oOda2REMlv9yiMxULRIt.jpg" 430 | }, 431 | "budget": 200000000, 432 | "genres": [ 433 | { 434 | "id": 28, 435 | "name": "Action" 436 | }, 437 | { 438 | "id": 12, 439 | "name": "Adventure" 440 | }, 441 | { 442 | "id": 878, 443 | "name": "Science Fiction" 444 | } 445 | ], 446 | "homepage": "http://marvel.com/movies/movie/221/guardians_of_the_galaxy_vol_2", 447 | "id": 283995, 448 | "imdb_id": "tt3896198", 449 | "original_language": "en", 450 | "original_title": "Guardians of the Galaxy Vol. 2", 451 | "overview": "The Guardians must fight to keep their newfound family together as they unravel the mysteries of Peter Quill's true parentage.", 452 | "popularity": 47.657091, 453 | "poster_path": "/gaHepzSTMkGwsSKAqiBgroSCf07.jpg", 454 | "production_companies": [ 455 | { 456 | "name": "Walt Disney Pictures", 457 | "id": 2 458 | }, 459 | { 460 | "name": "Marvel Studios", 461 | "id": 420 462 | } 463 | ], 464 | "production_countries": [ 465 | { 466 | "iso_3166_1": "US", 467 | "name": "United States of America" 468 | } 469 | ], 470 | "release_date": "2017-04-24", 471 | "revenue": 0, 472 | "runtime": 137, 473 | "spoken_languages": [ 474 | { 475 | "iso_639_1": "en", 476 | "name": "English" 477 | } 478 | ], 479 | "status": "Released", 480 | "tagline": "Obviously.", 481 | "title": "Guardians of the Galaxy Vol. 2", 482 | "video": false, 483 | "vote_average": 7.8, 484 | "vote_count": 260, 485 | "videos": { 486 | "results": [ 487 | { 488 | "id": "58ba57ac925141608401976f", 489 | "iso_639_1": "en", 490 | "iso_3166_1": "US", 491 | "key": "wUn05hdkhjM", 492 | "name": "Official Trailer 3", 493 | "site": "YouTube", 494 | "size": 1080, 495 | "type": "Trailer" 496 | }, 497 | { 498 | "id": "58f5e92492514127c700b0dc", 499 | "iso_639_1": "en", 500 | "iso_3166_1": "US", 501 | "key": "2WhQcK-Zaok", 502 | "name": "Official Sneak Peek", 503 | "site": "YouTube", 504 | "size": 1080, 505 | "type": "Teaser" 506 | }, 507 | { 508 | "id": "58ba57db925141607b01909d", 509 | "iso_639_1": "en", 510 | "iso_3166_1": "US", 511 | "key": "CaLNiC-bKHQ", 512 | "name": "Extended Big Game Spot", 513 | "site": "YouTube", 514 | "size": 1080, 515 | "type": "Teaser" 516 | }, 517 | { 518 | "id": "58ba5783c3a36866a50177e8", 519 | "iso_639_1": "en", 520 | "iso_3166_1": "US", 521 | "key": "dW1BIid8Osg", 522 | "name": "Official Teaser Trailer", 523 | "site": "YouTube", 524 | "size": 1080, 525 | "type": "Trailer" 526 | }, 527 | { 528 | "id": "58e5f74992514127e803fac8", 529 | "iso_639_1": "en", 530 | "iso_3166_1": "US", 531 | "key": "BSXAOywn_rE", 532 | "name": "Official \"One Month Only\" Teaser", 533 | "site": "YouTube", 534 | "size": 1080, 535 | "type": "Teaser" 536 | }, 537 | { 538 | "id": "58f5eb1f925141279500b7dc", 539 | "iso_639_1": "en", 540 | "iso_3166_1": "US", 541 | "key": "eX0KjDFvDAY", 542 | "name": "\"You're Welcome\" TV Spot", 543 | "site": "YouTube", 544 | "size": 1080, 545 | "type": "Teaser" 546 | }, 547 | { 548 | "id": "58f5eb5292514127b800b0dc", 549 | "iso_639_1": "en", 550 | "iso_3166_1": "US", 551 | "key": "MTrLaWIcdAs", 552 | "name": "\"The Hits Keep Coming\" TV Spot", 553 | "site": "YouTube", 554 | "size": 1080, 555 | "type": "Teaser" 556 | }, 557 | { 558 | "id": "58f5eb98925141277500b569", 559 | "iso_639_1": "en", 560 | "iso_3166_1": "US", 561 | "key": "0LWEYReXjQs", 562 | "name": "\"It's Showtime\" TV Spot", 563 | "site": "YouTube", 564 | "size": 1080, 565 | "type": "Teaser" 566 | } 567 | ] 568 | }, 569 | "cast": [ 570 | { 571 | "cast_id": 3, 572 | "character": "Peter Quill / Star-Lord", 573 | "credit_id": "53dd76ba0e0a265a930008e7", 574 | "id": 73457, 575 | "name": "Chris Pratt", 576 | "order": 0, 577 | "profile_path": "/hwzMHnBpfLutaOMVVMkIkLWHBYU.jpg" 578 | }, 579 | { 580 | "cast_id": 4, 581 | "character": "Gamora", 582 | "credit_id": "5526165c92514171b4001031", 583 | "id": 8691, 584 | "name": "Zoe Saldana", 585 | "order": 1, 586 | "profile_path": "/ofNrWiA2KDdqiNxFTLp51HcXUlp.jpg" 587 | }, 588 | { 589 | "cast_id": 5, 590 | "character": "Drax the Destroyer", 591 | "credit_id": "5526167ec3a36857ae0012fd", 592 | "id": 543530, 593 | "name": "Dave Bautista", 594 | "order": 2, 595 | "profile_path": "/mR7ZdtykA2MvT6ZCZtM4pjXW1gA.jpg" 596 | }, 597 | { 598 | "cast_id": 6, 599 | "character": "Rocket Raccoon (voice)", 600 | "credit_id": "55261691925141724800371e", 601 | "id": 51329, 602 | "name": "Bradley Cooper", 603 | "order": 3, 604 | "profile_path": "/2daC5DeXqwkFND0xxutbnSVKN6c.jpg" 605 | }, 606 | { 607 | "cast_id": 7, 608 | "character": "Baby Groot (voice)", 609 | "credit_id": "552616ab9251417248003723", 610 | "id": 12835, 611 | "name": "Vin Diesel", 612 | "order": 4, 613 | "profile_path": "/3RdYMTLoL1X16djGF52cFtJovDT.jpg" 614 | } 615 | ] 616 | }, 617 | "274870": { 618 | "adult": false, 619 | "backdrop_path": "/5EW4TR3fWEqpKsWysNcBMtz9Sgp.jpg", 620 | "belongs_to_collection": null, 621 | "budget": 110000000, 622 | "genres": [ 623 | { 624 | "id": 12, 625 | "name": "Adventure" 626 | }, 627 | { 628 | "id": 18, 629 | "name": "Drama" 630 | }, 631 | { 632 | "id": 10749, 633 | "name": "Romance" 634 | }, 635 | { 636 | "id": 878, 637 | "name": "Science Fiction" 638 | } 639 | ], 640 | "homepage": "http://www.passengersmovie.com/", 641 | "id": 274870, 642 | "imdb_id": "tt1355644", 643 | "original_language": "en", 644 | "original_title": "Passengers", 645 | "overview": "A spacecraft traveling to a distant colony planet and transporting thousands of people has a malfunction in its sleep chambers. As a result, two passengers are awakened 90 years early.", 646 | "popularity": 12.92414, 647 | "poster_path": "/5gJkVIVU7FDp7AfRAbPSvvdbre2.jpg", 648 | "production_companies": [ 649 | { 650 | "name": "Columbia Pictures", 651 | "id": 5 652 | }, 653 | { 654 | "name": "Village Roadshow Pictures", 655 | "id": 79 656 | }, 657 | { 658 | "name": "Original Film", 659 | "id": 333 660 | }, 661 | { 662 | "name": "Company Films", 663 | "id": 7193 664 | }, 665 | { 666 | "name": "Start Motion Pictures", 667 | "id": 19961 668 | }, 669 | { 670 | "name": "LStar Capital", 671 | "id": 34034 672 | }, 673 | { 674 | "name": "Wanda Pictures", 675 | "id": 83838 676 | } 677 | ], 678 | "production_countries": [ 679 | { 680 | "iso_3166_1": "US", 681 | "name": "United States of America" 682 | } 683 | ], 684 | "release_date": "2016-12-21", 685 | "revenue": 288903443, 686 | "runtime": 116, 687 | "spoken_languages": [ 688 | { 689 | "iso_639_1": "en", 690 | "name": "English" 691 | } 692 | ], 693 | "status": "Released", 694 | "tagline": "There is a reason they woke up.", 695 | "title": "Passengers", 696 | "video": false, 697 | "vote_average": 6.6, 698 | "vote_count": 2469, 699 | "videos": { 700 | "results": [ 701 | { 702 | "id": "58ba75fa925141607301c432", 703 | "iso_639_1": "en", 704 | "iso_3166_1": "US", 705 | "key": "8Up53jOaS-k", 706 | "name": "SOS", 707 | "site": "YouTube", 708 | "size": 1080, 709 | "type": "Teaser" 710 | }, 711 | { 712 | "id": "58ba7500c3a368666b019715", 713 | "iso_639_1": "en", 714 | "iso_3166_1": "US", 715 | "key": "IOVrvZ3aKt4", 716 | "name": "Gravity Loss Scene", 717 | "site": "YouTube", 718 | "size": 1080, 719 | "type": "Clip" 720 | }, 721 | { 722 | "id": "58ba7620c3a368663001a208", 723 | "iso_639_1": "en", 724 | "iso_3166_1": "US", 725 | "key": "hIdLVi5pXYM", 726 | "name": "Just the Beginning", 727 | "site": "YouTube", 728 | "size": 1080, 729 | "type": "Teaser" 730 | }, 731 | { 732 | "id": "58ba75db925141607301c40e", 733 | "iso_639_1": "en", 734 | "iso_3166_1": "US", 735 | "key": "PVhE3EO5krM", 736 | "name": "I Woke Up Too Soon", 737 | "site": "YouTube", 738 | "size": 1080, 739 | "type": "Clip" 740 | }, 741 | { 742 | "id": "58ba7572c3a36866af01a9a7", 743 | "iso_639_1": "en", 744 | "iso_3166_1": "US", 745 | "key": "GvoKXyVATS8", 746 | "name": "Time Out", 747 | "site": "YouTube", 748 | "size": 1080, 749 | "type": "Teaser" 750 | }, 751 | { 752 | "id": "58ba74eb925141609b01bd30", 753 | "iso_639_1": "en", 754 | "iso_3166_1": "US", 755 | "key": "LRqsCB-K784", 756 | "name": "Watch the First 10 Minutes Now!", 757 | "site": "YouTube", 758 | "size": 1080, 759 | "type": "Clip" 760 | }, 761 | { 762 | "id": "58ba7598c3a3686686019340", 763 | "iso_639_1": "en", 764 | "iso_3166_1": "US", 765 | "key": "3mSyz_uvuPw", 766 | "name": "Lock Down", 767 | "site": "YouTube", 768 | "size": 1080, 769 | "type": "Clip" 770 | }, 771 | { 772 | "id": "58f5324dc3a3680e9800339d", 773 | "iso_639_1": "en", 774 | "iso_3166_1": "US", 775 | "key": "sipflRaq2vg", 776 | "name": "Official \"Event\" Trailer", 777 | "site": "YouTube", 778 | "size": 1080, 779 | "type": "Trailer" 780 | }, 781 | { 782 | "id": "58ba74b5c3a3686630019fd3", 783 | "iso_639_1": "en", 784 | "iso_3166_1": "US", 785 | "key": "7BWWWQzTpNU", 786 | "name": "Official Trailer", 787 | "site": "YouTube", 788 | "size": 1080, 789 | "type": "Trailer" 790 | } 791 | ] 792 | }, 793 | "cast": [ 794 | { 795 | "cast_id": 2, 796 | "character": "Aurora Lane", 797 | "credit_id": "558089d4c3a3681645000046", 798 | "id": 72129, 799 | "name": "Jennifer Lawrence", 800 | "order": 0, 801 | "profile_path": "/tJnYgQkRg6Zizt4kE2yP1lfxt1F.jpg" 802 | }, 803 | { 804 | "cast_id": 119, 805 | "character": "Jim Preston", 806 | "credit_id": "5884ed46c3a368064d01f5eb", 807 | "id": 73457, 808 | "name": "Chris Pratt", 809 | "order": 1, 810 | "profile_path": "/hwzMHnBpfLutaOMVVMkIkLWHBYU.jpg" 811 | }, 812 | { 813 | "cast_id": 4, 814 | "character": "Arthur", 815 | "credit_id": "55cc436cc3a368055e00099f", 816 | "id": 3968, 817 | "name": "Michael Sheen", 818 | "order": 2, 819 | "profile_path": "/m05OsJdLlDC4pj2qYug0OevjUXu.jpg" 820 | }, 821 | { 822 | "cast_id": 7, 823 | "character": "Gus Mancuso", 824 | "credit_id": "57733d0992514153fb001d43", 825 | "id": 2975, 826 | "name": "Laurence Fishburne", 827 | "order": 3, 828 | "profile_path": "/mh0lZ1XsT84FayMNiT6Erh91mVu.jpg" 829 | }, 830 | { 831 | "cast_id": 94, 832 | "character": "Captain Norris", 833 | "credit_id": "585ced3ec3a3684090008694", 834 | "id": 1271, 835 | "name": "Andy García", 836 | "order": 4, 837 | "profile_path": "/zE3KYH6f6cxCehJJYKDTQa8sCaK.jpg" 838 | } 839 | ] 840 | }, 841 | "324552": { 842 | "adult": false, 843 | "backdrop_path": "/4TBLjAhQe1zJfR3zdHMWTrwbdLd.jpg", 844 | "belongs_to_collection": { 845 | "id": 404609, 846 | "name": "John Wick Collection", 847 | "poster_path": "/xUidyvYFsbbuExifLkslpcd8SMc.jpg", 848 | "backdrop_path": "/fSwYa5q2xRkBoOOjueLpkLf3N1m.jpg" 849 | }, 850 | "budget": 40000000, 851 | "genres": [ 852 | { 853 | "id": 53, 854 | "name": "Thriller" 855 | }, 856 | { 857 | "id": 28, 858 | "name": "Action" 859 | }, 860 | { 861 | "id": 80, 862 | "name": "Crime" 863 | } 864 | ], 865 | "homepage": "http://www.johnwick.movie/", 866 | "id": 324552, 867 | "imdb_id": "tt4425200", 868 | "original_language": "en", 869 | "original_title": "John Wick: Chapter 2", 870 | "overview": "John Wick is forced out of retirement by a former associate looking to seize control of a shadowy international assassins’ guild. Bound by a blood oath to aid him, Wick travels to Rome and does battle against some of the world’s most dangerous killers.", 871 | "popularity": 9.089423, 872 | "poster_path": "/1jvyy3UtMbWBHikj7byFJeY5Fc7.jpg", 873 | "production_companies": [ 874 | { 875 | "name": "Thunder Road Pictures", 876 | "id": 3528 877 | }, 878 | { 879 | "name": "LionsGate", 880 | "id": 7571 881 | }, 882 | { 883 | "name": "87Eleven", 884 | "id": 23008 885 | } 886 | ], 887 | "production_countries": [ 888 | { 889 | "iso_3166_1": "US", 890 | "name": "United States of America" 891 | } 892 | ], 893 | "release_date": "2017-02-08", 894 | "revenue": 161697595, 895 | "runtime": 122, 896 | "spoken_languages": [ 897 | { 898 | "iso_639_1": "en", 899 | "name": "English" 900 | }, 901 | { 902 | "iso_639_1": "it", 903 | "name": "Italiano" 904 | } 905 | ], 906 | "status": "Released", 907 | "tagline": "Never stab the devil in the back", 908 | "title": "John Wick: Chapter 2", 909 | "video": false, 910 | "vote_average": 6.5, 911 | "vote_count": 1158, 912 | "videos": { 913 | "results": [ 914 | { 915 | "id": "58cfcec29251415a61037950", 916 | "iso_639_1": "en", 917 | "iso_3166_1": "US", 918 | "key": "LZrX9mffH8Y", 919 | "name": "Official Trailer 2", 920 | "site": "YouTube", 921 | "size": 1080, 922 | "type": "Trailer" 923 | }, 924 | { 925 | "id": "58bded9b9251413407006629", 926 | "iso_639_1": "en", 927 | "iso_3166_1": "US", 928 | "key": "Wp3EE71PINI", 929 | "name": "Official Clip \"Car Chase\"", 930 | "site": "YouTube", 931 | "size": 1080, 932 | "type": "Clip" 933 | }, 934 | { 935 | "id": "58bdedb69251416084054f6a", 936 | "iso_639_1": "en", 937 | "iso_3166_1": "US", 938 | "key": "bQN5U7DbJdk", 939 | "name": "Official Pre-Game TV Spot \"Shade\"", 940 | "site": "YouTube", 941 | "size": 1080, 942 | "type": "Featurette" 943 | }, 944 | { 945 | "id": "58bdedcec3a36866a504f4cd", 946 | "iso_639_1": "en", 947 | "iso_3166_1": "US", 948 | "key": "Ib21sMpp8yo", 949 | "name": "Official Clip \"You Working\"", 950 | "site": "YouTube", 951 | "size": 1080, 952 | "type": "Clip" 953 | }, 954 | { 955 | "id": "58cfce9ec3a36811ce004deb", 956 | "iso_639_1": "en", 957 | "iso_3166_1": "US", 958 | "key": "y7pLCd7BgZA", 959 | "name": "Official Clip \"Suited Up\"", 960 | "site": "YouTube", 961 | "size": 1080, 962 | "type": "Clip" 963 | }, 964 | { 965 | "id": "58bded81925141126a03660d", 966 | "iso_639_1": "en", 967 | "iso_3166_1": "US", 968 | "key": "nMqETeQrgqU", 969 | "name": "Official Teaser Trailer \"Good To See You Again\"", 970 | "site": "YouTube", 971 | "size": 1080, 972 | "type": "Teaser" 973 | }, 974 | { 975 | "id": "58cfcef19251415a61037976", 976 | "iso_639_1": "en", 977 | "iso_3166_1": "US", 978 | "key": "ZABJ1bzrZvI", 979 | "name": "Official Training Featurette [UK]", 980 | "site": "YouTube", 981 | "size": 1080, 982 | "type": "Featurette" 983 | }, 984 | { 985 | "id": "58cfcf2bc3a36851040330d8", 986 | "iso_639_1": "en", 987 | "iso_3166_1": "US", 988 | "key": "Sx1Qm3gavRg", 989 | "name": "Official Teaser Trailer", 990 | "site": "YouTube", 991 | "size": 1080, 992 | "type": "Trailer" 993 | } 994 | ] 995 | }, 996 | "cast": [ 997 | { 998 | "cast_id": 0, 999 | "character": "John Wick", 1000 | "credit_id": "558cfff0c3a3687e65008ee6", 1001 | "id": 6384, 1002 | "name": "Keanu Reeves", 1003 | "order": 0, 1004 | "profile_path": "/id1qIb7cZs2eQno90KsKwG8VLGN.jpg" 1005 | }, 1006 | { 1007 | "cast_id": 9, 1008 | "character": "Cassian", 1009 | "credit_id": "56cf3bd4c3a3681e3c0034e3", 1010 | "id": 4238, 1011 | "name": "Common", 1012 | "order": 1, 1013 | "profile_path": "/xymkPDXqRKpmTvpGI2vzRm7fj9Q.jpg" 1014 | }, 1015 | { 1016 | "cast_id": 7, 1017 | "character": "The Bowler King", 1018 | "credit_id": "56cf3bbac3a3681e50002929", 1019 | "id": 2975, 1020 | "name": "Laurence Fishburne", 1021 | "order": 2, 1022 | "profile_path": "/mh0lZ1XsT84FayMNiT6Erh91mVu.jpg" 1023 | }, 1024 | { 1025 | "cast_id": 14, 1026 | "character": "Santino D'Antonio", 1027 | "credit_id": "56cf3c03c3a3681e3c0034f2", 1028 | "id": 59270, 1029 | "name": "Riccardo Scamarcio", 1030 | "order": 3, 1031 | "profile_path": "/zpphrSmdn2TR0F0kbVG5CAGqfxv.jpg" 1032 | }, 1033 | { 1034 | "cast_id": 4, 1035 | "character": "Ares", 1036 | "credit_id": "56cf3b959251413e5f002d6d", 1037 | "id": 1246972, 1038 | "name": "Ruby Rose", 1039 | "order": 4, 1040 | "profile_path": "/dLn9hK3qlmpLIDTAz0cCgAjYMsv.jpg" 1041 | } 1042 | ] 1043 | }, 1044 | "293167": { 1045 | "adult": false, 1046 | "backdrop_path": "/pGwChWiAY1bdoxL79sXmaFBlYJH.jpg", 1047 | "belongs_to_collection": null, 1048 | "budget": 190000000, 1049 | "genres": [ 1050 | { 1051 | "id": 28, 1052 | "name": "Action" 1053 | }, 1054 | { 1055 | "id": 12, 1056 | "name": "Adventure" 1057 | }, 1058 | { 1059 | "id": 14, 1060 | "name": "Fantasy" 1061 | } 1062 | ], 1063 | "homepage": "http://kongskullislandmovie.com/", 1064 | "id": 293167, 1065 | "imdb_id": "tt3731562", 1066 | "original_language": "en", 1067 | "original_title": "Kong: Skull Island", 1068 | "overview": "Explore the mysterious and dangerous home of the king of the apes as a team of explorers ventures deep inside the treacherous, primordial island.", 1069 | "popularity": 28.633731, 1070 | "poster_path": "/r2517Vz9EhDhj88qwbDVj8DCRZN.jpg", 1071 | "production_companies": [ 1072 | { 1073 | "name": "Warner Bros.", 1074 | "id": 6194 1075 | }, 1076 | { 1077 | "name": "Legendary Entertainment", 1078 | "id": 84419 1079 | } 1080 | ], 1081 | "production_countries": [ 1082 | { 1083 | "iso_3166_1": "US", 1084 | "name": "United States of America" 1085 | } 1086 | ], 1087 | "release_date": "2017-03-08", 1088 | "revenue": 559015391, 1089 | "runtime": 118, 1090 | "spoken_languages": [ 1091 | { 1092 | "iso_639_1": "en", 1093 | "name": "English" 1094 | } 1095 | ], 1096 | "status": "Released", 1097 | "tagline": "All hail the king", 1098 | "title": "Kong: Skull Island", 1099 | "video": false, 1100 | "vote_average": 6.0, 1101 | "vote_count": 1420, 1102 | "videos": { 1103 | "results": [ 1104 | { 1105 | "id": "58bde2c9c3a368668604a10f", 1106 | "iso_639_1": "en", 1107 | "iso_3166_1": "US", 1108 | "key": "44LdLqgOpjo", 1109 | "name": "Official Final Trailer", 1110 | "site": "YouTube", 1111 | "size": 720, 1112 | "type": "Trailer" 1113 | }, 1114 | { 1115 | "id": "58bde30e925141343500615a", 1116 | "iso_639_1": "en", 1117 | "iso_3166_1": "US", 1118 | "key": "LPjoUohkP5c", 1119 | "name": "IMAX Experience", 1120 | "site": "YouTube", 1121 | "size": 720, 1122 | "type": "Featurette" 1123 | }, 1124 | { 1125 | "id": "58f4e753c3a3680867027654", 1126 | "iso_639_1": "en", 1127 | "iso_3166_1": "US", 1128 | "key": "YK5hbs4LOI8", 1129 | "name": "Official Comic-Con Trailer", 1130 | "site": "YouTube", 1131 | "size": 1080, 1132 | "type": "Trailer" 1133 | }, 1134 | { 1135 | "id": "58f4e871c3a3680845026234", 1136 | "iso_639_1": "en", 1137 | "iso_3166_1": "US", 1138 | "key": "c8jHHJczUQo", 1139 | "name": "Kong Is King", 1140 | "site": "YouTube", 1141 | "size": 1080, 1142 | "type": "Featurette" 1143 | }, 1144 | { 1145 | "id": "58c1552cc3a36826580090d4", 1146 | "iso_639_1": "en", 1147 | "iso_3166_1": "US", 1148 | "key": "7EOTp_QPzY0", 1149 | "name": "1930's Style Trailer", 1150 | "site": "YouTube", 1151 | "size": 1080, 1152 | "type": "Trailer" 1153 | }, 1154 | { 1155 | "id": "58bde2f4925141609b0522b6", 1156 | "iso_639_1": "en", 1157 | "iso_3166_1": "US", 1158 | "key": "mk6YZm1u_W4", 1159 | "name": "\"Monster Battle\"", 1160 | "site": "YouTube", 1161 | "size": 1080, 1162 | "type": "Clip" 1163 | } 1164 | ] 1165 | }, 1166 | "cast": [ 1167 | { 1168 | "cast_id": 1, 1169 | "character": "Captain James Conrad", 1170 | "credit_id": "545b6685c3a368536b001255", 1171 | "id": 91606, 1172 | "name": "Tom Hiddleston", 1173 | "order": 0, 1174 | "profile_path": "/qB1lHPFBPIzw6I7EvsciZ5wyUNS.jpg" 1175 | }, 1176 | { 1177 | "cast_id": 7, 1178 | "character": "Lieutenant Colonel Packard", 1179 | "credit_id": "55cc43b9925141764f002092", 1180 | "id": 2231, 1181 | "name": "Samuel L. Jackson", 1182 | "order": 1, 1183 | "profile_path": "/dlW6prW9HwYDsIRXNoFYtyHpSny.jpg" 1184 | }, 1185 | { 1186 | "cast_id": 6, 1187 | "character": "Mason Weaver", 1188 | "credit_id": "55cc43afc3a3685564000522", 1189 | "id": 60073, 1190 | "name": "Brie Larson", 1191 | "order": 2, 1192 | "profile_path": "/tCDbIZKC8Im7oy4FRgqbkhjF0A.jpg" 1193 | }, 1194 | { 1195 | "cast_id": 11, 1196 | "character": "Bill Randa", 1197 | "credit_id": "56a31788c3a368388b001ef7", 1198 | "id": 1230, 1199 | "name": "John Goodman", 1200 | "order": 3, 1201 | "profile_path": "/mLJC7sRO3JnGkySJlwCJblvhBHm.jpg" 1202 | }, 1203 | { 1204 | "cast_id": 8, 1205 | "character": "Hank Marlow", 1206 | "credit_id": "55cc43be925141764b002099", 1207 | "id": 4764, 1208 | "name": "John C. Reilly", 1209 | "order": 4, 1210 | "profile_path": "/kUo2TPQp4kOWWvijvkjLl0v9PQB.jpg" 1211 | } 1212 | ] 1213 | } 1214 | } 1215 | -------------------------------------------------------------------------------- /12-vue-spa/src/assets/movieTimes.json: -------------------------------------------------------------------------------- 1 | { 2 | "315837": { 3 | "hallId": "H1", 4 | "hallName": "Salon 1", 5 | "times": ["10:00", "13:00", "16:00", "19:00", "22:00"] 6 | }, 7 | "283995": { 8 | "hallId": "H2", 9 | "hallName": "Salon 2", 10 | "times": ["10:00", "12:00", "14:00", "16:00", "18:00", "20:00", "22:00"] 11 | }, 12 | "337339": { 13 | "hallId": "H3", 14 | "hallName": "Salon 3", 15 | "times": ["10:00", "12:30", "15:00", "17:30", "19:00", "22:00"] 16 | }, 17 | "274870": { 18 | "hallId": "H4", 19 | "hallName": "Salon 4", 20 | "times": ["10:00", "13:00", "16:00", "19:00", "22:00"] 21 | }, 22 | "324552": { 23 | "hallId": "H5", 24 | "hallName": "Salon 5", 25 | "times": ["10:00", "12:30", "15:00", "17:30", "19:00", "22:00"] 26 | }, 27 | "293167": { 28 | "hallId": "H6", 29 | "hallName": "Salon 6", 30 | "times": ["10:00", "12:00", "14:00", "16:00", "18:00", "20:00", "22:00"] 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /12-vue-spa/src/assets/movies.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "poster_path": "/myRzRzCxdfUWjkJWgpHHZ1oGkJd.jpg", 4 | "adult": false, 5 | "overview": "In the near future, Major is the first of her kind: a human saved from a terrible crash, who is cyber-enhanced to be a perfect soldier devoted to stopping the world's most dangerous criminals.", 6 | "release_date": "2017-03-29", 7 | "genre_ids": [ 28, 18, 878 ], 8 | "id": 315837, 9 | "original_title": "Ghost in the Shell", 10 | "original_language": "en", 11 | "title": "Ghost in the Shell", 12 | "backdrop_path": "/lsRhmB7m36pEX0UHpkpJSE48BW5.jpg", 13 | "popularity": 39.651588, 14 | "vote_count": 746, 15 | "video": false, 16 | "vote_average": 6 17 | }, 18 | { 19 | "poster_path": "/gaHepzSTMkGwsSKAqiBgroSCf07.jpg", 20 | "adult": false, 21 | "overview": "The Guardians must fight to keep their newfound family together as they unravel the mysteries of Peter Quill's true parentage.", 22 | "release_date": "2017-04-24", 23 | "genre_ids": [ 28, 12, 878 ], 24 | "id": 283995, 25 | "original_title": "Guardians of the Galaxy Vol. 2", 26 | "original_language": "en", 27 | "title": "Guardians of the Galaxy Vol. 2", 28 | "backdrop_path": "/8sFWWIolWPm2FQLNt9cSKpNZJcz.jpg", 29 | "popularity": 29.910321, 30 | "vote_count": 85, 31 | "video": false, 32 | "vote_average": 7.3 33 | }, 34 | { 35 | "poster_path": "/iNpz2DgTsTMPaDRZq2tnbqjL2vF.jpg", 36 | "adult": false, 37 | "overview": "When a mysterious woman seduces Dom into the world of crime and a betrayal of those closest to him, the crew face trials that will test them as never before.", 38 | "release_date": "2017-04-12", 39 | "genre_ids": [ 28, 80, 53 ], 40 | "id": 337339, 41 | "original_title": "The Fate of the Furious", 42 | "original_language": "en", 43 | "title": "The Fate of the Furious", 44 | "backdrop_path": "/jzdnhRhG0dsuYorwvSqPqqnM1cV.jpg", 45 | "popularity": 76.799934, 46 | "vote_count": 985, 47 | "video": false, 48 | "vote_average": 6.9 49 | }, 50 | { 51 | "poster_path": "/5gJkVIVU7FDp7AfRAbPSvvdbre2.jpg", 52 | "adult": false, 53 | "overview": "A spacecraft traveling to a distant colony planet and transporting thousands of people has a malfunction in its sleep chambers. As a result, two passengers are awakened 90 years early.", 54 | "release_date": "2016-12-21", 55 | "genre_ids": [ 12, 18, 10749, 878 ], 56 | "id": 274870, 57 | "original_title": "Passengers", 58 | "original_language": "en", 59 | "title": "Passengers", 60 | "backdrop_path": "/5EW4TR3fWEqpKsWysNcBMtz9Sgp.jpg", 61 | "popularity": 12.852363, 62 | "vote_count": 2433, 63 | "video": false, 64 | "vote_average": 6.6 65 | }, 66 | { 67 | "poster_path": "/1jvyy3UtMbWBHikj7byFJeY5Fc7.jpg", 68 | "adult": false, 69 | "overview": "John Wick is forced out of retirement by a former associate looking to seize control of a shadowy international assassins’ guild. Bound by a blood oath to aid him, Wick travels to Rome and does battle against some of the world’s most dangerous killers.", 70 | "release_date": "2017-02-08", 71 | "genre_ids": [ 53, 28, 80 ], 72 | "id": 324552, 73 | "original_title": "John Wick: Chapter 2", 74 | "original_language": "en", 75 | "title": "John Wick: Chapter 2", 76 | "backdrop_path": "/4TBLjAhQe1zJfR3zdHMWTrwbdLd.jpg", 77 | "popularity": 8.537806, 78 | "vote_count": 1128, 79 | "video": false, 80 | "vote_average": 6.5 81 | }, 82 | { 83 | "poster_path": "/r2517Vz9EhDhj88qwbDVj8DCRZN.jpg", 84 | "adult": false, 85 | "overview": "Explore the mysterious and dangerous home of the king of the apes as a team of explorers ventures deep inside the treacherous, primordial island.", 86 | "release_date": "2017-03-08", 87 | "genre_ids": [ 28, 12, 14 ], 88 | "id": 293167, 89 | "original_title": "Kong: Skull Island", 90 | "original_language": "en", 91 | "title": "Kong: Skull Island", 92 | "backdrop_path": "/pGwChWiAY1bdoxL79sXmaFBlYJH.jpg", 93 | "popularity": 35.434623, 94 | "vote_count": 1372, 95 | "video": false, 96 | "vote_average": 6 97 | } 98 | ] 99 | -------------------------------------------------------------------------------- /12-vue-spa/src/assets/soldTickets.json: -------------------------------------------------------------------------------- 1 | { 2 | "315837": { 3 | "13:00": [ "F11", "F12" ], 4 | "16:00": [ "C10", "C11", "M8", "M9", "M10", "L6", "L7", "K9", "K10" ], 5 | "19:00": [ "H7", "H8", "L11", "L12", "M10", "M11", "M12", "M13" ], 6 | "22:00": [ "M7", "M8", "M9", "M10", "M11", "M12", "L6", "L7", "L12", "K8", "K9", "K10" ] 7 | }, 8 | "283995": { 9 | "18:00": [ "F11", "F12" ], 10 | "20:00": [ "C10", "C11", "M8", "M9", "M10", "L6", "L7", "K9", "K10" ], 11 | "22:00": [ "M7", "M8", "M9", "M10", "M11", "M12", "L6", "L7", "L12", "K8", "K9", "K10" ] 12 | }, 13 | "337339": { 14 | "17:30": [ "F11", "F12" ], 15 | "19:00": [ "C10", "C11", "M8", "M9", "M10", "L6", "L7", "K9", "K10" ], 16 | "22:00": [ "M7", "M8", "M9", "M10", "M11", "M12", "L6", "L7", "L12", "K8", "K9", "K10" ] 17 | }, 18 | "274870": { 19 | "13:00": [ "F11", "F12" ], 20 | "16:00": [ "C10", "C11", "M8", "M9", "M10", "L6", "L7", "K9", "K10" ], 21 | "19:00": [ "M7", "M8", "M9", "M10", "M11", "M12", "L6", "L7", "L12", "K8", "K9", "K10" ] 22 | }, 23 | "324552": { 24 | "17:30": [ "F11", "F12" ], 25 | "19:00": [ "C10", "C11", "M8", "M9", "M10", "L6", "L7", "K9", "K10" ], 26 | "22:00": [ "M7", "M8", "M9", "M10", "M11", "M12", "L6", "L7", "L12", "K8", "K9", "K10" ] 27 | }, 28 | "293167": { 29 | "16:00": [ "F11", "F12" ], 30 | "18:00": [ "C10", "C11", "M8", "M9", "M10", "L6", "L7", "K9", "K10" ], 31 | "20:00": [ "H7", "H8", "L11", "L12", "M10", "M11", "M12", "M13" ], 32 | "22:00": [ "M7", "M8", "M9", "M10", "M11", "M12", "L6", "L7", "L12", "K8", "K9", "K10" ] 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /12-vue-spa/src/assets/ticketPrices.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "price": "10.00", 4 | "label": "Tam" 5 | }, 6 | { 7 | "price": "8.00", 8 | "label": "Öğrenci" 9 | }, 10 | { 11 | "price": "5.00", 12 | "label": "Çocuk" 13 | } 14 | ] 15 | -------------------------------------------------------------------------------- /12-vue-spa/src/components/AppHeader.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /12-vue-spa/src/components/Confirmation.vue: -------------------------------------------------------------------------------- 1 | 17 | -------------------------------------------------------------------------------- /12-vue-spa/src/components/Home.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 42 | -------------------------------------------------------------------------------- /12-vue-spa/src/components/Loader.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 24 | -------------------------------------------------------------------------------- /12-vue-spa/src/components/Movie.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 33 | 34 | 43 | -------------------------------------------------------------------------------- /12-vue-spa/src/components/MovieDetails.vue: -------------------------------------------------------------------------------- 1 | 36 | 37 | 96 | 97 | 152 | -------------------------------------------------------------------------------- /12-vue-spa/src/components/SeatSelection.vue: -------------------------------------------------------------------------------- 1 | 42 | 43 | 117 | 118 | 168 | -------------------------------------------------------------------------------- /12-vue-spa/src/components/TicketSelection.vue: -------------------------------------------------------------------------------- 1 | 53 | 54 | 124 | 125 | 170 | -------------------------------------------------------------------------------- /12-vue-spa/src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import Vuex from 'vuex'; 3 | import VueRouter from 'vue-router'; 4 | import routerOptions from './router/routerOptions.js'; 5 | import storeOptions from './stores/Store.js'; 6 | import App from './App.vue'; 7 | 8 | Vue.use(Vuex); 9 | Vue.use(VueRouter); 10 | 11 | const { state, getters, mutations, actions } = storeOptions; 12 | const router = new VueRouter(routerOptions); 13 | const store = new Vuex.Store({ 14 | state, 15 | getters, 16 | mutations, 17 | actions, 18 | }); 19 | 20 | new Vue({ 21 | el: '#app', 22 | render: h => h(App), 23 | router, 24 | store, 25 | }); 26 | -------------------------------------------------------------------------------- /12-vue-spa/src/router/routerOptions.js: -------------------------------------------------------------------------------- 1 | import Home from '../components/Home.vue'; 2 | import MovieDetails from '../components/MovieDetails.vue'; 3 | import TicketSelection from '../components/TicketSelection.vue'; 4 | import SeatSelection from '../components/SeatSelection.vue'; 5 | import Confirmation from '../components/Confirmation.vue'; 6 | 7 | export default { 8 | routes: [ 9 | { 10 | path: '/', 11 | component: Home, 12 | }, 13 | { 14 | path: '/movie/:id', 15 | component: MovieDetails, 16 | }, 17 | { 18 | path: '/movie/:id/tickets', 19 | component: TicketSelection, 20 | }, 21 | { 22 | path: '/movie/:id/seat-selection', 23 | component: SeatSelection, 24 | }, 25 | { 26 | path: '/confirmation', 27 | component: Confirmation, 28 | } 29 | ], 30 | mode: 'history', 31 | } 32 | -------------------------------------------------------------------------------- /12-vue-spa/src/services/service.js: -------------------------------------------------------------------------------- 1 | export default { 2 | fetchMovies() { 3 | return firebase.database().ref('/movies').once('value'); 4 | }, 5 | 6 | fetchMovieDetails(id) { 7 | return firebase.database().ref(`/movieDetails/${id}`).once('value'); 8 | }, 9 | 10 | fetchTicketPrices() { 11 | return firebase.database().ref('ticketPrices').once('value'); 12 | }, 13 | 14 | fetchMovieTimes(id) { 15 | return firebase.database().ref(`/movieTimes/${id}`).once('value'); 16 | }, 17 | 18 | fetchSeating(hallId) { 19 | return firebase.database().ref(`/halls/${hallId}`).once('value'); 20 | }, 21 | 22 | fetchSoldTickets({ movieId, time }) { 23 | return firebase.database().ref(`/soldTickets/${movieId}/${time}`).once('value'); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /12-vue-spa/src/stores/store.js: -------------------------------------------------------------------------------- 1 | import service from '../services/Service.js'; 2 | 3 | const state = { 4 | movies: [], 5 | movieDetails: {}, 6 | halls: {}, 7 | movieTimes: {}, 8 | ticketPrices: [], 9 | soldTickets: {}, 10 | selectedMovieId: null, 11 | selectedTime: null, 12 | selectedTicketCounts: null, 13 | selectedMovieHallId: null, 14 | selectedSeats: null, 15 | }; 16 | 17 | const getters = { 18 | groupedMovies(state) { 19 | const grouped = []; 20 | 21 | state.movies.forEach((item, index) => { 22 | if (index % 3 === 0) { 23 | grouped.push([]); 24 | } 25 | grouped[grouped.length - 1].push(item); 26 | }); 27 | 28 | return grouped; 29 | }, 30 | }; 31 | 32 | const mutations = { 33 | setMovies(state, movies) { 34 | state.movies = movies; 35 | }, 36 | setMovieDetail(state, data) { 37 | const { id, details } = data; 38 | state.movieDetails[id] = details; 39 | }, 40 | setTicketPrices(state, prices) { 41 | state.ticketPrices = prices; 42 | }, 43 | setMovieTimes(state, data) { 44 | const { id, times } = data; 45 | state.movieTimes[id] = times; 46 | }, 47 | setSelectedTime(state, time) { 48 | state.selectedTime = time; 49 | }, 50 | setSelectedTicketOptions(state, tickets) { 51 | state.selectedTicketCounts = tickets; 52 | }, 53 | setSelectedMovieHallId(state, id) { 54 | state.selectedMovieHallId = id; 55 | }, 56 | setSeatingMap(state, data) { 57 | const { hallId, seating } = data; 58 | state.halls[hallId] = seating; 59 | }, 60 | setSoldTickets(state, data) { 61 | const { movieId, time, tickets } = data; 62 | state.soldTickets[movieId] = state.soldTickets[movieId] || {}; 63 | state.soldTickets[movieId][time] = tickets; 64 | }, 65 | setSelectedMovieId(state, id) { 66 | state.selectedMovieId = id; 67 | }, 68 | setSelectedSeats(state, seats) { 69 | state.selectedSeats = seats; 70 | }, 71 | }; 72 | 73 | const actions = { 74 | fetchMovies(context) { 75 | return service.fetchMovies().then((snapshot) => { 76 | context.commit('setMovies', snapshot.val()); 77 | }); 78 | }, 79 | fetchMovieDetails(context, id) { 80 | return service.fetchMovieDetails(id).then((snapshot) => { 81 | context.commit('setMovieDetail', { id, details: snapshot.val() }); 82 | }); 83 | }, 84 | fetchTicketPrices(context) { 85 | return service.fetchTicketPrices().then((snapshot) => { 86 | context.commit('setTicketPrices', snapshot.val()); 87 | }); 88 | }, 89 | fetchMovieTimes(context, id) { 90 | return service.fetchMovieTimes(id).then((snapshot) => { 91 | context.commit('setMovieTimes', { id, times: snapshot.val() }); 92 | }); 93 | }, 94 | fetchTicketingInfo(context, id) { 95 | return context.dispatch('fetchTicketPrices').then(() => { 96 | return context.dispatch('fetchMovieTimes', id); 97 | }); 98 | }, 99 | fetchSeatMap(context, hallId) { 100 | return service.fetchSeating(hallId).then((snapshot) => { 101 | context.commit('setSeatingMap', { hallId, seating: snapshot.val() }); 102 | }); 103 | }, 104 | fetchSoldTickets(context, { movieId, time }) { 105 | return service.fetchSoldTickets({ movieId, time }).then((snapshot) => { 106 | context.commit('setSoldTickets', { movieId, time, tickets: snapshot.val() }); 107 | }); 108 | }, 109 | fetchSeatingInfo(context, { movieId, time, hallId }) { 110 | return context.dispatch('fetchSeatMap', hallId).then(() => { 111 | return context.dispatch('fetchSoldTickets', { movieId, time }); 112 | }); 113 | } 114 | } 115 | 116 | export default { 117 | state, 118 | getters, 119 | mutations, 120 | actions, 121 | } 122 | -------------------------------------------------------------------------------- /12-vue-spa/webpack.config.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var webpack = require('webpack') 3 | 4 | module.exports = { 5 | entry: './src/main.js', 6 | output: { 7 | path: path.resolve(__dirname, './dist'), 8 | publicPath: '/dist/', 9 | filename: 'build.js' 10 | }, 11 | module: { 12 | rules: [ 13 | { 14 | test: /\.vue$/, 15 | loader: 'vue-loader', 16 | options: { 17 | loaders: { 18 | } 19 | // other vue-loader options go here 20 | } 21 | }, 22 | { 23 | test: /\.js$/, 24 | loader: 'babel-loader', 25 | exclude: /node_modules/ 26 | }, 27 | { 28 | test: /\.(png|jpg|gif|svg)$/, 29 | loader: 'file-loader', 30 | options: { 31 | name: '[name].[ext]?[hash]' 32 | } 33 | } 34 | ] 35 | }, 36 | resolve: { 37 | alias: { 38 | 'vue$': 'vue/dist/vue.esm.js' 39 | } 40 | }, 41 | devServer: { 42 | historyApiFallback: true, 43 | noInfo: true 44 | }, 45 | performance: { 46 | hints: false 47 | }, 48 | devtool: '#eval-source-map' 49 | } 50 | 51 | if (process.env.NODE_ENV === 'production') { 52 | module.exports.devtool = '#source-map' 53 | // http://vue-loader.vuejs.org/en/workflow/production.html 54 | module.exports.plugins = (module.exports.plugins || []).concat([ 55 | new webpack.DefinePlugin({ 56 | 'process.env': { 57 | NODE_ENV: '"production"' 58 | } 59 | }), 60 | new webpack.optimize.UglifyJsPlugin({ 61 | sourceMap: true, 62 | compress: { 63 | warnings: false 64 | } 65 | }), 66 | new webpack.LoaderOptionsPlugin({ 67 | minimize: true 68 | }) 69 | ]) 70 | } 71 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | YouTube'da Turkce VueJS anlattigim videolarda yazdigim kodlari bu repo altinda topladim. Videolarin tamamini [bu YouTube playlist'inde](https://www.youtube.com/playlist?list=PLa3NvhdFWNipwk1KXeUpVQnAiAfuBw4El) bulabilirsiniz. Kanalimda paylastigim tum videolara ise [buradan](https://www.youtube.com/c/fatihacet) ulasabilirsiniz. 2 | 3 | 4 | #### VueJS 01: VueJS ile Uygulama Geliştirme Sunumu 5 | [![http://f.acet.me/O8SV.png](http://f.acet.me/O8SV.png)](https://www.youtube.com/watch?v=byuboztKw9E&list=PLa3NvhdFWNipwk1KXeUpVQnAiAfuBw4El) 6 | 7 | #### VueJS 02: Hello World! 8 | [![http://f.acet.me/L4Cb.png](http://f.acet.me/L4Cb.png)](https://www.youtube.com/watch?v=Zkes5mS8n40&list=PLa3NvhdFWNipwk1KXeUpVQnAiAfuBw4El) 9 | 10 | #### VueJS 03: v-for ile Amazon benzeri bir shopping cart yapiyoruz 11 | [![http://f.acet.me/3gkk.png](http://f.acet.me/3gkk.png)](https://www.youtube.com/watch?v=kNmZAbgLkdw&list=PLa3NvhdFWNipwk1KXeUpVQnAiAfuBw4El) 12 | 13 | #### VueJS 04: Computed Properties ile dinamik data kullanimi 14 | [![http://f.acet.me/fpxQ.png](http://f.acet.me/fpxQ.png)](https://www.youtube.com/watch?v=hsrAukdWj8Q&list=PLa3NvhdFWNipwk1KXeUpVQnAiAfuBw4El) 15 | 16 | #### VueJS 05: Components 17 | [![http://f.acet.me/feLa.png](http://f.acet.me/feLa.png)](https://www.youtube.com/watch?v=LWM_7DpsnW4&list=PLa3NvhdFWNipwk1KXeUpVQnAiAfuBw4El) 18 | 19 | #### VueJS 06: vue-cli ve .vue dosyalarinin yapisi 20 | [![http://f.acet.me/cGUy.png](http://f.acet.me/cGUy.png)](https://www.youtube.com/watch?v=Y8pVruMaB9c&list=PLa3NvhdFWNipwk1KXeUpVQnAiAfuBw4El) 21 | 22 | #### VueJS 07: Giphy API kullanarak yeni bir app yapalim 23 | [![http://f.acet.me/5pIW.png](http://f.acet.me/5pIW.png)](https://www.youtube.com/watch?v=KWG4TbRXU8I&list=PLa3NvhdFWNipwk1KXeUpVQnAiAfuBw4El) 24 | 25 | #### VueJS 08: Vue Router 26 | [![http://f.acet.me/AKmo.png](http://f.acet.me/AKmo.png)](https://www.youtube.com/watch?v=1Z7WfxiDTjk&list=PLa3NvhdFWNipwk1KXeUpVQnAiAfuBw4El) 27 | 28 | 29 | #### VueJS 09: BONUS 1: Eksik kalan kisimlar 30 | [![http://f.acet.me/yrgn.png](http://f.acet.me/yrgn.png)](https://www.youtube.com/watch?v=V0wQxkaLpmk&list=PLa3NvhdFWNipwk1KXeUpVQnAiAfuBw4El) 31 | 32 | 33 | #### VueJS 10: Vue JS icin Unit ve E2E testler yazmak 34 | [![http://f.acet.me/UOPD.png](http://f.acet.me/UOPD.png)](https://www.youtube.com/watch?v=Ym4uH9kZEDc&list=PLa3NvhdFWNipwk1KXeUpVQnAiAfuBw4El) 35 | 36 | 37 | #### VueJS 11: Swagger ile API tasarlayalim 38 | [![http://f.acet.me/hLZO.png](http://f.acet.me/hLZO.png)](https://www.youtube.com/watch?v=i1ZyC0N-4Z8=PLa3NvhdFWNipwk1KXeUpVQnAiAfuBw4El) 39 | 40 | 41 | #### VueJS 12: Single Page Application 42 | [![http://f.acet.me/cHqm.png](http://f.acet.me/cHqm.png)](https://www.youtube.com/watch?v=dr--gckkxi8&index=4&list=PLa3NvhdFWNirpx6x-LIMfTrwOfLzCkfAU) 43 | --------------------------------------------------------------------------------