Writing modern React apps (w/ Redux Toolkit + Typescript + Material UI + Auth0) | David Armendáriz | Skillshare

Writing modern React apps (w/ Redux Toolkit + Typescript + Material UI + Auth0)

David Armendáriz, #NeverStopLearning

Writing modern React apps (w/ Redux Toolkit + Typescript + Material UI + Auth0)

David Armendáriz, #NeverStopLearning

Play Speed
  • 0.5x
  • 1x (Normal)
  • 1.25x
  • 1.5x
  • 2x
52 Lessons (4h 23m)
    • 1. Introduction

      2:16
    • 2. Defining the Code Editor App requirements

      3:03
    • 3. Installing Node.js (NVM, asdf)

      8:19
    • 4. Installing Docker and Docker Compose

      3:33
    • 5. Creating the Auth0 account

      2:35
    • 6. Creating the boilerplate

      3:18
    • 7. Configuring Prettier

      3:50
    • 8. Adding the dependencies

      2:23
    • 9. Dockerizing our app

      7:34
    • 10. Configuring Auth0

      4:30
    • 11. Creating the app config

      6:08
    • 12. Creating the AuthProvider component

      5:50
    • 13. Creating a common Loading component

      2:23
    • 14. Creating the dark mode slice

      3:54
    • 15. Adding tests for the dark mode reducer

      3:53
    • 16. Configuring Redux persist

      4:13
    • 17. Configuring the store

      5:15
    • 18. Creating the Redux provider

      2:20
    • 19. Creating typed Hooks

      1:46
    • 20. Configuring the app colors

      3:25
    • 21. Creating the Custom Theme Provider

      5:29
    • 22. Creating Protected Routes with Auth0

      2:47
    • 23. Creating the Routes component

      6:50
    • 24. Creating the Header component

      6:28
    • 25. Creating the SignIn component

      3:06
    • 26. Creating the SignOut component

      1:17
    • 27. Creating the authenticated and unauthenticated buttons

      2:43
    • 28. Testing the authentication

      2:30
    • 29. Creating the Home page component

      6:46
    • 30. Testing UI with React Testing Library

      3:04
    • 31. Defining the Custom File and File Viewer types

      5:03
    • 32. Creating the Files reducer

      4:24
    • 33. Adding the Files reducer business logic

      6:11
    • 34. Testing the files reducer (Part 1)

      9:44
    • 35. Testing the files reducer (Part 2)

      3:20
    • 36. Changing the store folder structure

      1:59
    • 37. Creating the selectActiveFiles selector

      6:58
    • 38. Creating the Open Workspace button

      6:50
    • 39. Reading files (Part 1)

      10:00
    • 40. Reading files (Part 2)

      6:03
    • 41. Creating an Extension Icon reusable component

      3:21
    • 42. Tests for the selectFileViewerData selector

      6:21
    • 43. Creating the selectFileViewerData selector

      10:13
    • 44. Creating the File Viewer component

      7:05
    • 45. Creating the Open File thunk

      7:16
    • 46. Creating the Code Editor page

      5:40
    • 47. Creating the Code Editor Container

      10:49
    • 48. Creating the Custom Tab Panel

      4:47
    • 49. Creating the onTabClick handler

      1:54
    • 50. Creating the Custom Tab Label component

      6:47
    • 51. Creaint the Close File thunk

      8:59
    • 52. Creating the Custom Monaco Editor and finishing the app

      8:13
19 students are watching this class
  • --
  • Beginner level
  • Intermediate level
  • Advanced level
  • All levels
  • Beg/Int level
  • Int/Adv level

Community Generated

The level is determined by a majority opinion of students who have reviewed this class. The teacher's recommendation is shown until at least 5 student responses are collected.

85

Students

--

Projects

About This Class

UPDATE: source code for this course: https://github.com/DavidArmendariz/code-editor-app-course

In this course, you will learn how to build a simple yet complex app (a code editor in the browser). You will learn a lot of things from such a simple project:

  1. React with Typescript
  2. React best practices
  3. Redux
  4. Redux Toolkit
  5. Material UI
  6. Testing
  7. Docker
  8. Authentication with Auth0
  9. Protecting routes with React Router Dom and Auth0
  10. Implementing dark mode

At the end of this course, you will be able to transfer all the knowledge you will get to a real world application. You can also take this project as a portfolio project. It contains lots of things that you would use in a big React application.

Meet Your Teacher

Teacher Profile Image

David Armendáriz

#NeverStopLearning

Teacher

Hi! I am David Armendáriz and I am an ecuadorian mathematician. I like everything related to Data Science and also I like to apply my knowledge in this topic to software.

See full profile

Class Ratings

Expectations Met?
  • Exceeded!
    0%
  • Yes
    0%
  • Somewhat
    0%
  • Not really
    0%
Reviews Archive

In October 2018, we updated our review system to improve the way we collect feedback. Below are the reviews written before that update.

Your creative journey starts here.

  • Unlimited access to every class
  • Supportive online creative community
  • Learn offline with Skillshare’s app

Why Join Skillshare?

Take award-winning Skillshare Original Classes

Each class has short lessons, hands-on projects

Your membership supports Skillshare teachers

Learn From Anywhere

Take classes on the go with the Skillshare app. Stream or download to watch on the plane, the subway, or wherever you learn best.

phone

Transcripts

