Admin Page Objective
The video builds an admin landing page that displays all articles in a paginated table. It includes options to edit existing articles and prepare for creating new ones.
Database Queries and Model Updates
New queries are added to retrieve all articles (not just published ones) and to support pagination with a count query. The model is updated to use these queries, accepting some duplication for simplicity.
Routing and Controller Setup
An /admin route is introduced with a corresponding controller action. The controller fetches paginated articles and passes them to a new admin view.
Admin View Layout and Structure
The admin page reuses the base layout and applies a grid-based structure. A header section introduces the page, followed by a table spanning two columns to display article data.
Table Construction and Components
A table is created with headers for title, created date, updated date, published status, and actions. A reusable header component is introduced to reduce repetition.
Rendering Article Data
Articles are looped over to populate rows dynamically. Created and updated timestamps are displayed, and published status is shown as either “Draft” or “Published.”
Conditional Styling and Actions
Published status is conditionally styled with color indicators for clarity. An “Edit” link is added per row, with plans to connect it to a dedicated edit page.
Pagination Integration
A pagination component is reused and configured for the admin route. Navigation between next and previous pages is verified.
Navigation and Future Enhancements
An admin link is added to the main navigation bar. Future steps include implementing authentication, conditional navigation visibility, logout functionality, and building the article creation form.
Let's build this admin UI landing page where we just show a table of all the articles in the database with a button to edit and also a button to create a new article. We need to do some plumbing because first we need to actually add another query so we can show not only the published articles and pages but all articles in pages so we can paginate them.
And we're going to still be using the published ads. So we're very close to this one. But yeah, this is fine to have a special purpose curious. So we just got to just generate curious. And then in our model, we can go down here and actually just grab the fine patented published articles. And we're just going to be changing the
here, and then we could basically, we could, yeah, we were a lot of FL, so I don't think that's much, we gain much from creating the body of the function into a reusable function, because we have both the query, query articles in pages and query articles in count, so we also,
We actually also need another query here where we have, where the count one is there. So let me just do this, do this, save, jump out, again, generate queries. And now in our models, article, down here we can say,
the same so we technically have some repetition here but since we are using these two different different queries I think this makes this makes sense we could also try to parameterize the queries but yeah sometimes it's not really worth the effort so I think this is actually this is actually fine and I changed the wrong query we need to change this one
So we give that a save, then we jump into our routes where we want to add admin page route, admin, and then in the controller, we want to basically do what we do in home, but with all articles instead of only the published articles. So we're just going to say admin and find paginated articles.
view. That does not exist yet. That's fine. We're going to add that in a second. Now we can say admin page. Go to admin controller. One last thing. We're going to go in here. We're going to create an admin. Let's just call it admin. Temple. Package views. Temple admin. Is that what we called it in controller? We call it admin
page. All right, so nothing really new happens here. We are just repeating most of the steps of stuff we've already done. Of course, we also need to pass there. Hatchy-nated articles and import the model. There we go. And now we are ready to fill out the admin page with the table and create an
So we're literally just gonna be doing the same steps as we have done with home and with article. We're gonna use the base layout. Let's say the title is admin. Then we're gonna wrap this in our main element with a class. Let me just close it. Give that a save. And in here we wanna say some margin on the top. We have the container. We're gonna say lg max width of 6xl.
One makes auto flex and flex call. We're not really going to be dealing with responsiveness on the admin. You could do that. And that's probably a good exercise for you to do yourself. But generally, you're probably going to access the admin from a desktop because it's an easy environment to write and update the articles in. But it's an exercise there for you to tackle if you want to. Great. Next up, let's just add
H1 tag that says admin. And let's make it text free Excel, text wide and some marking on the bottom. Then we're gonna create a diff. Of course, also with our class, let's close the diff. And in here we're gonna say grid and we want grid with two columns. All right, so this is gonna be the base
of the admin. Let's jump into the browser, give it a save. And let's try and go here to slash admin. And we see we have the admin. It's one tag, but we have nothing in here yet. All right, let's build out the table to show all of the articles. I'm going to start by creating a span. Same class again. And we're going to have this span one column.
Then there we go. And in here, what do we want? We want to have an H2 tag that says, should we just have it say articles, articles, H2. Let's add some styling. So say font semi-bold, text-based content, and text.xl. And underneath it, let's create a paragraph tag where we say manage
in one place. And let's make a text-based content 70 opacity so it doesn't stand out as much as the articles header. Alright, maybe that is a little bit too much. Text-based, what did we actually call it in the theme? Text-based content. Alright.
Maybe let's try with 90 instead. Nope. Okay. I don't want it to be this. So let's do it. Is that just a white and 70? I think that's probably gonna look a little bit better. No.
server. Right. Now we actually have the styles applied. Okay. Can we do text-based content? We can. Okay. Much, much better, but I actually like it with text-wide instead. Yeah. Let's go with
Are we better there? Yeah, that's probably good. All right. Next, let's do another span here. I'm going to say class, again called span one. Inside of here, we're going to have another h2. So we are now starting to repeat ourselves a bit here. We could. No, actually, we don't need another h2. What I'm doing, we just need a href.
to say that article. And do we actually want to grab our, we have our button link instead. So what do we want here? We want something to go to a route that we don't have yet because this is the ads article route that we will create in just a second. The title is gonna be ads.
So we're just going to leave this as to do for now, because in the upcoming episode, we're going to be dealing with the whole create article page. So we can update it there. What do we have then? OK. I don't really like that we don't take up all of the space. What are we doing? Let's just put in a border to debug this. OK.
here, so we say grid and place, grid, grid, and place items ends are much better, much better. So this is typically using borders is typically like a back end way of aligning things, probably better ways, but border really works good to see how much space does something take up.
All right, that's the top part in place. Now I want to deal with the table. So we're going to create a table element here, where we will say, again, class, and we will say mt4 to give it some briefing room. We're going to say this has to span two columns. And text is going to be text as m. Inside it, we are going to create a t, t header, table header.
That's going to be having the style of PG base 300. I'm going to add some border on the bottom of this element. And the border is just going to be gray 500. And in here, we need to add a table row. And inside of the hair here is going to be a table header. OK.
The table road does not need any styling, but the table header is going to be having text algae, text left, pdx, six, py, three, and font, semi, bold, and finally text-based content. And we're going to be having header for each of the, the basically the headers of the article we want to show. So we're going to have created that, we're going to have published that, updated and published, and we also want to have
So we're going to be repeating this header multiple times. Let's just make it into a component and say, temple, title, header. And only thing is going to accept is the title. Save and then we can use it down here to say, table, header. And we're going to have title.
Adds, maybe just give it a space, created ads. And then updated ads. What more did I actually want to show? I want to show published. Published as a Boolean. And then finally, we're going to leave one empty, which is going to be having a placeholder for where the edit button is going to go. All right, let's give that a save and see what we have now.
All right, I think that's a good place to be in. Next, we need to deal with the table body. So we're gonna create a T body element, which we also apply some styling to. We're gonna say BG base 200. We're gonna say D wide on the Y axis. And we're gonna say D wide gray 700.
see what that gives us. Nothing yet, because we don't have any elements. So inside of here, we're going to be creating a table, or table row. It's probably a table row here. And a table data, I believe it stands for. I'm not entirely sure here, to be honest. All right. The table row will simply add a hover to the base 350. So we can see what
row we are interacting with. And on the TD, we're going to say class. We're going to add some padding on the x-axis, padding on the y-axis. We're going to say fun should be medium. We want to use text-based content. And we want to truncate it if it overflows the row. And here, we are going to be passing some of the fields. But I think, again,
Let's take this and make it into components. So table data, writes. Do we actually want to do this? No, we don't want to do this because we're going to add in some if else. So this is what we're going to stick with. We're going to loop over all of the paginated articles, range, paginated articles.
here, and now we can say article.title, fix this import, see if something shows up now, and we have some articles showing up. Great, now let's just finish the other rows, so we have created that, updated that, published that, that we need a row for the edit button, so we need, what, we're gonna need four more,
passing the created, created that. So we format this to be this, and what are we complaining about? This should be good. Let me see what is happening.
So now can we do it? Okay. All right. Now we are showing something up, but the dates are correct. Yes. All right. All right.
We are getting there. Repeat this for updated adds. Adds and now instead of showing when something was published, we just want to show an indicator to see if anything, to see if it's published or in draft. So we're going to say, if article published, add is zero, then we will simply say drafts, else
say, published. Yes. So now we have draft and published. It would probably be nice if this field or this was showing some colors. So we can actually say something like, if I wrap this in brackets, say, a symbol, again, kv. We need two of them.
Here we wanna add text. Let's say text to warning. Let's see how it looks. Pop is that zero, right? And then text success if it's not zero. So if you actually have a date, then you're gonna say zero. Now,
Yeah, I like the orange, the yellowish color. I think that's good for this one. Right. And then the final one, we are just gonna have, actually we're gonna use a button link that goes to do, because this is gonna go to the edit page. It's just gonna say edit. Maybe we want to,
Let's actually add cursor pointer and hover underline it. So we have some indication now, but I don't really like that this is info. So should we actually update this with R?
class, we can add a class so we can add CSS to it depending on what it is. What do we want to do? Button link, no. I think we're actually just going to grab the link here, go back and say, going to be R to do.
And we're going to say edit, remove this. We're going to say secondary and secondary. I think that's a bit better. Now can we actually get it to go to the ends of the fields?
Let's try and say, what is it? Place self in? No. Can we not add this? Okay, we're gonna leave it for there. I think this is fine. Maybe we should add a different color. Let me move this text base content. Yeah, that looks a lot better.
So we do have some duplication here, which is fine because we would have to add a lot of if else logic to our component, which you can do with Temple. But sometimes it's also not really worth the effort. But if you see this in multiple places, maybe we can start to create a suite of buttons or bottom links components with all kinds of different options. But for now, we just need this one instance. So I actually like better to just
The copy-based code will have a little bit of duplication, but also a little bit more easier workflow and freedom to edit the button until we actually know what we want in the end. So one final thing we need to have an option to paginate through the articles. So this one is also going to span two columns. We'll have some margin on the y-axis of four. Let's see how that looks.
And we're gonna place it at the ends of the available space. We can just reuse our pagination. What do we actually call it? Pagination. There's actually no reason for this to be exported, so let me just un-export it.
admin. We are going to be passing the routes admin. Now admin page. And we're going to say, what did I call it? Hedginated articles. And next and previous page. Let's go in and see if that works.
We have some spacing now, and this is previous page that is wrong. Let me switch these rounds. Go back in here and give it a save. Now we have next page, next page, previous page, previous page. So this is a very simple admin, but at least now we can see our articles and we will increment the functionality to edit and add new ones.
What more do we want? We maybe want to update our navigation bar. So in base layout, we're going to add another element here to say, slash admin, admin. We have our admin option here. So if we go to home, we can now click admin. When we have dealt with
We will hide this navigation element, so it only shows if you are locked in. We also add a lock out button, and those two will again only be shown if you are authenticated. So the user only see the home button. All right. I think this is it for now. Let's jump into dealing with actually creating an article. So we need to accept some form data. We need to set up a form. We need to validate what we get.
Yeah, so next episode is set up likely to actually create an article so we can start managing it through our admin portal.