A Simple Concept - part 05
Now that we have an admin, let's give them a dashboard! So what are we going to need here? Holding true to the Rails convention, we need a model, which we already have. We will use the newsletter and contact / lead models. We need a controller, and a view. We will create a admin dashboard so let's create an admin controller. I used the -p flag and first ran:
bin/rails g controller admin -p
This showed that it would create the admin controller and also the admin folder in the views folder, but no view file. I want to go ahead and create the dashboard so I will also include the dashboard action in the command. Here is the new command:
bin/rails g controller admin dashboard
This command creates the admin controller and the view called dashboard. We use the generator to create the controller called admin and pass it the dashboard action. This creates a new folder in views called admin and puts the dashboard in it. Let's open the controller first.
We see that the dashboard action has been created. Let's check out the view. Here you can see the simple format that Rails created on making the view. Let's go to the browser and check out the page. If you visit your "localhost:3000/admin/dashboard" you will see the page. If yours looks anything like mine then you really don't see it because it is hidden under the navbar. My point here is that we should not be able to navigate to this page. We need to lock it down. Let's return to the admin controller.
Here we want to create an action that will check if the admin is signed in. If not then return to the root and say sorry. At the top of the class, just under the name, we call the before action on that action. This way the we check who you are before anything else. Some may suggest putting this auth action in a private section. Sure, but in my opinion there is no need at the moment. Here is what I have:
class AdminController < ApplicationController
before_action :authenticate_admin
def dashboard
@newsletter = Newsletter.all
end
# action to only allow admins
def authenticate_admin
if !admin_signed_in?
flash[:alert] = "Admin only."
redirect_to root_path
end
end
end
Now if you try to visit the admin dashboard you will be redirected, unless you are signed in of course. With the dashboard protected, let's gather some data. Above you can see that we can call the model like we would in the console and assign it to a variable. So within the dashboard action let's call the newsletter model and assign it the newsletter variable.
In the dashboard view we can loop through that variable and display those emails. Here is what I did to test this quickly. Of course we need to be signed in now. We will do the same thing for the Leads model.
领英推荐
<div class="flex flex-col justify-center items-center w-full text-gray-200 bg-slate-900 mt-20 min-h-[calc(100vh-88px)]">
<h1 class="font-bold text-4xl">Admin#dashboard</h1>
<p>Find me in app/views/admin/dashboard.html.erb</p>
<ul>
<% @newsletter.each do |news| %>
<li><%= news.email %></li>
<% end %>
</ul>
</div>
So here is what I ended up with that I will push to the repo branch. It is just a two grid columns layout with the newsletters on one side and the leads on the other.
<div class="flex flex-col justify-center items-center w-full text-gray-200 bg-slate-900 mt-20 min-h-[calc(100vh-88px)]">
<h1 class="font-bold text-4xl">Admin#dashboard</h1>
<p>Find me in app/views/admin/dashboard.html.erb</p>
<div class="grid grid-cols-2 gap-2 mt-6">
<div>
<ul>
<h2 class="text-xl font-bold">Newsletter</h2>
<% @newsletters.each do |news| %>
<li class="border border-gray-200 rounded px-2 py-1"><%= news.email %></li>
<% end %>
</ul>
</div>
<div>
<ul>
<h2 class="text-xl font-bold">Leads</h2>
<% @leads.each do |lead| %>
<div class="border border-gray-200 rounded px-2 py-1">
<div class="flex">
<li class="pe-1"><%= lead.first_name %></li>
<li><%= lead.last_name %></li>
</div>
<li><%= lead.email %></li>
<li><%= lead.phone %></li>
</div>
<% end %>
</ul>
</div>
</div>
</div>
Here is the admin controller:
class AdminController < ApplicationController
before_action :authenticate_admin
def dashboard
@newsletters = Newsletter.all
@leads = Lead.all
end
# action to only allow admins
def authenticate_admin
if !admin_signed_in?
flash[:alert] = "Admin only."
redirect_to root_path
end
end
end
Let's touch one more thing before we go. I noticed that the phone number is not formatted like I want. Now there are a lot of issues here if we want. Users are knuckle heads and we need to account for that. Did they put in the correct number of digits, do we need the 1 in front, Europe is different than North America. I am not going to dive into all that. I just want the area code wrapped in parentheses.
The phone number is used in the lead model. That is where we will put the code to format it. Before we save the phone field to the database we want to ensure it is formatted how we want. This action removes non-digit characters from a phone number, "gsub(/\D/, '')", then inserts parentheses and a dash to format it as (XXX) XXX-XXXX.
class Lead < ApplicationRecord
before_save :format_phone_number
private
# Reformat phone number to (123) 456-7890 from whatever the user entered
def format_phone_number
self.phone = self.phone.gsub(/\D/, '').insert(0, '(').insert(4, ') ').insert(9, '-')
end
end
There, that's better. Now we can put this up on Render. I know there are still issues to address like the navbar menu on mobile or the update functionality for the admin in leads. I encourage you to take a stab at it. As for me, I will get to that after we are set up on Render so we can see how CI / CD works.
I hope you are enjoying this build so far. See you in the next one. Till then, keep coding!