1. Introduction: Hi, my name is Debbie them and that is, and I am a software engineer and mathematician. In this course, we will be building modern React apps with TypeScript, with a redox toolkit of 0, material, UI, et cetera. So what we will be learning in this course are the following things. React with TypeScript react this practices redox, redox toolkit material UI testing with just Docker, authentication without 0, protecting routes with React router dominance 0, and implementing dark mode in our app. So this course is intended for beginners and intermediate React developers. Understanding of JavaScript and a basic understanding of redox is necessary. What to expect from this course. At the end of this course, you will be building a complex app while learning advanced concepts from reflux that you can use in a big project. You can also learn how TypeScript and helped to reduce bugs. You can also expect to learn how to manage authentication with alpha 0, specifically with the React SDK, I'm learned how to test some of the business logic of your app destructor of this course. We will rebuilding the app by parts. Thus, we will be building these up component by component in an order fashion. For example, we're going to focus on how to build the file viewer component, how to build the store, then configure it, how to build as lysis of the store and things like this. So we will be taking these order approach in order to build the app. So without further ado, see you in the next lecture, and I hope you enjoy this course. Bye bye. 2. Defining the Code Editor App requirements: Hi and welcome back. So now we're going to learn, while we're going to build, we're going to build to code editor app. So something like VSCode. But in the browser. And these are their parliaments of their app. First, we need authentication. So when the app starts, we shall see homepage. And the homepage, there should be a nav bar that has the title of the app and interact a login button. The login button should lead us authenticate using Google or some other methods like e-mail and password. If we authenticate successfully, we shall be read directed to a protected route where the code editor app will be accessible. Once in India, never, the login button should now be the login button. And if we click on this button, we should return to the homepage. Then for the code editor app itself, first, we will need a file explorer. So the actual half a tree-based file and directory Explorer. Given a directory as an input, it will show all the files and folder within the directory, including sub folders, obviously, all directories. She'll be in the collapsed state, an application load, but can then be expanded and collapsed by clicking on them. Directories and files. She'll have icons. Now, the editor itself, the app needs to have a code editor based on the Monaco code editor. Each file should open a new tab and we should be able to close the gaps. When we double-click a file in the file explorer, initial openness, a new tab in the code editor. So if you don't know what the Monaco code editor is, let's see. Let's search for this on Google and see the definition of it. So the Monaco editor is a code editor that powers Viscoat. A good page describing the code eight or feature is here. So you can click on there. And well, this is basically the code Ager, so we're going to have these in the browser basically. Okay. What else? The code editor app also needs a Workspace button, so an open workspace button. So when we are inside the code editor, a button shall be shown in enough fiber. And by clicking on this button, we should open a dialogue box that lets us select Add Directory. Finally, there are some non-explicit requirements. For example, when a reloading our files shall not be clear. That means there should be some kind of births systems in the app. For now, these are the requirements. See you in the next lecture. Bye bye. 3. Installing Node.js (NVM, asdf): Hi and welcome back. So before we start, we need some things for our development workflow. So first thing is obviously NodeJS. So at the time I am recording this video, the long-term support or LTS version of NodeJS is 14.16. So you can go to nodejs.org and here you will find the download beach. So in my case it says download for Linux because I am using Linux. If you're using Windows or macOS, then probably He's going to say download for Windows or Mac OS. Then you click on this button and install NodeJS. That's one way to install NodeJS. However, there are some other ways to install it, and I think they are way better than doing this. So we can do it also by using nvm, which is node version manager. So you can go to github.com slash and Vm dash as age slash and VM. And you will go to the official report of NVM. Here you will have table of contents that installing and updating part. So it's little more complicated, but not, not that much. You have to curl this and then execute with bash this install dot SH script. And then you're going to be able to use NBN. Okay, So how do you use any VM? Well, you can read through the documentation for, for example, usage. You can say to download, compile, and install the latest release of note. You have to run this command and VM install Node. If you want to install specific version of boat, you can say nvm install and the version. So you can put directly 14.16, okay? And then you simply say nvm use on the version you want to use, for example, 14.16. Okay? So that's one way. You have to be aware that for example, NVM is Version Manager for NodeJS, and it only works on any bus IX Compliance shell. So SH, dash z, SH for Mac for example, bash. And in particular on his blood forms, unix, macOS, and Windows. Windows Subsystem for Linux. So you can't use nvm. On the windows again. But there is something called, I think it's and VM Windows CE or something like that. Let me see. Yeah. So here's the note. And Vn does not support the Windows, but may work in Windows Subsystem for Linux, depending on the version of WSL. If I'm not wrong, the latest version of WSL, WSL 2. But there are some alternatives, for example, these ones and VM know these and VS. So you can go and check and VM Windows if you are a Windows user. And it says here that this is not the same thing as NBN, but it uses almost the same commands. Okay, so you can read through these documentation if you are a Windows user. So that's the second way you can install NodeJS. And the third way is by using this very, very cool tool called a SDF. Okay, so ASF is basically like nvm, but it can manage multiple runtime versions with a single CLI tool. Okay, so you can manage Node.js, Ruby, python, Elixir, and much, much other things. So you just have to install well, you have to have curl, good, and then you have to clone this repo. And yeah, that's basically it. Then a view or a Linux and you're using bash, you have to add this to your bash RC file. Okay? If you're in COSH, for example, you're a Mac user, then you have to add it to your z SH RC file. And that's it. In fact, this is my preferred method because I manage multiple languages. So if I go to the terminal and type, he has the F plug-in list, all. You're going to see that you're going to manage multiple things with a single CLI tool. For example. Or snow jazz is you'll be right here. You have Node.JS. You have thinks like Bentham, you have beach beam, you have Ruby, and lots of other things. Okay? So it's very, very simple to use. It has a great documentation. For example, I can say ASD F plug-in list and gives it the L NodeJS poetry, Python. I have a, a clean installation of we want to right now. But I had a more things here, like Go lang, Ruby and things like that. And you can say, for example, a SDF least NodeJS. And you can see that I have these versions installed here. And I have specifically version 14.16. Okay? And also you can list all the available versions with a supplement. Sdf list all NodeJS. And then it's going to show all of these version. If I can also type, for example, Python. And I'm going to have all of these versions of Python available. Okay? So it's very, very cool distal. Just one thing. In configuration. Make sure to have these dot a SDF RC file and have these legacy version file equal to yes. So I have the file and its legacy version file. Yes. This is four. For example, when we have a dot nvm RC file, then ASD F is going to recognize this file and set the local version of Node.JS to the one specified in the dot nvm RC file. For Python, I think it's the dot python dash version file. So you can specify the version of Python you're going to use in your projector. And ACF is going to recognize this. So that's what this thing does. So one more thing. As you may already have noticed, a SDF is only available for Linux and macOS. But I guess that if you are using Windows Subsystem for Linux, then it is also going to be available for WSL. Okay, so that's it for this video. See you in the next lecture. Bye bye. 4. Installing Docker and Docker Compose: Hi and welcome back. So now I hope you have Node.js installed in your machine. It doesn't matter the way. And now we're going to Seoul docker and docker compose. So you can go to docs dot docker that com slash in slash install. And here you will have the dogs for installing Docker. So if you are on Windows or Mac OS, That's very, very simple. You just have to go to one of those links and install the Docker desktop. Okay? So very, very simple. It's like an installation of some problem, okay? But if you are only an x like me, then you will have to have one of these these trusts, or in my case, I have 12. So I can go here and simply follow the instructions. So first, make sure you're going to have older versions of Docker. You can skip this step even if you haven't ever installed Booker and your machine. But you can always run this command. It's not going to to do something wrong. And then you have to set up the repository by running these commands. Audience, douglas official LGBT. Then running this command. And finally, you can sudo apt-get update, sudo apt-get install Docker CE, Docker CE CLI, and container the IO. And then you're going to have Docker installed in your machine so you can test that you have Docker. If you run this command, sudo docker run Helloworld, okay? If you're following these instructions, I also recommend to follow these optional boost in solving steps in order to use Docker as a non-root user. So basically, in order to run Docker commands without the pseudo keyword, okay, So do have to run this command, run this command, and that's it. Now you can, instead of sudo docker run helloworld, just docker run Hello World. And that is going to be better. So once you have installed Docker, we have to install Docker Compose. So here you have a top. And here you have insolvent bulls. If you're on Mac or Windows, then you are lucky because the docker-compose is included with Doug or desktop. If you're a Linux user or like me. Well, you just have to run these commands. So do curl this thing, then apply the executable permission so the binary. And finally, you will have Docker compose in your mission. I also recommend to have these command completion for Bash and TSH. So you can also follow these steps for command completion. Okay? And that's basically it. Now you have Docker and Docker Compose intermission. See you in the next lecture. Bye bye. 5. Creating the Auth0 account: Hi and welcome back. So forth. Thing we need is VS code. So here you can use VSCode, that is what I recommend. Or you can use whatever you want. Webstorm, for example, but it's not free or sublime text or whatever you feel comfortable with. So as I told you, I really recommend Visual Studio Code. It's lightweight and it's very, very borrower. I also like WebStorm, but it's not free. You have legged trial of 30 days and then you have to pay in order to use WebStorm. Okay? Now, the fifth thing we need is enough account. So it's also free. And recently, as it says here, Alta bout of 0. So that's the coolness. Now you can login, sign up. I will do it with my Google account. Ok. And let's wait for it. And I didn't have any time domain. I can create anything here. So I'm just going to create React course GoDaddy drop or something like that. These should be unique so you won't be able to, to copy my tenant domain. Okay. Then I click on Next. And you can say it's personal and create account. And that's it. We can go to applications and we can create an application. So let's go and create a single page web application. For example, Angular React View. And let's create it. Okay, so I have graded a new obligation. And as you can see here, it's called myapp. I'm going to stay with a generic name. And that's it. We have created an OP 0 counts and an application inside the account. I hope you liked this video. See you in the next lecture. Bye bye. 6. Creating the boilerplate: Hi and welcome back. So now it's time to start coding. So let's go to a folder, for example, where you store all of the rebels. I have a folder called The rebels, where I store all of my personal rebels and now check the version of Node you're using. So as you can see here, I'm using version 10.22 points 0. So as I am using a SDF, I can say SDF global NodeJS 14.16. Okay? And yep, I can now execute this command and the x Create React app. Okay? And you can name it whatever you want. I'm going to name it, go with a dollar AP course and dash, dash template script. And for that, you have to wait some seconds or minutes, depending on the speed of your machine. Okay. So I'm going to pause the video. Okay, so now it is complete. So I can cd into code editor app course. And I can open this project with VS Code with this command codes and that. Okay, so now I have this thing here. Let me open a terminal here. And I can start typing Jahren start or some like that. However, I'm going to create the NVM RC file. So this was the file I was talking about in earlier videos. Here you can specify the version that you want to use. So for example, 14.16. And I am going to change NodeJS to the version I had earlier, which was 10.22. So if I type node dash be outside this terminal, I'm going to have version 10.22 because I have, I have it. I have note. Version 10.22 points 0 globally. And in this project, because I have a specified in the NVM RC file that I want to use locally, version 14.16. Then I can do this node minus v. And yeah, I'm using this version of node. Okay? So that's it for this video. I hope you like it. See you in the next lecture. Bye bye. 7. Configuring Prettier: And welcome back. So today we're going to add pre-test configuration. If you don't know what criteria is. Well, it's basically a formatter for JavaScript and other things like HTML, CSS, et cetera. So if you're using this code, you can go to the Extension stop and tie prettier. And hopefully you will find this in the first place. So you can go and install it. And then we are going to create a dot-product here, RC dot JSON. Okay? So here I'm going to specify some rules that will be useful when we coat or application. So first is semi equal to true. So this means that we're going to use semicolon in all of our code. Second one is single quote to true. Well, as the name suggests, we're going to use single quotes framed with 120. So this means that the line length will be always 100 attorney. And also trailing comma ES6. So basically trailing comma ES6 means to put a trailing comma. So that means a comma at the end, the last element of an array or an object. Also, we're going to use top width equal to 2. Okay? So that's it. Now, if you're using his goat, you can configure when to format your code. You can go to File Preferences and settings. I like to have all of my settings inside JSON. So you can go here and say open settings in JSON. And as you can see, I'm very organized. And first thing you need these editor, that format unsafe equal to true. So that basically means format the code when you save the file. And then hearing the preacher section that they have made these, you have breacher that require conflict equal to true. So this basically means just format the code. If you have these preacher that JSON file. And you can ignore this. But if you have also like an editor config, then I am going to ignore that completely. Okay, so that's the configuration for VSCode. If you're using something else like WebStorm, well, then you can go to Google and type WebStorm prettier, just like this, and open the first link. And here it says that if you are using Web Store in 2020, 21, horrible, then you simply need to go to Preferences, languages and frameworks, demo script breach here, and enable the option Ron on safe or files. So pretty precise. But if you're using an earlier version, then you have to run prettier on Save using a file watcher or using preacher with easily and which requires more configuration. Or using breacher as an external tool. If you're using something else like Sublime Text or atom, well, I can't help you because I haven't used those go editors. Okay, so that's basically everything you need for configuring prettier. I hope you like this video. See you in the next lecture. Bye bye. 8. Adding the dependencies: And welcome back. So now we're going to install some dependencies, and I'm going to explain you what these dependencies do, okay? So I already have them prepared. I'm just going to copy and Bayesian. And I'm going to explain you one by one. So up 0 slash officer react is the thing we need in order to use off 0 with the React material UI slash score. Our old, the core components inside the material UI Module, UI slash icons are the icons we can use for our material. Yea. But till a UI slash lab are some components that are experimental. Monaco editor or slash react is basically the Monaco editor version for react. So it's a component that we can use in order to have the Monaco editor available. This is the Monaco editor is needed for the types. So remember we're using TypeScript. So these brackets here doesn't include the types, but these 10 tosses, so we also need this. Then we're going to use also a redox ds slashed. All good, so basically redox toolkit, which is a framework to write standard redox. We're going to need the Lovasz for a simple task. We're going to also need the tabs on Lovasz. Remember we're using TypeScript. We're going to need React redux. We're going to need the types of React radix again because we're using TypeScript, we're going to use React Rotterdam for routing. And again, types slash React router at them. We're going to need UUID to generate some random, but you need your ideas. And again, the types because we're using JavaScript and redox persist. For persistence, the types as well. So you click on Enter and wait for all of these packages to be installed. Okay, so that's it for this video. I hope you like them. See you in the next lecture. Bye bye. 9. Dockerizing our app: Hi and welcome back. So now it's time to duck her eyes our application. So for these, we're going to create three files related to Docker. So the first one is going to be the Docker file. The second line is going to be that they'll Kurt ignore file. And the third one is going to be the Docker compose YAML file. Okay, fine. So let's start with the Docker file. First, we are going to need the note version 14.16 and we're going to use the Alpine version. These means the lightweight version of Node 14.160. Then we're going to say, Hey, I want my working directory to be these app. And if it doesn't exist, just create it. I need to set a path environment variable, which is going to be up slash node modules slash dot. And I'm going to append it at the end, the existing environment barbel. So this is needed for us to use React scripts inside the container. Okay. Then we're going to copy package star the JSON into the current working directory. So this basically means copy package.json, package dash log the JSON. Why we're doing this? Well, if nothing changed in package.json or package bash lot adjacent, then we want to use the cache here. We don't want to install dependencies every time. Every time we, we start these Docker container because the dependencies haven't changed, so there's no need to do that. Then we're going to do npm install dash, dash silent. Okay. And then we're going to copy everything from the root directory into the working directory inside the container. Finally, we're going to execute the command npm start. And that's basically our Docker file. Now, when we run this step, we want to ignore some things. So for example, we want to ignore node modules because we're going to install Node modules inside the container. We want to ignore and npm that bug, the bug if it exists. So. These file is created whenever there is some error. For example, when installing at baggage, we want to ignore the belt. So suppose we ran, we ran NPM built. Well then a build directory is going to be created and we want to ignore that, are going to ignore the Docker, ignore file itself. And we want to ignore the folder. So if I type ls minus a, you can see that in fact a dot git is going to be, it is always greater than when you have a good rebel. Okay, so that's it for Docker file and Docker ignore and Docker Compose are going to do that now. So let's say we're going to use version 3. We're going to have, well just to one service, in this case, the front and it's going to have a container name. You can put whatever you want here. I'm going to say code editor app. Okay? The built. You can pass the context. And you can pass also that the Docker file is called Dockerfile. So if you want to rename these, you can, you can specify it here. That it's not called Dockerfile but annular think. But we want to be explicit and I wanted you to understand what this thing does. So it's basically saying I have inside this root directory or a file called Dockerfile. And you have to take, you have to run the steps specified there. Then the volumes are going to have two volumes. The first one is the current director, which is going to be mounted to the app directory inside the container. Okay? And also this app node modules volume. Okay. Now I'm going to have boards. I'm going to expose the port 3000 from the host. So I actually need this. And I'm going to map it to that port 3000 in the container. Also, I'm going to define an environment variable, which is going to be chunky Dar, use bolding equals to true. So this is basically for having hot reloading. Okay, so now we have everything set up. And now we can simply say docker-compose up minus d. And first is, it's going to pull the image and the note 14.16 dash alpine. Then, well, everything succeeded. Now it's going to run npm installed but silently. Okay, so let's wait for this to complete. Okay, so everything looks okay. It says here that 137 packages, I'll look for funding. Okay, so now we have everything set up. If you type docker ps, then you're going to see that we have our container running. So you can even say docker logs goes editor app, which is the container name. Remember, I'm here, you can say that the typical logs you will see if you weren't using Docker. So I'm going to go to localhost 3000 and as you can see, I have my react up, up and broken. So that's very cool. And that's it for this lecture. I hope you like it. See you in the next lecture. Bye bye. 10. Configuring Auth0: Hi and welcome back. So now before we start coding, we need some additional configuration in Auth 0. Okay, So you can go to your applications, to these applications tab and go to my app. And we need inside settings to configure the allowed callback URLs. Okay? So in this case, it's going to be http localhost 3000. So what does this means? Well, you have the description here. After the user authenticates, we will only call back to any of the URL specified here. So you can specify multiple valid URLs by commas separating them. Okay? And as we're going to develop everything in our machine, then it is sufficient if we just put http localhost 3000. We also need to put this inside the allowed login logout URL. So again, a set of URLs that are valid to re-direct to after logo from 0. So after a user logs out from 0, you can redirect them with a return to query parameter. The URL that you use in return two must be listed here. Okay, So when we code this part, that's going to be cleaner to you. And last thing we have to do is to put the same thing in allowed web origins. And yeah, so these are the allowed the web origins for use with that gross or eating authentication device flow and wet message response mode. And you can read more about this if you click on them. So, yeah, I think those are the only things we need to configure it. If you want, you can change the name of this up and don't forget to save the changes. So yeah, now you have everything set up for authors 0. Now, we need also to put these two things. So the domain and that client ID inside some environment marbles. Okay, so let's go here and make it dot M file and also it dot, dot x sample file. Okay? So here in the DATEV that the example file, I'm going to say a React app ID. And also react up to 0 domain. So environment variables that are going to be used inside the ER React application must begin with React underscore up. And this is basically just a guideline for new developers. So there are going to see these dark damp that the example file and they're going to say, Oh, I need these things. Maybe you need to ax, ask someone else to give them to me. And this is the file where you're going to actually put everything. So I'm just going to copy this and I'm going to copy that the main here and the client ID here. And well has these contains sensitive information, then don't forget to put that inside gitignore file. So I'm just going to put this at the end of the of the file that the, that the dot M file shall not be committed to the remote rep. Okay, so I think that's everything for this video. Now we're going to be able to use I'll 0. Perfect. Actually let me also change the name of this thing. Okay? And safe. Okay, so I hope you liked this video. See you in the next lecture. Bye bye. 11. Creating the app config: Hi and welcome back. So now it's time to start actually coding our application. So well, let's start by defining some folder structure here. Inside source, I'm going to have assets. And inside assets I'm going to have images, okay, so basically some images are going to be there. Also. I'm going to have a common folder or I'm going to put some constant some types. I don't know, Thanks like that. Then I'm going to have components where we're going to have our actual React components. And then we're going to have conflict. Where am I going to basically put some configuration there? Then I'm going to have betas are, and we're going to create our basis. And we're going to have a redox folder on Google Store or redox identical It's store. And we're going to have also your routes folder, everything related to routes or two, routing is going to be here. And I'm going to have enough folder. Everything related to authentication is going to be here. And I'm going to have theme, everything related to theme, it's going to be here. And utils. If we needed some utility function, then probably it's going to be there. Okay, so that is going to be our folder structure for this project. Now in conflict, I'm going to put on up conflict that TF file. And I'm going to create an app config object. And here I'm going to say Auth 0 domain is going to be the environment Bravo processed and amp, react up Auth 0 domain. And if these comps undefined, it shouldn't call common defined. But if it does, I'm going to put an empty string there. And here I'm going to put this the second property, the 0 client ID. Again, this comes from the environment variable react up. I'll 0 client ID. And again, if these concepts on the Find, then we put an empty string there. Well, I saved the file, hit got automatically formatted, and this is the trailing comma I was talking about earlier. Then I'm going to explore default, these app config. So when you export default, I think it's always a best practice to but first name and then explored the full name. So why we're doing this? Well, if you use your environment variables directly, then TypeScript is going to complain saying, Hey, your environment Burwell, probably ys on the fly and so you have to take care of that. And by doing this where we're always saying that officer of domain is a string. So as you can say, authors domains of property, which is a string of 0, client ID is always a string. Okay, So that's cool. And this also has the purpose of centralizing all of your environment variables in just one place. And you didn't have to have them all over your code. Okay, so that's it for the app config. Then let's go to localhost 3000. So this is localhost 3000. That's our beautiful reacts. And now we're going to get rid of basically everything here. I'm just going to put helloworld gay. I'm going to get rid of these className. And so we didn't need these apps dot css nor these logo. So we can get rid of these app dot CSS. We can get rid of these Logo, SVG and also this test. Okay, so now we have our React app. Let's see what happened. Yeah, we have hello world. Now, let's inspect this little bit. As you can see, this doesn't take the whole screen so that it doesn't take the whole height of the screen. So in order to fix that, because we wanted to take this the whole screen, we're going to go to index dot CSS, and we're going to add here at the top of the file HTML. I'm going to say the, she'll take 100% of the screen. The body which is inside the HTML, should take the height of its brand, which is already 100%. Okay? And also remember that our obligation gets mounted inside a, a beef with an idea of root. So I know why the extension of the seas, Django HTML. So let me change this to simply HTML. Okay, so here we have this div with an ID of roots. So we cancel like that with CSS, with this symbol. And route again and again that we can say, Hey, take the whole the height of the parent, which in this case the parent is body. So as you can see, these the if is inside the body. And these body is inside these HTML. Okay, So that's basically it. If we inspect. Now we can see that the ID, the ID occupies the whole height of the screen. Okay. That's, that's it. I hope you liked this video. See you in the next lecture. Bye bye. 12. Creating the AuthProvider component: And welcome back. Today we're going to grade the auth provider TSX component inside the app folder upgrade this file. I'm going to create the new reactor function export component with the snippet. And here I'm going to receive some props. And we're going to say that this prompts has the types of prompts with children, okay? And these perhaps with children, requires one type argument, as you can see here. And that's basically the properties that are additional to the children property. If I hover on here, it says that the prompts with children has these children property with it, which is optional, AMA, which is sub-type react note, and it also sets other properties, okay? But we're not going to have any other properties in this component or we're not going to use them. So we're going to put an empty object. Okay? Now we're going to return an Auth 0 provider and looks like Viscoat didn't autocomplete that order and make the automatic import. So we're going to import this manually from 0 slash 0 react. So here are going to say, give me the 0 provider. Okay, if I hover here, it says that these component needs us, perhaps the domain, the client ID. They're ready read URI, and also we're going to give the unread direct callback. Okay? So first, we're going to render here props that children. So again, if I hover here, it says that my app is the children of these off her provider. So yeah, we're going to provide our app here. So we're going to wrap our app with these auth provider. Okay, so now the provider and the, it's the domain. And remember we had that in our app config. So I'm going to have the authors here are the mean and the client ID, again comes from app config dot of 0 client ID. And what else they're read during the URI is going to be window.location dot. No need to change that. Remember, it is already here. Window.location, that origin. And the red direct callback. It's going to be a function that we're going to create right now. Okay? So this function is going to be an error function and it is going to receive as an argument the opposite state, which is going to be of type any. Ok. Now these are red, they're callback is going to be cold, obviously on red erect. So when we are being redirected, we want to change the history. Okay, so we're going to say history that bush and these apostate is basically similar to the query params of the URL. So you're going to understand this when we are being read directed to the universal login off of 0. But these apostate can contain the return to query parameter. And if it doesn't exist, we just go to Window dot location that Bethany. Okay, so we need to have access to this history. And that's where we're going to use the US History hook, which is from React router. So this auth provider at the same time needs to be erupt inside a router. More specifically, a browser router from React, router them. Okay, so now that we have created this component, let's do that. So inside index that TSX we are going to do, we're going to do, we're going to wrap her up with off provider. Okay. So let's wrap up our app. And the second thing is that we're going to wrap the auth provider itself. We have a router. Okay, so let me first do this and let's import this router. So yeah, let me do something like this. Import browser router has a router from React, sorry, from React, router, dumb. And that's basically it. Yeah. So why I have done this inside of the index.js x and not inside the app.js x. Well, sometimes when we do testing, we want to wrap our app with other, with marks off for example, this provider or most of the redox provided that we're going to see later. And that's why we put all of these providers outside of our app. Okay, so that's basically it for this video. I hope you like it. See you in the next lecture. Bye bye. 13. Creating a common Loading component: Welcome back. So one component that we're going to use a lot in these application is going to be the loading component. So basically like a spinner or linear progress that shows the user that we are loading something or where waiting for something. Okay, So let's create it inside components. And in fact, I saw here that I wanted to put these common inside components. So let's actually move that common folder inside components and inside common. Let's create a new folder called yeah, loading or loader, whatever you want. I'm going to name it loading. And inside loading, I'm going to say loading that TSX. Again, we can use our snippet. And here this is going to be a very, very basic component. So basically we're just going to return a linear parameters, okay? So linear progress comes from material UI core. If you're unsure, you can always go to the material UI and search for loading or something like that. Or maybe Yeah, you can search on Google. Probably. It's better loading component material UI. Yeah, Here you have CMYK, CMYK color. You have circle or loaders, you have linear, you have customized whatever you want, someone to use, the simple linear progress here so that these one linear. And that's what I'm going to return here. So I am putting these components inside common loading because it's going to be used inside virus parts of the obligation. And instead of returning linear progress in all of those parts, we just return a centralized loading component. So whenever we want to change, for example, material you add self or we want to change those circular progress. We just have to make a change in one simple place. Okay, so that's it for this video, very simple video. I hope you like it. See you in the next lecture. Bye bye. 14. Creating the dark mode slice: Hi and welcome back. So today we're going to start configuring our store, which I think is the most complex part of our obligation. So first, we're going to create what it's called a slice in redox toolkit. And it's going to be a very simple slice for activating or deactivating the dark mode. Okay, so let's go to New Folder and create this folder called dark mode. And here I'm going to create a reducer dot ts file. Okay? So I'm going to say const, dark more the slice. And we're going to use this, create a slice, which is a function from redox told Pete. So the name of this slice, so is light is basically a part of the store. The name is going to be dark mode. Okay? We also need to specify initial estate, and it's a good practice to separate. So we're going to export const, initial state. And I'm going to explain later why we're doing this. And initially the dark mode is going to be disabled, so initial state is going to be false. Okay? So now we have provided the name, the initial state, and now it's time for implement, implementing the reducers. So in this case, we're just going to have one reducer and it's going to be called Toggle dark mode. Okay? So this toggle dark mode expects a state and we can simply return the state. But the contrary, so if this is false, then this is going to be true. And it is true. If the state is true, there's going to be false. So that's why this called Toggle dark mode or just changing from false to true. Okay, Now we're going to export const. And inside these darker mode slice, we're going to have access to these actions. So inside of this actions who are going to have toggle dark mode. So when we create the reducer with his life automatically, redox tool kit is going to give us a total dark mode of action. So remember, this is an action and this is the reducer. Does action needs to be called in order to execute all of these toggle dark mode logic, which in this case is literally just one level of goat. Then we have to export also the reducer because we're going to need that in order to configure our store. So we're going to say export default, darks modus lights. And we also have these reducer property, and this is going to give us all of these reducers. Okay? So as simple as that, we have created a slice which is going to be in charge of toggling the dark mode in our obligation. So I hope you like it. See you in the next lecture. Bye bye. 15. Adding tests for the dark mode reducer: Come back. So now let's test our reducer. So remember that in Brooks is a good practice to Buddha Allah for business logic into the reducers. So it makes sense to test the reducers. So inside dark mode, Let's put a file called reducer, the test.js. Ok. So let's put up the scribe a statement saying that we're going to test that dark mode reducer. So the first test is going to say that shoot returned the initial state if no action is provided. If no known action is provided. Okay? Okay, so here we're going to put directly the statement. We are going to use a dark mode reducer. So probably we need to import it manually. Dark mode reducer from reducer. Okay, so dark mode reducer. As you can see, the first parameter is a state, which in this case is a Boolean, false or true or undefined. So let's put on the Find. Okay, so let's assume that we don't have that the state is undefined at this point. And the second parameter is an action. So we're going to put an empty object, which is going to denote our action. Now, we're going to say that this needs to equal the initial state. Okay? So remember, that's why I exported the initial state here. Now TypeScript is complainant, same argument of type empty object. He's not assignable to parameter of type any action. So here, let's say that this is a payload action. Okay? So we're saying here to TypeScript. Trust us, these empty object is a payload action. Sometimes TypeScript allows us, allows us to do this, sometimes not, but in this case, it is allowing us. Now let's go to the terminal and run drawn test. Okay? And as you can see, these tests is passing. Okay, let's create two more tests. So the second one is going to say should enable dark mode if it is disabled. Okay? So let's expect dark mode reducer. Now the state, if it is disable, the dark mode is going to be false and the action is toggle dark mode. Okay? So this should be equal to true because the dark mode reducer is going to return the new state, which in this case is true because we're passing that toggle dark mode. I don't remember. The toggle dark mode should enable the dark mode. Now we're going to basically copy this thing here and say Shaoul disabled dark mode if it is enabled. And basically, if it is enabled and this state is true, and it will change to false. So yeah, all of the three tests are passing. So that's it for this video. I hope you like it. Fit you in the next lecture. Bye bye. 16. Configuring Redux persist: Hi and welcome back. Now that we have our dart mode reducer, we need to actually configure our store. So sorry, let's create inside the store folder a file called root reducer. So rubra, these are going to have all of our reducers. Okay? So let's go and create wrote reducer with combined reducers. Let's say dark mode is going to use the dark mode reducer. So as you can tell, VS Code is not giving me that, that the completion. In order to be able to use that, we're going to do a little trick. And we're going to say dark mode reducer. We're going to sign dark mode slice dot reducer to a variable called dark mode reducer. And then we're going to export default that dark mode reducer. Now B, It's good. It's going to be able to say, Hey, I want dark mode reducer important for me. Then we just simply export default, the root reducer. Okay? Now we need to configure also the persistence. Okay, So for that we're going to create a file called persist config T S. Okay? And we're going to create the persist config object that is going to have a key of root. Ok, telling that we want to persist some reducers of the root word user. We also need the storage. So for that, we're going to import the storage from red expresses St slash, slash, starch. So basically we're going to use the local storage here. Okay? And finally, we need to white list or specify what reducers we want to persist or what parts of the store we want to persist. Where we're only having dark mode here. So we're just going to say waitlist, an array with one element which is dark mode. Okay? Now, we also need the persistent reducer. So persisted reducers going to be equal to persist reducer. And it's going to be imported from redox persist. And here we're going to balance the persist config and also the root reducer. And we simply export default, the persisted reducer. Okay, So we are having, sorry, for CSE, the reducer. Okay, so we're having here some problems. They are related to TypeScript. It says that IEP goal not find a declaration file for a module, read X persist and try to install type slash red X persist. So we have that package. So there is some kind of issue here. Here it is. Types rather expressed just in order to solve this issue. Let's go to these react dash, dash m dot d dot ts. And let's copy and paste this line here. And instead of reactive scripts, Let's put rather persist. And that's shold. Fix this little problem here. Okay, so now we have the proceeds config and the root reducer configured. In the next lecture, we're going to configure the store itself. I hope you liked this video. See you in the next lecture. Bye bye. 17. Configuring the store: And welcome back. Now we are going to configure the store itself with redox toolkit. So redox toolkit has these configure store that add some middle worse by default to the red bookstore setup automatically. Okay, So for development, we have these three default middle worse, that are the thunk for using redox thunks, the immutability state environment invariant surgery, and serializable state invariant. Okay? So this is four. For example, conditionally dispatch in some actions. And this is for the immutability of things in the store. And this is for not storing things that are in knots are liable in the state, like for example, a blob of something like that. Okay. In production, we're only going to have these Thank here. But we, if we don't specify the middle where we're going to have in development those three things and in production this, okay, when we use the redox persist, we still want the middle worse. But the persists, the redox persist is going to also dispatch some actions and they are going to violate these sparked off. Sarah lives have ability to check middleware. Okay, so let's see this in action now that you have a grasp of what is doing redox toolkit in behind the scenes. Okay, so let's go to store, Let's go and create a store dot ts file. So let's create a store with a configure store. Okay? So first we have to pass a reducer and we're going to pass the persistent reducer we just created. And then we have to specify the middleware. Okay, So as I told you, we can get that the fault middlewares and make some modifications with these, get the fault middleware, middleware import. So it says that while the callback notation with configure storage shown in the last example is the recommended way of using get the fold MAE the world. It can also be important to be used independently from the configure, the store. Okay? So we're going to use that get default middleware. And we are going to say serializable check. And we're going to pass ignored actions. So this, we want to ignore the serializability check with some actions coming from a redox persist, okay? And these actions are the following. So ignore actions equal to flush. Okay? So this comes from a red X persist, as you can see, rehydrate again from rather expressive boss. Red X persist, persist, persist, birch, and register. So these things are actions from radix persist and we don't want a serial, serializability check for those specific actions. Okay? Also deaf, the walls. Are going to say process that Nadav different from production. So this is going to allow us to use the redox DevTools only if we are not in production. We don't want people to start experimenting with a rather store in production. Okay, so now we need to export, const the persister. So we're going to call the persists store. Function from relatives persist with the store here. We're going to explore the full store because we're also going to need it. And also weren't going to explore exports sometimes. So they are going to be the root, the state, okay? So the route state, we can get the type with these return-type, okay? Which is something from TypeScript. And here we can say, Hey, give me the type of the store that gets the state. Okay? And also we want the type of the dispatch, and we're going to call it app this batch. And that is simply the type of store, dot dispatch. And that's it. Now we have configured our store here. I hope you liked this video. See you in the next lecture. Bye bye. 18. Creating the Redux provider: Okay, so now we can start building the redox provider or store provider, and we're going to call it redox provider. So I'm going to call this component redox provider dot JSX. Again, use this snippet. And here I'm going to again in perhaps say, Hey, I want breakups with children. And an empty object because we're not we're not going to receive any other thing besides the children. So I'm going to return a provider. This comes from rhythms, okay, and here we need to pass the store. So hopefully we exported that from the store dot ts file. And inside here, we're also going to have that persist gate, which is from redox persist, okay? And here we need to pass the persister. And again, we exported that from store dot ts. We also need to pass a fallback components. So that means hill loading component. And that is going to be the loading component we created in earlier videos. Okay? So this is just in case it takes long time to retrieve the store from, from local storage. And then we're going to pass props dot children here. And that's it. That is the redox provider that we are going to be able to use in, in our app. So in fact, let's do it right now. Let's go to our index dot DSX. And we are going to put, we're going to wrap our obligation with a red X provider. So what we can do this redox provider like that, and that's it. I hope you liked this video. See you in the next lecture. Bye bye. 19. Creating typed Hooks: Welcome back. So last thing we're going to do, relate it to read books. Well, we're going to make, make another reducer later. But we need some hooks, typed hooks because we're using TypeScript. So we're doing, we're doing this just because we're using TypeScript. So remember in a store that ts, we created these types route the state and app dispatch. And these has a return type of a store that gets state, which in fact gives you, um, all the state if you call this function again and have Dispatch gives you the type of the store that dispatch function. Okay, so now let's export, const, use this batch. And that is going to be a call to use this patch, which comes from reactor radix. But we're going to pass the AP dispatch type from the store file. And we're also going to export const, use app selector. And that is going to be useful vector. Okay? That also comes from React redox, but we're going to give it a title. So typed use selector hook, and as an argument, we're going to pass the route state. So inside of our app, we're going to use these, use up dispatch and use absolute vector. And that is because these two things are already typed. So that's it for this video. See you in the next lecture. Bye bye. 20. Configuring the app colors: Welcome back. So now we're going to create getting other provider, and that is going to be the custom theme provider. So we're going to use a material you are here to modify some things off of the customisation of her up. So I just realized that some of the folders that I created there earlier were deleted. And that's probably because I made some good reset or something like that. And they got deleted because they were empty. But no problem. Let's create them again. So I had this folder called theme. And inside theme I'm going to create a file called colors that TS. So here is where I'm going to centralize all of the colors used in our style. So okay, so first I'm going to create these colors object, which is going to have a background. And the background for the app is going to be white. So we put wider. In fact, first before creating these up colors, I'm going to use or create, sorry, another object called common colors. And this is going to have like the colors white. So I can simply reference that color here, like common colors, common colors white. And that way I am not recipient goat. Then let's also create the black here. Black. And that is going to be 0000, 0000. And I'm going to say that the font for the AP color is going to be common colors, dot black. Then I'm going to say primary color. That isn't, I'm not going to take that from the common colors. I'm just going to define it here. It's going to be this one. So material UI has like a purple or something like that for the primary color. We're going to modify that with a custom theme provider and say that I want these to be the new primary color. Okay, So now also we're going to export const the dark colors. And basically the background is just going to be common colors. Not sorry, the background is not going to be black. It's going to be more light. So I'm going to pass this color here. Any three to be 32. Okay? And the font is going to be coming colors white. Yeah, that's going to be white. So let me put the ones that come from common colors at the top and the other ones at the bottom. Okay, so these are going to be the colors for our app. Now we have to create the custom theme provider, and that is what we're going to do in the next video. So I hope you liked this video. See you in the next lecture. Bye bye. 21. Creating the Custom Theme Provider: Hi and welcome back. So now we are going to create our custom theme provider. Okay, So let's create here cuz Danthine provider, that TSX. And yeah, that's it. Custom theme provider. So now we are going to use our dark mood variable from the state, from the redox state. So let's say dark mode. And in order to use the in-order together, dark mode, sorry, we're going to use the US have selector. I hope that we created so this hook, we can simply say state. And for understate you, I need that dark mode, okay? So as you can see, the state already gave me the autocompletion. And I'm told me, Hey, dark mode is here, and that is because I am using a type selector. So now we have the dark mode in our hands. Hearing the props. Before I forget, let's put props with children. And again, we're not going to have additional properties. And now for the theme, we're going to use these create material UI theme function. And here we're going to first in the palette. So this is a property we can set. We can say type. If dark mode is enabled. So if dark mode is true, then dark, otherwise polite. So this is going to help us a little bit with managing the dark mode, but it's not going to be sufficient. Also, we can set the primary color. So we can say that the main primary color is going to come from the app colors. That primary. Okay, so now we have changed the primary color and we also want some custom things like the background color. So for the background color, again, we're going to say is dark mode enabled? If yes, then we're going to use a dark mode, colors dot background. Otherwise, we're going to use the app colors dot background. So that's the first property. And the second property is the font. Again, if dark mode is enabled, then we're going to use dark mode. Colors, dot font, otherwise, up colors that font. Okay, so now TypeScript, he's complaining because in theory we cannot set these properties in that create new theme function. So for that, we are going to declare module and say material UI slash core slash styles slash create me. Material UI theme. And we're going to say that interface theme. The theme also has a background, which is a string, and a font, which is also a string. Okay? Also we need to declare another interface, Theme Options. And here we're going to say, we're going to basically repeat these things here. Okay? And that's it. So this FIM is for when we are going to use this in the Maker, start with a mix styles function, so don't worry about this and this theme options are for the, for S2, the creative theme. Hey, we can also set these properties here. Okay, so now we have created our theme. Now we need to use the theme provider. Theme provider from material UI. Looks like it didn't. Got important. Yeah. So now we can pass here the fame. And of course, we need to pass the children. And that's it. We have created our custom theme provider. Now we simply need to wrap this. So let's put it here. Custom theme provider. And now we're going to have enabled dark mode. Well, not by default, we need to do something still. But this is going to help us a lot to centralize the dark mode and management of our app. And also other things like the primary color. So that's it for this video. I hope you like it. See you in the next lecture. Bye bye. 22. Creating Protected Routes with Auth0: Hi and welcome back. Now we're going to create a protected route component inside off. So let's create it protected the route that TSX. Let's use our snippet. Find in the probes, we're going to say, perhaps with children. And in this case, we're going to say that additionally, we're going to set key, which is of type string, and it can be anything. So this is basically a very, very flexible, maybe you can say. And that is because we're going to need to pass lots of things here. So first, let's deconstruct the prompts. So in power-ups we have children and the rest. So we're going to use the rest operator on. We're going to assign that to arcs. Now here we're going to return a route. So that comes from React Rotterdam. And this is a self-enclosed component. And here we're going to say component is going to be weak authentication required. And we're going to pass the children here and also some options. So on red directing simply is going to load this component here. So the loading component we just created some videos ago. And also we are going to pass the rest of the arcs. So with these three dots here, okay, Now, this is basically everything. But TypeScript is complaining and saying argument of type react note is not assignable to parameter of type, component type. So we're going to simply say these as Component type. And that's it. Problem solved. So these protected route is going to only render components if we are authenticated with Auth 0. That's why we use these authentication with authentication required. Okay, so that's it for this video. Hope you like it. See you in the next lecture. Bye bye. 23. Creating the Routes component: Hi and welcome back. Now let's create the routes component. So again, I think it got deleted. That's created again. And here let's create this routes that DSX file. Okay, so let's use our snippet. And here I'm going to first define some styles. So for that I'm going to create this user styles variable. And I'm going to use these makes styles function. So these needs a callback. And these needs to return a, an object. So in this object is we're going to write on CSS in JavaScript. So CSS and JS, and I'm going to say main is going to have a height of 100%. We're going to display flex and we're going to have a flex direction of column. So by default, flex direction is row, but we want column in this case. Also for the page, we're going to have a height of 100%. Okay, fine. So now inside routes we can't use or have these glasses object by calling these uses styles like this. Okay? And we simply need to return a div with the class name. Okay? This class name is going to be classes start and you can see Maine. And inside this main, we're going to have a header component that we haven't created. So let's simply put a header here. And below this, we're going to have another div with a class name, Sorry, class name of classes, that page. And here is where we're going to have our routes. So we're going to have this switch from it got exported from material UI, but actually it's the switch from, let me see this one, react Rotterdam. Okay, so here we're going to have all of our routes. But we wouldn't have those components yet. But still, let's create them. So the first is going to be a protected route. So protected route. Again, and we need to specify some path. For that. We're going to create the separate routes dot ts. And here is where we're going to centralize all of our routes. So this is going to be an object with home property and go to editor with slash editor. So this going to be the, the route for the home and this is going to be the road for the code editor app. And we're going to export default routes as simple as that. And now here in the protected route, we're going to be able to define the path, which is going to be a route that go the editor. And the component is going to be the code editor page. But we didn't have anything yet. So let's simply create an inland component here, saying code editor, something like that. And the second route is going to be public route. So we're going to say exact path. Also here we're going to say exact path, exact value. And here we're going to say routes.com. And here's where we're going to do something interesting. First, let's import this route from React Rotterdam. Okay? And let's use the use of 0 hook. So use of 0. And here we're going to use the ISS. We're going to have the ISS authenticate. So this is a property that is going to tell the, is going to tell us, is the user authenticated or not? Okay? And here we're just going to say if the user is authenticated, then read direct him. So we're going to use a red direct component here. Read direct him to routes dot code editor. Otherwise, render the home component that again we haven't created, so I'm just going to pass it the same home. Okay? Also, we're going to extract that is loading component here. So this is loading is going to tell us if we are authenticating, wherein the process of I'm logging in the user, sorry. Okay, so if this is loading, and then we're going to return the loading component we created earlier. And that's it. I think we have everything in place, so just in case, let me go to localhost 3000. And yeah, we still have our helloworld. And that's because in app that TSX was still have this Hello World. So instead, let's just returned routes. Okay, So routes, and these can be self closed component. Okay, So now that we have this, we have these header and Home. And if we inspect these components, we can see that the header occupies this part of the screen and the home, the rest. So that's what we want. Okay, So that's it for this video. See you in the next lecture. Bye bye. 24. Creating the Header component: Hi and welcome back. So we created this route, that JSX component, okay? And here was specified, these header right now is simply a text same header. So let's create a header component inside components common. So we're going to create a new folder called Heather. Fine. So here let's create a header, the TSX file. And again, let's use our snippet. Okay, so first, let's create some styles with use the Styles and make styles. Again, this needs to return an object and simply we're going to say tidal flux one. Okay? And here we're going to say const classes equal to use styles, as simple as that. Okay? Now, we are also going to need is authenticated from US the use of 0 cook. And we're also going to need the dispatch from the US up this batch OK that we created earlier from the red export. Okay, so we're also going to need the dark mode. It's bearable. For that. We're going to use u sub selector. Remember, here are going to have the state and the state is going to give you the start vote. What else do we need? We need a callback or a handler onchange dark modes. So this is going to be a function that is simply going to dispatch toggle dark mode. Okay. I don't think we need something else. And here we're just going to, instead of returning this div, we're going to return an app bar, raw material UI. Okay? And inside these sidebar, we're going to have a toolbar. Okay, So in the sub-par, we're going to say position relative. And in the toolbar, first we're going to have a topography. Okay, and we're going to say variant H6. And we are going to give it a class name of glasses dot title. And we're going to say code that he turned out. Okay. And also then we're going to have all of our buttons. So the first First, we're going to include a dark mode icon. So we're going to say dark mode icon. And this is going to be an icon from material UIs. So we're going to say import dark mode icon from material UI slash slash brightness too. So you can check those Huygens in the material UI icons, Material icons. That searching Google that. I don't know. Let's search for brightness too. So this is the brightness to I come up, I want to use. Okay, so just below or next to the dark mode icon, because this is going to be next to the DICOM. We're going to put a switch and that switch. Now, that is the switch from material you, I'm not the one from React router, dom. And we're going to say onchange and change dart mode and color default. And whether it's checked or not, that's going to be given by the dark mode Bible that we extract that with use absolute lecture. Okay? Now, next to that, we're going to say, if is authenticated the user, then we're going to put some buttons. I don't know, I'm going to call it authenticated buttons. Otherwise, we're going to render the unauthenticated Buffon's. Okay. So I think that's it for this component. Let's see the result in localhost. Yep, so we need to put that component here instead of this div, Heather. Okay, So it didn't go to import it. Yeah, now it is important. And now we have these header here, okay? And we have the unauthenticated buttons that we need to change. And this button is actually changing the dark mode. So for that, you can download the redox deaf too. So just searching Google redox dev tools. This is a Chrome extension, but I am using brief, I'm brave also supports Chrome extensions. So I can go to the console and here type redox or just going to this icon here and lead me on top of that button. As you can see, I am dispatch in this section, and it is changing dark mode to draw. And if I do it again, it is changing dark mode to false. So this is working as expected. I hope you liked this video. See you in the next lecture. Bye bye. 25. Creating the SignIn component: Hi and welcome back. So now we're going to create the sign-in component. So let's go to the app folder and create sign in that TSX. And here we're going to use our snippet again. And yeah, so here we're going to use the use of 0 hook. So use off 0. And we're going to get these lugging with re-direct. You can experiment if you want, with lugging with pop-up. So I'm going to use login with resurrect. And also let's create some styles films first. So uses styles. Make a Styles return an object. Okay? And we're going to say that the button, I want the color of the text to be App colors dot, sorry, not up colors, but rather common colors. White. So I don't want these bottom, the texts of these buttons to change the color. Whether we are in dark mode or not, I wanted always to be white, so that's why I'm putting here color, common colors, white. Okay, so now we can use glasses. We've used the styles, and we also need a plugin. So yeah, it's a good practice to have all of our functions separate it from the, from the code and the JSX code. And here we're just going to return button. So a blots and from material UI and a text saying sign-in or lugging, whatever you want. I'm going to put sign-in. And with a class name of classes dot bottom. And I'll click. It's going to be on lugging. So this is what I was trying to tell. In fact, I could have done this like this. Lugging with re-direct. But it's a good practice to do it like this because maybe we have more logic here. I don't know, more complex things we want to set something in the state are no. And that's why I am just separating these own login from here. Okay, So now we have the sign-in button. That's everything for this video. I hope you like it. See you in the next lecture. Bye bye. 26. Creating the SignOut component: Hi and welcome back. So now we're going to create a Sign Out component. So again, inside up, we're going to basically copy and paste because it's very similar. So let's first rename this component to sign out. And instead of lugging a width, redirect are going to say logout. And here logout. And we pass the return to be window location that are eaten. Okay? And yeah, debits and the styles are the same. Maybe we can refract her that and put them in in some commonplace, but we're going to leave it like that. And here, instead of signing, It's going to be Sign Out. And instead of login, it's actually going to be on sign out. Also in sign-in, I should put on Sign-in just to be consistent on sign. Okay. So that's it for this component. I hope you like it. See you in the next lecture. Bye bye. 27. Creating the authenticated and unauthenticated buttons: Hi and welcome back. So now that we have are signing and sign out components, Let's start building this authenticated buttons and unauthenticated buttons. So first, let's build the knot or unauthenticated on authenticated bottoms. Tsx, again with a snippet. And here we're just going to simply put our sign-in components. As simple as that. If you want to put some other buttons, then you're free to do so. But here I'm just going to the depth. So This is an easy step. Sign, sorry, on thin the kid buttons or it is. And let's also create off and the key that buttons TSX again, snippets. And here we're going to have more things. So first, let's create some styles. Styles. With Mecca styles. Remember, we need to return an object. We the root or main or whatever you want to. Same of flex. Yeah. I think that the default flex direction is row, so we didn't have to specify it. Here. We're just going to say const classes is the styles. And we're going to have a className of glasses, root. Okay? And we're going to have to DFS, well, in fact, two components, but this one, we haven't created an easy open workspace button. We're going to create it later. And the second one is a Sign Out component. Okay, so as simple as that. Okay. So yeah, let's see what are the results. Yeah, we have signing here. But I'm going to test this in the next lecture, so I hope you like it. Yeah, So I am forgetting something. Before leaving. Let's put these authenticate it buttons. Okay. So I hope you liked this video. See you in the next lecture. Bye bye. 28. Testing the authentication: And welcome back. If I tried to test this. So let's go to sign in. I'm going to, this is called the universal login from 0. So let's continue with Google. Let's accept, Let's authorize the app. If you do this, you're going to see this error. So this error is because here in the routes that TSX, first, I didn't pass that children. I passed eight component. And if you go to protected route, then you're going to see that we have breves with children. And yet here I'm using the children, by the way, didn't have any children here. So instead of doing this, we need to do two changes. First, That's the children obviously. And second, we need to, for example, code editor. I mean, this is going to be changed later. And these needs to be a function that returns some DSX, like a code editor app or something like that. Okay, so now we have to pass these good editor here. And if we do that, then AD is fixed. Okay, so now let's test, sign out. Sign in again, continue with Google. And I am now inside the code editor app. So you can see here I have these open workspace, which is not the bottom, it's just text. And yeah, that's it. If you go to 0, 0 to the part of users and roles and you go to users and refresh this page. Then you're going to see that these user, which is me, and got automatically created when we sign in with Google. So you basically have like a database here and author 0 on. You can also connect to your own database. But if I am not a branch, that is a paid feature, okay? And it's also more complicated. This you may imagine. Okay, so that's it. Make sure to make the change. Don't worry, we're going to change this code editor later. I'll see you in the next lecture. Bye bye. 29. Creating the Home page component: Hi and welcome back. So now that we have basically all of the structure of our app will the front. We're going to start building the pages. So here in the main page, we're going to show a little list of the programming languages supported within our code editor. So that's just the detail, but still we're going to do it and I'm going to show you how to do it. Okay, so here in assets, inside assets we have a folder called images and inside images, we have all of these SVG. Okay, so for example, if I open this, I have the Java icon and I have Ruby icon, tap, scraped, et cetera, et cetera. So first, let's create the page. So let's create inside Pages folder called home. And inside home a folder called conduct TSX. Okay, so again, we'll use our snippet and let's create some styles with user status. Mix styles. And this yield return an object. But now here I'm going to take the theme and the theme is going to contain. So remember, the background and the font that is going to be automatically changed based on the, the dark mode is enabled or not. Okay, So first in the root, Let's say that we want display flex. We want the flex direction of column K. We want a height of 100%. We want to justify the content to the center. You want to align the items to the center and the background color. Background color is going to be a theme that, that ground. Okay? And we are also going to have a welcome message. And these welcome message is going to have the following styles. Going to have a padding of 15 pixels, a font size of 30 pixels, and a color theme. That fund. Okay, so now we have these two styles that we can use inside our home components so we can get glasses from is the styles. And here I'm going to have this div with a class name of glasses dot root. Yeah. And inside we're going to create another div with a welcome to the code editor app message. And this is going to have a class name of classes that welcome message. And below these, we are going to have a programming languages component, which is that list. We're going to use these as V 0s here. So for that insight components, sorry, inside components, we are going to create a new folder called Tom. And this is where we're going to put all of our home components or components related to home. So we're going to say programming languages list that TSX. And just because I'm lazy, I'm going to copy and faced the component. So this is how you would import the SVG is. So import React component as and you can put whatever name you want. So CSS icon, CSS SVG or whatever you want and you have to import it from these assets. Images, yes, three CSS3 original, which is this file here. Okay? And also you can give them some styles like for example, a padding, height, the width, well, these two, or at least one of these two is mandatory. Otherwise you're not going to and see your icon. It's going to render with a height of 0 and with a width of 0. So you have to specify the height or the width or both. And yep, Then I'm just here rendering a list of programming liquids. So let's go to Hong TSX. And below this, I'm going to render that component programming. Yep, and this should be programming languages list. Okay? In fact, this is not a arrow function component. So let's convert it to that. And export default. Programming languages list just to be consistent with the rest of the application. And that's it. So now let's see the result. Let's sign out. And let's go to the routes also. And here instead of rendering this, we're going to render the homepage. So home. Yeah. So now we have these beautiful screen here. And if we turn on dark mode, yeah, you can see that this thing, the text of this thing changed, but the background is deal white. So let's go here. And correct background color. It's not a background clip. And again, now this is worth so dark mode is working, everything is looking fine. So I hope you liked this video. See you in the next lecture. Bye bye. 30. Testing UI with React Testing Library: Welcome back. Well, I just wanted to note that in this course we're going to do, we're going to test the more the business logic of the app rather than the UI part. Yet, I have a whole course. Testing the UI is hosted in platforms like you. They mean Skillshare and it's called destine React app with React testing library. However, I wanted to give you an example of how I will do a very simple test. So for example, for the home, I will say home dot test the TSX and test something like shoot, render, the welcome message. So here I'm just going to say render the home component. Okay? And these render, which should come from React testing library, is going to give me query by texts and many, many other functions. So query by text is going to allow me to query something like text, the name suggests. And I'm going to extract query by text. So something like welcome to the code editor and welcome to the code editor up to be in the document. Okay, so if I now go to the terminal and Ron Johnson test, yep. These test is passing because I have that message in this component. So that's a very simple test. Obviously not that useful, but we can test many, many other things when we have some interaction. And yet that's why we probably want to also make tests on the whole app. And that's why I have all of the providers outside the app because now I can mug these redox provider. I can muck probably the auth provider. I'm not sure. But yeah, this is how you do testing of the UI. We react Deci and diaper. And is also note worth mentioning that with the reactants in library, you are not testing the internals of the components, but rather the behavior of the user. That's the philosophy of React, destine library. Other testing libraries like enzyme concentrates on testing the internals of the components rather than the behavior. Okay, so that's it for this video. Hope you like it. See you in the next lecture. Bye bye. 31. Defining the Custom File and File Viewer types: Hi and welcome back. So now we're going to spend some time coding our file reducer. So that's going to also be part of the store. And he's going to be in charge of managing everything related to the file viewer feature. Okay, So first, before doing that, we need some types. So let's create a new folder called types. And first, let's create the user file type. Okay? So we're going to export the folder, an interface user file. And this interface is going to have an IV, which is going to be string name, which is going to be a string relative bath, which is going to restrain the code, again a string and extension again string. So everything here is going to be a string. Okay, So let me explain it to you. Suppose we have this file App.js x. It's going to have in our application ID, which is going to be a unique ID, auto-generate it with a UUID package. I mean, which in this case is up that TSX, a relative path. So if I copy the relative path, let me see where is it here. Copy relative path. It's going to be something like this or a slash app.js x. Sorry. The code is going to be the actual contents. So everything here, like Function App or turn, everything here is going to be the code. And the extension is going to be dot TSX. So the extension of the file, so that's our user file on coastal type. Now, let's create another one called file viewer, a structure that Ts. Okay, so I'm going to export the fault than interface called file viewer structure. And we're going to have an idea of a string, fame name of a string, an extension which is going to be optional, which is going to be a string also. And some children, okay? Which again is going to be optional. And here's the interesting part. We're going to have an array of file viewer structure. So now you can see that we are going to deal with recursion because we have an interface that uses itself for its definition. So why I am doing this like this? So let's go to material UI. And we're going to use these three view React component, which is the trivial we get that presents a hierarchical list. Okay? So here you can play around, and this is exactly what we want. So something like this, which also has Viscoat for example. Okay, so let's see a little bit the code in TypeScript. Okay? So this is how these component is. We have some trade views, create EMS. But let's go down. And let me see where is it. Yeah, here it is. So here in the rich object part, it says, well the trivial and tried him component API maximizes flexibility. An extra step is needed to handle a rich object. Let's consider a data variable with the following shape. Recursion can be used to handle it. So again, as I told you, we're going to deal with recursion. So here you can see that in this example we have generated an interface called render tree, which has an ID, a name, and children, which is optional, and it references itself. We have the same here. And the additional part is this extension here that we're going to need in order to render the extension items. Okay. So I suggest you took take a look at this and see how this is name. And obviously I'm going to explain this to you because this is the most difficult part of the application. So I hope you like it. See you in the next lecture. Bye bye. 32. Creating the Files reducer: And welcome back. So now let's start creating a new reducer in our store, which is going to be the file or do, sir. Okay. So let's call this files. Let's file but files employer. And let's say we are going to create the reducer. And here, let me see what did I put here? Dark mode slides. Here. I'm going to put files slice. And we're going to create a slice like this. Okay, So we need some things here. So first, the name, which is going to be called files. And the second thing we need is the initial state. So here in this file are going to export an interface called files state. Okay? And we're going to have three properties. So the first one is going to be user files, which is going to be an array of user file. So remember that time we just create it. Well, user file is going to be an array of that. Active files is going to be an array of strings. And they are going to contain the IDs of the user files that are active so that are present in the code editor. Then we're going to have the editor active file. Okay? And this is going to be string or not. So this is the file that is currently active. So if I were to give you an example, user files will be all of these files in my directory. Active files will be app.js eggs reducer that ts from files on reducer that ts from dark mode. And the editor active file will be the one I am currently coding right now. So reducer ts from files, fine. So that is going to be the interface. Now we need to say that the initial state is going to have the file state, type. And initial state, sorry, files. And initially user files is going to be an empty array. Active files is going to reveal some men theory and the editor active file is just going to be null. Okay, so now we can safely put the initial state. And as you can see, the other thing we need are the reducers. So here we're going to put reducers, and right now we're not going to put the reducers. Let's simply as we did here, take out the actions. Well, we didn't have actions right now. So let's say files reducer is going to be files lies that reducer. And let's export default these files reducer. Okay, so now we can simply go to our wrote reducer. Remember this is where we combine all of our reducers and say files is going to be from files reducer. And that's it. Now we have created a new reducer in our store. So in the next video, we're going to actually code the business logic of these of these reducers. Okay, so I hope you like this video. See you in the next lecture. Bye bye. 33. Adding the Files reducer business logic: Hi and welcome back. So now let's start grading the logic of our reducers. So the first thing is going to be set files. Okay? So remember, are going to, sorry, this state. And set files actually is going to receive a second parameter, which is going to be an action, which is going to be of type payload action. And in payload action, we can pass a second argument, which is the, the type of the payload that we're going to pass. So in this case is going to be user file. Okay, so we already have that and it's going to be an array of user files. So what we need to do here is simply say, let's state that user files equal to the actual payload. And we need to say a state dot active files equals to an empty array. So why an anterior a in the active files? Well, we're going to call this action when we set the files. After we upload that directory, and after we upload that directory and the directory, sorry, we're going to have all of the active files set to an empty array. So aren't going to reset the active files if you want to say, let, say it like that. Okay. So that's the first one. The second one is an active file. Okay? So this is going to receive as the first argument, the state. And the second argument is going to be an action and the load action as string. So this is simpler. We're just going to push interactive files. The action that the payload, which is going to be a string. Remember this is going to be an ID of one of these user files. Okay, so that's the second reducer. The third reducer is going to be remove active file. Again. This is going to receive as the first argument, the state. And the second argument is going to be an action with payload action, again, a string. So we need to remove an active file. And for that, That's simple. We're going to say estate that active files is equal to a state that active files that filter. And we're going to say file ID. File ID different from the one that comes from the actual payload. So we're basically filtering and excluding the file ID that is equal to the one that comes from the payload. That's how we remove an active file. Okay, now, we have to have another reducer which is going to be called file code. Again, this is going to have the state of the first argument and something more complicated as the second argument. So again, we're going to say action will be of type payload action. Okay? And here we're going to have an object which is good to have finally D string and new code. Again, string. Okay, let me correct this. So update file code. So first, let me from action that payload, get file ID and new code. Okay? So first we're going to say user files. State that user files. So get me that the user files. And we're going to say let user file, the user files that find file file.txt equal to file ID. Okay, so first we are, we're finding that the user file with these file ID. So that's the first step. And if user file exists, are just going to say user file, that code is equal to the new code. And that's basically it. Okay, so that's the code for updating the file. The code of file, sorry. And last but not least, we're going to have a reducer called set editor active file. Again, this is going to receive a state. And as a second argument, It's going to be an action which is going to be of type payload action, which is going to be a string or null. Okay? And we're going to say state dot editor active file equal to action dot bailed. Okay, so as simple as that, now we have basically all of the business logic needed for our reducer to work. Now, we have to test this file, and that's what we're going to do in the next video. So I hope you like this video. See you in the next lecture. Bye bye. 34. Testing the files reducer (Part 1): Hi and welcome back. So now we're going to start writing our tests. But before that, I forgot to export the actions. So files, It's lies that actions, and now we're going to have access to set files are files. Said files. I like the file. Remove up the file, update file code and set editor active file. Okay, so now we have these actions. Now we can start writing our tests. So let's say red user.name test.js. And let's start with a describe files reducer. Okay? And the first test is going to be Shoal return the initial state. So let me just copy these thing, actually, this text here. Okay, so assume returned initial state if no known action is provided. So again, samples but statement with files reducer. We're going to pass on the file and we're going to pass an empty object, does a payload action. Okay? And we're going to expect this to equal the initial state. Initial state from files reducer, okay? We also need to import this. Okay? Second test is going to be shoes set user files when action is set files. Okay, so this test is going to be a little more complicated. So we're going to say const, user files. That's going to be an array of what? Well, we need an ID. Let's say one, ID1 or whatever name. Index.js, whatever relative path is going to be something like test index.js. And the code is going to be something like console log helloworld. And the extension is going to be obviously JS, which is JavaScript. Okay, so for this, we're going to say x vector that resolved is going to be equal to, well, let's pass all the initial state and active files needs to be now an empty array name. And the user files need to be these ones here. Okay, Our going to expect files reducer. So we're going to pass the initial state. We're going to say set files, user files. And these needs to return a new state, which is going to be. So, let's say expected results. And rename expected result to expected state, something like that. So in our terminal, Let's run Yarn test and see if this past, yeah, both tests are passing them. Okay, so let's add a new test called Shoot, add a new file, ib. When action is add active file. Now, file ID is going to be something like one or probably two hours. That's fine. But that state is going to be something like we pass the initial state and active files. It's going to be an array with these violet D. Okay, I don't wanna go into say expect files reducer, initial state had active file. And we're going to pass a file ID, and this needs to equal the expected state. So again, these test is passing. So let's add yet another test. Should remove a file ID when action is remove active file. Okay? So let's say that the file ID is equal to one. Let's say that now the initial, Let's call this modified initial state. Okay, So the modified initial state is going to be user files. So, well, I don't want to write everything for the user file, so I'm just going to have everything from the initial state. And the only thing that is going to change is active files, which is going to have a file ID. So this modified initial state, we're going to pass this to the files reducer, okay? And the expected state is going to be again initial state, but now active files is going to be an empty array. After we pass the remove our defile action. So expect files reducer, how we pass a modified initial state and we pass a remove active file action with the file ID. And this should equal the expected state. Okay, So for tests are passing. Now, let's still write more tests. And let's say shoot, update the code of a file. When action is update file code. Okay? So now the payload is going to be something like file ID. One new code, something like hadn't no print hello world. Although this is Python, but it doesn't matter. Okay, now, the modified initial state, again, initial state. And in the user files, we're going to write an ID of one, a code of console log helloworld. Okay? A name of index.js, relative of something like test index.js and extension of JavaScript. And the bed to the state is going to be something like initial state. And user files is going to be almost the same. Okay, So let me copy and paste this. But instead of, let me see there is an error here. I am missing a bracket, okay? And here also, I am missing a bracket or not. So this racket should not be here. Okay, So here what I was telling you is that instead of console Hello World, we shall have now print helloworld inside this code property. So the expected statement is basically going to be expect file reducer, okay? Modified initial state. And second argument is going to be updated file code with the payload. And this should equal expected state. Okay, So again, this test is passing and yeah, so I think this video is getting long. So in the next video, we're going to write more tests. So how do you like this one? See you in the next lecture. Bye bye. 35. Testing the files reducer (Part 2): Hi and welcome back. So let's start writing yet more tests. The other test that we're going to write is when we don't file, find, sorry, a, an ID of a file. So here we're going to say Schulman not update the code of or the state when. Okay, So let me think about this. Shoe not update the state when Update File code. Okay, reducer does not find the file. So that can happen probably for an error, but can happen. So we're going to say two and we're going to leave these unchanged. So in that case, two is not inside user files. So these should not be, this should not be modified, sorry. Okay, so now our test is passing. In fact, here we can simply say expected state equal modified initial state. And a test is still going to pass so that we write less code. Okay? Now the last test that we are going to write is going to be shold, said, the editors. So in this case we're going to have, we're going to need these double-quotes. Shows that the tours active file when action is set, editor active. Okay. We're going to say file ID is going to be equal to 1. Okay? And expected, expected the state is going to be well, whatever we have in the initial state. And the editor active file equal to the file ID. So let's say expect files reducer. So initial state set at interactive file, we're going to pass a file or deep to equal expected state. Okay, so those are the tests that we are going to write for these Reducer. So as you can see, these reducer dot test has more lines that the reducer itself. So this happens all the time that the test files always or almost always have more lines of code, that thing you're trying to test. So yeah, that's IPD for the tests. I hope you liked this video. See you in the next lecture. Bye bye. 36. Changing the store folder structure: Hi and welcome back. So now that we have our files and dark mode, ready users, I want to make some legal modification in the folder structure store. I want to put these two things inside reducers. Okay? So let's put these two things inside reducers. And yeah, we have to update the imports. So let me see. Yep. Uh, thing cure, it is correct that files reducer should be inside. Reducers slash files reducer. So yeah, ten things got changed. Well, most of them are deletes and updates are paddings. And here in header. Yeah, this looks correct. Okay. So why I am doing this change right now? Well, I want to also put selectors and thunks. So I want to put selectors and thunks. So if I were to put selectors and thanks, the same level of these things here, then probably that will be a misconception because you can say, Hey, selectors is going to be a reducer and thanks is also reducer. But that is not the case. Reducers are only these two ones. And selectors, as we're going to see, are things that select from the state. That's why we have the name. And thoughts are things to conditional dispatch actions. Okay, so just wanted to make that little changed. Have you liked this video? See you in the next lecture. Bye bye. 37. Creating the selectActiveFiles selector: Welcome back. So let's start creating our first selector. So it is going to be called select Active Files. Okay? And we're going to create a new file called select Active Files that TS, okay? And this is going to be a function called select active files, which is going to receive guests, the files part of the stored. So files which is of type file state. Okay. And from files, files, we're going to select user files and active files. Okay? And we're going to return user files dot filter, and we're going to filter the file. Active files includes file ID. Okay? So we're basically telling, give me all the user files that such that the file IB is included inside these files array. So remember, active files, EC string is an array of strings, sorry. And these are strings are IPs. Okay? Then we're going to export default, and we're going to use these create selector. Okay? And these grids lecture yet comes from reselect, but it also comes from redox ds toolkit. So I don't know why B is good. Imported directly from re-select. But when we installed redox TTS toolkit, we also installed re-select. Okay. So for those of you who don't know, reselect is basically a package or a library that allows us to memorize these calls here. So if I call select but active files, then I'm going to be able to memorize that. That's selector here. Okay? So basically this operation here. Okay, so create selector first is going to have as the first argument, a function that returns these files here. So it's going to be rich state. And this route state from this state, I'm going to have the files. And the second argument is going to be these functions. So select active files. So that's how we create a selector. Now let's create the tests for this thing here. So select the files that active files that test.txt. Okay, so we're going to say test should return only the active files, okay? And let's put some user files. So in this case we're going to put more things like ID1, name, index one, the GS relative path tests, index one, the JS code. We can repeat this several times like Hello world. And the extension is going to be js. So let me copy and paste this three times. And here I'm going to change this to 22333. Okay, so now we're going to say that the active files is an array. I. We're going to only select 13. Okay? So now the state is going to be something like files, user files and files from game. And yeah, we're going to tell TypeScript, Hey, trust us, the c's of type root estate. Okay, So yeah, I need to import it manually because this code is not helping me. So root state from that missing, it shall be here. Okay. Let me sit. So now we need an expected result, K, and that is going to be an array with only 13. So I'm going to copy and paste this. And I'm going to remove the second one because the second file is not an active file. And we're going to say select active files. So we're going to import that this function here. So yep. And here we're going to say we're going to pass the state and to equal expected results. And let's see what happens if we run giant test. So yeah, it is passing. So this select active file, you can see is the export default. So it is not this function because this function is not even exported, but is everything here, okay? And remember we need to pass here the state. So that's why we're, we're, we're passing here the state, and that's it. Now we have a way to select only the active files. So I hope you liked this video. See you in the next lecture. Bye bye. 38. Creating the Open Workspace button: Welcome back. So now we're going to concentrate on the open a Workspace button. So if we go to our app and sign-in with Google, yeah, we can see our goal that interrupt. And here we're going to see these open workspace text because right now I think it's just a diff. So if you go to the authenticated buttons you're going to see on the DEF. So we're going to concentrate on creating these button here. And that is where we're going to spend lots of time. Okay, so let's go to the code. Let's create a folder called code editor inside components. And here are going to create a new folder called open workspace. Or you can naming up an workspace, open workspace bottom, whatever you want. Okay, so here I'm going to say open workspace that TSX, and use our snippet wraps up. Fine. So we need to do several things here. First, let me explain this to you. We're going to use a button from material you I. And this button, when we click on that, we need to trigger a, the file dialogue in order to select a directory. So we need a button and then we need also an input of type file. Okay? So we are going to need a href. So when we click on the button, we bleak on data href because the input is going to be, is not going to be displayed, so it will have a display, none. In fact, let's first create the styles. So use the Styles. Styles. These needs to return an object. We're going to have bottom. This is only going to have a color of common colors that the white. So it doesn't matter if we are in dark mode or not. We always want this to be white. Then the input is going to have a simple property of these planar. Okay, so that's east. The first thing. Now we can get the glasses object from USA styles. And inside this div, we're going to have a button from material UI. And we're going to say open a workspace. We're also going to need the href that I was telling you. So we're going to create it Directory, input ref. And we're going to say use href, which is a HUC from React. It's going to have initial value of null. Our going to bat these, the type HTML input element. Okay, fine. Now let's create an onclick handler. So I'm going to say on click. Is just going to say directory, input ref dot current, Gleick. Ok. So in this button, we're going to simply say these has a class name of classes that the bottom. And onclick, we want to call this onclick handler. Okay, so that's it for the button. Now, as I told you, we also need any input, but this input is going to be hidden. So we're going to have an input of type file of className, classes dot input. Okay? And we're going to say directory equals to an empty string. We also need web Keith directory equal to an empty string. Again, we need to set up the href. The href is going to be directory. You put ref. And we need also an onchange handler. And we're going to call it on files uploaded. And for now that's created on a file is uploaded. And we're going to simply say Cancel console log tests or whatever you want. So we're going to spend lots of time on these files uploaded in later videos. First, let's get rid of this problem. So for TypeScript, this directory and webkit Directory attributes, attributes that they don't exist for TypeScript. So when we need to do the following thing, so don't worry for this part. This is just the TypeScript problem with the polar molecule react interface, HTML, attributes, extents, attributes, and the attributes. Okay? With passage of time here. And say directory is an optional property and then AD is a string. And web Keith directory is also an optional rubber gene. It can also shrink. Okay, so now we have the component almost ready because we need to everything here. And let's go to the authenticated buttons and replace this with open workspace. Okay? And I think that's everything we need. Now we have these open a workspace as you can see, and it will trigger these these file dialogue. Okay? So obviously we're going to test these later. But that's it for this video. I hope you like it. See you in the next lecture. Bye bye. 39. Reading files (Part 1): And welcome back. Now we have our open workspace button. And I have this folder with several files. For example, BY the JS ago, JSX, et cetera, et cetera. So if I click on this button and let me open the console and click on that example directory. That new refresh Hurst. You're going to see that test because that is the console log with here. Okay, so now let's see what is the content of the files. So I'm going to say ghost files, directory input graph, the current files. And we're going to say, Hey, TypeScript, trust me, this is a file, file list, which is a built-in type. So you're going to have to import anything. Okay? And let's make a console log of files. And let's go again here. That's upload this thing here. Let me refresh first. Again, upload. As you can see, we have a file list and these are all of the files present. So as you can see, we have a several pieces of information. For example, last modified, we have last modified date. We have the name of the file, the size, the type, and the whip kit relative path. Okay, so that's cool. Now we need a way to handle all of the, all of these files and convert them into our user file type. Okay, so we need that each of these files, each of these pieces here have an ID, a name, a relative path, the code, and the extension. Okay? So in order to do that, we are going to use a sync thunks because reading files is an asynchronous task. So it makes sense to use a sync thunks. So basically in a sink Fang is a function that accepts a redox reaction type of string and a callback function that should return a price. So that's everything you need to know. Here we have an example. We have Users slash fetched by ID status. So in our case it's going to be something like files slash route files or something like that. And the second argument is an async function, where the first argument is what you want to pass to the thunk. And the second argument is the thunk API. This API has several things like, for example, dispatch gets state, and these extra options here. So we're going to be interested in dispatch from thunk API because we're going to dispatch the set files action. Iv, when we read all of the data from the files, everything is correct. Now we're going to set the files. Okay, So this is better explained. If we coat just one more thing. When you create an async found you have these, you can put this extra reducers. We've fetched user by ID, which is this thing here that fulfilled. So that's a property you're going to have. And when this fulfills, you can do whatever you want in your reducer. But in this case we're not going to use that because we're going to use the set files action. But we can still do something like this if we wanted to. We also have pending and rejected. So those are the three things we can put for each thank in the extra reducers. So this is very useful when we have, for example, an API call and the APA coal God rejected. Then, for example, in the, in the extra root releasers we can say, hey, if this was rejected, then do something like, I don't know, setting the loading to falls or something like that. And I don't know setting a narrower or whatever you want. Okay? So this is a very, very powerful feature from radix toolkit. Okay, so now let's go to the store. And here, yep, Let's go and create the thans folder. Again, it got deleted. Let's create it again. And insight. Thanks. Let's create a read files folder. And inside the ridge file folder, read files dot txt. Okay, so here is where we're going to put all of our business logic of reading a file. Okay, so first, I'm going to create a wreath single file function, which is going to receive a file which is going to be a of type custom file. And it's going to return a promise returning a user file. So these custom file, file we haven't created yet, so we need to create it in the folder. So let's go to types and create custom file dot ts and is going to be very easy. It's going to be an interface called custom file, which is going to extend to the built-in interface file. And it's going to have a wet get relative path. So remember, each file had this webkit relative bad. And we're going to say BCS, a string. Okay, now we can import this thing. And here we're going to put all of the logic related to reading a single file, okay? So obviously we're going to return a new promise. Okay? And yeah, I need this arrow here. Okay, we're going to return a new promise. And inside here we're going to create the reader a FileReader instance. So new file reader. And we're going to say Reader dot onload. So when the file is loaded, we're going to have from file the name under Web Kit relative path. So remember, if we go here, we had this name and these webkit relative path. So we're going to get those things. And yeah, just put a default and a string just to be sure. And we're going to say const IV, and we're going to generate a random IV. So how do we do that? Well, remember, Dad, we installed on where is it? Uuid so we can safely import that. So we're going to say Import before, as you Eddie before from UID. And here I'm just going to say generate a new random before UUID. Now the code, we're going to say if the type of the reader that the result is a string shall be a string, then are going to say, give me the reader dot result. Otherwise. Give me an empty string. Then we're going to say does bleed at name. It's going to be name, dot split. And all. We're going to tell that the separator is a dot. So basically what we're doing is taking this name and splitting learnings from MD. So now we can know the extension. So we're going to say extension is going to be split at name of a split at name dot length minus 1. We can also do split at name one. But just to be sure, I'm just going to do it like this. And finally, we can resolve this premise with the id, with the name, with the code, with the extension, and with the relative path, which is going to be the Web Kit relative path. So now this is returning a user file. So a premise of the user file, which contains all of those properties. Okay, So these video is getting loud, so I'm going to bus here. I hope you liked this video. See you in the next lecture. Bye bye. 40. Reading files (Part 2): Hi and welcome back. So before we complete this part, here, I forgot to put either read this text. And here we shall, we shall put file. Okay? So if we don't put this, then these premise will never fulfill. And the reader Don dot onload is never going to be called. So Bish, be sure to have these line of code here. Okay, So now we're ready to create our a sinc function. So let's create it right now. So we're going to say const, read files, create a sync funk. And the first argument is going to be the action. So it will be files slash read files. And the second is going to be the, uh, think callback. Okay, so the first argument is going to be files, which is going to be of type file list. So remember, this is a built-in type. And the second argument is going to be thunk API. But from funky API, we're only going to need the dispatch. So we're going to deconstruct that these batch. Okay, So now we're ready to put all of our logic here. So first of all, we're going to need let me go to the app and refresh open workspace example. And remember that we canceled out this. So this is like a list of files. So I am not sure if we can iterate this thing directly. But instead we're going to take this length. So tiny nine, we're going to iterate from 0 to 28, get the file at that index, and then create the promise with his rid single filed and put everything in an array of promises. And then we're going to wait for promises at all. And we're going to pass these array of promises. Okay, so let's get this number of files, which is going to be files that length. And we're going to create the premises array. So we can do it like this. I write that from, we're going to say length equals to number of files. And then we need a call back. The first marble is going to be used, and the second variable is that index. So for this index, we can get the file at that index. And we can also return the promise. With this red single file. We pass the file. Okay, so now we have these array of promises. Now we can say const, processed files or user files. And here we're going to wait, premise that all we pass that array of promises. Okay, last thing we need to do is to dispatch the set files, okay? And then we're going to pass the user files. And finally we export default the read files async fuck. Ok, so now here we can convert this to an async function. And instead of console log, we're going to put these in a try-catch. So try catch error. If there is something wrong, we're going to console log the error. Otherwise we're going to await for the dispatch. So we need that this batch, Let's get it here, use this batch. So we're going to dispatch these read files and we pass the files. Okay, so that's basically it. Let's test that new functionality. So let me refresh the page. Here. Let me go to the redox DevTools. Let's commit everything. Open workspace, example, Upload. So as you can see, three actions got dispatched. So this first one pending, this set files. So you can see we put lots of information here, so let's well, that's open here, one. So as you can see, the file number four is this thing here. Okay. So looks correct. And these files read files fulfilled. So here you can do whatever you want with these action in the extra reducers part. So here you can manage the, this file slash files slash spending and also these files read files for field. You just have to pass this extra reducers here. Okay, So that, that, that is it. Now we have our files in the store, so pretty, pretty cool. Okay, so that's it for this video. Hope you like it. See you in the next lecture. Bye bye. 41. Creating an Extension Icon reusable component: Hi and welcome back. So we're going to start coding the file viewer component. And I think this is the most complex part of the app. Okay, so let's go and first, before coding the component, define some constants. So here inside these constants folder, you can put it inside the conflict if you want. I'm going to create supported extensions that Ts. Okay? So here I'm just going to copy and paste. And I'm going to explain you what I am doing here. Okay, So here we have an object where the keys are the extensions, and the values are the programming languages that corresponds to the extension. And here we're just saying this is an object that has the key as a string and a string. Okay, so nothing too fancy here. The other thing I want to do is to create a component called Extension icon. So this extension icon component is going to be the like these little icons here we have in this code or the ones we have here in the file viewer. So those are going to be the extension icons. So inside code editor, let's create extention. I can. Okay, and here again, I'm just going to copy and paste a bunch of stuff. So first, let me create extension and I conduct TSX. Let me create the component with a snippet and I'm going to copy and paste all of these SVGs. Remember these SVGs are inside the assets slash images. Okay, so I'm going to copy and paste some the component itself. Because this is just repeating things. So here, first, we need to specify that in the props, we are going to have an extension which is going to be optional. And that is going to be string. If you want to be more drawn to separate, maybe we can create an interface extension string and say that the prompts is of type prompts. Also we need these, these styles for the icon that is going to be releasing. Just use the Styles. Styles. And we return an object icon with a height of 15 pixels and a width of again 50 pixels. Okay, so that's it for this component and for the support that extensions. That's it for this video. Hope you like it. See you in the next lecture. Bye bye. 42. Tests for the selectFileViewerData selector: And welcome back. So today we're going to start writing the tests for converting a user files array to reach object data structure. Okay, so remember, if we go to Type and go to user file, we have that each file that is stored in redox has these properties here. So somehow we need to convert these to these file viewer structure, which is almost the same as the one we have here with the additional property of extension that is going to be useful for us for having the extension icon component, rendering the corresponding icon after file. Okay, So this is challenging. And for that, we're going to create a new selector. So inside selectors, we're going to create a new folder called Select File Viewer data or whatever you want. I think that is a good name. So late file viewer data, linked file viewer data, the test.js. Ok, so here we're going to write just one test. We're going to say shoot, return a tree. Or Schultz, convert a list of user files to the file viewer structure. And that's it. Okay, so let's create some user files. For example, the first one is going to have an idea of one, a name of index1 dot ds, relative bath of, I don't know, test index one that JS code sounded like console log helloworld. Although this, these, sorry, this code is not meant to be used in the algorithm extension JS. And let's repeat this, but modify it a little bit. Okay, So for the second element, we're going to say id2 index two dot ds. And this is going to be test slash sub-folder slash index.js. And these remains the same. And here in the third element we're going to say index three dot JS is going to be test index three, the GS. Okay, now we have our user files. Now let's create the state that say that the files, these are files and let's tell that script. Trust me, these is a state and I need to import probably their roots date. So import road state from store. Okay. Then we're going to say cons, expected result, okay, So this is the thing that matters the most. So we need to convert these to these, okay? So for the ID, I'm going to say expect any string. And you're going to see why in a moment, name should be test. Because all of these files are inside this test directory. And now we need these children. Okay, so the first step, the first element of this children array is going to have an ID of one. So I'm going to put one here, Name Index 1 dot ds and extension JS. Okay? The second element is going to be more interesting. The IV, we're going to say expect any strength. We're going to say that the name is going to be subfolder. And these element itself is going to have children. These children is going to contain a unique element. An idea of to a name of index.js and an extension of J S. Okay, so this is the second element. And the third. The third element is going to be similar to these first element, an idea three and a name of index three dot JS. And the next station after, yes. Okay, So now we simply need to say expect, select File Viewer data. We pass a state and we say this needs to equal the expected result. Okay, so if I run urine test, obviously this is going to fail because I don't have the Select File Viewer that does electro yet. And that is what we are going to do in the next video. So here in this video, I just want to, to show you an example of how this should be converted to these recursive or tree structure if you want to say it like that. Okay, so I hope you liked this video. See you in the next lecture. Bye bye. 43. Creating the selectFileViewerData selector: Hi and welcome back. So now let's try to code that selector itself and tried to make this test class. So let's create the Select File Viewer data that ts. And create this select File Viewer data. We just go into receive user files, which is of type user file, but an array of user file. And he's going to return a file viewer structure. Okay? So now we can export default and we're going to create selector. Again, this comes from reselect, but it also counts for redox toolkit. So let's change the port. I don't know why VS Code is not giving me the right thing port. And I'm going to pass the first argument, the state, which is of type route state. And we're going to get state that files, that user files, and select File Viewer data as the second argument. Okay, so now let's try to code the logic in order for the tests to pass. First. I'm going to calculate them. Sir files length. So this is user files that length. Now we're going to have these variable result, which is going to be the result. So I'm going to save these is of type file viewer structure. And right now TypeScript is going to complain saying, Hey, this is not a file, file viewer structured type, but I'm going to say, trust me, TypeScript. In a moment. It is going to be of type file viewer structure. So we return the result. And here is where we have to put the logic. So we're going to iterate through each of these files. So in a for loop, we're going to say let I equals 0, I less than user files length I plus, plus. Okay. I'm going to get the user file, same user files at index I. And I'm going to get some properties from user file. So they're going to be name, relative, path, ID and extension. Okay? And then I'm going to get these bats variable. And I'm going to say relative path that split by these lash. So paths is going to be an array of, for example, in this, for this file, it's going to be an array with test as a first element on index one dot js as the second element. Okay? Also we are going to make a for loop, so we're going to need another variable. I'm going to name it J. It's going to start with 0. And we're going to play with these children variable the bit you're going to see in a moment. So we're going to say while paths of j is different from name, we're going to do something here. So for example, here in this example, we're just going to iterate in the while loop once. Because this test, I mean these paths variable is going to have tests and index one the JS. And in the second iteration, index one that J S is going to be equal to the name which is index.js. And that is where we're going to stop iterating. Okay? So first, if j is equal to 0, okay? And second IV, we didn't have result that name. Then we're going to say or assault that ID is going to be j dot ToString came and were sold. That name is going to be equal to bats of J. In fact, these verbal pats, j is going to be used a lot. So let me create a variable. Okay? And the result that children is going to be equal to an empty array. Finally, we increment by one. Either we have a name in the result or not, and we continue. Okay, if j is different from 0, we're going to extract these children by saying result that children, okay? And now we are sure, we're pretty sure that these children exists. So we're going to put an exclamation mark on these tells TypeScript, hey, result that children exists. Okay? Okay. Now we're going to find the sub-folder inside these children. And we're going to say const subfolder children that find. So I'm going to say child were child dot name is equal to the path. Okay? So now we have two cases. Either the sub folder exists or it doesn't exist. So if this subfolder exist, so if sub folder, we're going to say children is going to be equal to a sub folder that children. Else. If this sub folder does not exist, we're going to push an element to the existing children. It's going to, it's going to have an idea of j that just drink. It's going to have a name of bath, and it's also going to have a children, which in this case going to be an empty array. Finally, we're going to set children again to the last element of the current children. So children of children length minus one. Okay, so that's everything. Also. Don't forget j plus plus. So we need to increment that variable. Otherwise, we're not going to be stuck in an infinite while loop. Okay? And yeah, now remember that in the last iteration, bats of j is equal to name, so we need to do something at the end. So here again, we have two cases. So in the first case, we didn't set the children variable, so we enter to the IF, IF, and then we continued and continued, took me out of the while loop. In that case, children is going to be undefined. So I'm going to say if children is not defined, then we're going to say a result children. And we need to push something. So we need to push the IB of the file, the name, and the extension. Okay? And here we are pretty sure that these children exists because we said it here in this line, line 22. And we have the other case where children does exist. Okay? So in that case, we need to remember children. Is this sorry? So we need to access again the children. So we're going to say children that children that push. And again, we're going to put the ID name and the extension. Okay, So in order to not repeat code, I'm going to put file data. All of these properties here. And here I'm going to put vile data. And here again, file data. Okay, now, TypeScript is complaining saying that this property children does not exist. We're pretty sure it exists or going to put that. And also we're going to tell TypeScript, hey, these children is of type file viewer structure. Okay, so I know this part is complicated, but feel free to check this code and to analyze it very carefully and try to understand. So if you understand it in the first place, well, you are good to go. If not, please try to read it carefully and understand it. Now that we have everything. I think I didn't import this into the test, so let me do it and let's try to run the test. So Jahren test, and the test is passing so you can feel free to write more tests if you want. But now I am pretty comfortable that this test is passing. So that's it for this video. Hope you like it. I know it was a little difficult, but I hope you like it. See you in the next lecture. Bye bye. 44. Creating the File Viewer component: Welcome back. So now let's create the file viewer component. Inside go that heater and new folder called file viewer. And here file viewer, that TSX. Ok, and let's use our custom snippet. And here I'm going to first define some styles with use the Styles, make a styles. And in this case I'm going to take the theme and I'm going to return an object. So the root is going to have a padding of 0 pixels, ten pixels, ten pixels, a height of 100%, a width of 100%. We're going to have also a tree item, which is going to have a padding of two pixels, a color of theme dot font. That's why I have the theme here. And when we didn't have files, we're going to have an empty message with a color of theme, that font. Okay, so now in the file viewer, I'm going to have access to these classes. And I'm also going to need the file view word data obviously. And for that I'm going to use the US Up selector. And I'm going to pause here the subtle leg file viewer data. So all that hard work, we're going to be able to use that. Now. With the active. We're also going to need the active files, okay? But, well, not now. We're going to use that in a later B. So here I'm going to just define another function. I mean, yeah, another react arrow function, which is going to be called render tree. And it's going to receive nodes. We, the file viewer, a structure. Okay? And here I'm just going to return a tree item from material UI, okay? And industry RNA, it's going to have a class name of glasses subtree item. It's got to have a key of nodes, dot ID. It's going to have a node ID of, again, note notes that I deem it's going to have a label of notes that name, sorry, nodes, that name. What else? It's going to have an end icon, which is going to be the extension. Hi, Can we just created? And remember we need to pass the extension. In this case, it's going to be nodes. That extension. Okay. In fact, let me convert this withdrawal return because I'm using lots of things of the nodes. So nodes here I'm going to get the node ID, node ID, the name, and also the extension. Okay? So I'm going to replace this with no, they deem these with probably it will be a good idea to rename it to note name. Just to be pretty clear. And these extension I think UT self-explanatory and I need to return this. Okay, fine. So inside this tree item, I'm going to say array that is reading notes that children. So if this thing is and our aim, then I'm going to make a map here. Note step children that map. And then we're going to say nodes, render tree, node, otherwise null. So here is where we are using the recursion. Let me see. Here it is saying render tree is assigned the value but never used. Okay? So we're going to use the render tree in the moment. Now here in this return. Well, after, before doing that, we're going to check object dot keys, file viewer data that length. So if we didn't have anything in the file viewer data are just going to return a div saying no files. And here in the class name, we're going to put glasses that empty message. And here now in the return, we're going to say tree view from material UI. And inside these are going to render the tree recursively with a file viewer data. And for the preview, we're going to put the class name of glasses that route. And we're going to have a default collapse icon of folder, Open icon. Folder, Open icon. So we need to import these folder Open icon. I'm just going to copy the import here. Folder Open icon, it's from material UI icons. And for the default expand icon and default expand icon, we are going to use a folder, ICC folder. Okay, so again, these folder icon comes from material UI icons. And yeah, let me see. Yep. Now we have the file viewer ready to use. Okay, so everything I did here, you can also find it here in this example from the material UI documentation. In fact, here it is. I've tried to make it very similar to this example here. Okay, so I hope you liked this video. See you in the next lecture. Bye bye. 45. Creating the Open File thunk: Hi and welcome back. So we built our file viewer component, but we're missing something. We're missing the on DoubleClick handler. We shall put in these three items. So the striatum is either a folder or a file. So we need to handle the case where this is a folder and where this is a file. So let's say on the whole clique, we're going to call a function. Okay? So this function is going to be called on select note and are going to pass notes, which is going to have the file viewer structure. And here we're going to dispatch a redox think. Okay, it is going to be an asynchronous thank not an a synchronous one. We can still use an asynchronous 11 if we want. We simply don't put anything that is with that needs the await keyword and we're done. But in order to show you how to create seem Cronus, thanks. We're going, we're not going to use that. Create a sync func. Okay? So here I'm going to call this unselect node. And we're going to pass the notes. And I just realize that it will be a better idea to just rename this to note instead of notes. Okay, so here we're going to dispatch the action. But first we have to create the thunk. So inside the store and inside thunks, we're going to create the new thank called Open file. Okay. So let's create the open file.js file. And let's start creating the function. So first, this function is going to receive a note which is going to have the file viewer structure. Okay? And then we're going to return another arrow function, which is going to have a dispatch as the first argument. And this is of type this batch, this dispatch. And the second argument is going to be GetState. And this is of type a function that returns a root. So I know this looks confusing, but this just means get a state is going to be a function that returns the root state. Okay, so first, let's take the active files from the state. First, we call these functions GetState. And then what we can get the active files by, by saying state dot files, that active files. Now let's get also the extension and also the file, sorry, the ID of the note. Okay, so we're going to name this, rename this file extension and these file ID. Okay? And in case this doesn't count the fine, I'm just going to put it on an empty string. Ok, now we're going to say, if also, let me deconstruct but children here. Children, okay, so remember children is optional. So we're going to say if this node has children, so that means that is a sub-directory because it has children. Or we're going to get the support that extensions and we're going to pass a file extension. Or the file extension is not in the support of the extensions, then we simply return. We don't dispatch anything. In fact, if we do that, then we're going to, we're going to move these lines here. Okay? Now, there is a second option that if the active files does not include the file ID, then we shall dispatch in action. And what action should we dispatch the AV active file okay, to the file ID. And at the end, we need to dispatch, we need to dispatch an action to set the editor active file to the file ID. Okay, and finally we export default these open file. Okay, so let's review what we just did here. Okay? So first we say if the node has children or IV, that means this is a four sub directory or folder. And we don't have to do anything there. And if it is, it is it is a file, but it's extension is not in the support of extensions. Then again, we don't do nothing here. Then we check if this file is in the active files. Okay? If it is not in the active file, sorry, then we should add it to the active file. So remember in our example it will be file viewer, an open file. So the IDs of these two things, okay? And finally, we need to set the adductor active file. So for example, if I am here in the code, in this file viewer from VS Code, and I go to this file viewer. If I double-click on this, then what happened? First? I checked if it is already in the active file. So as it is already in the active files, we don't dispatch this action. Second, it got up in this tab got open. And that means we dispatch this action. We said set editor at the file. And that's why this thing is now open. Okay, So now let's dispatch this action by saying open file. And here I'm going to pass them out. And that's it. So obviously I need dispatch. So for that, I'm going to get dispatch. Use up dispatch. Okay? Yep. Now we have completed the file viewer functionality. I hope you liked this video. See you in the next lecture. Bye bye. 46. Creating the Code Editor page: Hi and welcome back. So we have done a lot in the course. I know there are some parts that gets, can get very complicated. But we were, we were able to solve all of those problems. Okay, So now I want to start building the last part of this application, which is the code editor itself. So we're going to start by building the code editor page. So let's go to Pages, and let's go to code editor. Okay? And here let's type code editor that TSX, and let's use our snippet. Okay, So first we're going to define lots of styles. So use styles, make styles. And we return an object and we're going to use the theme variable here. So first, we're going to have the root with the display flex. Hi, 100%, with 100%. Justify content of center. Align items to the center. And a background color. Background color of theme, dot background. Okay. Now we're going to also give the styles for the file viewer, which is our component that we're going to use, are going to again say display flex, flex one, height, 100%. Align items to the center. Justify the content to the center. What else? We're going to put a border right, of one pixel dashed black. So you're going to see these in a moment. And we're also going to have a max width of 300 pixels and an overflow of Alta. Okay, so now we can get the classes subject from use the Styles. That's fine. And we're going to return a beef with the class name of glasses dot root. And inside here we're going to have a class name of classes, that file viewer. And here we're going to put our file viewer component. Okay? And below this thing, we're going to have our gap. It's going to be the editor container. And let's start also writing the status for this. So I'm going to say code editor container. And that's going to have a flex of three and a height of 100%. Okay? So the class name, classes ago that torque container. Okay, so now we can go to router routes that TSX. And here we're going to add a new route. Okay? So here we're going to say yep, so I already have it here, I didn't see it. So instead of doing this, I'm just going to say I'm going to import that code editor. So let me see if b as code helps. Looks like it helped me. So now we have here in this protected route, the code editor. Okay, so let's go and tried to sign in. And yet we have now the file viewer and the editor container. So in fact, we can now, if everything went well, test the file viewer. I'm going to upload. And as you can see, I have all of my files here, so that's pretty, pretty cool. And let's open the redox. Let's commit everything. And let's try to double-click on this other file, copy.txt. So as you can see, two actions got dispatch, this ad active file, and this set editor active file. If I go to the state, you're going to see that I have all of these user files and only these active file here. And the editor active file is the file with these ID. So that's pretty, pretty cool. We are very, very close to achieving our goal of having the code editor app. So that's it for this video. In the next videos, we're going to tackle the problem of building the tops by UC in some material UI components. So I hope you liked this video. See you in the next lecture. Bye bye. 47. Creating the Code Editor Container: Hi and welcome back. So now we're going to build the taps from our code editor. And here we have a very simple example from the material UI documentation, saying simple taps, simple example with no frills. Okay, and here we can see more and more examples on probably. We will like to have these one scrollable tabs. So in case we have like lots of files. So you can see the example from here. So let's try to simplify this and start building our taps from the code editor. Okay, So all the components related to the code editor are going to be hearing components code editor. Okay. So here I'm just going to put editor container. Okay. So the first file is going to be heavy tore container, TSX. Okay? And we're going to have our snippet do the work. Okay, so let's start building some styles with styles. Styles. And you know, we have to return the object, but we're going to use the theme here. Okay? Are going to say root flags, one height of 100% of the parent and an overflow of hidden. So why I am putting these upper flow? Well, when we build our monochromatic per component, it has some styling problems. It overflows Berkeley and I don't know why. And this is the only solution. I managed to get this thing work correctly. Also, we're going to have an empty message. So these are going to be the styles for the empty message. Again, display flex height 100%. And they justify content of center, align items to the center. And finally, for the color, we're going to use the theme, that font. Okay, so now we have dark mode enabled for the empty message. Now we're going to get the class, this object, use styles. Ok, and now it's time to do the work. So when we are going to have empty, an empty message, well, when we didn't have active files, so it makes sense to get the active files. And remember, we have a selector for that. Select active files. So let's go and get the active files. We use app selector and bass industrial lacked active file selector. Find. Now we have the active files. And we can simply say, if active files that length. If these active files, that land is 0, because we are in a gating that we're going to return a div with the class name, Sorry, class name of classes, that empty message and saying select the file. Okay? Now, if this is not the case, we have to return the taps, right? So for this div, I'm going to have a className of glasses that root k. And here we're going to put the navbar from material UI. It's going to have a position static and eye colored fault. You can see these prompts in the documentation. And here we're going to put the tabs component, okay? And inside the tabs component, we need to render some tabs. And those taps correspond to the active files that we just got here. So we're going to map through all of these active files because Active Files is an array. And we're going to say map active file, the file. And you're going to get the active file ID by saying active file dot ID. And I am gone to, I'm going to return a tab which we need to import from material UI. Okay? And this tab, we're going to pass a key of active file ID. Active file ID. And that's, that's all for now. So in fact, we can put this active file ID directly. Okay, No, no need to create a variable. Okay? And for these tabs, we need to pass, I'm sorry, here we also need to pass a label. So for now let's just put foo or test. We're going to spend some more time in that Tub label component. Here in the tabs, we need to specify lots of things. So first, we need to say that text color we want is a primary. We want the indicator color to be the primary. So bunch of style related things. We need these to be a variant, scrollable, scrollable, and scroll buttons. So again, you can find these options in the documentation. But the important thing here are the value, okay? And the onchange handler, okay? So the value must be a number and the unchanged. Well it can be anything. So for now, let's say const, handle change is going to receive an event and it's going to receive a tab position, which is going to be a number. So I told you and the event is going to be of type change event. Okay, and this needs some arguments. We can pass here an empty object. Okay? And here I'm just going to console log for, for the moment. Again, we're going to think more deeply of what shall we do here. Okay? So as I told you, we need a value. And for calculating the value, we need the editor active file. So again, let's get the editor active file, editor, active file. And here we can use again the US app selector and get the state and from the state that the state that files, that editor active file. Okay, now that we have the editor active file in the value, we're going to see if editor active file exists. Then we're going to have from the active files ID's. So again, this is something that, that we need. So I'm going to get active files. Id's. Again, use the app selector. Get this from state the state dot files that are defiles. So remember, active files is an array of IDs, as we already have access files here. I'm renaming these two active files id. So if the editor active file exists, then we're going to get from this array the index of the editor active file. Otherwise we're going to return 0. Okay, so that's it for the value and for the onchange are going to say handle change. Or probably on top, clique will be a better name. Okay? Now, when we click on a tab, we're going to pass these value, which is a number, and we're going to pass it to this untapped click handler. So that's why it tap position is a number. Okay, so I hope this is clear. Now that we have the app bar, we need the tab panel. So if we go here to the documentation of material UI, you're going to see that we need the app bar and also the top panel. So for the tab panel, again, we have to iterate through the active file. So we're going to say active files dot map. We're going to get the active file. Okay? And here we're going to simply return the top panel, tab, panel. Okay? And for the key, I'm going to use the active file ID. So I did here. And I'm going to also pass the active file. The file. Okay? So right now this is not a valid because in the next lecture, actually, we're going to create our own custom tab panel. So that's why here TypeScript is complaining that we're not passing a value, and so on. So don't worry, in the next lecture we're going to create the top panel component. So I hope you like this video. See you in the next lecture. Bye bye. 48. Creating the Custom Tab Panel: Hi and welcome back. So remember that in the last video, we stopped here. So we need to return or render a top panel. And this panel is right now from material UI slash lab. In fact, we didn't want that. We want to create our own custom top panel. So inside the editor container, let's say cools down top panel dot TSX. Let's use our snippet and let's define an interface for the prompts of these components. So first, we're going to get the active file, the whole active file. So remember this is of type user file. And the second thing is the editor active file, which is going to be string or not. So remember, a interactive file can't be a string or null. And we say prompts is of type prompts. Okay, now let's get a simple style. So use the styles with Mega styles. And here we're going to simply return an object, we the root property. And this property is going to have a height of 100%. So very simple. Now here I'm going to have their classes with user styles. And then we're going to get the props. We're going to get the active file and the editor active file. From the active file, I'm going to get the IV and I'm going to rename it to active file ID. Okay, so the thief we're going to return needs to have a className of classes that route. And it also needs other properties. So for example, a role of the panel just for assigning this deliverable. And the most important thing here is the hidden property. So this thing is going to be hidden. The editor active file is not equal to the active file ID. So if you want an example here I have four active files in my VS code. So open file code editor that TSX and editor container dots ESX. These tab panels, that corresponding tab panels of these taps are hidden. The one that is not hidden is the one from the editor active file. So that is custom tab panel dot TSX. So everything here is the top panel for the staff. And for these ones they are simply Heav'n. Okay, so that's, that's it. And here we're going to actually render our monocle code editor. So we need to go this also, but we're going to do that later. Okay, so in the editor container, instead of this top panel, we're going to get the custom tab panel. And remember we need to pass the active file. So I did file is going to be equal to the active file. And we also need the editor active file, which is going to be equal to editor active file. Okay, so now if we go here, well, we need one thing more. And it is going to decode editor page. And instead of returning this text, we're going to return the editor container. Okay, so now we are ready to test this functionality. So he in fact, I already have this. So let me refresh the page. Let's open a workspace. Let's upload the files, and let's double-click on this thing. So as you can see this tab and go to open. So it's named for right now because in our tab we have the label of f2 are going to correct that in the next video. And as you can see, if I click on main, double-click on main.out go. Then it said these as the editor active file. And these are my two, my two active file. So if I click here, it is not doing anything because we need to also click, sorry, also code these on top click handler. So that's it for this video. In the next one we're going to go the tab, the custom tab label. Okay, So I hope you like it. See you in the next lecture. Bye bye. 49. Creating the onTabClick handler: Hi and welcome back. So before we code our custom tab label, we're going to call the on tab click, which I think is pretty, pretty easy. So remember, these are receives the tap position. So in theory, we can get the active file ID by saying, Hey, from active files ID's active file. So this gives me the, the ID at position, tap position. And if the active file, the is not equal to the editor active file. Because what we need to dispatch an action, and that action is going to be the set editor active file. So Dispatch. Dispatch. Yeah, we need the u-sub dispatch. So this bulge is up Dispatch. Okay? And we are going to dispatch the set editor active file. And we're going to pass in the active file ID. So if we do this, then here I have two tabs. Now you can see that the tabs are changing. In fact, let's inspect what is happening here. So right now in my state, the editor active file is 9, 3, blah, blah, blah. And if I click here, then the editor active file change to this one. If I click on the same thing, nothing will happen because this condition is not met. Okay, so that's it for the on tab, click. Hope you like it. See you in the next lecture. Bye bye. 50. Creating the Custom Tab Label component: Hi and welcome back. So now we need to create our custom tab label component. And you're going to see that it's not that easy to close the file. So lots of things happen when we close the file. So without further ado, let's go into the editor container and create this custom tab labeled TSX component and use our reactants nepa. So we have Custom Tab Label. We need to define the interface for the props. So in this case it's just going to have an active file which is of type user file. As easy as that. We're going to have the prompts of type prompts. Okay, so let's define also some styles with just tiles. Make styles. Let's return here an object. And let's make sure we pass the theme variable. Okay? And in the root we're going to say display flex. So we want the, we want a, a that's something I didn't tell you, but we want a tab labeled very similar to these ones. So when Extension icon, the name of the file and these clothes icon. Okay? And so we need display flex because we want to show all of these three things. Horizontally. We want align items to the center. We want to justify content to the center. We also want to text transform. None. That's afforded a route for the file name. We want a padding of 0 pixels and five pixels to the sites. And we want the color off themes that font on the, we want that close icon to have a position absolute and write 0. So these two things mean put the clothes icon the very right of the top. And we also want this to have a color of Fame dot formed. Okay, now we have access to the classes object from USA styles. Okay? And we also need the active file. So from the props, we're going to get the active file. I'm from. Yeah. So I have a typo here. It's active file, not the I shall be lowercase. And from the active file we're going to get the ID, the name, and the extension. Those are the three things that we are going to need from the file through in the name, filename is to be more clear. And here in this div, we're going to say, Sorry, glass name of glasses, dot root. We're going to have an extension icon. So we're going to reuse the extension Ico we just built. We're going to pass the extension. Okay. And we're going to have also another div with a class name of classes dot filename. And we're going to render the filename here. And we're going to have a close icon. So. Fortunately, material you, I have a close icon so we can import it from material UI slash icon slash close. How do I know this? Well, just go to the documentation and you are going to see that close icon. You can search your clothes. And if you want, you can use these, you can use that. You're going to use this whatever you want. Okay? So these close icon is going to have a class name of glasses that close item. And here is the important part. We need the onclick handler, so we need here to pass something. I'm going to call that all close. And this is going to receive an event, which is going to be an mouse event. So make sure to import it from React. And this needs to do lots of logic. So first, let's pass this UNCLOS. Second, let's connect these custom tab a label in the editor container. So instead of label for, we're going to render here the Custom Tab Label. And obviously we need to pass the active file. So we simply pass it. Okay, now, here we need to do something very, very important. We need to stop the propagation. So what does this mean? Remember that the customer Tub label. So this component here is the children of these tabs component. And this, when you click on these tabs component, you are actually triggering these on tab click handler. When we close our file, we don't want these on tab click under to be triggered because weird things can happen. We can dispatch said that IT or active files of something we are about to close. We don't want that. We just want to trigger these UNCLOS handler. Okay, so now let's go to our application and open the redox Def tools. So where is it? It is here. Okay, so let's commit. And here I have my, my file. So let's open these main.py and these main.out TFX. Okay, so if I click here, obviously the set editor active file is going to be triggered. That's correct. But if I click on the Close icon, nothing is going to happen and that's correct. We didn't want to dispatch the set edit directly file. If we don't click on these, but we rather click on the file itself. Then again, the set that are active file is going to render, and that is correct. So in the next lecture, we need to do something else to create, sorry to close the file. And that's where we're going to use another redox think. So, I hope you liked this video. See you in the next lecture. Bye bye. 51. Creaint the Close File thunk: Hi and welcome back. So we were in our custom Tub label and in his own clothes handler. We still need to put some logic in order to close the file. Okay, so let's go to the store. Let's go to the thunks. And here we're going to create a new folder called Close file. And inside this folder, close file.txt. And here's where we're going to create there. Thank in order to manage the logic of closing the file. Okay, so let's create a function called close file, which is going to receive a file ID, which is the file that we are going to remove from the active files. And this is going to return another function which is going to have the dispatch as the first argument and the get the state as the second argument. So remember that get the state needs to have the roots, state needs to return the root state, Sorry. Okay, so here I'm going to get the files. Well first the state, and that is with a good state function. And then the files with state dot files. And here I'm going to get two things. I'm going to get the active files and we're going to deconstruct the active files and editor active file. So let me also get the active files length because that is something that we're going to need. Active files length, remember, active files is an array of IDs. Okay, so now we have two cases to care about here. The first case is when active files on length is greater than or equal to two. So we have right now at least two files. So if we close one file, we have the other one. That is the same case when we have more than two files. And the other case is when we have less than or equal to one. So if we have just one file, then we're going to close all of the, all of the tops and the editor active file should be null. So here I'm going to dispatch the set editor active file, and we are going to pass null. At the end of whatever we do, we have to dispatch the remove active file. So remember, this was an action to filter. So let's see, let's go to either the radius or and see that definition. So this is the logic to, to filter out the Arctic files. Okay, so we need to dispatch this action with the file ID we want to remove and we export default the Cloud file. Okay, So now here in this case, we need to handle again two cases. So the first case is. When the editor active file is equal to the file ID or the file, the next file we are going to close is equal to the editor active file. So in that case, we need to dispatch the same action with the new active file. So how do we get these new active file? Well, let's define these. Get new electrophile function. Get new active file, which is going to receive the active files ID's, which is an array of strings. The active files length, which is a number, and the file ID, which is a string. Okay? Again, so this active files, we call our calculated here, but we already have it here, so we're going to just pass it. So first I'm going to get the index of the active file. So active file, or it's none of the active file, but rather I'm filed to be removed, file to be removed index. So I can think of a better name. File to be removed. Index is going to be active files ID's index both and the file ID. Okay? Now we have two cases here. The first one is that the file to be removed, index plus one is equal to the active files length. Okay? So this means that the file we are going to close is the last top. In that case, we're just going to return that ID of the tab that is to the left. Okay, so that will mean to return the active files id of fat to be removed index minus one. Otherwise, we're going to return the active files ID's of that file that is to the right of the file we want to close. So file to be removed, index plus one. Okay? So here we're going to calculate the new active file. So this will be getting your active file ID, new active file ID, get New York to file a D. We're going to pass the active files, the active files length and the file ID. And if the editor active file is equal to the file ID, or the new active file I D is equal to the editor. So let's put it like this editor. Active file is equal to the new active file it deep. In these two cases, we want to dispatch the set editor active file of the new active file ID. Okay? So this is the logic in order to close a file. So as I was telling you, closing as file is more complex that you may think. Now let's test this and see if it works. So let me refresh and open our workspace again. Example upload. Again. Let's open main that go main.out, IRB, index.js and main.py. So I'm going to close this file. Sorry. I need to go to the custom tab label and get this. But first, this batch use up dispatch. And the second thing we need is to dispatch these, close a file with the file ID, which in this case is this thing here. So I'm going to just rename the file ID just to be clear. Okay, so now let's see. And tried to close this file. It got closed. Let's try to go here and close this file. And let's try to go here. Close this file and close this file. Looks like everything is working as expected. So I suggest you to look at this code and if you didn't catch it, first, then try to understand the code. So try to read it and try to understand it. Okay, so that's it for this video, we are very close to getting our code editor to work. 100%. Hope you liked this video. See you in the next lecture. Bye bye. 52. Creating the Custom Monaco Editor and finishing the app: Hi and welcome back. Now we're going to actually code the custom Monaco Editor Component. So remember in Kusto on top panel, we're just rendering a text here. But now we need to create our custom Monaco Editor dot TSX component. So let's use this snippet here. Okay? And let's go to interface and the clerk, the props, which is going to be active file of type, user file. Great. Now let's say the promises of props. Let's get from perhaps the active file. From active file that's got the id, which is going to be the file ID. Let's get the extension and also the code which I'm going to rename it to original coped. Okay, now let's use the USA state hook. So important from React and the initial value is going to be original code. So basically this state here is going to allow us to change the content of the file instantly. But obviously we need to also update it from the store. Okay? So now we also need the language. So let's get the language. So remember, we're going to get the support that extensions map the keys extension and it is going to return me one of these things here. So either JavaScript, TypeScript, Python, Ruby, java, et cetera. Okay, Now we're going to return instead of a div vi editor, which is the default export of Monaco Editor react. Here I'm going to say, hey, have a width of 100%, a height of 100%. The language. You're going to support this, this one, the theme. Yeah, so for the fame, we also need the dark mode. So we're going to get the dark mode with use absolute vector. So from state, get me the dark mode. So theme, if dark mode is enabled, it is going to be be as dark. Otherwise it's going to be BS light. Okay? The value, that means the content in the editor is going to be the code. So remember that comes from the state. We also need a loading component because it may take a time for the editor to melt. Finally, and the most important part is that we need the onchange handler. So we're going to define an on change handler here. So let's get it. Const on change. And this is going to receive a new code which can call the find or no, I don't know. And I'm going to defaulted to an empty string. And we're going to use this set code with new code. Fine, now we can change code. In fact, let me replace this Monaco Editor more. So it's called Kusto Monaco Editor. And let me pass the active file. So the file, so this construct, and we're going to pass it in another line so that I can get the whole Arctic file here. Okay, so if I go here, open a workspace. Let's open a file. I can now change this. I can pull whatever I want. But obviously, this is not going to be stored in the redox or store. So we need a way or we need to dispatch an action. And that action is going to be the update file called action. Okay? But it will be an efficient to dispatch this action every time we press a key. So we're going to use a device balance. And hopefully I'm low dash hazard the balance method. We're going to take advantage of that. So we're going to save the bounced safe. Use callback, which is a React hook. And as you can see here in this hover, it says it receive a callback and it also receive a dependency array. So for the callback, we're going to use that the balance from Lada, SHE, and we're going to say that these receives a file ID, the new code. And here is where we're going to dispatch. So again, we need that Dispatch. Let me get it. Use up dispatch. Or going to dispatch the update file code action are going to pass the file ID and the new code. Okay? And the second argument of DeBow is the weight. So we need to define a weight. I'm going to say after 1 second, dispatch this action. Now as the second argument, we need to pass an empty array here in the unchanged. Now we can call the denounced the safe with the file ID and also the new code. Okay, So it says here we have a warning that the US callback received a function whose dependencies are unknown person inland function instead. So for now we're just going to disable this for the moment. Okay? Now we can't test this. So let me open the console here. Let's open a redox. And actually let me go to main.py because that's, I know Python. So I'm going to say Hello, Python, the C's the bounce. So these action is not going to fire after 1 second. Okay? And now the action got dispatched. So B, after I stopped writing code and these action got dispatched. And let's see. Let's go to the state and let's go to user files. First. Let's see what's the editor active file. So it's 699 E3. So let's try to find it. The thing that begins with six, looks like. So it's 6, 99. Here it is. It's number 15. And as you can see, this is the code helloworld print helloworld level, level. So yep, got update it. So I think we have done lot here. I can also open the subfolder just in case you didn't notice. Yet, we have done a lot. So let's sign out from our application. And yep, that's the code editor app. Hope you liked this video. See you in the next lecture. Bye bye.