├── .gitignore ├── README.md ├── index.html ├── package.json ├── src ├── App.vue ├── Compose.vue ├── Content.vue ├── Important.vue ├── Inbox.vue ├── Messages.vue ├── Sent.vue ├── Sidebar.vue ├── Trash.vue ├── ViewMessage.vue ├── assets │ ├── css │ │ └── style.css │ └── images │ │ └── profile.jpg ├── data │ ├── messages.js │ └── random-messages.js └── main.js └── webpack.config.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .idea 3 | .DS_Store -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Vue.js Mail Example Application 2 | 3 | This repository contains the code for the second example application from the [Vue.js: From Beginner to Professional course](https://l.codingexplained.com/r/vuejs-course?src=github). 4 | 5 | ## Getting up and Running 6 | 7 | ``` bash 8 | # Install the dependencies 9 | npm install 10 | 11 | # Serve with hot reload at http://localhost:8080 12 | npm run dev 13 | 14 | # Build for production with minification 15 | npm run build 16 | ``` 17 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Mailbox 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sample-project", 3 | "description": "A Vue.js project", 4 | "version": "1.0.0", 5 | "author": "", 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 | "bootstrap": "^3.3.7", 13 | "font-awesome": "^4.7.0", 14 | "jquery": "^3.1.1", 15 | "moment": "^2.17.1", 16 | "vue": "^2.1.0" 17 | }, 18 | "devDependencies": { 19 | "babel-core": "^6.0.0", 20 | "babel-loader": "^6.0.0", 21 | "babel-preset-es2015": "^6.0.0", 22 | "cross-env": "^3.0.0", 23 | "css-loader": "^0.25.0", 24 | "file-loader": "^0.9.0", 25 | "vue-loader": "^10.0.0", 26 | "vue-template-compiler": "^2.1.0", 27 | "webpack": "^2.1.0-beta.25", 28 | "webpack-dev-server": "^2.1.0-beta.9" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | -------------------------------------------------------------------------------- /src/Compose.vue: -------------------------------------------------------------------------------- 1 | 41 | 42 | -------------------------------------------------------------------------------- /src/Content.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | -------------------------------------------------------------------------------- /src/Important.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | -------------------------------------------------------------------------------- /src/Inbox.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | -------------------------------------------------------------------------------- /src/Messages.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | -------------------------------------------------------------------------------- /src/Sent.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | -------------------------------------------------------------------------------- /src/Sidebar.vue: -------------------------------------------------------------------------------- 1 | 43 | 44 | -------------------------------------------------------------------------------- /src/Trash.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | -------------------------------------------------------------------------------- /src/ViewMessage.vue: -------------------------------------------------------------------------------- 1 | 40 | 41 | -------------------------------------------------------------------------------- /src/assets/css/style.css: -------------------------------------------------------------------------------- 1 | .mail-box { 2 | border-collapse: collapse; 3 | border-spacing: 0; 4 | display: table; 5 | table-layout: fixed; 6 | width: 100%; 7 | } 8 | 9 | .mail-box aside { 10 | display: table-cell; 11 | float: none; 12 | height: 100%; 13 | padding: 0; 14 | vertical-align: top; 15 | } 16 | 17 | .mail-box .sm-side { 18 | background: none repeat scroll 0 0 #e5e8ef; 19 | border-radius: 0 0 4px 4px; 20 | width: 25%; 21 | } 22 | 23 | .mail-box .lg-side { 24 | background: none repeat scroll 0 0 #fff; 25 | border-radius: 0 4px 4px 0; 26 | width: 75%; 27 | } 28 | 29 | .mail-box .sm-side .user-head { 30 | background: none repeat scroll 0 0 #00a8b3; 31 | color: #fff; 32 | height: 90px; 33 | padding: 20px; 34 | } 35 | 36 | .user-head img { 37 | float: left; 38 | border-radius: 50%; 39 | } 40 | 41 | .user-head .user-name { 42 | display: inline-block; 43 | margin: 0 0 0 10px; 44 | } 45 | 46 | .user-head .user-name h5 { 47 | font-size: 14px; 48 | font-weight: 300; 49 | margin-bottom: 0; 50 | cursor: default; 51 | } 52 | 53 | .user-head .user-name .email-address { 54 | color: #87e2e7; 55 | font-size: 12px; 56 | cursor: default; 57 | } 58 | 59 | a.mail-dropdown { 60 | background: none repeat scroll 0 0 #80d3d9; 61 | border-radius: 2px; 62 | color: #01a7b3; 63 | font-size: 10px; 64 | margin-top: 20px; 65 | padding: 3px 5px; 66 | } 67 | 68 | .compose-wrapper { 69 | padding: 20px; 70 | } 71 | 72 | .inbox-body { 73 | padding: 20px 0 20px 20px; 74 | } 75 | 76 | .btn-compose { 77 | background: none repeat scroll 0 0 #ff6c60; 78 | color: #fff; 79 | padding: 12px 0; 80 | text-align: center; 81 | width: 100%; 82 | } 83 | 84 | .btn-compose:hover { 85 | background: none repeat scroll 0 0 #f5675c; 86 | color: #fff; 87 | } 88 | 89 | .btn-compose:visited { 90 | color: #fff; 91 | } 92 | 93 | ul.inbox-nav { 94 | display: inline-block; 95 | margin: 0; 96 | padding: 0; 97 | width: 100%; 98 | } 99 | 100 | .inbox-divider { 101 | border-bottom: 1px solid #d5d8df; 102 | } 103 | 104 | ul.inbox-nav li { 105 | display: inline-block; 106 | line-height: 45px; 107 | width: 100%; 108 | } 109 | 110 | ul.inbox-nav li i { 111 | width: 25px; 112 | text-align: center; 113 | } 114 | 115 | ul.inbox-nav li a { 116 | color: #6a6a6a; 117 | display: inline-block; 118 | line-height: 45px; 119 | padding: 0 20px; 120 | width: 100%; 121 | } 122 | 123 | ul.inbox-nav li a:hover, ul.inbox-nav li.active a, ul.inbox-nav li a:focus { 124 | background: none repeat scroll 0 0 #d5d7de; 125 | color: #6a6a6a; 126 | text-decoration: none; 127 | } 128 | 129 | ul.inbox-nav li a i { 130 | color: #6a6a6a; 131 | font-size: 16px; 132 | padding-right: 10px; 133 | } 134 | 135 | ul.inbox-nav li a span.label { 136 | margin-top: 13px; 137 | } 138 | 139 | .inbox-head { 140 | background: none repeat scroll 0 0 #41cac0; 141 | color: #fff; 142 | height: 90px; 143 | padding: 20px; 144 | } 145 | 146 | .inbox-head h3 { 147 | display: inline-block; 148 | font-weight: 300; 149 | margin: 0; 150 | padding-top: 12px; 151 | } 152 | 153 | .inbox-head .sr-input { 154 | border: medium none; 155 | border-radius: 4px 0 0 4px; 156 | box-shadow: none; 157 | color: #8a8a8a; 158 | float: left; 159 | height: 40px; 160 | padding: 0 10px; 161 | } 162 | 163 | .inbox-head .sr-btn { 164 | background: none repeat scroll 0 0 #00a6b2; 165 | border: medium none; 166 | border-radius: 0 4px 4px 0; 167 | color: #fff; 168 | height: 40px; 169 | padding: 0 20px; 170 | } 171 | 172 | .table-inbox { 173 | border: 1px solid #d3d3d3; 174 | margin-bottom: 0; 175 | } 176 | 177 | .table-inbox tr td { 178 | padding: 12px !important; 179 | } 180 | 181 | .table-inbox tr td:hover { 182 | cursor: pointer; 183 | } 184 | 185 | .table-inbox tr td .fa-star.important, .table-inbox tr td .fa-star:hover { 186 | color: #f78a09; 187 | } 188 | 189 | .table-inbox tr td .fa-star { 190 | color: #d5d5d5; 191 | } 192 | 193 | .table-inbox tr.unread td { 194 | background: none repeat scroll 0 0 #f7f7f7; 195 | font-weight: 600; 196 | } 197 | 198 | ul.inbox-pagination { 199 | float: right; 200 | } 201 | 202 | ul.inbox-pagination li { 203 | float: left; 204 | } 205 | 206 | .mail-option { 207 | display: inline-block; 208 | margin-bottom: 10px; 209 | width: 100%; 210 | } 211 | 212 | .mail-option .btn-group a.btn { 213 | background: none repeat scroll 0 0 #fcfcfc; 214 | border: 1px solid #e7e7e7; 215 | border-radius: 3px !important; 216 | color: #afafaf; 217 | display: inline-block; 218 | padding: 5px 10px; 219 | } 220 | 221 | .mail-option .btn-group a.btn:hover { 222 | background-color: #e7e7e7; 223 | } 224 | 225 | .fileinput-button { 226 | background: none repeat scroll 0 0 #eeeeee; 227 | border: 1px solid #e6e6e6; 228 | } 229 | 230 | .inbox-body .modal .modal-body input, .inbox-body .modal .modal-body textarea { 231 | border: 1px solid #e6e6e6; 232 | box-shadow: none; 233 | } 234 | 235 | .btn-send, .btn-send:hover { 236 | background: none repeat scroll 0 0 #00a8b3; 237 | color: #fff; 238 | } 239 | 240 | .btn-send:hover { 241 | background: none repeat scroll 0 0 #009da7; 242 | } 243 | 244 | .modal-header h4.modal-title { 245 | font-family: "Open Sans",sans-serif; 246 | font-weight: 300; 247 | } 248 | 249 | .modal-body label { 250 | font-family: "Open Sans",sans-serif; 251 | font-weight: 400; 252 | } 253 | 254 | .heading-inbox h4 { 255 | border-bottom: 1px solid #ddd; 256 | color: #444; 257 | font-size: 18px; 258 | margin-top: 20px; 259 | padding-bottom: 10px; 260 | } 261 | 262 | .sender-info { 263 | margin-bottom: 20px; 264 | } 265 | 266 | .sender-info img { 267 | height: 30px; 268 | width: 30px; 269 | } 270 | 271 | .sender-dropdown { 272 | background: none repeat scroll 0 0 #eaeaea; 273 | color: #777; 274 | font-size: 10px; 275 | padding: 0 3px; 276 | } 277 | 278 | .view-mail a { 279 | color: #ff6c60; 280 | } 281 | 282 | .attachment-mail { 283 | margin-top: 30px; 284 | } 285 | 286 | .attachment-mail ul { 287 | display: inline-block; 288 | margin-bottom: 30px; 289 | width: 100%; 290 | } 291 | 292 | .attachment-mail ul li { 293 | float: left; 294 | margin-bottom: 10px; 295 | margin-right: 10px; 296 | width: 150px; 297 | } 298 | 299 | .attachment-mail ul li img { 300 | width: 100%; 301 | } 302 | 303 | .attachment-mail ul li span { 304 | float: right; 305 | } 306 | 307 | .attachment-mail .file-name { 308 | float: left; 309 | } 310 | 311 | .attachment-mail .links { 312 | display: inline-block; 313 | width: 100%; 314 | } 315 | 316 | .fileinput-button { 317 | float: left; 318 | margin-right: 4px; 319 | overflow: hidden; 320 | position: relative; 321 | } 322 | 323 | .fileinput-button input { 324 | cursor: pointer; 325 | direction: ltr; 326 | font-size: 23px; 327 | margin: 0; 328 | opacity: 0; 329 | position: absolute; 330 | right: 0; 331 | top: 0; 332 | transform: translate(-300px, 0px) scale(4); 333 | } 334 | 335 | .fileupload-buttonbar .btn, .fileupload-buttonbar .toggle { 336 | margin-bottom: 5px; 337 | } 338 | 339 | .files .progress { 340 | width: 200px; 341 | } 342 | 343 | .fileupload-processing .fileupload-loading { 344 | display: block; 345 | } 346 | 347 | * html .fileinput-button { 348 | line-height: 24px; 349 | margin: 1px -3px 0 0; 350 | } 351 | 352 | * + html .fileinput-button { 353 | margin: 1px 0 0; 354 | padding: 2px 15px; 355 | } 356 | 357 | @media (max-width: 767px) { 358 | .files .btn span { 359 | display: none; 360 | } 361 | .files .preview * { 362 | width: 40px; 363 | } 364 | .files .name * { 365 | display: inline-block; 366 | width: 80px; 367 | word-wrap: break-word; 368 | } 369 | .files .progress { 370 | width: 20px; 371 | } 372 | .files .delete { 373 | width: 60px; 374 | } 375 | } 376 | 377 | .message { 378 | font-size: 18px; 379 | } 380 | 381 | .attachments { 382 | margin-top: 30px; 383 | } -------------------------------------------------------------------------------- /src/assets/images/profile.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codingexplained/vuejs-mail-app/9f4f3f2ca1c1a82ae38ed38b6095ad4b2a304e90/src/assets/images/profile.jpg -------------------------------------------------------------------------------- /src/data/messages.js: -------------------------------------------------------------------------------- 1 | import moment from 'moment'; 2 | 3 | export default [ 4 | { 5 | subject: 'How did we do?', 6 | content: ` 7 |

Hello,

8 |

You recently completed a purchase, and we'd like to know how we did. Your feedback is very important to us!

9 |

Please click the following link to complete the survey. We're not going to lie, it will take way more than 5 minutes.

10 |

SurveyDonkey.com

11 | `, 12 | isImportant: false, 13 | isDeleted: false, 14 | isRead: false, 15 | type: 'incoming', 16 | date: moment().subtract(10, 'minutes'), 17 | from: { 18 | name: 'SurveyDonkey.com', 19 | email: 'survey@surveydonkey.com' 20 | }, 21 | attachments: [] 22 | }, 23 | { 24 | subject: 'Login from new device', 25 | content: ` 26 |

Hello Bo,

27 |

We noticed that your account was used to sign in from a new device, and we're pretty worried about it.

28 |

It looks like the login came from Moscow, Russia, so unless you are on vacation, you're probably in big trouble.

29 |

We just thought we'd let you know.

30 |

Good luck with that!

31 |

Google Security Team

32 | `, 33 | isImportant: false, 34 | isDeleted: false, 35 | isRead: false, 36 | type: 'incoming', 37 | date: moment().subtract(30, 'minutes'), 38 | from: { 39 | name: 'Google', 40 | email: 'security@accounts.google.com' 41 | }, 42 | attachments: [] 43 | }, 44 | { 45 | subject: 'Your password has been reset', 46 | content: ` 47 |

Hello Bo,

48 |

This is just to notify you that someone (hopefully you) has reset your Facebook password.

49 |

The Facebook Team

50 | `, 51 | isImportant: true, 52 | isDeleted: false, 53 | isRead: true, 54 | type: 'incoming', 55 | date: moment().subtract(75, 'minutes'), 56 | from: { 57 | name: 'Facebook', 58 | email: 'no-reply@facebook.com' 59 | }, 60 | attachments: [] 61 | }, 62 | { 63 | subject: 'Booking confirmation #52798', 64 | content: ` 65 |

Hello Bo,

66 |

Thank you for booking your stay on Hotels.com.

67 |

You will find your reservation details attached to this message.

68 |

We hope that you enjoy your stay!

69 | `, 70 | isImportant: true, 71 | isDeleted: false, 72 | isRead: true, 73 | type: 'incoming', 74 | date: moment().subtract(2, 'days'), 75 | from: { 76 | name: 'Hotels.com', 77 | email: 'booking@hotels.com' 78 | }, 79 | attachments: [ 80 | { 81 | fileName: 'booking.pdf', 82 | size: 1000000 83 | } 84 | ] 85 | }, 86 | { 87 | subject: "Hey, what's up?", 88 | content: ` 89 |

Hey, want to grab a cup of coffee soon?

90 |

Let me know if you get this, because who really uses e-mail these days?

91 | `, 92 | isDeleted: false, 93 | type: 'outgoing', 94 | date: moment().subtract(7, 'days'), 95 | from: { 96 | name: 'Bo Andersen', 97 | email: 'fake@codingexplained.com' 98 | }, 99 | attachments: [] 100 | }, 101 | { 102 | subject: 'Thank you for your purchase', 103 | content: ` 104 |

Thank you!

105 |

We have received your payment, and your products are on the way!

106 |

Order ID: ABCD1234

107 | `, 108 | isImportant: false, 109 | isDeleted: false, 110 | isRead: true, 111 | type: 'incoming', 112 | date: moment().subtract(2, 'weeks'), 113 | from: { 114 | name: 'Amazon', 115 | email: 'orders@amazon.com' 116 | }, 117 | attachments: [ 118 | { 119 | fileName: 'order.pdf', 120 | size: 2000000 121 | } 122 | ] 123 | }, 124 | { 125 | subject: 'Please activate your account', 126 | content: ` 127 |

You recently signed up for Skype, and you need to activate your account.

128 |

You can do this by clicking the below link, which expires in 10 seconds, so you better hurry!

129 |

Activate your profile

130 |

Hope you made it!

131 |

The Skype Team

132 | `, 133 | isImportant: true, 134 | isDeleted: false, 135 | isRead: true, 136 | type: 'incoming', 137 | date: moment().subtract(2, 'months'), 138 | from: { 139 | name: 'Skype', 140 | email: 'accounts@skype.com' 141 | }, 142 | attachments: [] 143 | }, 144 | { 145 | subject: 'Get More Traffic to Your Website', 146 | content: ` 147 |

Hello,

148 |

This is clearly spam, and we don't even know your name. But since you don't have a spam filter, we thought we'd try to trick you into clicking the below phishing link.

149 |

Oh, by the way, you are visitor number 1,000,000,000 on some unknown website, so you just won one billion dollars. True story, just click the link now!

150 |

Click Here Now

151 | `, 152 | isImportant: false, 153 | isDeleted: true, 154 | isRead: false, 155 | type: 'incoming', 156 | date: moment().subtract(3, 'months'), 157 | from: { 158 | name: 'We Spam, inc.', 159 | email: 'scam@spam.com' 160 | }, 161 | attachments: [] 162 | }, 163 | { 164 | subject: 'Collaboration', 165 | content: ` 166 |

Hey Adam,

167 |

I would like to talk with you about a possible collaboration. I think we would both benefit from working together.

168 |

Let me know if you are interested in having a word.

169 |

Best regards,

170 |

Bo Andersen

171 | `, 172 | isDeleted: false, 173 | type: 'outgoing', 174 | date: moment().subtract(100, 'days'), 175 | from: { 176 | name: 'Bo Andersen', 177 | email: 'fake@codingexplained.com' 178 | }, 179 | attachments: [] 180 | }, 181 | { 182 | subject: 'I want to buy your guitar', 183 | content: ` 184 |

Hey there!

185 |

I saw that you have a guitar on sale. I never played an instrument, but I figured I'd be super good at it.

186 |

Even though I know it's extremely annoying, I'm just going to ask "how much?"

187 |

Let me know!

188 | `, 189 | isDeleted: false, 190 | type: 'outgoing', 191 | date: moment().subtract(4, 'months'), 192 | from: { 193 | name: 'Bo Andersen', 194 | email: 'fake@codingexplained.com' 195 | }, 196 | attachments: [] 197 | }, 198 | { 199 | subject: 'Remember your event on Tuesday', 200 | content: ` 201 |

This is a reminder that you have registered for an event at the local tax authorities on Tuesday.

202 |

Perhaps you thought you paid a lot of taxes, living in the world's most expensive country. But no, we have a little surprise for you.

203 |

Can't wait to see you there!

204 | `, 205 | isImportant: false, 206 | isDeleted: true, 207 | isRead: true, 208 | type: 'incoming', 209 | date: moment().subtract(5, 'months'), 210 | from: { 211 | name: 'Tax Authorities', 212 | email: 'taxes@we-want-your-money.com' 213 | }, 214 | attachments: [ 215 | { 216 | fileName: 'invite.ics', 217 | size: 500000 218 | } 219 | ] 220 | }, 221 | { 222 | subject: 'Wrong Delivery', 223 | content: ` 224 |

Hey,

225 |

I ordered a pizza from you guys yesterday. I ordered a vegetarian one, but you delivered a meat lover's pizza.

226 |

I only noticed this half way through eating it, so obviously I am quite upset about that.

227 |

Please deliver a new pizza tonight, but this time a vegetarian one, but with bacon.

228 |

Regards,

229 |

An Angry Customer

230 | `, 231 | isDeleted: false, 232 | type: 'outgoing', 233 | date: moment().subtract(6, 'months'), 234 | from: { 235 | name: 'Bo Andersen', 236 | email: 'fake@codingexplained.com' 237 | }, 238 | attachments: [] 239 | }, 240 | { 241 | subject: 'Looking for a developer', 242 | content: ` 243 |

Hey Bo,

244 |

We are looking for a developer who knows Elasticsearch and Vue.js. Would you be interested in hearing more about it?

245 |

This is obviously just a message that I sent to hundreds of other people without checking out their CV first.

246 |

Let me know if you are open to talking about it.

247 |

Best regards,

248 |

A random recruiter

249 | `, 250 | isImportant: false, 251 | isDeleted: false, 252 | isRead: false, 253 | type: 'incoming', 254 | date: moment().subtract(7, 'months'), 255 | from: { 256 | name: 'Random Recruiter', 257 | email: 'random@recruiter.com' 258 | }, 259 | attachments: [ 260 | { 261 | fileName: 'job-description.pdf', 262 | size: 3000000 263 | } 264 | ] 265 | }, 266 | { 267 | subject: 'Your video is live!', 268 | content: ` 269 |

Hey Coding Explained,

270 |

Your video titled "Why Vue.js is Awesome" is now live on YouTube!

271 |

You can find it here: https://youtu.be/watch?v=hg23hgls

272 | `, 273 | isImportant: false, 274 | isDeleted: false, 275 | isRead: true, 276 | type: 'incoming', 277 | date: moment().subtract(8, 'months'), 278 | from: { 279 | name: 'YouTube', 280 | email: 'video@youtube.com' 281 | }, 282 | attachments: [] 283 | }, 284 | { 285 | subject: "Here's what you missed", 286 | content: ` 287 |

Hey Bo,

288 |

In case you missed what happened on Slack yesterday, here you go.

289 |

We choose to believe that you went on a vacation or something, since you didn't open up the app.

290 |
    291 |
  1. Brandom messaged you
  2. 292 |
  3. 12 new messages in #general
  4. 293 |
  5. 34 new messages in #crashed_systems
  6. 294 |
  7. 56 new messages in #urgent
  8. 295 |
296 |

You should probably check that out. Just sayin'.

297 |

The Slack Team

298 | `, 299 | isImportant: false, 300 | isDeleted: false, 301 | isRead: true, 302 | type: 'incoming', 303 | date: moment().subtract(9, 'months'), 304 | from: { 305 | name: 'Slack', 306 | email: 'notifications@slack.com' 307 | }, 308 | attachments: [] 309 | }, 310 | { 311 | subject: 'Thank you for your purchase', 312 | content: ` 313 |

Thank you for your purchase at SoundGear.com

314 |

You bought the following item:

315 | 318 | `, 319 | isImportant: false, 320 | isDeleted: false, 321 | isRead: true, 322 | type: 'incoming', 323 | date: moment().subtract(10, 'months'), 324 | from: { 325 | name: 'SoundGear.com', 326 | email: 'orders@soundgear.com' 327 | }, 328 | attachments: [ 329 | { 330 | fileName: 'order-confirmation.pdf', 331 | size: 2540000 332 | } 333 | ] 334 | } 335 | ]; 336 | -------------------------------------------------------------------------------- /src/data/random-messages.js: -------------------------------------------------------------------------------- 1 | import moment from 'moment'; 2 | 3 | export default [ 4 | { 5 | subject: 'Confirm your subscription', 6 | content: ` 7 |

Hello Bo,

8 |

Thank you for subscribing to our newsletter!

9 |

Before we can start spamming your mailbox, please confirm your subscription by clicking the below link.

10 |

Confirm Subscription

11 |

Thanks again!

12 | `, 13 | isImportant: false, 14 | isDeleted: false, 15 | isRead: false, 16 | type: 'incoming', 17 | date: moment(), 18 | from: { 19 | name: 'Coding Explained', 20 | email: 'irony@codingexplained.com' 21 | }, 22 | attachments: [] 23 | }, 24 | { 25 | subject: 'CrunchBase Daily', 26 | content: ` 27 |

Here's what happened yesterday.

28 | 33 |

Try to pay more attention next time.

34 | `, 35 | isImportant: false, 36 | isDeleted: false, 37 | isRead: false, 38 | type: 'incoming', 39 | date: moment(), 40 | from: { 41 | name: 'CrunchBase', 42 | email: 'daily@crunchbase.com' 43 | }, 44 | attachments: [] 45 | }, 46 | { 47 | subject: 'Design', 48 | content: ` 49 |

Hey Bo, here's the design that you requested.

50 |

Let me know what you think. Hope you like it!

51 |

Sarah

52 | `, 53 | isImportant: false, 54 | isDeleted: false, 55 | isRead: false, 56 | type: 'incoming', 57 | date: moment(), 58 | from: { 59 | name: 'Sarah', 60 | email: 'sarah-designer@gmail.com' 61 | }, 62 | attachments: [ 63 | { 64 | fileName: 'design.psd', 65 | size: 14700000 66 | } 67 | ] 68 | } 69 | ] -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './App.vue' 3 | 4 | export const eventBus = new Vue(); 5 | 6 | new Vue({ 7 | el: '#app', 8 | render: h => h(App) 9 | }) 10 | -------------------------------------------------------------------------------- /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 | --------------------------------------------------------------------------------