title
Full Stack Todo List Tutorial using Vue.js & AdonisJs
description
We are going to build a simple full stack todo list application using Vue.js for the front end and Adonis to implement the REST API. Also uses Vuetify.
Vue.js section starts at 1:11:14
Cody's Channel: https://www.youtube.com/channel/UCsrVDPJBYeXItETFHG0qzyw
💻 Code: https://github.com/codyseibert/vue-adonis-todo
🐦 Follow Cody on twitter: https://twitter.com/CodyLSeibert
--
Learn to code for free and get a developer job: https://www.freecodecamp.com
Read hundreds of articles on programming: https://medium.freecodecamp.com
detail
{'title': 'Full Stack Todo List Tutorial using Vue.js & AdonisJs', 'heatmap': [{'end': 13733.684, 'start': 13597.441, 'weight': 1}], 'summary': 'Tutorial series covers building a to-do list app using vue.js and adonis.js, including creating a rest api, troubleshooting, user authentication, database models, handling exceptions, vue.js setup, state and component management, and deployment on digitalocean.', 'chapters': [{'end': 298.053, 'segs': [{'end': 132.147, 'src': 'embed', 'start': 0.329, 'weight': 0, 'content': [{'end': 0.869, 'text': 'Hey everyone,', 'start': 0.329, 'duration': 0.54}, {'end': 12.294, 'text': "I'm Cody Seibert and welcome to a full stack tutorial where I'm going to show you how to build a front end single page application using Vue.js and also using Vuex as our state store.", 'start': 0.869, 'duration': 11.425}, {'end': 19.056, 'text': "And then that's going to connect to a back end written in Adonis.js basically to create our REST API.", 'start': 13.294, 'duration': 5.762}, {'end': 25.54, 'text': "And then I'm going to deploy this on DigitalOcean after we finish And so let me just show you really quick what I'm going to be building.", 'start': 19.677, 'duration': 5.863}, {'end': 28.783, 'text': "Basically, it's a very simple to do list application, woohoo.", 'start': 26, 'duration': 2.783}, {'end': 30.944, 'text': 'In the left, we have projects.', 'start': 29.783, 'duration': 1.161}, {'end': 33.206, 'text': 'So we can click different projects here to change.', 'start': 31.004, 'duration': 2.202}, {'end': 39.771, 'text': 'We can create projects, edit them and delete them.', 'start': 34.587, 'duration': 5.184}, {'end': 43.915, 'text': 'Then for each project, we can create different tasks.', 'start': 41.353, 'duration': 2.562}, {'end': 47.73, 'text': 'and then also mark them as completed.', 'start': 46.089, 'duration': 1.641}, {'end': 52.152, 'text': 'Go ahead and delete some, edit some more.', 'start': 47.75, 'duration': 4.402}, {'end': 56.294, 'text': 'Of course, you can log out, and then you can log back in.', 'start': 53.393, 'duration': 2.901}, {'end': 59.466, 'text': 'So a very, very simple application.', 'start': 57.625, 'duration': 1.841}, {'end': 66.368, 'text': 'Hopefully, this is a good start just to kind of explain the concepts of Vue and Adonis.', 'start': 59.486, 'duration': 6.882}, {'end': 68.809, 'text': "So let's just go ahead and get started building out this application.", 'start': 66.388, 'duration': 2.421}, {'end': 73.211, 'text': "All right, so now that we know what we're trying to build, let's go ahead and create a new repository.", 'start': 69.309, 'duration': 3.902}, {'end': 75.271, 'text': "So on my GitHub account, I'm going to click New.", 'start': 73.651, 'duration': 1.62}, {'end': 78.312, 'text': "This is for people who don't know how to create a repo.", 'start': 76.292, 'duration': 2.02}, {'end': 82.414, 'text': "So I'm going to name the repo Vue Adonis Todo.", 'start': 78.452, 'duration': 3.962}, {'end': 88.159, 'text': "Go ahead and make that MIT and I'll create that repo.", 'start': 84.718, 'duration': 3.441}, {'end': 95.322, 'text': "Once my repo is created, I'm just going to go ahead and click this clone or download and then copy this to my clipboard.", 'start': 89.88, 'duration': 5.442}, {'end': 99.304, 'text': "Then in my terminal of VS code, I'm going to go into my workspace.", 'start': 96.442, 'duration': 2.862}, {'end': 108.727, 'text': "I'm going to get clone and type in that repo URL and go ahead and just CD into that folder.", 'start': 99.324, 'duration': 9.403}, {'end': 113.389, 'text': 'In fact, I should probably open the folder here in my workspace.', 'start': 109.127, 'duration': 4.262}, {'end': 117.653, 'text': "So for this tutorial, I'm going to split it up into two major sections.", 'start': 114.289, 'duration': 3.364}, {'end': 122.057, 'text': "The first section, I'm going to focus on building out the REST API using Adonis.js.", 'start': 117.693, 'duration': 4.364}, {'end': 127.903, 'text': "And then the second section, I'm going to be connecting to that REST API using Vue.js for the front end.", 'start': 122.718, 'duration': 5.185}, {'end': 132.147, 'text': "So if you're not really interested in learning how to use Adonis to build a REST API,", 'start': 128.584, 'duration': 3.563}], 'summary': 'Cody seibert will demonstrate building a vue.js single page application with vuex, connecting to an adonis.js back end to create a rest api, and deploying on digitalocean. the application is a simple to-do list with projects, tasks, and user authentication.', 'duration': 131.818, 'max_score': 0.329, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez8329.jpg'}, {'end': 178.575, 'src': 'embed', 'start': 153.312, 'weight': 8, 'content': [{'end': 159.338, 'text': "Instead, what I want to do is just use it, explain the things that I'm doing as I'm doing them,", 'start': 153.312, 'duration': 6.026}, {'end': 162.641, 'text': 'and then leave it up to you to learn more about the framework in the future.', 'start': 159.338, 'duration': 3.303}, {'end': 168.526, 'text': "So to start using Adonis, let's go ahead and go to their website, and just look at the installation section.", 'start': 163.442, 'duration': 5.084}, {'end': 174.692, 'text': 'Basically, to get started, they say we need to install the global Adonis CLI tool.', 'start': 170.528, 'duration': 4.164}, {'end': 178.575, 'text': "which I already have installed, so I'm not going to run this command.", 'start': 176.414, 'duration': 2.161}], 'summary': 'Using adonis framework, explaining steps, leaving learning to the audience.', 'duration': 25.263, 'max_score': 153.312, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez8153312.jpg'}], 'start': 0.329, 'title': 'Vue.js and adonis.js to-do app', 'summary': 'Covers building a simple to-do list application using vue.js and vuex for the front end, adonis.js for the back end to create a rest api, and deploying it on digitalocean, with a focus on explaining the concepts of vue and adonis.', 'chapters': [{'end': 113.389, 'start': 0.329, 'title': 'Building vue.js and adonis.js to-do app', 'summary': 'Covers building a simple to-do list application using vue.js and vuex for the front end, adonis.js for the back end to create a rest api, and deploying it on digitalocean, with a focus on explaining the concepts of vue and adonis.', 'duration': 113.06, 'highlights': ['The chapter covers building a simple to-do list application using Vue.js and Vuex for the front end, Adonis.js for the back end The tutorial demonstrates building a front end single page application using Vue.js and Vuex as the state store, and connecting it to a back end written in Adonis.js to create a REST API.', 'Deploying the application on DigitalOcean The tutorial includes deploying the completed application on DigitalOcean after the development process.', "Creating a new repository on GitHub and cloning it to the local workspace The presenter guides through the process of creating a new repository on GitHub, naming it 'Vue Adonis Todo', setting it as MIT, creating the repo, and then cloning it to the local workspace."]}, {'end': 298.053, 'start': 114.289, 'title': 'Adonis.js rest api with vue.js front end', 'summary': 'Covers building a rest api using adonis.js and connecting to it using vue.js for the front end. it includes installation, project setup, and server hosting, with a focus on api-only development.', 'duration': 183.764, 'highlights': ['Building REST API using Adonis.js The chapter focuses on building a REST API using Adonis.js, emphasizing API-only development and server setup on localhost:3333.', 'Connecting to REST API using Vue.js for front end The tutorial covers the connection to the REST API using Vue.js for the front end, with an emphasis on separating server and client code.', "Adonis CLI installation and usage The tutorial includes details on Adonis CLI installation and usage, including global Adonis CLI tool installation and commands like 'adonis new' and 'adonis serve.'"]}], 'duration': 297.724, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez8329.jpg', 'highlights': ['Covers building a simple to-do list application using Vue.js and Vuex for the front end, Adonis.js for the back end', 'Building REST API using Adonis.js', 'Connecting to REST API using Vue.js for front end', 'Deploying the application on DigitalOcean', 'Creating a new repository on GitHub and cloning it to the local workspace', 'The tutorial demonstrates building a front end single page application using Vue.js and Vuex as the state store, and connecting it to a back end written in Adonis.js to create a REST API', 'The chapter focuses on building a REST API using Adonis.js, emphasizing API-only development and server setup on localhost:3333', 'The tutorial covers the connection to the REST API using Vue.js for the front end, with an emphasis on separating server and client code', 'Adonis CLI installation and usage', "The presenter guides through the process of creating a new repository on GitHub, naming it 'Vue Adonis Todo', setting it as MIT, creating the repo, and then cloning it to the local workspace", 'The tutorial includes deploying the completed application on DigitalOcean after the development process', "The tutorial includes details on Adonis CLI installation and usage, including global Adonis CLI tool installation and commands like 'adonis new' and 'adonis serve.'"]}, {'end': 1001.238, 'segs': [{'end': 334.61, 'src': 'embed', 'start': 298.914, 'weight': 0, 'content': [{'end': 306.721, 'text': "Another cool thing I'll state about this Adana serve command is that as you edit your JS files and save them,", 'start': 298.914, 'duration': 7.807}, {'end': 308.842, 'text': "it's going to restart your server for you automatically.", 'start': 306.721, 'duration': 2.121}, {'end': 313.026, 'text': "So it's kind of using like NodeMon behind the scenes where it just watches your files and restarts them.", 'start': 308.902, 'duration': 4.124}, {'end': 317.915, 'text': "So before we get too much further into this tutorial, let's go ahead and commit what we have.", 'start': 314.312, 'duration': 3.603}, {'end': 321.919, 'text': "I'm going to say initial Adonis setup.", 'start': 317.935, 'duration': 3.984}, {'end': 327.224, 'text': 'So at this point, let me just go ahead and give a quick overview on some of the files that are generated.', 'start': 323.42, 'duration': 3.804}, {'end': 328.785, 'text': "I'm not going to go over all these files.", 'start': 327.384, 'duration': 1.401}, {'end': 334.61, 'text': "I'm just going to focus on the ones we need to implement our functionality, and then we can kind of cover more as time progresses.", 'start': 328.825, 'duration': 5.785}], 'summary': 'Adana serve command automatically restarts server on js file save, simplifying development workflow.', 'duration': 35.696, 'max_score': 298.914, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez8298914.jpg'}, {'end': 528.398, 'src': 'embed', 'start': 500.116, 'weight': 3, 'content': [{'end': 510.163, 'text': 'So the first thing I want to do with our to-do list tutorial application is I want the ability for users to register new users or new accounts.', 'start': 500.116, 'duration': 10.047}, {'end': 511.844, 'text': 'So how would we do this?', 'start': 510.763, 'duration': 1.081}, {'end': 519.45, 'text': 'Obviously, the first thing we want to do is create a new endpoint or a new route where they can hit with a post request to create a new account.', 'start': 511.964, 'duration': 7.486}, {'end': 528.398, 'text': "If I go to the start folder and go back to my routes.js file, inside here, we can simply do a route.post because we're doing a post request.", 'start': 520.15, 'duration': 8.248}], 'summary': 'Developing a new endpoint in the to-do list tutorial application to enable user registration.', 'duration': 28.282, 'max_score': 500.116, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez8500116.jpg'}, {'end': 760.861, 'src': 'embed', 'start': 730.239, 'weight': 4, 'content': [{'end': 734.021, 'text': 'So another cool thing Adonis has is you have the ability to group routes with a prefix.', 'start': 730.239, 'duration': 3.782}, {'end': 739.083, 'text': "So let's say I wanted to append slash API in front of all these different routes that I had.", 'start': 734.861, 'duration': 4.222}, {'end': 744.406, 'text': 'So, if you imagine I had like 10 different routes and I wanted to append API to all of them, you could do it this way,', 'start': 739.103, 'duration': 5.303}, {'end': 748.008, 'text': 'where you have a bunch of copy and paste like URLs with the same prefix.', 'start': 744.406, 'duration': 3.602}, {'end': 756.42, 'text': 'Or one way to do it is I just simply do route group, asset a callback function, put my route in.', 'start': 749.978, 'duration': 6.442}, {'end': 760.861, 'text': 'And then after the group, you just say prefix with API.', 'start': 756.44, 'duration': 4.421}], 'summary': 'Adonis allows grouping routes with a prefix, simplifying url management.', 'duration': 30.622, 'max_score': 730.239, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez8730239.jpg'}, {'end': 892.019, 'src': 'embed', 'start': 865.007, 'weight': 2, 'content': [{'end': 869.15, 'text': 'I see that testing and the password is printed out to our terminal.', 'start': 865.007, 'duration': 4.143}, {'end': 874.913, 'text': 'So we grabbed the parameters or the payload body successfully using something like this.', 'start': 869.21, 'duration': 5.703}, {'end': 887.595, 'text': 'The next step to how would we register a user is we need to use the Lucid model to create and persist a new user to the database.', 'start': 876.806, 'duration': 10.789}, {'end': 892.019, 'text': "So to get started on that, let's go ahead and include that user model.", 'start': 888.576, 'duration': 3.443}], 'summary': 'Using lucid model to register a user and persist to database.', 'duration': 27.012, 'max_score': 865.007, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez8865007.jpg'}], 'start': 298.914, 'title': 'Adana serve command and project setup in adonis', 'summary': 'Explains the adana serve command in adonis, providing an overview of generated files and folders, including routes, models, and migrations. it also covers implementation of a register endpoint, creating a user controller, grouping routes with prefixes, and persisting a new user to the database.', 'chapters': [{'end': 1001.238, 'start': 298.914, 'title': 'Adana serve command and project setup in adonis', 'summary': 'Explains the functionality of the adana serve command in adonis, which automatically restarts the server on saving js files, and provides an overview of the generated files and folders, including routes, models, and migrations. it also covers the implementation of a register endpoint, creating a user controller, grouping routes with prefixes, and persisting a new user to the database.', 'duration': 702.324, 'highlights': ['The Adana serve command automatically restarts the server on saving JS files, functioning similarly to NodeMon behind the scenes. This demonstrates the efficiency of the Adana serve command by automatically restarting the server upon saving JS files, enhancing the development process.', 'Explanation of the generated files and folders, including routes, models, and migrations, in the Adonis project setup. Provides an overview of the essential files and folders required for implementing functionality, emphasizing the importance of routes, models, and migrations in the project setup.', 'Implementation of a register endpoint and creation of a user controller to handle the callback logic. Illustrates the process of creating a register endpoint and a user controller to manage the callback logic, enhancing the organization and modularity of the code.', 'Grouping routes with prefixes and handling different route versions for improved organization and scalability. Demonstrates the use of route grouping with prefixes for enhanced organization and scalability, showcasing the flexibility of managing different route versions.', "Inclusion of the Lucid model to create and persist a new user to the database, utilizing async methods and the 'use' keyword. Showcases the process of leveraging the Lucid model to create and persist a new user in the database, emphasizing the use of async methods and the 'use' keyword for efficient database operations."]}], 'duration': 702.324, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez8298914.jpg', 'highlights': ['The Adana serve command automatically restarts the server on saving JS files, functioning similarly to NodeMon behind the scenes. This demonstrates the efficiency of the Adana serve command by automatically restarting the server upon saving JS files, enhancing the development process.', 'Explanation of the generated files and folders, including routes, models, and migrations, in the Adonis project setup. Provides an overview of the essential files and folders required for implementing functionality, emphasizing the importance of routes, models, and migrations in the project setup.', "Inclusion of the Lucid model to create and persist a new user to the database, utilizing async methods and the 'use' keyword. Showcases the process of leveraging the Lucid model to create and persist a new user in the database, emphasizing the use of async methods and the 'use' keyword for efficient database operations.", 'Implementation of a register endpoint and creation of a user controller to handle the callback logic. Illustrates the process of creating a register endpoint and a user controller to manage the callback logic, enhancing the organization and modularity of the code.', 'Grouping routes with prefixes and handling different route versions for improved organization and scalability. Demonstrates the use of route grouping with prefixes for enhanced organization and scalability, showcasing the flexibility of managing different route versions.']}, {'end': 1481.762, 'segs': [{'end': 1141.253, 'src': 'embed', 'start': 1001.238, 'weight': 0, 'content': [{'end': 1008.722, 'text': "so if we're using mysql or postgres, you need to make sure you install the correct driver, but in this case we're using sqlite.", 'start': 1001.238, 'duration': 7.484}, {'end': 1012.848, 'text': 'So we should be able to just install that and we should be good to go.', 'start': 1010.666, 'duration': 2.182}, {'end': 1015.09, 'text': "Let's try it again and hopefully it works.", 'start': 1013.549, 'duration': 1.541}, {'end': 1019.314, 'text': 'So if I click send, we are getting yet another error.', 'start': 1015.13, 'duration': 4.184}, {'end': 1021.116, 'text': "So let me see what's going on here.", 'start': 1019.574, 'duration': 1.542}, {'end': 1024.898, 'text': 'And one thing I do to kind of debug is I have JS pin loaded up.', 'start': 1021.136, 'duration': 3.762}, {'end': 1026.641, 'text': 'I can just paste the HTML fine here.', 'start': 1024.919, 'duration': 1.722}, {'end': 1031.526, 'text': "And this is saying that there's no such table as users.", 'start': 1027.882, 'duration': 3.644}, {'end': 1037.984, 'text': 'And the reason that this is throwing an error is because we forgot to run our migration scripts.', 'start': 1034.041, 'duration': 3.943}, {'end': 1041.748, 'text': "So let's move on to yet another topic, which is migration.", 'start': 1038.826, 'duration': 2.922}, {'end': 1049.874, 'text': 'So if I open up a new terminal here and do adonis help, we can see what command we have related to migrations.', 'start': 1041.808, 'duration': 8.066}, {'end': 1052.616, 'text': "If you see here, there's five commands for migrations.", 'start': 1050.694, 'duration': 1.922}, {'end': 1056.239, 'text': "The one we're kind of curious to use would be migrations colon run.", 'start': 1052.656, 'duration': 3.583}, {'end': 1060.642, 'text': "And that's going to run through your migration scripts and run anything that it hasn't already ran yet.", 'start': 1056.819, 'duration': 3.823}, {'end': 1067.008, 'text': "So here I'm listening to Adonis migration, run, run that.", 'start': 1062.244, 'duration': 4.764}, {'end': 1071.051, 'text': "And that's going to create our user table and our token table.", 'start': 1068.329, 'duration': 2.722}, {'end': 1078.558, 'text': 'So finally, if I were to do a post request on that endpoint, we should be able to persist that user.', 'start': 1072.573, 'duration': 5.985}, {'end': 1079.919, 'text': 'And look, it did.', 'start': 1079.238, 'duration': 0.681}, {'end': 1081.34, 'text': 'We got our email back.', 'start': 1080.459, 'duration': 0.881}, {'end': 1083.102, 'text': 'We got a password, which is hash back.', 'start': 1081.36, 'duration': 1.742}, {'end': 1086.825, 'text': 'We got our username created at updated at, and we had got an ID.', 'start': 1083.962, 'duration': 2.863}, {'end': 1096.884, 'text': 'So just to verify that this is actually persistent to the database, if we try to do this again, notice we get an error back.', 'start': 1089.98, 'duration': 6.904}, {'end': 1101.386, 'text': "If we look at this error, it's going to say that a constraint failed.", 'start': 1098.204, 'duration': 3.182}, {'end': 1104.047, 'text': "There's no unique user email.", 'start': 1101.926, 'duration': 2.121}, {'end': 1109.03, 'text': "So basically, this error is saying that we've already used the email and we can't use it again.", 'start': 1105.308, 'duration': 3.722}, {'end': 1113.292, 'text': "So we know that it's trying to create that same user input into the database.", 'start': 1110.051, 'duration': 3.241}, {'end': 1117.593, 'text': "It's throwing an exception and it's sending a 500 status code back with an error message.", 'start': 1113.832, 'duration': 3.761}, {'end': 1126.236, 'text': 'Awesome So as a really, really quick recap, we created a new route, which accepts a post request to auth slash register.', 'start': 1118.354, 'duration': 7.882}, {'end': 1131.818, 'text': "We prefix it with API and we're binding that to the user controller register action or method.", 'start': 1126.536, 'duration': 5.282}, {'end': 1137.468, 'text': 'Then inside the user controller, we made an async function, which takes the requests.', 'start': 1132.622, 'duration': 4.846}, {'end': 1141.253, 'text': 'It takes the parameters or body from the request.', 'start': 1138.39, 'duration': 2.863}], 'summary': 'Debugged and ran migration scripts, successfully persisted data to the database, and handled duplicate entry error.', 'duration': 140.015, 'max_score': 1001.238, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez81001238.jpg'}, {'end': 1216.789, 'src': 'embed', 'start': 1185.179, 'weight': 1, 'content': [{'end': 1191.122, 'text': 'So to do so, again, we just need to make a new method here inside this controller called async login.', 'start': 1185.179, 'duration': 5.943}, {'end': 1195.024, 'text': "And that's going to take the request object for now.", 'start': 1192.523, 'duration': 2.501}, {'end': 1199.507, 'text': 'And again, we need to grab the email and password from that request.', 'start': 1196.245, 'duration': 3.262}, {'end': 1201.068, 'text': "I'll just do that.", 'start': 1200.347, 'duration': 0.721}, {'end': 1209.012, 'text': "And then secondly, there's something cool that's already built into Adonis, which is an auth property that's passed in here.", 'start': 1201.088, 'duration': 7.924}, {'end': 1216.789, 'text': 'And basically what auth does is it has a couple of helper function functions on it that allows you to try to authenticate your user.', 'start': 1210.287, 'duration': 6.502}], 'summary': 'Create an async login method in the controller to authenticate user', 'duration': 31.61, 'max_score': 1185.179, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez81185179.jpg'}], 'start': 1001.238, 'title': 'Sqlite troubleshooting and user authentication', 'summary': 'Covers troubleshooting sqlite setup, running migration scripts, and using adonis commands to create user and token tables. it also demonstrates user registration, authentication, persisting user data, handling constraints, and generating jwt tokens using adonis.', 'chapters': [{'end': 1071.051, 'start': 1001.238, 'title': 'Troubleshooting sqlite and running migration scripts', 'summary': 'Highlights the process of troubleshooting errors in setting up sqlite, including the need to run migration scripts, and demonstrates the use of adonis commands to create user and token tables.', 'duration': 69.813, 'highlights': ["The reason for the error is the failure to run migration scripts, which led to the absence of the 'users' table.", "Using Adonis commands, specifically 'migrations:run', helps in running migration scripts to create necessary tables like 'user' and 'token'.", 'Highlighted the importance of installing the correct driver for databases like MySQL or Postgres, while demonstrating the ease of using SQLite for the current setup.']}, {'end': 1481.762, 'start': 1072.573, 'title': 'User authentication and registration', 'summary': 'Demonstrates the process of creating a new route and controller for user registration and authentication using adonis, including persisting user data to the database, handling constraints, and generating jwt tokens for user authentication.', 'duration': 409.189, 'highlights': ['Persisting user data to the database The speaker demonstrates how a post request to the specified endpoint successfully persists user data to the database, including email, password, username, created at, updated at, and ID.', "Handling constraints and error messages The error message 'constraint failed' is explained, indicating the attempt to reuse an existing email, resulting in a 500 status code error message, preventing duplicate user creation.", 'Creating a new route and controller for user registration The process of creating a new route and controller for user registration is detailed, emphasizing the use of async functions, object deconstruction, and the use of await for user creation and return.', "Generating JWT tokens for user authentication The process of using Adonis' built-in auth property and JWT authentication is explained, including the configuration of auth types, JWT token creation based on email and password, and the verification process for successful login."]}], 'duration': 480.524, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez81001238.jpg', 'highlights': ["Using Adonis commands, specifically 'migrations:run', helps in running migration scripts to create necessary tables like 'user' and 'token'.", "The process of using Adonis' built-in auth property and JWT authentication is explained, including the configuration of auth types, JWT token creation based on email and password, and the verification process for successful login.", 'Persisting user data to the database The speaker demonstrates how a post request to the specified endpoint successfully persists user data to the database, including email, password, username, created at, updated at, and ID.', 'Creating a new route and controller for user registration The process of creating a new route and controller for user registration is detailed, emphasizing the use of async functions, object deconstruction, and the use of await for user creation and return.', 'Highlighted the importance of installing the correct driver for databases like MySQL or Postgres, while demonstrating the ease of using SQLite for the current setup.', "Handling constraints and error messages The error message 'constraint failed' is explained, indicating the attempt to reuse an existing email, resulting in a 500 status code error message, preventing duplicate user creation.", "The reason for the error is the failure to run migration scripts, which led to the absence of the 'users' table."]}, {'end': 2119.94, 'segs': [{'end': 1615.378, 'src': 'embed', 'start': 1530.36, 'weight': 3, 'content': [{'end': 1533.803, 'text': 'We get back our payload that has a token in it.', 'start': 1530.36, 'duration': 3.443}, {'end': 1537.766, 'text': 'Awesome So we just made a new login method.', 'start': 1534.924, 'duration': 2.842}, {'end': 1542.149, 'text': 'We modified the register method to call login after we register.', 'start': 1538.546, 'duration': 3.603}, {'end': 1547.033, 'text': 'And then we created the route to allow us to register in login.', 'start': 1542.169, 'duration': 4.864}, {'end': 1548.914, 'text': "We're making some good progress.", 'start': 1547.053, 'duration': 1.861}, {'end': 1555.119, 'text': 'Now we just need to move on to creating some new database models.', 'start': 1548.954, 'duration': 6.165}, {'end': 1559.021, 'text': "And before we move on to that, let's just go ahead and commit what we have.", 'start': 1556.479, 'duration': 2.542}, {'end': 1562.483, 'text': "So I'm going to say registration slash login and commit that.", 'start': 1559.041, 'duration': 3.442}, {'end': 1567.766, 'text': "And then we can start fresh and I've died back into this file.", 'start': 1562.503, 'duration': 5.263}, {'end': 1578.133, 'text': 'So since we are planning to make a to-do list application, one thing I want to include is a new project model.', 'start': 1569.488, 'duration': 8.645}, {'end': 1581.896, 'text': 'So I plan to separate my data into projects.', 'start': 1579.694, 'duration': 2.202}, {'end': 1585.238, 'text': 'Then inside the projects we have tasks.', 'start': 1582.436, 'duration': 2.802}, {'end': 1595.023, 'text': "So let's look back at the Adonis CLI and see what commands we can use to try to help us create a new model.", 'start': 1587.378, 'duration': 7.645}, {'end': 1596.124, 'text': 'So I do Adonis help.', 'start': 1595.083, 'duration': 1.041}, {'end': 1600.027, 'text': 'Notice here we have a make model.', 'start': 1598.066, 'duration': 1.961}, {'end': 1604.63, 'text': 'So Adonis make model help.', 'start': 1600.047, 'duration': 4.583}, {'end': 1610.194, 'text': 'And basically, we just pass the name of the model.', 'start': 1607.752, 'duration': 2.442}, {'end': 1615.378, 'text': "And then there's also a controller and migration if you want to create a migration for the model.", 'start': 1611.155, 'duration': 4.223}], 'summary': 'Developed a new login method, registered route, and plans for new database models for a to-do list application.', 'duration': 85.018, 'max_score': 1530.36, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez81530360.jpg'}, {'end': 1832.858, 'src': 'embed', 'start': 1807.103, 'weight': 4, 'content': [{'end': 1812.949, 'text': 'We declared a title inside that migrations projects table.', 'start': 1807.103, 'duration': 5.846}, {'end': 1817.254, 'text': 'And we also declared a user ID which references the users table.', 'start': 1813.21, 'duration': 4.044}, {'end': 1821.409, 'text': 'And then we declare some associations in our project and user model.', 'start': 1818.507, 'duration': 2.902}, {'end': 1825.752, 'text': 'So what we want to do is we need to run our migration again.', 'start': 1822.41, 'duration': 3.342}, {'end': 1832.858, 'text': "So if I do migration run, that's going to only run that project migration script because we've already ran those past two right?", 'start': 1825.812, 'duration': 7.046}], 'summary': 'Declared title in migrations projects table, referenced user id, and ran migration script.', 'duration': 25.755, 'max_score': 1807.103, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez81807103.jpg'}, {'end': 1889.952, 'src': 'embed', 'start': 1858.555, 'weight': 5, 'content': [{'end': 1863.278, 'text': 'So here, if I do make controller, so Adonis make controller help to get more information.', 'start': 1858.555, 'duration': 4.723}, {'end': 1871.541, 'text': "I'm going to pass it the project as a name so that we have a new controller called project.", 'start': 1863.298, 'duration': 8.243}, {'end': 1874.943, 'text': "That's going to be an HTTP type of controller.", 'start': 1872.182, 'duration': 2.761}, {'end': 1881.688, 'text': "And inside of our project controller, let's just go ahead and do a index method.", 'start': 1877.386, 'duration': 4.302}, {'end': 1889.952, 'text': 'And what this method is supposed to do is supposed to return all the projects that are associated with the user.', 'start': 1881.708, 'duration': 8.244}], 'summary': 'Using adonis make controller to create an http type controller named project, with an index method returning all user-associated projects.', 'duration': 31.397, 'max_score': 1858.555, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez81858555.jpg'}, {'end': 2031.873, 'src': 'embed', 'start': 2002.134, 'weight': 0, 'content': [{'end': 2007.318, 'text': 'So, at this point, what we want to do is when we declare the route.', 'start': 2002.134, 'duration': 5.184}, {'end': 2014.624, 'text': 'we also want to declare a middleware function so that we can parse the JWT token from the request.', 'start': 2007.318, 'duration': 7.306}, {'end': 2019.568, 'text': 'So, inside of our line 22,, where we declare our index,', 'start': 2015.905, 'duration': 3.663}, {'end': 2025.408, 'text': "we want to make sure that we add a middleware call and tell it that it's going to be an auth call.", 'start': 2019.568, 'duration': 5.84}, {'end': 2031.873, 'text': "So basically, we're going to authenticate the user with that JWT token before we run our controller here.", 'start': 2025.508, 'duration': 6.365}], 'summary': 'Add a middleware function to parse jwt token for user authentication before running the controller.', 'duration': 29.739, 'max_score': 2002.134, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez82002134.jpg'}, {'end': 2077.342, 'src': 'embed', 'start': 2054.614, 'weight': 1, 'content': [{'end': 2063.077, 'text': 'Typically, the way to pass a JWT token is inside the header, you have an authorization key and then you pass it, something called bearer,', 'start': 2054.614, 'duration': 8.463}, {'end': 2065.058, 'text': 'and then the token like so', 'start': 2063.077, 'duration': 1.981}, {'end': 2067.534, 'text': 'And then inside Postman.', 'start': 2066.434, 'duration': 1.1}, {'end': 2077.342, 'text': 'what we have is we have environments where we can just set up kind of key value pairs so we can use those in all of our requests.', 'start': 2067.534, 'duration': 9.808}], 'summary': 'Use jwt token in header for authorization; set key-value pairs in postman environments.', 'duration': 22.728, 'max_score': 2054.614, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez82054614.jpg'}, {'end': 2132.431, 'src': 'embed', 'start': 2099.57, 'weight': 2, 'content': [{'end': 2101.931, 'text': 'So at this point, we get a message back that says hello world.', 'start': 2099.57, 'duration': 2.361}, {'end': 2108.674, 'text': "And then if we were to leave off this authentication token, we're going to get back that same error saying that JWT token was not provided.", 'start': 2102.311, 'duration': 6.363}, {'end': 2113.737, 'text': 'This is also going to check your token to make sure it is valid.', 'start': 2111.416, 'duration': 2.321}, {'end': 2119.94, 'text': "So if I were to go and try to create and spoof my own token and send it to this endpoint, it's not going to work as expected.", 'start': 2113.797, 'duration': 6.143}, {'end': 2132.431, 'text': 'So, going back to our code, the main thing that we wanted to kind of show is that once we fetch off dot, get user.', 'start': 2122.964, 'duration': 9.467}], 'summary': 'The transcript discusses authentication token usage and validation in api calls.', 'duration': 32.861, 'max_score': 2099.57, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez82099570.jpg'}], 'start': 1482.462, 'title': 'Implementing user authentication, database models, and adonis cli', 'summary': 'Covers implementing user authentication, creating database models, and using adonis cli to create models and controllers. it also discusses jwt token handling, including creating routes, middleware functions, and using authorization headers to ensure secure user authentication. additionally, it provides details on creating a new http controller and running migration scripts to result in a table called projects in the database.', 'chapters': [{'end': 1581.896, 'start': 1482.462, 'title': 'Implementing user authentication and creating database models', 'summary': 'Discusses the implementation of user authentication, including creating a new login method and modifying the register method to return a token, as well as the plan to create new database models for a to-do list application.', 'duration': 99.434, 'highlights': ['The implementation of a new login method that returns a token after user registration, enhancing the authentication process.', 'Modifying the register method to call the new login method after user registration, improving the user experience.', "Planning to create new database models for a to-do list application, indicating the direction of the project's development."]}, {'end': 1881.688, 'start': 1582.436, 'title': 'Adonis cli: creating models and controllers', 'summary': 'Covers creating a new model using adonis cli, including making a migration script, declaring attributes and associations, and running the migration script, resulting in a table called projects in the database. it also discusses creating a new http controller called project with an index method.', 'duration': 299.252, 'highlights': ['Creating a new model using Adonis CLI The tutorial explains the process of creating a new model using Adonis CLI, including making a migration script, declaring attributes and associations.', 'Running the migration script to create a table called projects in the database After declaring attributes and associations, the migration script is run, resulting in a table called projects in the database.', 'Creating a new HTTP controller called project with an index method The tutorial discusses the process of creating a new HTTP controller called project with an index method to handle creating new projects.']}, {'end': 2119.94, 'start': 1881.708, 'title': 'Project authentication and jwt token handling', 'summary': 'Discusses the implementation of project authentication and handling of jwt tokens, including the creation of a route, middleware function for token parsing, and the use of authorization headers to pass the token, ensuring secure user authentication.', 'duration': 238.232, 'highlights': ['The chapter discusses the implementation of project authentication and handling of JWT tokens. This is the main topic of the transcript.', 'The creation of a route and middleware function for token parsing is explained. Describes the process of creating a route and middleware function.', 'The use of authorization headers to pass the token is demonstrated. Explains the process of passing the token using authorization headers.', 'The need to ensure the validity of the token is highlighted. Emphasizes the importance of token validity for secure authentication.']}], 'duration': 637.478, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez81482462.jpg', 'highlights': ['The creation of a route and middleware function for token parsing is explained. Describes the process of creating a route and middleware function.', 'The use of authorization headers to pass the token is demonstrated. Explains the process of passing the token using authorization headers.', 'The need to ensure the validity of the token is highlighted. Emphasizes the importance of token validity for secure authentication.', 'Creating a new model using Adonis CLI The tutorial explains the process of creating a new model using Adonis CLI, including making a migration script, declaring attributes and associations.', 'Running the migration script to create a table called projects in the database After declaring attributes and associations, the migration script is run, resulting in a table called projects in the database.', 'Creating a new HTTP controller called project with an index method The tutorial discusses the process of creating a new HTTP controller called project with an index method to handle creating new projects.', 'The implementation of a new login method that returns a token after user registration, enhancing the authentication process.', 'Modifying the register method to call the new login method after user registration, improving the user experience.', "Planning to create new database models for a to-do list application, indicating the direction of the project's development."]}, {'end': 3009.093, 'segs': [{'end': 2170.897, 'src': 'embed', 'start': 2122.964, 'weight': 3, 'content': [{'end': 2132.431, 'text': 'So, going back to our code, the main thing that we wanted to kind of show is that once we fetch off dot, get user.', 'start': 2122.964, 'duration': 9.467}, {'end': 2134.233, 'text': 'it prints out that user information here.', 'start': 2132.431, 'duration': 1.802}, {'end': 2140.177, 'text': 'So we have access to user dot ID inside of this controller if we wanted to use it.', 'start': 2134.433, 'duration': 5.744}, {'end': 2145.281, 'text': "I'll go ahead and just print that out at the endpoint one more time.", 'start': 2140.197, 'duration': 5.084}, {'end': 2156.585, 'text': "And notice here is printing out one because if you remember in JWT IO, when I decode this token, it's printing out user ID of one.", 'start': 2148.74, 'duration': 7.845}, {'end': 2161.448, 'text': 'And what that does is going to fetch the user from the database using UID.', 'start': 2157.866, 'duration': 3.582}, {'end': 2164.63, 'text': 'And then we have access to that user model here.', 'start': 2162.028, 'duration': 2.602}, {'end': 2170.897, 'text': "Okay, so we're almost done with this project index method.", 'start': 2167.335, 'duration': 3.562}], 'summary': 'Code fetches user information and prints user id at endpoint.', 'duration': 47.933, 'max_score': 2122.964, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez82122964.jpg'}, {'end': 2347.373, 'src': 'embed', 'start': 2320.763, 'weight': 0, 'content': [{'end': 2326.585, 'text': 'And then finally we want to create the project and associate it with the user right?', 'start': 2320.763, 'duration': 5.822}, {'end': 2334.508, 'text': 'So if we do await user.projects.save and pass the project, and then finally we can return that project.', 'start': 2326.625, 'duration': 7.883}, {'end': 2341.531, 'text': "So recap, we created a route for that project's create method.", 'start': 2337.569, 'duration': 3.962}, {'end': 2343.412, 'text': "We make sure it's authenticated.", 'start': 2342.111, 'duration': 1.301}, {'end': 2345.252, 'text': 'We grab the user.', 'start': 2344.452, 'duration': 0.8}, {'end': 2347.373, 'text': 'We fetch the title from the request.', 'start': 2345.753, 'duration': 1.62}], 'summary': 'Created route for project creation, authenticated user, fetched title.', 'duration': 26.61, 'max_score': 2320.763, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez82320763.jpg'}, {'end': 2422.468, 'src': 'embed', 'start': 2395.964, 'weight': 5, 'content': [{'end': 2399.846, 'text': 'And then we can kind of just knock out all the remaining project methods.', 'start': 2395.964, 'duration': 3.882}, {'end': 2413.338, 'text': "Okay, so the last two methods we're going to create on the projects controller is going to be a create or, I'm sorry, not create.", 'start': 2408.453, 'duration': 4.885}, {'end': 2415.28, 'text': "it's going to be a delete and an update method.", 'start': 2413.338, 'duration': 1.942}, {'end': 2418.143, 'text': "So let's go back to our routes.", 'start': 2417.042, 'duration': 1.101}, {'end': 2422.468, 'text': "And let's go ahead and make a new endpoint that takes a delete request.", 'start': 2418.243, 'duration': 4.225}], 'summary': 'Create delete and update methods for projects controller.', 'duration': 26.504, 'max_score': 2395.964, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez82395964.jpg'}, {'end': 2614.674, 'src': 'embed', 'start': 2586.66, 'weight': 1, 'content': [{'end': 2589.064, 'text': "So let's just go ahead and save this and try to test it out.", 'start': 2586.66, 'duration': 2.404}, {'end': 2595.843, 'text': 'So going back here, notice that this user has a bunch of different projects associated with it.', 'start': 2591.38, 'duration': 4.463}, {'end': 2602.527, 'text': "So let me describe project three, and I'm going to go to the delete request and tell it to delete project three.", 'start': 2595.863, 'duration': 6.664}, {'end': 2608.19, 'text': "So after I run that, it's returning the project information that was deleted.", 'start': 2602.547, 'duration': 5.643}, {'end': 2614.674, 'text': 'And if I go back to my get request, try to fetch all the projects, notice that three does not exist in this list anymore.', 'start': 2608.29, 'duration': 6.384}], 'summary': 'Deleting project three resulted in successful removal from the list.', 'duration': 28.014, 'max_score': 2586.66, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez82586660.jpg'}, {'end': 2853.571, 'src': 'embed', 'start': 2827.586, 'weight': 2, 'content': [{'end': 2834.17, 'text': 'So something cool in Adonis that I need to point out is that when an exception is thrown in your controller,', 'start': 2827.586, 'duration': 6.584}, {'end': 2837.072, 'text': "it's going to return that exception to the user.", 'start': 2834.17, 'duration': 2.902}, {'end': 2841.655, 'text': "So I don't need to have if statements and specify certain status codes and return.", 'start': 2837.112, 'duration': 4.543}, {'end': 2844.297, 'text': 'Instead, I could abstract that into an exception.', 'start': 2842.175, 'duration': 2.122}, {'end': 2853.571, 'text': 'So again, going back to a really useful Adonis CLI, if I do Adonis help, notice that we can make an exception here.', 'start': 2846.408, 'duration': 7.163}], 'summary': 'Adonis automatically returns exceptions, reducing need for if statements and status codes.', 'duration': 25.985, 'max_score': 2827.586, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez82827586.jpg'}], 'start': 2122.964, 'title': 'Adonis project controller methods', 'summary': 'Discusses the implementation of create, delete, and update methods in the adonis project controller, including authentication, fetching user data, creating and associating projects, and handling exceptions, with a focus on verifying user permissions and improving controller cleanliness through exception handling.', 'chapters': [{'end': 2170.897, 'start': 2122.964, 'title': 'Accessing user information in controller', 'summary': 'Showcases accessing user information in a controller to demonstrate the retrieval of user data from a database and the utilization of the user id.', 'duration': 47.933, 'highlights': ["The controller demonstrates accessing user information by printing out the user ID, which is '1' in this case.", 'The user ID is retrieved from the token and used to fetch the corresponding user from the database, providing access to the user model.']}, {'end': 3009.093, 'start': 2171.658, 'title': 'Adonis project controller methods', 'summary': 'Discusses the implementation of create, delete, and update methods in the adonis project controller, including authentication, fetching user data, creating and associating projects, and handling exceptions, with a focus on verifying user permissions and improving controller cleanliness through exception handling.', 'duration': 837.435, 'highlights': ['The chapter discusses the implementation of create, delete, and update methods in the Adonis project controller The chapter delves into the implementation of essential methods such as create, delete, and update in the Adonis project controller.', 'The create method involves authentication, fetching user data, creating and associating projects The create method involves authenticating the user, fetching user data, creating new projects, associating them with the user, and returning the created project.', 'The delete method focuses on verifying user permissions and handling exceptions The delete method involves verifying user permissions, handling exceptions, and ensuring that the user has access to delete the specified project.', 'The chapter emphasizes improving controller cleanliness through exception handling The chapter focuses on improving the cleanliness of the controller by utilizing exception handling to streamline error management and reduce the need for numerous if statements.']}], 'duration': 886.129, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez82122964.jpg', 'highlights': ['The create method involves authenticating the user, fetching user data, creating new projects, associating them with the user, and returning the created project.', 'The delete method involves verifying user permissions, handling exceptions, and ensuring that the user has access to delete the specified project.', 'The chapter focuses on improving the cleanliness of the controller by utilizing exception handling to streamline error management and reduce the need for numerous if statements.', "The controller demonstrates accessing user information by printing out the user ID, which is '1' in this case.", 'The user ID is retrieved from the token and used to fetch the corresponding user from the database, providing access to the user model.', 'The chapter discusses the implementation of create, delete, and update methods in the Adonis project controller.']}, {'end': 4211.709, 'segs': [{'end': 3096.482, 'src': 'embed', 'start': 3040.93, 'weight': 0, 'content': [{'end': 3047.673, 'text': 'That is a really high level overview of exceptions and how you can handle them to return custom status codes to your requests.', 'start': 3040.93, 'duration': 6.743}, {'end': 3052.135, 'text': "Let's go ahead and commit what we have now and move on to the last one, which is going to be update.", 'start': 3048.713, 'duration': 3.422}, {'end': 3058.165, 'text': "I'm gonna call this one destroy with exceptions.", 'start': 3056.624, 'duration': 1.541}, {'end': 3062.966, 'text': 'Go back to my code and get back to a nice state.', 'start': 3059.265, 'duration': 3.701}, {'end': 3065.087, 'text': 'Just continue working.', 'start': 3064.007, 'duration': 1.08}, {'end': 3074.451, 'text': 'Okay, so the last route that we want to add for projects would be an update route.', 'start': 3070.249, 'duration': 4.202}, {'end': 3082.774, 'text': "So here, if I say route dot patch and again that's gonna be project slash ID and we're going to say update,", 'start': 3075.831, 'duration': 6.943}, {'end': 3084.675, 'text': "that's going to also need the auth middleware.", 'start': 3082.774, 'duration': 1.901}, {'end': 3089.241, 'text': "So we created our route, let's go to our controller and create our action.", 'start': 3085.64, 'duration': 3.601}, {'end': 3096.482, 'text': "So I'm going to say update auth request params, very similar code.", 'start': 3089.281, 'duration': 7.201}], 'summary': 'Overview of handling exceptions and adding an update route for projects.', 'duration': 55.552, 'max_score': 3040.93, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez83040930.jpg'}, {'end': 3273.862, 'src': 'embed', 'start': 3246.103, 'weight': 2, 'content': [{'end': 3254.065, 'text': "Again, we can go here and say make model, and then we're going to pass it task with hyphen M, so it creates our migration scripts.", 'start': 3246.103, 'duration': 7.962}, {'end': 3263.968, 'text': "And let's move to our migration scripts and just add whatever we need for the task entry.", 'start': 3256.006, 'duration': 7.962}, {'end': 3273.862, 'text': "So task is going to have title and it's also going to be associated with a project.", 'start': 3266.989, 'duration': 6.873}], 'summary': "Using 'make model' to create migration scripts for task entry with title and association with a project", 'duration': 27.759, 'max_score': 3246.103, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez83246103.jpg'}, {'end': 3361.694, 'src': 'embed', 'start': 3334.971, 'weight': 3, 'content': [{'end': 3339.835, 'text': 'and we should be able to actually use our Lucid models to start manipulating with that table.', 'start': 3334.971, 'duration': 4.864}, {'end': 3346.6, 'text': "Okay, so let me go ahead and just close out some of these so it's not so overwhelming.", 'start': 3343.397, 'duration': 3.203}, {'end': 3354.766, 'text': 'Take a step back, what are we doing? So we want the ability for users to create new tasks.', 'start': 3348.321, 'duration': 6.445}, {'end': 3361.694, 'text': "And because of the way a task is set up, you can't really have a task unless you have a project in which it associates with.", 'start': 3356.311, 'duration': 5.383}], 'summary': 'Developing the ability for users to create new tasks associated with projects using lucid models.', 'duration': 26.723, 'max_score': 3334.971, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez83334971.jpg'}], 'start': 3010.313, 'title': 'Handling exceptions, project update, task creation and management', 'summary': 'Explains how to handle exceptions and return custom status codes, covers creating an update route and controller for projects with authentication middleware, creating a new model for tasks, setting up migration scripts, and managing tasks within a project, emphasizing association and authentication requirements.', 'chapters': [{'end': 3065.087, 'start': 3010.313, 'title': 'Handling exceptions and custom status codes', 'summary': 'Explains how to handle exceptions to return custom status codes, such as returning a 404 not found error when a resource does not exist, providing a high-level overview of the process.', 'duration': 54.774, 'highlights': ['The chapter provides an example of copying a handler to handle exceptions and returning a 404 not found error when a resource does not exist.', 'It emphasizes the importance of handling exceptions to return custom status codes to requests.', "The chapter concludes with a mention of moving on to the 'update' and 'destroy with exceptions' topics."]}, {'end': 3217.16, 'start': 3070.249, 'title': 'Project update route and controller', 'summary': 'Covers creating an update route and controller for projects, implementing authentication middleware, fetching and updating project details, and verifying successful updates, demonstrating the completion of the main crud methods for projects.', 'duration': 146.911, 'highlights': ['Demonstrating the completion of the main CRUD methods for projects The chapter covers the creation of an update route and controller, completing the main CRUD methods for projects.', 'Implementing authentication middleware for the update route The update route includes the implementation of authentication middleware to ensure secure access to project updates.', 'Fetching and updating project details The chapter explains the process of fetching project details, updating the title, and saving the changes.']}, {'end': 3637.146, 'start': 3218, 'title': 'Creating tasks and projects', 'summary': 'Covers creating a new model for tasks, setting up migration scripts, creating endpoints for users to post tasks to projects, and creating a method to fetch all tasks associated with a project, emphasizing the need for a project to be associated with a task and the authentication requirements.', 'duration': 419.146, 'highlights': ["Creating a new model for tasks and setting up migration scripts The speaker explains the process of creating a new model for tasks and setting up migration scripts by using the 'make model' command and specifying the fields for the tasks, such as title and association with a project.", 'Setting up endpoints for users to post tasks to projects and authentication requirements The chapter discusses the creation of an endpoint for users to post tasks to projects, emphasizing the need for a project to be associated with a task, and the authentication requirements to ensure user access to the project.', 'Creation of a method to fetch all tasks associated with a project The speaker covers the creation of a method to fetch all tasks associated with a project, allowing users to easily test and view the tasks associated with a specific project.']}, {'end': 4211.709, 'start': 3637.226, 'title': 'Task creation and management', 'summary': 'Covers the process of creating and managing tasks within a project, including fetching, creating, updating, and deleting tasks, using project ids for association and verification of user access. testing reveals successful creation of tasks and endpoints, and debugging is shown in ensuring proper access and functionality.', 'duration': 574.483, 'highlights': ['Tasks creation and management process The transcript covers the process of creating and managing tasks within a project, including fetching, creating, updating, and deleting tasks.', 'Successful creation and testing of task endpoints Testing reveals successful creation of tasks and endpoints, demonstrating functionality of the implemented methods.', 'Verification of user access to project The process involves verifying that the user has access to the project using project IDs and ensuring proper access to the associated tasks.', 'Debugging and resolving access issues Debugging process is shown in ensuring proper access and functionality, including identifying and resolving access issues during task update and deletion.']}], 'duration': 1201.396, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez83010313.jpg', 'highlights': ['The chapter emphasizes the importance of handling exceptions to return custom status codes to requests.', 'The update route includes the implementation of authentication middleware to ensure secure access to project updates.', "The speaker explains the process of creating a new model for tasks and setting up migration scripts by using the 'make model' command.", 'The transcript covers the process of creating and managing tasks within a project, including fetching, creating, updating, and deleting tasks.']}, {'end': 6139.834, 'segs': [{'end': 4274.445, 'src': 'embed', 'start': 4242.176, 'weight': 0, 'content': [{'end': 4246.34, 'text': "And then as time goes on, you'll notice that these CRUD methods are basically the same for every single resource.", 'start': 4242.176, 'duration': 4.164}, {'end': 4253.227, 'text': 'So you could probably create a helper method that decorates these controllers that kind of does this logic for you.', 'start': 4247.001, 'duration': 6.226}, {'end': 4258.888, 'text': "But for the sake of the tutorial, let's not dive into refactoring or do anything like that.", 'start': 4254.724, 'duration': 4.164}, {'end': 4267.558, 'text': 'Basically, we have a way for users to register, log in, create projects, create tasks, update those tasks and projects, and delete them and stuff.', 'start': 4259.509, 'duration': 8.049}, {'end': 4274.445, 'text': "So we're at a good state now that we can commit what we have, wrap this up, and move on to the Vue.js tutorial.", 'start': 4268.459, 'duration': 5.986}], 'summary': 'Crud methods are the same for every resource. users can register, log in, create projects and tasks, update, and delete them. ready to move to vue.js tutorial.', 'duration': 32.269, 'max_score': 4242.176, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez84242176.jpg'}, {'end': 4311.9, 'src': 'embed', 'start': 4281.707, 'weight': 1, 'content': [{'end': 4287.554, 'text': "And very similar to the last section, I'm kind of just going to create it as I go and explain what I'm doing.", 'start': 4281.707, 'duration': 5.847}, {'end': 4291.68, 'text': 'If you feel lost at any time, feel free to pause and go look up the Vue documentation.', 'start': 4288.075, 'duration': 3.605}, {'end': 4300.051, 'text': 'So to get started with building out the UI, you move over to the Vue CLI GitHub repo.', 'start': 4293.706, 'duration': 6.345}, {'end': 4305.174, 'text': 'The latest version they have out is Vue version 3 beta.10.', 'start': 4300.791, 'duration': 4.383}, {'end': 4311.9, 'text': "I'm going to install version beta 9 because I'm getting issues with 10.", 'start': 4306.155, 'duration': 5.745}], 'summary': 'Creating ui using vue cli, installing vue version 3 beta.9 due to issues with beta.10', 'duration': 30.193, 'max_score': 4281.707, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez84281707.jpg'}, {'end': 4573.948, 'src': 'embed', 'start': 4527.668, 'weight': 2, 'content': [{'end': 4536.512, 'text': "So starting off, I'm going to include import sync from Vuex router sync.", 'start': 4527.668, 'duration': 8.844}, {'end': 4540.033, 'text': "I'm going to import Vuetify.", 'start': 4538.592, 'duration': 1.441}, {'end': 4543.575, 'text': 'from beautify.', 'start': 4542.915, 'duration': 0.66}, {'end': 4549.657, 'text': "Let's see what else we might need.", 'start': 4548.317, 'duration': 1.34}, {'end': 4555.559, 'text': "I think that's kind of all we need for right now.", 'start': 4549.677, 'duration': 5.882}, {'end': 4559.14, 'text': 'But what we can do is just include both of those or run them.', 'start': 4556.519, 'duration': 2.621}, {'end': 4561.521, 'text': "So I'm say sync the store with the router.", 'start': 4559.16, 'duration': 2.361}, {'end': 4567.303, 'text': 'And then I want to tell you to use beautify.', 'start': 4565.222, 'duration': 2.081}, {'end': 4573.948, 'text': 'And I think that should be a good start.', 'start': 4571.687, 'duration': 2.261}], 'summary': 'Imported sync from vuex router sync and vuetify from beautify. synced the store with the router and used beautify.', 'duration': 46.28, 'max_score': 4527.668, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez84527668.jpg'}, {'end': 4629.85, 'src': 'embed', 'start': 4604.337, 'weight': 4, 'content': [{'end': 4611.251, 'text': 'And if we did everything right, we should have those additional plugins like beautify in the view X router sync set up.', 'start': 4604.337, 'duration': 6.914}, {'end': 4617.166, 'text': "And just to verify that I'm going to go to my view plugin here.", 'start': 4614.045, 'duration': 3.121}, {'end': 4622.408, 'text': "So that's a, this is a Chrome plugin that you can install or using view X and debugging it.", 'start': 4617.406, 'duration': 5.002}, {'end': 4629.85, 'text': 'So as I change routes, we should see our route change in our state.', 'start': 4623.608, 'duration': 6.242}], 'summary': 'Setting up additional plugins like beautify in the view x router sync for debugging.', 'duration': 25.513, 'max_score': 4604.337, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez84604337.jpg'}, {'end': 4799.946, 'src': 'embed', 'start': 4770.735, 'weight': 5, 'content': [{'end': 4772.815, 'text': "So the first thing I'm going to do is just load up the beautify docs.", 'start': 4770.735, 'duration': 2.08}, {'end': 4777.957, 'text': 'So view to fi go to their docs here.', 'start': 4772.835, 'duration': 5.122}, {'end': 4786.983, 'text': "We're going to be using this throughout our tutorial to kind of figure out what components we can use to build up our application.", 'start': 4779.721, 'duration': 7.262}, {'end': 4799.946, 'text': 'So first off, they say in order to set up your app with beautify, you need to make sure that you have everything wrapped in a V app component.', 'start': 4791.824, 'duration': 8.122}], 'summary': 'Tutorial will use beautify docs to build app components with v app component.', 'duration': 29.211, 'max_score': 4770.735, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez84770735.jpg'}, {'end': 5197.183, 'src': 'embed', 'start': 5167.75, 'weight': 7, 'content': [{'end': 5169.03, 'text': 'Let me just make this into a new line.', 'start': 5167.75, 'duration': 1.28}, {'end': 5170.651, 'text': "So it's a read.", 'start': 5169.07, 'duration': 1.581}, {'end': 5176.014, 'text': 'Cool So we have a button that says projects and it has a little icon to the left of it.', 'start': 5172.793, 'duration': 3.221}, {'end': 5180.536, 'text': "So people can understand that that's like your main view for seeing your projects and to do list items.", 'start': 5176.034, 'duration': 4.502}, {'end': 5183.898, 'text': 'One thing I want to fix really quick is this margin here.', 'start': 5181.257, 'duration': 2.641}, {'end': 5185.698, 'text': "That's easy to be added.", 'start': 5183.938, 'duration': 1.76}, {'end': 5197.183, 'text': "So what I'm going to do is I'm going to go to that title here, and I'm just going to add a class of MR-4, which means margin right four.", 'start': 5185.919, 'duration': 11.264}], 'summary': 'Improving ui by adding margin to the projects button for better visibility.', 'duration': 29.433, 'max_score': 5167.75, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez85167750.jpg'}, {'end': 5249.57, 'src': 'embed', 'start': 5212.625, 'weight': 6, 'content': [{'end': 5213.926, 'text': "So we're going to need a register button.", 'start': 5212.625, 'duration': 1.301}, {'end': 5216.788, 'text': "We're going to need a log out button.", 'start': 5215.527, 'duration': 1.261}, {'end': 5221.791, 'text': "And we're going to need a login button.", 'start': 5220.47, 'duration': 1.321}, {'end': 5236.559, 'text': "And I also want to include some icons on those I just like putting icons next to my buttons, although I'm not sure if that's good UX or not.", 'start': 5230.834, 'duration': 5.725}, {'end': 5242.444, 'text': "So for register, I'm going to say count box.", 'start': 5238.06, 'duration': 4.384}, {'end': 5246.147, 'text': 'For login, I want to do a fingerprint.', 'start': 5244.325, 'duration': 1.822}, {'end': 5249.57, 'text': 'And then for log out, I want to say exit to app.', 'start': 5247.208, 'duration': 2.362}], 'summary': 'A website needs a register, login, and log out buttons with accompanying icons for count box, fingerprint, and exit to app.', 'duration': 36.945, 'max_score': 5212.625, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez85212625.jpg'}, {'end': 5390.651, 'src': 'embed', 'start': 5354.061, 'weight': 8, 'content': [{'end': 5357.764, 'text': 'So it would make sense to pull this out into a separate component right?', 'start': 5354.061, 'duration': 3.703}, {'end': 5363.768, 'text': "Because these buttons down here, like when we have our content, the router view doesn't need to know about the toolbar header.", 'start': 5358.885, 'duration': 4.883}, {'end': 5372.178, 'text': "So to do that, what I'm going to do is I'm going to first copy and paste this.", 'start': 5365.993, 'duration': 6.185}, {'end': 5379.523, 'text': "Actually, in fact, I'm going to cut it and I'm going to make a new component called toolbar.", 'start': 5374.079, 'duration': 5.444}, {'end': 5390.651, 'text': "And then I'm going to scaffold that out and I'm going to paste that HTML inside of that template.", 'start': 5379.543, 'duration': 11.108}], 'summary': "Creating a separate 'toolbar' component for better organization and reusability.", 'duration': 36.59, 'max_score': 5354.061, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez85354061.jpg'}, {'end': 5518.979, 'src': 'embed', 'start': 5492.018, 'weight': 9, 'content': [{'end': 5498.103, 'text': 'So the next component or view I want to work on is going to be the register view so that we can actually register users.', 'start': 5492.018, 'duration': 6.085}, {'end': 5501.766, 'text': "So let's go ahead and get started on that.", 'start': 5500.385, 'duration': 1.381}, {'end': 5507.55, 'text': 'If we go to our toolbar, notice that we had a register button.', 'start': 5501.946, 'duration': 5.604}, {'end': 5512.114, 'text': 'If we wanted that to actually do something when we clicked it,', 'start': 5509.111, 'duration': 3.003}, {'end': 5518.979, 'text': 'we could simply add the property to and pass it the URL we want to redirect the user to when they click on the button.', 'start': 5512.114, 'duration': 6.865}], 'summary': 'Developing the register view to enable user registration and adding a redirect url to the register button.', 'duration': 26.961, 'max_score': 5492.018, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez85492018.jpg'}, {'end': 5796.77, 'src': 'embed', 'start': 5765.665, 'weight': 10, 'content': [{'end': 5770.668, 'text': "One thing I'll notice is that no, I don't want this to expand the entire page with.", 'start': 5765.665, 'duration': 5.003}, {'end': 5778.992, 'text': "So if we were to go back to our component, instead of using a div, let's do an actual container.", 'start': 5773.669, 'duration': 5.323}, {'end': 5780.053, 'text': "So I'll say V container.", 'start': 5779.032, 'duration': 1.021}, {'end': 5792.088, 'text': 'And then make sure we update the closing element and then inside the container, you can do a V layout row wrap.', 'start': 5784.525, 'duration': 7.563}, {'end': 5796.77, 'text': 'And again, these are just beautify built-in components for layout.', 'start': 5793.128, 'duration': 3.642}], 'summary': 'Using v container and v layout for efficient page layout.', 'duration': 31.105, 'max_score': 5765.665, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez85765665.jpg'}, {'end': 5922.139, 'src': 'embed', 'start': 5873.885, 'weight': 11, 'content': [{'end': 5880.733, 'text': "It kind of gives us the benefit of responsive websites without having to do much work, but we're not focusing on making a responsive website.", 'start': 5873.885, 'duration': 6.848}, {'end': 5888.643, 'text': "So let's keep on moving on and try to implement the actual registration, a login, um, functionality.", 'start': 5880.753, 'duration': 7.89}, {'end': 5894.097, 'text': "Cool, so now we're getting into the actual logic of this registration page.", 'start': 5889.653, 'duration': 4.444}, {'end': 5899.682, 'text': 'And we need to first start figuring out how to bind stuff to Vuex.', 'start': 5895.258, 'duration': 4.424}, {'end': 5907.269, 'text': "So for anyone who's not really familiar with Vuex, basically it's a place where you have all of your application logic stored in a single place.", 'start': 5901.043, 'duration': 6.226}, {'end': 5916.577, 'text': 'And then your components are going to update that state and fire off actions and mutations to change the state.', 'start': 5908.249, 'duration': 8.328}, {'end': 5922.139, 'text': "I guess the benefit of that is it's very easy to understand where all your application is.", 'start': 5917.217, 'duration': 4.922}], 'summary': 'Focusing on implementing registration and login functionality, and understanding vuex for application logic.', 'duration': 48.254, 'max_score': 5873.885, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez85873885.jpg'}, {'end': 6080.25, 'src': 'embed', 'start': 6049.094, 'weight': 13, 'content': [{'end': 6056.958, 'text': 'So in order to kind of bind these to change these, we need to first make a couple of mutations.', 'start': 6049.094, 'duration': 7.864}, {'end': 6061.264, 'text': "So if I go here, I'm going to add another property called mutations.", 'start': 6058.203, 'duration': 3.061}, {'end': 6070.487, 'text': 'And inside this mutations property, we can just define different functions that will affect our state here.', 'start': 6064.625, 'duration': 5.862}, {'end': 6072.848, 'text': "So I'm going to say set register email.", 'start': 6070.507, 'duration': 2.341}, {'end': 6080.25, 'text': "That's going to take a state and also an email as a payload.", 'start': 6074.188, 'duration': 6.062}], 'summary': "To bind and change, make mutations, add 'set register email' function.", 'duration': 31.156, 'max_score': 6049.094, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez86049094.jpg'}], 'start': 4214.312, 'title': 'Building rest api and vue.js setup', 'summary': 'Focuses on building a rest api, setting up vue.js, installing dependencies, ui development, app refactoring, and implementing registration logic with vuex, including specific versions and features like vue version 3 beta.9 and vuex persisted state.', 'chapters': [{'end': 4408.407, 'start': 4214.312, 'title': 'Building rest api and setting up vue.js', 'summary': 'Highlights the process of building a rest api which includes creating routes, implementing crud methods for various resources, and concludes with transitioning to setting up the vue.js front end by installing vue version 3 beta.9 and setting up a new project with specific features using vue cli.', 'duration': 194.095, 'highlights': ['Building a REST API with CRUD methods for various resources The process of building a REST API involves creating routes and implementing CRUD methods for various resources, such as registering users, logging in, creating projects and tasks, and updating and deleting them.', 'Transitioning to setting up the Vue.js front end After completing the REST API, the focus shifts to setting up the Vue.js front end by installing Vue version 3 beta.9 and creating a new project with specific features using Vue CLI.']}, {'end': 4730.402, 'start': 4408.407, 'title': 'Setting up vue app dependencies and initialization', 'summary': 'Covers the installation of additional dependencies like axios, lodash, beautify, vuex persisted state, and vuex router sync, setting up the main.js file to include these dependencies, and verifying the functionality using vue plugin and debugging.', 'duration': 321.995, 'highlights': ['The chapter covers the installation of additional dependencies like Axios, Lodash, Beautify, Vuex Persisted State, and Vuex Router Sync. It mentions the installation of key dependencies for the Vue app, including Axios for HTTP requests, Lodash for utility functions, Beautify for styling components, Vuex Persisted State for storing state in local storage, and Vuex Router Sync for synchronizing store state and router.', 'Setting up the main.js file to include the installed dependencies like Vuex Router Sync and Beautify. It explains the process of including the installed dependencies in the main.js file, such as importing Vuex Router Sync and Beautify, and setting them up to sync the store with the router and use Beautify.', 'Verifying the functionality using Vue plugin and debugging to ensure the proper setup of additional plugins like Beautify and Vuex Router Sync. It mentions the use of a Vue plugin for debugging and verifying the functionality of additional plugins like Beautify and Vuex Router Sync, including checking route changes in the state to confirm proper synchronization.']}, {'end': 5331.888, 'start': 4730.442, 'title': 'Building vue application ui', 'summary': 'Discusses building a vue application ui using beautify, including setting up a v app component, adding a toolbar with buttons and icons, and customizing the ui for a to-do list application.', 'duration': 601.446, 'highlights': ['Setting up a V app component is necessary for using Beautify, as everything needs to be wrapped in it to ensure proper functionality. The transcript mentions that in order to set up the app with Beautify, it is necessary to have everything wrapped in a V app component.', 'Adding a toolbar with buttons and icons for functions like registering, logging out, and navigating to projects is demonstrated, with the process of customization and styling explained. The chapter describes the addition of buttons and icons to the toolbar for functions such as registering, logging out, and navigating to projects, along with the process of customization and styling.', 'Customizing the UI for a to-do list application by adding color, fixing the position of the toolbar, and adjusting the layout of buttons and icons is covered. The transcript discusses the customization of the UI for a to-do list application by adding color, fixing the position of the toolbar, and adjusting the layout of buttons and icons.']}, {'end': 5868.452, 'start': 5331.908, 'title': 'Refactoring vue.js app', 'summary': 'Discusses refactoring a vue.js app to decouple components, including creating a separate toolbar component and a register view with input fields and a register button, aiming to improve code organization and user interaction.', 'duration': 536.544, 'highlights': ['Creating a separate toolbar component to decouple components and improve code organization. The speaker explains the process of creating a separate toolbar component to avoid a large app.vue file, with the current file already hitting 30 lines.', 'Creating a register view with input fields and a register button to improve user interaction. The speaker describes the steps to create a register view with input fields for email and password, along with a register button, aiming to enhance user interaction.', 'Using V container and V layout to organize the layout and center the content. The speaker demonstrates the use of V container and V layout to organize the layout, center the content, and adjust the width and position of components for better visual presentation.']}, {'end': 6139.834, 'start': 5873.885, 'title': 'Implementing registration logic with vuex', 'summary': 'Discusses implementing the logic for registration using vuex, focusing on binding data to vuex, creating modules, mutations, and debugging eslint issues.', 'duration': 265.949, 'highlights': ['The chapter discusses implementing the logic for registration using Vuex, focusing on binding data to Vuex, creating modules, mutations, and debugging ESLint issues.', 'Vuex is a place to store application logic, which allows components to update the state and fire off actions and mutations to change the state, making it easy to understand the application flow and changes over time.', 'The state for the register component needs to store the register email and register password, both initially set to null, which will be bound and changed using mutations.', 'The process involves creating a new file for the authentication module, exporting a store module, including the module in the main store, and defining mutations to affect the state by binding and changing data.']}], 'duration': 1925.522, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez84214312.jpg', 'highlights': ['Building a REST API with CRUD methods for various resources', 'Setting up the Vue.js front end with Vue version 3 beta.9', 'Installing key dependencies for the Vue app like Axios, Lodash, Beautify, Vuex Persisted State, and Vuex Router Sync', 'Setting up main.js file to include installed dependencies like Vuex Router Sync and Beautify', 'Verifying functionality using Vue plugin and debugging for proper setup of additional plugins', 'Setting up a V app component for using Beautify', 'Adding a toolbar with buttons and icons for functions like registering, logging out, and navigating to projects', 'Customizing the UI for a to-do list application by adding color, fixing the position of the toolbar, and adjusting the layout of buttons and icons', 'Creating a separate toolbar component to decouple components and improve code organization', 'Creating a register view with input fields and a register button to improve user interaction', 'Using V container and V layout to organize the layout and center the content', 'Implementing the logic for registration using Vuex, focusing on binding data, creating modules, mutations, and debugging ESLint issues', 'Explaining the purpose of Vuex as a place to store application logic and allowing components to update the state and fire off actions and mutations to change the state', 'Defining mutations to affect the state by binding and changing data for the register component']}, {'end': 6894.696, 'segs': [{'end': 6231.93, 'src': 'embed', 'start': 6169.353, 'weight': 0, 'content': [{'end': 6173.818, 'text': 'So, with that being said, how do we actually bind our view component to change those?', 'start': 6169.353, 'duration': 4.465}, {'end': 6186.389, 'text': 'So, if we go back to our register.vue file, what we need to do is first import a couple of helper functions from Vuex.', 'start': 6174.906, 'duration': 11.483}, {'end': 6195.012, 'text': "So I'm first going to do import map state, and I'm going to do map mutations from Vuex.", 'start': 6186.429, 'duration': 8.583}, {'end': 6206.467, 'text': 'And to use these basically just kind of decorate your component object with calling these functions.', 'start': 6197.819, 'duration': 8.648}, {'end': 6214.834, 'text': 'So, for an example, if we wanted the ability to call, set password or set registration email, or one of these,', 'start': 6206.527, 'duration': 8.307}, {'end': 6216.856, 'text': 'we need to map the mutations to our object.', 'start': 6214.834, 'duration': 2.022}, {'end': 6219.525, 'text': "So I'm gonna say map Mutations.", 'start': 6216.876, 'duration': 2.649}, {'end': 6223.006, 'text': 'Actually, first of all, I need to bind that to a method.', 'start': 6220.826, 'duration': 2.18}, {'end': 6225.187, 'text': "So I'm going to say methods is an object.", 'start': 6223.046, 'duration': 2.141}, {'end': 6228.128, 'text': 'And then I want to map some mutations to that.', 'start': 6225.867, 'duration': 2.261}, {'end': 6231.93, 'text': "That's a function where I can pass it the module name.", 'start': 6229.509, 'duration': 2.421}], 'summary': 'Use vuex to bind view component for mutations and methods', 'duration': 62.577, 'max_score': 6169.353, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez86169353.jpg'}, {'end': 6335.345, 'src': 'embed', 'start': 6309.043, 'weight': 2, 'content': [{'end': 6312.764, 'text': 'All right, so if everything worked well, I should be able to start using these.', 'start': 6309.043, 'duration': 3.721}, {'end': 6323.987, 'text': 'So the first thing I want to do is I want to go up here, and I want to bind the value of my text fields to its corresponding state value.', 'start': 6314.865, 'duration': 9.122}, {'end': 6327.128, 'text': "So I'm going to say value is equal to register email.", 'start': 6324.007, 'duration': 3.121}, {'end': 6335.345, 'text': "That's going to bind this text field to whatever the state value is down here.", 'start': 6331.462, 'duration': 3.883}], 'summary': 'Using binding to connect text fields with state values.', 'duration': 26.302, 'max_score': 6309.043, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez86309043.jpg'}, {'end': 6525.168, 'src': 'embed', 'start': 6496.638, 'weight': 3, 'content': [{'end': 6504.511, 'text': "So now when I type, you'll notice that it's firing off a Vuex mutation down here, authentication slash set register email.", 'start': 6496.638, 'duration': 7.873}, {'end': 6507.877, 'text': "And as that's changing, it's updating our state.", 'start': 6505.272, 'duration': 2.605}, {'end': 6515.842, 'text': 'And another cool thing I can show is we can travel back in time to all the different values of our state.', 'start': 6509.218, 'duration': 6.624}, {'end': 6525.168, 'text': "So if I wanted to go back to when my app first loaded, notice that it's going to load my initial store values here, and that's reflected in our UI.", 'start': 6515.942, 'duration': 9.226}], 'summary': 'Using vuex mutation to update state; ability to travel back in time to initial store values demonstrated.', 'duration': 28.53, 'max_score': 6496.638, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez86496638.jpg'}, {'end': 6569.481, 'src': 'embed', 'start': 6536.459, 'weight': 4, 'content': [{'end': 6539.041, 'text': "Let's go back to our code and try to figure out what else is remaining.", 'start': 6536.459, 'duration': 2.582}, {'end': 6543.125, 'text': 'So we had the ability to type into the email and password.', 'start': 6539.662, 'duration': 3.463}, {'end': 6545.587, 'text': "We're updating our store with the corresponding values.", 'start': 6543.145, 'duration': 2.442}, {'end': 6548.79, 'text': 'Now what we want to do is, when the user clicks register,', 'start': 6546.208, 'duration': 2.582}, {'end': 6555.877, 'text': 'we want to fire off a Vuex action to kind of hit that register endpoint we created on our previous tutorial section.', 'start': 6548.79, 'duration': 7.087}, {'end': 6562.303, 'text': "So on this button, I'm going to add an at click callback.", 'start': 6557.719, 'duration': 4.584}, {'end': 6569.481, 'text': "And I'm going to call the register method, which we haven't included yet.", 'start': 6565.017, 'duration': 4.464}], 'summary': 'Updating store with email and password input, registering user with vuex action.', 'duration': 33.022, 'max_score': 6536.459, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez86536459.jpg'}, {'end': 6646.287, 'src': 'embed', 'start': 6618.427, 'weight': 5, 'content': [{'end': 6625.114, 'text': 'So in this particular case, we want to grab the registry email and password, and we want to do a post request to our register endpoint.', 'start': 6618.427, 'duration': 6.687}, {'end': 6632.321, 'text': 'So before we get too far ahead of ourselves, I want to make a new component called HTTP dot JS.', 'start': 6626.195, 'duration': 6.126}, {'end': 6634.864, 'text': "So I'm going to do HTTP dot JS.", 'start': 6632.521, 'duration': 2.343}, {'end': 6639.809, 'text': "And inside here, we're going to export a function.", 'start': 6636.606, 'duration': 3.203}, {'end': 6644.786, 'text': 'which is going to return a new Axios object.', 'start': 6641.343, 'duration': 3.443}, {'end': 6646.287, 'text': "So I'm going to say axios.create.", 'start': 6644.806, 'duration': 1.481}], 'summary': 'Create http dot js component to return new axios object for post request to register endpoint.', 'duration': 27.86, 'max_score': 6618.427, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez86618427.jpg'}], 'start': 6139.834, 'title': 'Vue.js state and component management', 'summary': 'Covers binding view components to module state properties using vuex, mapping mutations, updating store with corresponding values, and implementing http requests for vue component state management.', 'chapters': [{'end': 6252.275, 'start': 6139.834, 'title': 'Vue.js state management and mutation', 'summary': 'Discusses binding view components to change module state properties in vue.js using helper functions from vuex, and mapping mutations to the object, enabling the component to have specific methods for state changes.', 'duration': 112.441, 'highlights': ['The chapter discusses binding view components to change module state properties in Vue.js using helper functions from Vuex. Discussing how to bind view components to change module state properties, demonstrating the use of helper functions from Vuex.', 'It explains mapping mutations to the object, enabling the component to have specific methods for state changes. Explanation of mapping mutations to the object, enabling the component to have specific methods for state changes.']}, {'end': 6894.696, 'start': 6252.335, 'title': 'Vue component state management', 'summary': 'Explains the process of binding text fields to state values, updating the store with corresponding values, and firing off vuex actions to hit the register endpoint, including implementing http requests and proxying api requests to a different port.', 'duration': 642.361, 'highlights': ['Binding text fields to corresponding state values The speaker demonstrates binding the value of text fields to register email and register password state values, allowing the inputs to fetch and populate the values from the store.', 'Updating store with corresponding values on input change The process of updating the Vuex store by firing off Vuex mutations for register email and register password on input change is explained, demonstrating the dynamic update of the state.', 'Firing off Vuex actions to hit the register endpoint The speaker discusses the requirement to trigger Vuex actions when the user clicks register, demonstrating the process of adding an @click callback to call the register method and mapping the register action from the authentication module.', 'Implementing HTTP requests and proxying API requests The implementation of HTTP requests using Axios for making a post request to the register endpoint, and the proxying of API requests to a different port using view.config.js is detailed, addressing the issue of hosting the API in a different port.']}], 'duration': 754.862, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez86139834.jpg', 'highlights': ['Demonstrating the use of helper functions from Vuex to bind view components to change module state properties.', 'Explanation of mapping mutations to the object, enabling the component to have specific methods for state changes.', 'Binding text fields to register email and register password state values, allowing the inputs to fetch and populate the values from the store.', 'Explaining the process of updating the Vuex store by firing off Vuex mutations for register email and register password on input change, demonstrating the dynamic update of the state.', 'Discussing the requirement to trigger Vuex actions when the user clicks register, demonstrating the process of adding an @click callback to call the register method and mapping the register action from the authentication module.', 'Detailing the implementation of HTTP requests using Axios for making a post request to the register endpoint and the proxying of API requests to a different port using view.config.js.']}, {'end': 7994.436, 'segs': [{'end': 6997.456, 'src': 'embed', 'start': 6968.251, 'weight': 2, 'content': [{'end': 6971.773, 'text': "So let's go back to our HTTP, change this timeout to five seconds instead.", 'start': 6968.251, 'duration': 3.522}, {'end': 6975.996, 'text': "And let's try to hit that endpoint again.", 'start': 6973.154, 'duration': 2.842}, {'end': 6982.781, 'text': "OK, we're getting an error.", 'start': 6976.016, 'duration': 6.765}, {'end': 6985.623, 'text': "I think it's saying that the user already exists.", 'start': 6982.801, 'duration': 2.822}, {'end': 6986.724, 'text': 'And it does.', 'start': 6986.184, 'duration': 0.54}, {'end': 6990.767, 'text': "I'll do hello with an exclamation mark.", 'start': 6986.744, 'duration': 4.023}, {'end': 6993.369, 'text': 'Try to register that user instead.', 'start': 6992.008, 'duration': 1.361}, {'end': 6997.456, 'text': 'Well, OK, this one actually works, so we got back that token.', 'start': 6994.895, 'duration': 2.561}], 'summary': 'Adjusted http timeout to 5 seconds, successfully registered a user and received a token.', 'duration': 29.205, 'max_score': 6968.251, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez86968251.jpg'}, {'end': 7065.53, 'src': 'embed', 'start': 7031.525, 'weight': 1, 'content': [{'end': 7039.089, 'text': 'Okay, so first thing we wanted to do is we said we wanted to store the token inside the store.', 'start': 7031.525, 'duration': 7.564}, {'end': 7045.372, 'text': "So if I do a dot, then you can grab data that's returned from the Axios request.", 'start': 7039.289, 'duration': 6.083}, {'end': 7059.148, 'text': 'And then inside this data, we can simply do commit Set token, data.token.', 'start': 7051.835, 'duration': 7.313}, {'end': 7063.969, 'text': "Of course, we don't have a commit or a mutation called set token, so let's add one.", 'start': 7060.169, 'duration': 3.8}, {'end': 7065.53, 'text': "We'll say set token.", 'start': 7064.47, 'duration': 1.06}], 'summary': 'Create a mutation to store token retrieved from axios request.', 'duration': 34.005, 'max_score': 7031.525, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez87031525.jpg'}, {'end': 7188.831, 'src': 'embed', 'start': 7094.848, 'weight': 0, 'content': [{'end': 7097.47, 'text': 'Notice that it fires off the set token mutation.', 'start': 7094.848, 'duration': 2.622}, {'end': 7100.033, 'text': 'And now in our state, we have a token set.', 'start': 7098.111, 'duration': 1.922}, {'end': 7103.035, 'text': "So that's step one.", 'start': 7102.255, 'duration': 0.78}, {'end': 7107.459, 'text': 'Step two is we need to change our router location.', 'start': 7103.636, 'duration': 3.823}, {'end': 7117.283, 'text': 'So we need to first import that router, so import router from dot dot slash router, just to import this file here.', 'start': 7109.497, 'duration': 7.786}, {'end': 7123.007, 'text': "And then if we want to dynamically change the route that we're on, we can do router dot push.", 'start': 7119.344, 'duration': 3.663}, {'end': 7125.229, 'text': "I'm going to say go to the root.", 'start': 7123.548, 'duration': 1.681}, {'end': 7131.313, 'text': "Let's try registering with yet another one.", 'start': 7129.332, 'duration': 1.981}, {'end': 7137.138, 'text': "So I'll just say hello, click register, and notice that it redirected us when we successfully logged in.", 'start': 7131.333, 'duration': 5.805}, {'end': 7140.269, 'text': 'So a couple of other things we want to do.', 'start': 7138.567, 'duration': 1.702}, {'end': 7141.81, 'text': 'is what if there was a login error right?', 'start': 7140.269, 'duration': 1.541}, {'end': 7144.012, 'text': 'What if the user tried to log in and it was incorrect?', 'start': 7141.83, 'duration': 2.182}, {'end': 7148.256, 'text': 'So we should probably display some sort of registration error on this page.', 'start': 7144.793, 'duration': 3.463}, {'end': 7153.321, 'text': "So to do that, we're going to need yet another store variable called a registerError.", 'start': 7149.117, 'duration': 4.204}, {'end': 7155.863, 'text': 'Maybe null by default.', 'start': 7153.341, 'duration': 2.522}, {'end': 7159.967, 'text': 'We want a mutation to be able to set registerError.', 'start': 7156.804, 'duration': 3.163}, {'end': 7181.164, 'text': 'And then in our register.vue file, we want to add a new alert.', 'start': 7174.918, 'duration': 6.246}, {'end': 7183.326, 'text': 'Probably add it right above the register button.', 'start': 7181.184, 'duration': 2.142}, {'end': 7188.831, 'text': "So I'll say v alert right in that component.", 'start': 7183.426, 'duration': 5.405}], 'summary': 'Setting token mutation, changing router location, displaying registration error.', 'duration': 93.983, 'max_score': 7094.848, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez87094848.jpg'}, {'end': 7501.684, 'src': 'embed', 'start': 7460.387, 'weight': 3, 'content': [{'end': 7470.208, 'text': "And here I'm going to say computed is equal to map getters of the authentication module.", 'start': 7460.387, 'duration': 9.821}, {'end': 7472.35, 'text': 'And then I want to say is logged in.', 'start': 7470.869, 'duration': 1.481}, {'end': 7483.157, 'text': 'So that will basically grab us that getter function and we can call it up here to display and hide different things.', 'start': 7472.37, 'duration': 10.787}, {'end': 7490.282, 'text': 'So if we are logged in, you want to display log out.', 'start': 7486.019, 'duration': 4.263}, {'end': 7497.178, 'text': "I'm going to say V if we are logged in.", 'start': 7494.335, 'duration': 2.843}, {'end': 7501.684, 'text': 'This should always be displayed.', 'start': 7500.462, 'duration': 1.222}], 'summary': "Using computed map getters to display 'log out' if logged in.", 'duration': 41.297, 'max_score': 7460.387, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez87460387.jpg'}, {'end': 7658.139, 'src': 'embed', 'start': 7624.955, 'weight': 4, 'content': [{'end': 7631.179, 'text': 'or sorry, the projects button went away and the logout button went away.', 'start': 7624.955, 'duration': 6.224}, {'end': 7633.821, 'text': "Now we're showed register and login.", 'start': 7632.4, 'duration': 1.421}, {'end': 7635.422, 'text': 'And we can also check the store.', 'start': 7633.901, 'duration': 1.521}, {'end': 7637.223, 'text': 'Notice that token is set to null now.', 'start': 7635.922, 'duration': 1.301}, {'end': 7647.897, 'text': 'I think what we also want to do though is we want to redirect the user to the login page whenever we click logout.', 'start': 7640.055, 'duration': 7.842}, {'end': 7658.139, 'text': 'So maybe instead of mapping a mutation, we could either create an action or we could just create the logout functionality here.', 'start': 7649.117, 'duration': 9.022}], 'summary': 'The projects and logout buttons disappeared, leaving only register and login options. the token is now null, and there is a need to redirect users to the login page upon clicking logout.', 'duration': 33.184, 'max_score': 7624.955, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez87624955.jpg'}, {'end': 7770.607, 'src': 'embed', 'start': 7733.22, 'weight': 5, 'content': [{'end': 7735.841, 'text': "If I go to my view, and I'm going to make a new component called login.", 'start': 7733.22, 'duration': 2.621}, {'end': 7742.403, 'text': "And I'm just going to copy and paste from register because it's going to be basically the same thing with different mutations and actions.", 'start': 7735.881, 'duration': 6.522}, {'end': 7752.247, 'text': 'Login So copy the register component and made a login view here.', 'start': 7746.165, 'duration': 6.082}, {'end': 7760.11, 'text': "If I go to router, let's go ahead and make a login route.", 'start': 7752.307, 'duration': 7.803}, {'end': 7770.607, 'text': "And inside the login route, let's just do login here.", 'start': 7768.086, 'duration': 2.521}], 'summary': 'Creating a login component by copying from register, and adding a login route.', 'duration': 37.387, 'max_score': 7733.22, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez87733220.jpg'}], 'start': 6895.976, 'title': 'Troubleshooting user registration and authentication', 'summary': 'Covers troubleshooting user registration issues such as server response time and user feedback, implementing error handling, and authentication module implementation, including user login status check, toolbar component update, and login/register functionality.', 'chapters': [{'end': 7123.007, 'start': 6895.976, 'title': 'Troubleshooting user registration and token storage', 'summary': 'Details troubleshooting steps for user registration, including changing server timeout, token storage in store, and router location change, aiming to resolve issues with server response time and user feedback.', 'duration': 227.031, 'highlights': ['The server did not respond within a second, prompting a timeout change to five seconds for user registration, resulting in successful registration with a new user.', 'Storing the token in the store is accomplished through a commit Set token mutation, which sets the state.token to the received token, ensuring successful token storage.', 'The process includes troubleshooting steps, such as examining server response time, implementing token storage in the store, and dynamically changing the router location, with successful resolution of server response time and user feedback issues.']}, {'end': 7395.988, 'start': 7123.548, 'title': 'User registration error handling', 'summary': 'Demonstrates implementing error handling for user registration, including setting and displaying registration errors, with a focus on rendering error messages and redirecting upon successful registration.', 'duration': 272.44, 'highlights': ['Setting and displaying registration errors The process of setting and displaying registration errors, including the implementation of an alert component to render error messages based on the defined register error.', 'Redirecting upon successful registration The redirection process upon successful registration, ensuring that users are redirected upon successful registration and the nullification of registration errors for subsequent registration attempts.', 'Handling login errors Addressing the handling of login errors, including the need to display registration errors when a user attempts to log in with incorrect credentials.']}, {'end': 7994.436, 'start': 7399.09, 'title': 'Implementing authentication module', 'summary': "Details the implementation of a getter function for checking user login status, updating the toolbar component to display buttons based on the user's login status, implementing the logout functionality, creating the login view and functionality, and adding the necessary mutations and actions for login and register.", 'duration': 595.346, 'highlights': ["Implementing a getter function to check user login status and updating the toolbar component to display buttons based on the user's login status. The chapter details the implementation of a getter function for checking user login status and updating the toolbar component to display buttons based on the user's login status.", 'Implementing the logout functionality by setting the token to null and redirecting the user to the login page. The chapter covers the implementation of the logout functionality by setting the token to null and redirecting the user to the login page.', 'Creating the login view and functionality by adding the necessary mutations and actions for login. The chapter involves creating the login view and functionality by adding the necessary mutations and actions for login.']}], 'duration': 1098.46, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez86895976.jpg', 'highlights': ['The process includes troubleshooting steps, such as examining server response time, implementing token storage in the store, and dynamically changing the router location, with successful resolution of server response time and user feedback issues.', 'Storing the token in the store is accomplished through a commit Set token mutation, which sets the state.token to the received token, ensuring successful token storage.', 'The server did not respond within a second, prompting a timeout change to five seconds for user registration, resulting in successful registration with a new user.', "Implementing a getter function to check user login status and updating the toolbar component to display buttons based on the user's login status.", 'Implementing the logout functionality by setting the token to null and redirecting the user to the login page.', 'Creating the login view and functionality by adding the necessary mutations and actions for login.', 'Setting and displaying registration errors The process of setting and displaying registration errors, including the implementation of an alert component to render error messages based on the defined register error.', 'Redirecting upon successful registration The redirection process upon successful registration, ensuring that users are redirected upon successful registration and the nullification of registration errors for subsequent registration attempts.', 'Handling login errors Addressing the handling of login errors, including the need to display registration errors when a user attempts to log in with incorrect credentials.']}, {'end': 9724.522, 'segs': [{'end': 8046.066, 'src': 'embed', 'start': 7994.436, 'weight': 0, 'content': [{'end': 8001.238, 'text': 'as this was testing one and a login with that same username and password and at worked as well.', 'start': 7994.436, 'duration': 6.802}, {'end': 8007.1, 'text': 'Awesome So we have register and we have login working.', 'start': 8004.219, 'duration': 2.881}, {'end': 8008.341, 'text': 'We have log out working.', 'start': 8007.32, 'duration': 1.021}, {'end': 8011.902, 'text': "We're hiding and showing different buttons based on the token being set.", 'start': 8008.361, 'duration': 3.541}, {'end': 8021.27, 'text': "Let's go ahead and commit what we have for this login functionality, and then we can move on to something else.", 'start': 8015.427, 'duration': 5.843}, {'end': 8028.014, 'text': "So let's move on to actually displaying the ability to add projects and add tasks and stuff like that.", 'start': 8022.571, 'duration': 5.443}, {'end': 8032.696, 'text': 'So the first thing we need to start out with is kind of like a projects panel.', 'start': 8028.054, 'duration': 4.642}, {'end': 8041.282, 'text': "So if we go to the main view here, our home view, This is kind of what we're looking at right here.", 'start': 8034.257, 'duration': 7.025}, {'end': 8046.066, 'text': "So I'm going to actually rename this to projects.", 'start': 8042.082, 'duration': 3.984}], 'summary': 'Successful login and functionality implemented, moving on to adding projects and tasks.', 'duration': 51.63, 'max_score': 7994.436, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez87994436.jpg'}, {'end': 8098.834, 'src': 'embed', 'start': 8078.819, 'weight': 3, 'content': [{'end': 8089.381, 'text': 'the first thing I want to kind of display is a panel on the left with the title that says projects and then inside that panel I want to display a list of my projects and then an input box at the bottom.', 'start': 8078.819, 'duration': 10.562}, {'end': 8091.862, 'text': 'So we can create a new project.', 'start': 8089.822, 'duration': 2.04}, {'end': 8098.834, 'text': "So first thing is full idea of a panel is something that we're going to be using throughout the application.", 'start': 8094.051, 'duration': 4.783}], 'summary': "Panel with 'projects' title, list of projects, and input box for new project creation to be displayed on the left side of the application.", 'duration': 20.015, 'max_score': 8078.819, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez88078819.jpg'}, {'end': 8158.09, 'src': 'embed', 'start': 8128.47, 'weight': 4, 'content': [{'end': 8134.231, 'text': 'And inside that raised white panel, or card I mean, I want to declare a toolbar.', 'start': 8128.47, 'duration': 5.761}, {'end': 8138.071, 'text': 'And I want to make sure that it is flat.', 'start': 8134.251, 'duration': 3.82}, {'end': 8139.692, 'text': "I'm going to say dense.", 'start': 8138.091, 'duration': 1.601}, {'end': 8140.612, 'text': "I'm going to say dark.", 'start': 8139.712, 'duration': 0.9}, {'end': 8142.512, 'text': "And I'm going to say color of.", 'start': 8141.292, 'duration': 1.22}, {'end': 8152.314, 'text': 'Then inside that toolbar, I want to say be toolbar.', 'start': 8142.532, 'duration': 9.782}, {'end': 8158.09, 'text': 'title is going to be equal to whatever the user passing in a property.', 'start': 8153.925, 'duration': 4.165}], 'summary': 'Declare a flat, dense, dark toolbar inside a raised white panel.', 'duration': 29.62, 'max_score': 8128.47, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez88128470.jpg'}, {'end': 8329.302, 'src': 'embed', 'start': 8289.297, 'weight': 5, 'content': [{'end': 8293.039, 'text': "Um, let's go ahead and do some layout here.", 'start': 8289.297, 'duration': 3.742}, {'end': 8295.32, 'text': "So that's not right next to the side of it.", 'start': 8293.099, 'duration': 2.221}, {'end': 8299.143, 'text': "So instead of using a div home, I'm just going to do a B container.", 'start': 8296.061, 'duration': 3.082}, {'end': 8300.884, 'text': 'So V container.', 'start': 8299.442, 'duration': 1.442}, {'end': 8312.108, 'text': "I'm going to leave that out for now.", 'start': 8308.064, 'duration': 4.044}, {'end': 8316.45, 'text': 'In the container, we want a VLayout.', 'start': 8314.45, 'duration': 2}, {'end': 8321.155, 'text': 'And in the VLayout, of course, we want a VFlex.', 'start': 8319.174, 'duration': 1.981}, {'end': 8328.141, 'text': "And this flex is going to be, I'm going to say, small of four.", 'start': 8321.995, 'duration': 6.146}, {'end': 8329.302, 'text': "So it's going to be four columns.", 'start': 8328.262, 'duration': 1.04}], 'summary': 'Creating layout with b container, vlayout, and vflex of 4 columns.', 'duration': 40.005, 'max_score': 8289.297, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez88289297.jpg'}, {'end': 8518.601, 'src': 'embed', 'start': 8484.295, 'weight': 6, 'content': [{'end': 8490.101, 'text': "So inside here, I'm going to say, give me a text field.", 'start': 8484.295, 'duration': 5.806}, {'end': 8498.591, 'text': 'And we just want to allow the user to type in the new name of their project.', 'start': 8493.545, 'duration': 5.046}, {'end': 8509.079, 'text': "So I'm going to say, let's see, placeholder is going to be my project name, dot, dot, dot.", 'start': 8499.411, 'duration': 9.668}, {'end': 8512.8, 'text': 'Save this and make sure everything is correctly.', 'start': 8510.779, 'duration': 2.021}, {'end': 8514.76, 'text': 'All right, so we have a text field called my project name.', 'start': 8512.82, 'duration': 1.94}, {'end': 8518.601, 'text': 'And then we also need a submit button.', 'start': 8516.881, 'duration': 1.72}], 'summary': 'Creating a text field for project name input and a submit button.', 'duration': 34.306, 'max_score': 8484.295, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez88484295.jpg'}, {'end': 8648.528, 'src': 'embed', 'start': 8617.84, 'weight': 7, 'content': [{'end': 8622.944, 'text': "Let's give it dark and see what happens.", 'start': 8617.84, 'duration': 5.104}, {'end': 8626.49, 'text': 'All right, so we have a Create button now that looks a little bit nicer.', 'start': 8624.144, 'duration': 2.346}, {'end': 8628.756, 'text': "It's a little bit down further to line up with this.", 'start': 8626.53, 'duration': 2.226}, {'end': 8642.926, 'text': 'So similar to what we did at the log in and register, we need to listen to when the keys change on the text field and then update the store.', 'start': 8634.204, 'duration': 8.722}, {'end': 8648.528, 'text': "And of course, we also need to set the value to something that's coming from the store.", 'start': 8644.247, 'duration': 4.281}], 'summary': 'Developed a create button and implemented text field updates for store.', 'duration': 30.688, 'max_score': 8617.84, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez88617840.jpg'}, {'end': 8802.994, 'src': 'embed', 'start': 8718.344, 'weight': 8, 'content': [{'end': 8720.324, 'text': 'So then here, of course, we need to bind value.', 'start': 8718.344, 'duration': 1.98}, {'end': 8722.784, 'text': "It's going to be new project name.", 'start': 8720.344, 'duration': 2.44}, {'end': 8726.565, 'text': 'We need to make sure we include those.', 'start': 8724.905, 'duration': 1.66}, {'end': 8734.967, 'text': 'So import map mutations, map state from Vuex.', 'start': 8726.605, 'duration': 8.362}, {'end': 8745.279, 'text': "And computed, we're going to say map state of projects now, because we're using the projects module.", 'start': 8737.617, 'duration': 7.662}, {'end': 8747.5, 'text': 'And we need a new project.', 'start': 8746.019, 'duration': 1.481}, {'end': 8765.105, 'text': 'And then for methods, mapping mutations, set new project name.', 'start': 8751.821, 'duration': 13.284}, {'end': 8780.067, 'text': 'So again, when we do input, we just need to pass set new project name.', 'start': 8775.626, 'duration': 4.441}, {'end': 8786.569, 'text': "All right, so let's verify that this is working as expected.", 'start': 8780.087, 'duration': 6.482}, {'end': 8787.569, 'text': "So I'm going to type hello.", 'start': 8786.629, 'duration': 0.94}, {'end': 8790.65, 'text': "That's sending off the mutations for set project name.", 'start': 8788.17, 'duration': 2.48}, {'end': 8795.152, 'text': "And we're seeing that update get reflected here in the Vuex state.", 'start': 8791.351, 'duration': 3.801}, {'end': 8802.994, 'text': 'So I guess the last step is we just need to send off an action to the back end.', 'start': 8797.412, 'duration': 5.582}], 'summary': 'Configuring vuex for new project name input and state mutation.', 'duration': 84.65, 'max_score': 8718.344, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez88718344.jpg'}, {'end': 9027.415, 'src': 'embed', 'start': 8990.035, 'weight': 10, 'content': [{'end': 8996.297, 'text': 'Create Sending off a request to API slash projects rating of 401 Unauthorized.', 'start': 8990.035, 'duration': 6.262}, {'end': 8999.399, 'text': "Let's look at the Network tab and see what's going on here.", 'start': 8997.018, 'duration': 2.381}, {'end': 9003.421, 'text': 'Saying my JWT is malformed.', 'start': 9001.48, 'duration': 1.941}, {'end': 9008.463, 'text': "So let's look at the headers.", 'start': 9006.862, 'duration': 1.601}, {'end': 9015.345, 'text': 'And for some reason, the token is not on the headers.', 'start': 9013.243, 'duration': 2.102}, {'end': 9018.107, 'text': "So let's go back to HTTP.", 'start': 9015.645, 'duration': 2.462}, {'end': 9027.415, 'text': 'Did I maybe spell something wrong? Headers, authorization, error, state authentication.', 'start': 9018.127, 'duration': 9.288}], 'summary': 'Api request to /projects received 401 unauthorized error due to malformed jwt and missing token in headers.', 'duration': 37.38, 'max_score': 8990.035, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez88990035.jpg'}, {'end': 9342.263, 'src': 'embed', 'start': 9311.016, 'weight': 11, 'content': [{'end': 9314.857, 'text': 'Let me just go ahead and commit what we have, and we can go back and create more logic in a second.', 'start': 9311.016, 'duration': 3.841}, {'end': 9328.791, 'text': 'So the next thing we want to do is, when the projects component is mounted,', 'start': 9323.786, 'duration': 5.005}, {'end': 9333.715, 'text': 'we want to fetch all the projects that the user has and just render it in this list here.', 'start': 9328.791, 'duration': 4.924}, {'end': 9342.263, 'text': 'Because if I were to restart this page or refresh this page and log back in, notice that we did create projects on that user,', 'start': 9333.735, 'duration': 8.528}], 'summary': "Commit current progress, fetch and render user's projects on component mount.", 'duration': 31.247, 'max_score': 9311.016, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez89311016.jpg'}, {'end': 9543.949, 'src': 'embed', 'start': 9515.238, 'weight': 13, 'content': [{'end': 9518.859, 'text': 'So pretty straightforward as to how to fetch projects and how to create projects now.', 'start': 9515.238, 'duration': 3.621}, {'end': 9524.916, 'text': 'The two other pieces of functionality we kind of need for projects is.', 'start': 9521.394, 'duration': 3.522}, {'end': 9529.159, 'text': 'we need to be able to edit this title and we need to be able to delete the project.', 'start': 9524.916, 'duration': 4.243}, {'end': 9538.145, 'text': "So what I'm going to do is I'm going to try to add a button here, which is like a pencil button.", 'start': 9535.043, 'duration': 3.102}, {'end': 9543.949, 'text': "And when you click it, it's going to make this become a text field so that we can edit it as needed.", 'start': 9538.666, 'duration': 5.283}], 'summary': 'Demonstrating project fetching, creation, editing, and deletion functionality.', 'duration': 28.711, 'max_score': 9515.238, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez89515238.jpg'}], 'start': 7994.436, 'title': 'Vue.js project development', 'summary': 'Covers successful implementation of login, logout, and token-based button controls, creating a reusable panel component for projects, vue.js project creation, and troubleshooting api integration and displaying projects with a focus on using vuex for state management and handling http requests.', 'chapters': [{'end': 8078.819, 'start': 7994.436, 'title': 'Login functionality and displaying projects', 'summary': 'Discusses the successful implementation of login, logout, and token-based button controls, and it transitions to the plan for adding project and task functionalities.', 'duration': 84.383, 'highlights': ['Successfully implemented register, login, and logout functionalities. Implemented register, login, and logout functionalities.', 'Hiding and showing different buttons based on the token being set. Implemented dynamic button control based on token status.', 'Transitioning to displaying the ability to add projects and tasks. Transitioning to add project and task functionalities.']}, {'end': 8617.82, 'start': 8078.819, 'title': 'Creating a panel component for projects', 'summary': 'Describes the process of creating a reusable panel component for displaying projects and an input box, allowing the addition of new projects, along with the layout and rendering of the panel.', 'duration': 539.001, 'highlights': ["A panel component called 'projects' with a list of projects and an input box for creating new projects is created, and it is intended to be used throughout the application. A panel component named 'projects' is created to display a list of projects and an input box for adding new projects, meant for universal usage in the application.", 'The panel is defined with specific styling, including white color, elevation of two, and a toolbar with a user-defined title. The panel is styled with white color, elevation of two, and a toolbar containing a user-defined title.', 'The layout is structured using VLayout and VFlex, with the panel placed on the left and a placeholder for tasks on the right. The layout is organized using VLayout and VFlex, positioning the panel on the left and creating a placeholder for tasks on the right.', 'A text field for entering project names and a submit button for creating new projects are added inside the projects panel. A text field for entering project names and a submit button for creating new projects are incorporated within the projects panel.']}, {'end': 8913.688, 'start': 8617.84, 'title': 'Vue.js project creation', 'summary': 'Covers the process of creating a new project in a vue.js application, including updating the store, binding values, and sending off an action to the backend, with a focus on using vuex for state management and handling http requests.', 'duration': 295.848, 'highlights': ['The process involves creating a new project in a Vue.js application and updating the store by listening to changes on the text field and setting the value to something from the store.', 'Importing the projects module in the main index.js file and binding the new project name to the state.', 'Implementing the action to send off a request to the backend to create a new project, involving an HTTP post request and updating the Vuex state with the new project data.', 'Utilizing Vuex for state management, including creating a new mutation to set the new project name and using map state and map mutations for handling state and mutations.']}, {'end': 9724.522, 'start': 8917.491, 'title': 'Troubleshooting api integration and displaying projects', 'summary': 'Covers troubleshooting api integration, displaying projects, and creating logic for editing and deleting projects. key points include adding authorization headers, handling jwt token errors, creating and rendering projects, fetching projects from the backend, and implementing logic for editing and deleting projects.', 'duration': 807.031, 'highlights': ['Adding authorization headers for API requests and handling JWT token errors The speaker emphasizes the need to add authorization headers to API requests and troubleshoots a JWT token error, highlighting the importance of securing API requests.', 'Creating and rendering projects in the frontend The speaker demonstrates creating and rendering projects in the frontend, indicating progress in the development process and successful integration with the backend.', "Fetching projects from the backend and displaying them in the frontend The speaker explains the process of fetching projects from the backend and displaying them in the frontend, ensuring that the user's projects are accurately rendered.", 'Implementing logic for editing and deleting projects The speaker discusses the need to implement logic for editing and deleting projects, outlining the upcoming development steps to enhance user interaction with the displayed projects.']}], 'duration': 1730.086, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez87994436.jpg', 'highlights': ['Successfully implemented register, login, and logout functionalities.', 'Implemented dynamic button control based on token status.', 'Transitioning to add project and task functionalities.', "A panel component named 'projects' is created to display a list of projects and an input box for adding new projects, meant for universal usage in the application.", 'The panel is styled with white color, elevation of two, and a toolbar containing a user-defined title.', 'The layout is organized using VLayout and VFlex, positioning the panel on the left and creating a placeholder for tasks on the right.', 'A text field for entering project names and a submit button for creating new projects are incorporated within the projects panel.', 'The process involves creating a new project in a Vue.js application and updating the store by listening to changes on the text field and setting the value to something from the store.', 'Implementing the action to send off a request to the backend to create a new project, involving an HTTP post request and updating the Vuex state with the new project data.', 'Utilizing Vuex for state management, including creating a new mutation to set the new project name and using map state and map mutations for handling state and mutations.', 'The speaker emphasizes the need to add authorization headers to API requests and troubleshoots a JWT token error, highlighting the importance of securing API requests.', 'The speaker demonstrates creating and rendering projects in the frontend, indicating progress in the development process and successful integration with the backend.', "The speaker explains the process of fetching projects from the backend and displaying them in the frontend, ensuring that the user's projects are accurately rendered.", 'The speaker discusses the need to implement logic for editing and deleting projects, outlining the upcoming development steps to enhance user interaction with the displayed projects.']}, {'end': 13736.425, 'segs': [{'end': 10214.096, 'src': 'embed', 'start': 10178.447, 'weight': 3, 'content': [{'end': 10183.571, 'text': "notice that nothing changes because we haven't actually bound to the input callback on the project edit.", 'start': 10178.447, 'duration': 5.124}, {'end': 10198.834, 'text': 'So we need to go back and go here and say add a new mutation called set project title, state project.', 'start': 10183.611, 'duration': 15.223}, {'end': 10201.338, 'text': 'actually, this is going to be a message.', 'start': 10198.834, 'duration': 2.504}, {'end': 10209.695, 'text': "so i'm going to say project title And then project.", 'start': 10201.338, 'duration': 8.357}, {'end': 10211.055, 'text': 'that title is equal to title.', 'start': 10209.695, 'duration': 1.36}, {'end': 10214.096, 'text': 'So we have a simple mutation, we can set the title.', 'start': 10212.096, 'duration': 2}], 'summary': 'Adding a new mutation to set project title in the callback to bind to the input on project edit.', 'duration': 35.649, 'max_score': 10178.447, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez810178447.jpg'}, {'end': 10407.528, 'src': 'embed', 'start': 10372.174, 'weight': 5, 'content': [{'end': 10378.636, 'text': 'And then go back to our actions or our part projects module and create an action called a project.', 'start': 10372.174, 'duration': 6.462}, {'end': 10392.488, 'text': 'Basically, what we want to do is just send off a patch request to the endpoint that we have.', 'start': 10384.458, 'duration': 8.03}, {'end': 10398.873, 'text': "So I'm going to say HTTP patch on projects slash project.id.", 'start': 10392.588, 'duration': 6.285}, {'end': 10403.116, 'text': 'And then this needs to be string interpolation, so we can use backticks.', 'start': 10398.893, 'duration': 4.223}, {'end': 10407.528, 'text': 'OK, there we go.', 'start': 10407.028, 'duration': 0.5}], 'summary': 'Creating a project action to send a patch request to the endpoint using string interpolation.', 'duration': 35.354, 'max_score': 10372.174, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez810372174.jpg'}, {'end': 10728.279, 'src': 'embed', 'start': 10694.613, 'weight': 0, 'content': [{'end': 10698.936, 'text': 'You go to the network tab, notice it made a delete request to project two.', 'start': 10694.613, 'duration': 4.323}, {'end': 10707.36, 'text': 'And if I were to refresh and log back in, that project has been deleted from the list.', 'start': 10700.857, 'duration': 6.503}, {'end': 10712.97, 'text': 'Go ahead and delete everything and see how it works.', 'start': 10710.589, 'duration': 2.381}, {'end': 10725.997, 'text': "One thing I'll also notice is when I press Enter on this text field, it does not create the project.", 'start': 10719.774, 'duration': 6.223}, {'end': 10728.279, 'text': "So let's go ahead and try to implement that as well.", 'start': 10726.057, 'duration': 2.222}], 'summary': 'Delete request made to project two; unable to create project on pressing enter.', 'duration': 33.666, 'max_score': 10694.613, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez810694613.jpg'}, {'end': 10785.857, 'src': 'embed', 'start': 10757.041, 'weight': 4, 'content': [{'end': 10760.823, 'text': 'This is going to be called edit and delete projects.', 'start': 10757.041, 'duration': 3.782}, {'end': 10770.467, 'text': 'Alright. so before we move on to this tasks panel, I want to go ahead and abstract some things that we can reuse components,', 'start': 10763.462, 'duration': 7.005}, {'end': 10773.429, 'text': 'because tasks is basically going to be very similar to this projects panel.', 'start': 10770.467, 'duration': 2.962}, {'end': 10780.213, 'text': 'So, first thing I want to abstract is this bottom create thing or section that we have.', 'start': 10774.87, 'duration': 5.343}, {'end': 10785.857, 'text': 'I want to have a component which has a create button where I can change this text dynamically through a prop.', 'start': 10780.213, 'duration': 5.644}], 'summary': 'Creating reusable components for edit and delete projects functionality.', 'duration': 28.816, 'max_score': 10757.041, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez810757041.jpg'}, {'end': 12633.761, 'src': 'embed', 'start': 12588.11, 'weight': 6, 'content': [{'end': 12594.155, 'text': 'So let me just copy save project and delete project and just change that as needed into our actions.', 'start': 12588.11, 'duration': 6.045}, {'end': 12597.74, 'text': 'So save task.', 'start': 12596.138, 'duration': 1.602}, {'end': 12599.261, 'text': "I'm going to take a task.", 'start': 12597.76, 'duration': 1.501}, {'end': 12613.716, 'text': "And then that's going to hit tasks, task.id, task, task, and delete task, task, remove task.", 'start': 12601.103, 'duration': 12.613}, {'end': 12628.739, 'text': "Forgot to bring in the unsetEditMode, so I'm going to do unsetEditMode and be false.", 'start': 12623.117, 'duration': 5.622}, {'end': 12633.761, 'text': "OK, let's see if we're missing anything.", 'start': 12632.22, 'duration': 1.541}], 'summary': 'Developing and testing project and task actions for implementation.', 'duration': 45.651, 'max_score': 12588.11, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez812588110.jpg'}, {'end': 13264.495, 'src': 'embed', 'start': 13230.232, 'weight': 1, 'content': [{'end': 13234.395, 'text': 'Basically, now when I refresh the page, I had to log in one more time.', 'start': 13230.232, 'duration': 4.163}, {'end': 13241.8, 'text': "But now, when I refresh the page, it's going to cache everything that was in my store inside local storage,", 'start': 13234.435, 'duration': 7.365}, {'end': 13245.163, 'text': "meaning that I don't have to log in again or whatnot.", 'start': 13241.8, 'duration': 3.363}, {'end': 13252.628, 'text': "So basically, exactly how I have my app state before I leave and refresh, that's how it's going to load back up.", 'start': 13246.324, 'duration': 6.304}, {'end': 13255.49, 'text': 'So if you notice, I clicked on this project and it loaded back up for me.', 'start': 13252.708, 'duration': 2.782}, {'end': 13264.495, 'text': "So it's very useful in terms of like UX, because you don't want a user to have to keep logging in over and over again,", 'start': 13258.372, 'duration': 6.123}], 'summary': 'Improved page refresh to store app state in local storage, eliminating the need for repeated logins for better ux.', 'duration': 34.263, 'max_score': 13230.232, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez813230232.jpg'}, {'end': 13733.684, 'src': 'heatmap', 'start': 13597.441, 'weight': 1, 'content': [{'end': 13601.724, 'text': "And if everything worked, it should say it's hosted on 000 80.", 'start': 13597.441, 'duration': 4.283}, {'end': 13603.865, 'text': 'Then we can go up here and try to go to local.', 'start': 13601.724, 'duration': 2.141}, {'end': 13607.488, 'text': 'We can try to go to the IP address here.', 'start': 13605.967, 'duration': 1.521}, {'end': 13611.37, 'text': 'Just hit it and see what happens.', 'start': 13610.069, 'duration': 1.301}, {'end': 13613.875, 'text': 'And so our app is now loaded.', 'start': 13612.674, 'duration': 1.201}, {'end': 13619.518, 'text': "It's hosted at this port on, or it's hosted at this IP port 80.", 'start': 13613.895, 'duration': 5.623}, {'end': 13621.639, 'text': 'We can see that our app is running.', 'start': 13619.518, 'duration': 2.121}, {'end': 13624.761, 'text': 'Make sure that we can actually log in.', 'start': 13623.34, 'duration': 1.421}, {'end': 13626.442, 'text': "Let's just click login and see what happens.", 'start': 13624.861, 'duration': 1.581}, {'end': 13630.824, 'text': 'And it successfully logged us into our app.', 'start': 13628.162, 'duration': 2.662}, {'end': 13643.498, 'text': 'Cool So I mean, basically, you just follow these steps if you wanted to get your app running in production.', 'start': 13638.715, 'duration': 4.783}, {'end': 13650.884, 'text': 'And of course, you can use other things like Heroku or cloud compute to deploy your application.', 'start': 13643.518, 'duration': 7.366}, {'end': 13657.669, 'text': "But that's just this is just one way to do it really quickly and really cheaply because you can have a lot of apps running on the same droplet.", 'start': 13650.944, 'duration': 6.725}, {'end': 13660.591, 'text': "And the setup wasn't too difficult.", 'start': 13659.13, 'duration': 1.461}, {'end': 13666.143, 'text': 'The final step is we probably want to install a better way to run our server.', 'start': 13662.202, 'duration': 3.941}, {'end': 13670.784, 'text': "So let's install a tool called PM2 globally.", 'start': 13666.783, 'duration': 4.001}, {'end': 13674.185, 'text': 'So npm install global PM2.', 'start': 13670.984, 'duration': 3.201}, {'end': 13679.086, 'text': "And once that's done installing, I could just do PM2 start server.js.", 'start': 13675.145, 'duration': 3.941}, {'end': 13685.767, 'text': 'And that is going to be a tool which kind of monitors my server and it will restart it if it were to crash for whatever reason.', 'start': 13680.106, 'duration': 5.661}, {'end': 13694.957, 'text': "So that's done installing.", 'start': 13694.036, 'duration': 0.921}, {'end': 13697.8, 'text': 'Now I can do PM2 start server.js.', 'start': 13695.077, 'duration': 2.723}, {'end': 13702.605, 'text': "That's going to spawn a PM2 daemon on my server.", 'start': 13698.861, 'duration': 3.744}, {'end': 13703.846, 'text': 'So I can hit it again here.', 'start': 13702.705, 'duration': 1.141}, {'end': 13709.031, 'text': "Here it's loading fine.", 'start': 13703.866, 'duration': 5.165}, {'end': 13723.141, 'text': 'Cool So that pretty much sums up my full stack view Adonis DigitalOcean deployment tutorial.', 'start': 13713.756, 'duration': 9.385}, {'end': 13729.363, 'text': 'If you have any comments or you want to leave me feedback of how I can make my tutorials better, feel free to do so in the comments below.', 'start': 13723.761, 'duration': 5.602}, {'end': 13733.684, 'text': "I hope this tutorial didn't go too quick and I hope I kind of explained what I was doing.", 'start': 13729.383, 'duration': 4.301}], 'summary': 'Tutorial demonstrates deploying app on digitalocean with pm2 for monitoring and restarting server.', 'duration': 136.243, 'max_score': 13597.441, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez813597441.jpg'}, {'end': 13729.363, 'src': 'embed', 'start': 13695.077, 'weight': 2, 'content': [{'end': 13697.8, 'text': 'Now I can do PM2 start server.js.', 'start': 13695.077, 'duration': 2.723}, {'end': 13702.605, 'text': "That's going to spawn a PM2 daemon on my server.", 'start': 13698.861, 'duration': 3.744}, {'end': 13703.846, 'text': 'So I can hit it again here.', 'start': 13702.705, 'duration': 1.141}, {'end': 13709.031, 'text': "Here it's loading fine.", 'start': 13703.866, 'duration': 5.165}, {'end': 13723.141, 'text': 'Cool So that pretty much sums up my full stack view Adonis DigitalOcean deployment tutorial.', 'start': 13713.756, 'duration': 9.385}, {'end': 13729.363, 'text': 'If you have any comments or you want to leave me feedback of how I can make my tutorials better, feel free to do so in the comments below.', 'start': 13723.761, 'duration': 5.602}], 'summary': 'Deployed server using pm2, demonstrating full stack view in adonis digitalocean deployment tutorial.', 'duration': 34.286, 'max_score': 13695.077, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez813695077.jpg'}], 'start': 9724.582, 'title': 'Vue project edit and deployment', 'summary': 'Covers implementing edit functionality, persisting backend changes, saving, deleting, and creating projects, abstracting components for reusability, building a task panel, and deploying a single page application with adonis on digitalocean.', 'chapters': [{'end': 10178.447, 'start': 9724.582, 'title': 'Implementing edit functionality in vue', 'summary': 'Discusses implementing edit functionality in a vue project, toggling between edit and non-edit modes, displaying a vtextfield for editing, and using vif to toggle elements based on edit mode.', 'duration': 453.865, 'highlights': ["Toggling between edit and non-edit modes by changing the project's isEditMode boolean and using VIF to display elements accordingly.", "Displaying a VTextField to edit the project title and binding its value to the project's title.", 'Implementing a check icon to unset edit mode and using VIF to toggle between edit and non-edit modes.', 'Styling the edit functionality by adding hover effects and cursor pointer for user feedback.']}, {'end': 10552.151, 'start': 10178.447, 'title': 'Edit project mutation and backend persistence', 'summary': 'Covers adding a mutation to set the project title and ensuring backend persistence by sending a patch request, resulting in successful reflection of changes in the projects view and automatic focus and key up functionality for saving edits.', 'duration': 373.704, 'highlights': ['Adding a mutation to set the project title and ensuring backend persistence A mutation is added to set the project title, and backend persistence is ensured through a patch request, resulting in successful reflection of changes in the projects view.', 'Automatic focus and key up functionality for saving edits The text field is configured to automatically focus when clicked and to trigger the save functionality on pressing enter, enhancing user experience and efficiency.', 'Creating new projects and editing projects The ability to create and edit projects is successfully implemented, marking a significant progress in the development.']}, {'end': 10855.576, 'start': 10552.651, 'title': 'Edit and delete projects', 'summary': 'Covers the implementation of saving, deleting, and creating projects, including persisting data, making delete requests, and creating projects through keyup events, resulting in successful deletion and creation of projects, also emphasizing the abstraction of components for reusability.', 'duration': 302.925, 'highlights': ['Successfully deleted project from the list The process of deleting a project involves making a delete request to project slash ID, removing the project from the list, and verifying its successful deletion from the network tab.', 'Creating projects through keyup events The implementation of creating projects through keyup events is showcased, enabling the creation of projects by pressing Enter on the keyboard, resulting in the successful creation of projects.', 'Abstraction of components for reusability The chapter emphasizes the abstraction of components, such as the bottom create section, into separate components for reusability, showcasing the intention to abstract create record into a separate component called create record dot view.']}, {'end': 11506.335, 'start': 10858.077, 'title': 'Component abstraction and event handling', 'summary': 'Discusses abstracting functionality into components, emitting events for input changes and create actions, and creating an abstract component for editable records which takes in props and emits events when certain things happen, with a demonstration of creating a new component and passing props to make it functional.', 'duration': 648.258, 'highlights': ['Abstracting functionality into components The speaker discusses abstracting functionality into components for allowing props to be passed in for setting, like placeholder text, and emitting certain events when things change.', "Emitting events for input changes and create actions The chapter explains emitting events for input changes on a text field and creating actions by emitting events like 'create' on key enter and clicking the button.", 'Creating an abstract component for editable records The speaker demonstrates creating an abstract component for editable records, which takes in props and emits events when certain things happen, without having any knowledge about the type of project or task.']}, {'end': 12390.315, 'start': 11509.197, 'title': 'Implementing task panel in vue', 'summary': 'Outlines the implementation of a task panel in vue, covering the creation of abstract components for editing, deleting, saving, and creating new tasks, as well as the setup of actions, mutations, and state for fetching and displaying tasks, and the creation of new tasks, with a focus on integrating these functionalities with the projects module.', 'duration': 881.118, 'highlights': ['Creation of abstract components for editing, deleting, saving, and creating new tasks Two abstract components are created for editing, deleting, saving, and creating new tasks in the task panel.', 'Setup of actions, mutations, and state for fetching and displaying tasks Actions, mutations, and state are set up to fetch and display tasks in the task panel, with a focus on mapping actions and mutations.', 'Integration of functionalities with the projects module Functionalities are integrated with the projects module, including setting the current project, fetching tasks for the current project, and handling the creation of new tasks.']}, {'end': 13211.739, 'start': 12393.418, 'title': 'Building single page application with rest api', 'summary': 'Details the process of creating and reusing components, implementing logic for editing and saving tasks, and adding a checkbox to mark tasks as completed, with a focus on connecting a single page application to a manually created rest api.', 'duration': 818.321, 'highlights': ['Implementing logic for editing and saving tasks The process involves creating and reusing components, displaying editable records, and setting logic for editing, saving, and deleting tasks.', 'Adding a checkbox to mark tasks as completed The tutorial demonstrates extending the existing editable record module to include a slot for rendering items, adding a checkbox to mark tasks as completed, and implementing logic for toggling the completed state.', 'Connecting a single page application to a manually created REST API The chapter emphasizes the process of connecting a single page application to a REST API that is created manually, showcasing examples of building a full stack application with Vue and Adonis JS.']}, {'end': 13736.425, 'start': 13212.86, 'title': 'Full stack view adonis deployment', 'summary': 'Covers enabling local storage for app state persistence, building and deploying a single page application using a quick and simple method, and setting up a server with node.js and adonis on a digitalocean droplet.', 'duration': 523.565, 'highlights': ['Enabling local storage for app state persistence Enabling the Create Persisted State plugin to cache app state in local storage, eliminating the need for users to repeatedly log in and ensuring that the app state loads exactly as before upon page refresh.', "Quick and simple method to deploy a single page application Demonstrating the process of building a view application using 'NPM run build' and deploying it by copying the files to a public folder, acknowledging that this method is not the best practice but providing a quick and simple way to deploy the application.", 'Setting up a server with Node.js and Adonis on a DigitalOcean droplet Guiding the process of creating a DigitalOcean droplet, installing Node.js, MPM, and Adonis CLI, cloning the project, installing dependencies, configuring the .env file, running migration scripts, and using PM2 to monitor and restart the server.']}], 'duration': 4011.843, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/dfEZlcPvez8/pics/dfEZlcPvez89724582.jpg', 'highlights': ['Successfully deleted project from the list', 'Enabling local storage for app state persistence', 'Setting up a server with Node.js and Adonis on a DigitalOcean droplet', 'Adding a mutation to set the project title and ensuring backend persistence', 'Creating new projects and editing projects', 'Integration of functionalities with the projects module', 'Implementing logic for editing and saving tasks']}], 'highlights': ['Successfully implemented register, login, and logout functionalities.', 'The Adana serve command automatically restarts the server on saving JS files, functioning similarly to NodeMon behind the scenes. This demonstrates the efficiency of the Adana serve command by automatically restarting the server upon saving JS files, enhancing the development process.', 'The process includes troubleshooting steps, such as examining server response time, implementing token storage in the store, and dynamically changing the router location, with successful resolution of server response time and user feedback issues.', 'The chapter emphasizes the importance of handling exceptions to return custom status codes to requests.', 'Building a REST API with CRUD methods for various resources', 'Setting up the Vue.js front end with Vue version 3 beta.9', 'Creating a new repository on GitHub and cloning it to the local workspace', 'The tutorial includes deploying the completed application on DigitalOcean after the development process', 'The creation of a route and middleware function for token parsing is explained. Describes the process of creating a route and middleware function.', 'The need to ensure the validity of the token is highlighted. Emphasizes the importance of token validity for secure authentication.']}