00:00
[MUSIC]
00:05
Next, let's add in a paginated list of our movies for
00:08
our admin so that they're able to manage them,
00:10
put actions within that table.
00:11
Let's hide that pack away.
00:13
Within our routes file, let's scroll down to
00:14
where we have our admin section at.
00:16
I believe that's down near the bottom.
00:18
Yep, right here. Let's add in router.get/movies,
00:23
and let's add in an admin movies controller.
00:27
We don't have that created quite yet,
00:29
but we'll create that here in a second with
00:30
an index method as movies.index.
00:34
Remember that we have this route group
00:35
prefixed with the name of admin.
00:37
So this will really be admin.movies.index.
00:40
So it won't collide with our existing movies.index.
00:43
I'm going to jump into my terminal now,
00:44
stop our server, clear that out.
00:46
Node.asemakecontroller admin/movies,
00:51
and we'll do hyphen R to create that as a resource.
00:54
Cool. So this created our controller at
00:56
appcontrollers admin movies controller.ts.
00:59
Let's go and clear that out and boot our server back up.
01:01
So npm run dev.
01:02
Let's hide that back away.
01:03
Now you get a sense of why we're prefixing
01:05
these admin controllers with the word admin,
01:07
because we already have a movies controller imported right here.
01:11
We can go and give that a copy as a starting point.
01:13
Paste it in here, prefix the name with admin,
01:15
jump down to the actual import path,
01:17
and prefix that with admin/ as well.
01:19
Again, by nesting our controllers inside of subfolders,
01:21
we're able to give them a purpose and
01:23
also keep the names simplified as well.
01:26
Cool. So we can give that a save.
01:27
Let's scroll all the way back down because that's
01:29
where we'll be needing to pick back up here within this file.
01:31
Let's go and jump into our new movies controller or our admin.
01:34
Again, by creating this as a resource,
01:36
we're stubbed with the resourceful methods that we get.
01:38
So index, create, store, show, edit, update, and destroy.
01:42
You may have some ESLint warnings and errors for unused properties,
01:45
but that's okay. We'll take care of that as we fill this out.
01:47
All right. So let's start by getting our movies.
01:49
So const movies equals await.
01:51
We can import our movie model.query.
01:53
For the admin section, we're going to want to get back all of our movies.
01:56
You could add filtering in using the same approach that we
01:58
did with our watch list and movies pages.
02:00
Since we've already covered how you can go about that,
02:02
we're going to skip that here for this page.
02:03
So let's just order this by the updated at and descending order.
02:08
So we'll get them by most recently updated to the oldest updated.
02:12
Let's add paginate to the end of that.
02:14
This is where we'll want to grab the page and the per page counts.
02:17
So we can grab our request.
02:19
While we're in here, we'll also grab our view out of our HTTP context.
02:22
We can do const page equals request input page and default that to one.
02:28
If it's not provided, we'll provide that in there.
02:30
Per page, maybe we'll do 30.
02:32
Then we need to define our base URL.
02:34
So movies.baseURL, and we can import our router to make URL,
02:40
or our admin movies index page.
02:43
Since we're not worrying about filtering for this particular page,
02:45
we're not going to have additional query strings to worry about
02:47
depending onto these generated pagination URLs.
02:50
But if you did, as we previously covered,
02:52
you have movies.queryString at your disposal that you can provide
02:55
a key value record pair into to add query strings into your generated URLs.
02:59
So let's go ahead and return view.renderPages/.
03:04
Rather than putting this inside of our movies directory,
03:07
we're going to keep this scoped inside of our admin directory,
03:09
and we'll create another movies index page inside of there,
03:12
and provide our movies in.
03:14
If we wanted to list out some additional details,
03:16
we can go ahead and preload that onto our query as well.
03:18
So we could say preload the director and preload the writer.
03:23
Of course, there's aggregates and counts that we could do as well.
03:26
So we could do with count,
03:27
and we could say count our cast members and count crew members as well.
03:32
Let's also go ahead and preload our status into,
03:34
I forgot about that relationship status, and there we go.
03:37
So now we should have everything preloaded onto our movies that we'll need.
03:40
Let's go ahead and scroll on down and create our page.
03:42
So we'll scroll down to,
03:44
let's see, our pages admin section.
03:47
Right-click that folder, new file,
03:49
create a new movies directory with an index.edge page inside of it.
03:53
We have our app, we want to apply our layout.adminlayout and end that.
03:58
Now, we'll apply an h1 in here that says movies,
04:01
and then let's just do a simple table.
04:02
So we'll do a table with a T head and a table row with a table heading,
04:08
showing the movie title,
04:09
then maybe another one with the status,
04:12
then maybe writer director,
04:13
and maybe counts,
04:15
and then we'll do an empty one for actions.
04:17
For our T body,
04:19
go ahead and scroll down a little bit.
04:20
We're going to want to loop over each of our movies and apply them in as a row.
04:23
So we'll do @each movie in movies,
04:26
end our each, add in our table row,
04:29
table data, movie title,
04:31
TD, movie status, name,
04:34
another TD where we can do our movie.writer.fullname/moviedirector.fullname.
04:41
We'll have a TD for our counts and a TD for our actions.
04:46
So let's pause there for now and let's jump into
04:48
our admin layout and add an additional link for this new page.
04:51
So we have an href equals routes,
04:54
admin, movies, index, and we'll just call that movies.
04:57
Go ahead and close that out,
04:58
jump back into our browser and let's see what we get.
05:00
So let's jump into our new movies page.
05:02
It's not pretty, but it is there and it is working.
05:05
You can see our movie title,
05:06
the movie status, the writer, and director,
05:09
and it will take care of our counts and action here momentarily.
05:11
But first, I think we're going to need to make the text small,
05:14
maybe even extra small just to fit within our table here.
05:17
So let's jump up to our table class,
05:18
text extra small to try and squeeze everything in here real quick.
05:22
It'd probably also be good to go ahead and break these down on
05:24
separate lines and annotate which is which here.
05:27
So let's wrap this one here in a div and do writer,
05:31
colon, and then paste that back in.
05:33
Then let's do the same thing here,
05:35
director, colon, and paste their name back in there.
05:38
Now, let's take care of our counts.
05:39
So we'll do something similar for this.
05:41
So we'll split them up one per line.
05:43
We'll have our cast members as movie.
05:46
For this, we'll want to reach inside of the movies extras object as
05:50
counts aggregates and the like are not direct model properties.
05:53
So they're going to be plopped inside of our extras object.
05:56
I believe this should be called cast members_count.
06:00
Give that a copy because all that we need to do is switch cast to
06:03
crew and we'll have our crew members count there as well.
06:06
Give that a save and let's see if we got that right.
06:08
So let's jump back into our browser.
06:10
Okay. So now we have I'm your boogeyman,
06:12
post-production, writer, director,
06:14
cast members of four,
06:16
crew members of three.
06:17
It looks like everything there is working A-okay for our movies here so far.
06:20
So we'll worry about adding the actions in and subsequent lessons.
06:23
For now though, we need to get the pagination rigged up.
06:25
Now, on our movies page,
06:26
we've already added this in via our buttons right down here.
06:30
So we can replicate this into a component so that we can reuse it on our movies page,
06:34
as well as our watch list page,
06:36
and now our admin movies page as well.
06:39
So let's hide this back away and we want to jump into
06:41
either our movies or watch list index page.
06:44
We have it defined in both of them.
06:46
So we can scroll down to where we have,
06:47
let's see our pagination looks to start right here.
06:50
So we'll place our cursor right there.
06:51
I'm just going to go ahead and collapse this down and
06:53
jump down and select the end div there.
06:55
We can cut this out,
06:56
scroll up to our components.
06:58
Let's right-click that, new file, pagination,
07:01
and let's create an index.edge file within there.
07:04
Paste that in and there we go.
07:05
So everything within here should mostly rely on
07:08
our pagination methods and properties.
07:11
I'm going to just scroll through here real quick just to
07:13
verify that that is actually the case.
07:16
We have a pagination array right there that we'll want to
07:18
make sure that we're instantiating inside of this component as well.
07:21
But apart from that, everything does seem to be coming directly from the paginator.
07:24
Let's jump back into our pages movies and
07:26
see if we can find where that pagination is coming from.
07:28
Doesn't look like it's coming from our edge file.
07:30
So let's jump up into our movies controller
07:33
because it must be coming from here then.
07:35
Scroll down and sure enough, there is our pagination.
07:38
This can easily be refactored and moved down into our pagination components.
07:42
So I'm going to go ahead and get rid of that,
07:44
and we can remove that out of the page state there too.
07:46
Hit "Command P" and jump back into our new pagination components.
07:49
Scroll up to the top, give ourselves a couple of lines and we can paste that in.
07:52
It's not going to be formatted quite yet,
07:54
but what we're going to want to do is at let,
07:57
we can create the range min,
07:58
same as we were within our controller, just like so.
08:01
We want to do the exact same thing for our range max.
08:04
So at let, there we go,
08:05
as well as our pagination.
08:07
So at let there too.
08:09
What we want to do next is normalize all of our movies properties,
08:13
which is our movies paginator,
08:14
into a nonspecific name.
08:16
So I think the most appropriate name for that is probably going to be paginator,
08:20
as it controls all of our pagination logic by providing us our properties and methods.
08:25
So we'll go ahead and do a replace all there,
08:27
and everything should still be a okay with how we had it.
08:30
So we'll scroll through here,
08:31
make sure there's no red squigglies, looks okay.
08:33
Let's go and give this a save,
08:34
jump back into our movies page at exclamation point,
08:37
pagination, since this will be self-closing,
08:39
and provide in our paginator is our movies.
08:43
Let's give that a save, jump back into our browser,
08:45
and let's jump into our movies page to test it out.
08:47
Looks like I got a missing token.
08:48
Yeah, I never ended the let there for that one.
08:51
So let's go ahead and take care of that,
08:52
jump to our pagination component,
08:54
and there we go.
08:55
That looks better. Give that a save,
08:56
jump back into our browser,
08:57
give this a refresh once more.
08:59
Let's go and scroll on down and make sure everything's working here.
09:01
So page two, three, four, next goes to two,
09:04
and last goes to 28, first goes to one.
09:07
Awesome. So everything there does seem to be working a-okay.
09:09
Next, what we want to do is apply
09:11
the exact same paginator component into our watchlist page.
09:14
So let's hide our browser back away,
09:15
jump on down to our watchlist page,
09:17
which seems to be right here
09:19
off the root of our pages directory.
09:20
Scroll down to where we should have our pagination starting,
09:23
go ahead and hit the caret to collapse that down,
09:25
and we just need to get rid of everything there.
09:27
And this should be the exact same.
09:28
So at exclamation point, pagination, paginator,
09:32
and I believe we called it movies here as well.
09:34
Then we'll jump into our watchlist controller,
09:36
Join The Discussion! (0 Comments)
Please sign in or sign up for free to join in on the dicussion.
Be the first to Comment!