Building An Admin Panel
Now that you have completed the previous
Hello World,
Make a Simple Website and
Database Work Flows guides. It is
important to note that all the guides combine together into a single project
we will be moving on to building an admin panel. The first step we will be doing
is creating a route folder and within that route folder we will create a
Admin.js
file and you will use the following code: Admin.js
.
'use strict'
const fs = require('kado/lib/FileSystem')
class Admin {
static register (app) {
const route = new Admin(fs.path.join(__dirname, '../view/admin'))
app.get('/admin/', route.index())
app.get('/admin/login/', route.login())
app.post('/admin/login/', route.login())
app.get('/admin/logout/', route.logout())
}
The code above uses fs(filesystem)
require in order to get the
(‘kado/lib/FileSystem’)
then we use the class function to call the admin
object. Then we make a static method named register to be called when routes
should be placed into the application. The next line
const route = new Admin(fs.path.join(__dirname, '../view/admin'))
makes an
instance of our route object, then placing fs.path.join
method to create and
join the path in a string. Lastly, we use the _dirname
variable to tell us the
absolute path of the directory containing the executing file. then using
app.get
for matching and handling a specific route when requested.
Now we will place a homepage route by adding additional code to Admin.js:
Admin.js
.
index () {
return (req, res) => {
if (!req.session.get('staff')) {
return res.render('admin/error', { error: 'Must be logged in' })
}
req.locals._pageTitle = 'Home'
res.render('admin/home')
}
}
The above code is for creating an index and in that we use return to get our
request and response. Then using if(!req.session.get(‘staff’)) {
we can send
the user to an error page saying they are not logged in successfully get the
session we will return and render a response
(‘admin/error’, { error: ‘Must be logged in’ })
. On the last two lines the
pageTitle
is set and we render the page using res.render(‘admin/home’)
.
Next, we will add a login method to handle displaying and authenticating staff
members. Adding on to Admin.js: Admin.js
.
login () {
return (req, res) => {
if (req.body.email) {
req.session.set('staff', { email: req.body.email })
res.statusCode = 302
let referer = req.headers.referer || '/admin/'
if (referer.match(/\/admin\/login\/$/)) referer = '/admin/'
res.setHeader('Location', referer)
return res.end()
}
req.locals._pageTitle = 'Login'
res.render('admin/login')
}
}
Above, we make the login method which will display a login page or test a staff
members authentication. Depending on whether or not req.body.email
is present
we will check for the staff members login to be valid. When req.body.email
is
present, we test authentication and if valid create a session, otherwise
display a login page for the staff member to input authentication details.
Upon a successful login we redirect the user to where they previously came
from in case they were hot linked into the application.
Finally place this section of code to handle staff logging out of the system:
Admin.js
.
logout () {
return (req, res) => {
req.session.set('staff', undefined)
res.statusCode = 302
res.setHeader('Location', '/admin/login/')
return res.end()
}
}
}
The above code will create the logout route to clear staff sessions. Setting the
staff session to undefined makes it appear as if it never existed. After doing
so, we set the status code to 302 and redirect the user back to the login page
by setting the Location header to /admin/login/
.
Then you will use the following code to represent the current module and exports
as a module: Admin.js
.
module.exports = Admin
Now that we have completed the admin.js we will be creating a Help.js
file
and with in the Help.js file we will be using the following code: Help.js
.
'use strict'
const Assert = require('kado/lib/Assert')
const fs = require('kado/lib/FileSystem')
const HelpModel = require('../model/HelpModel')
const Module = require('kado/lib/Module')
const Route = require('../lib/Route')
class Help extends Module {
constructor () {
super()
this.app = null
this.name = 'help'
this.title = 'Help'
this.description = 'Manage help articles'
}
The code above we use Assert
, fs
, HelpModel
, Module and Route to require
and connect the listed folder and files. Next we use the class Help extends
module to create the child class of another class, then we use the
constructor()
function that initializes our object, then using the super
class to call the constructor to access the parent properties and methods which
will be the this.app
, .name
, .title
, and .description
.
The next section of code we will use the following: Help.js
.
list () {
return async (req, res) => {
const db = this.db.getEngine()
const query = HelpModel.list()
const rv = await Route.listRoute(db, query)
req.locals._pagetitle = 'List Help Articles'
res.render('admin/help/list', { rows: rv[0], fields: rv[1] })
}
}
The above code creates a list method to show all our Help articles in a list. To do so it makes a query to the database using the modules list method and our included listRoute helper method from Route. Next, we set the page title and finally render the page passing our database return values to the template.
Use the following for the the next section of code: Help.js
.
listAction () {
return async (req, res) => {
const db = this.db.getEngine()
const query = HelpModel.delete()
const rv = await Route.listActionRoute(db, query, req.body)
if (rv.deleted) res.setHeader('X-Deleted', rv.deleted)
res.redirect('/admin/help/')
}
}
The above code adds the edit method which retrieves our Help article from the
database and then displays a form where the staff member can edit the content.
Assert.isType ensures that the database returned an appropriate response.
Finally, we render the admin/help/edit
template by passing the instance of the
HelpModel
.
Moving on to the next section of code you will be using is the following:
Help.js
.
create () {
return (req, res) => {
req.locals._pagetitle = 'Create Help Article'
res.render('admin/help/create')
}
}
The next line we use create()
so that we use the object to set the page title
and use the create Help article and then render the (‘admin/help/create’)
.
Under the above code you will now be using the following: Help.js
.
edit () {
return async (req, res) => {
const db = this.db.getEngine()
const query = HelpModel.byId(req.query.get('id'))
const rv = await db.execute(query.toString(), query.toArray())
Assert.isType('Array', rv[0])
const help = new HelpModel(rv[0].shift())
res.render('admin/help/edit', { help: help })
}
}
Now we will be using the edit()
in order to edit the db, query and rv. First
we get the database engine. Then we call the query to the HelpModel.byid
to
get the id query, next we execute the database query to a string and an array.
The next line we have Assert.isType
which will get us the array and get the
new HelpModel
value. Lase we rent the (‘admin/help/edit’, { help: help })
.
Use the following to create the save()
: Help.js
.
save () {
return async (req, res) => {
const db = this.db.getEngine()
const id = req.body.id || 0
await Route.saveRoute(db, HelpModel, id, req.body)
res.redirect('/admin/help/')
}
}
The save method will allow you to save the changes made on the create or edit
form into the database. This is done by passing the contents of req.body
to
the Route.saveRoute
method which handles inserting or updating the database
record. The next section of code you will use the following: Help.js
.
admin (app) {
this.app = app
this.db = this.app.database.getEngine('mysql')
app.get('/admin/help/', this.list())
app.get('/admin/help/create/', this.create())
app.get('/admin/help/edit/', this.edit())
app.post('/admin/help/', this.listAction())
app.post('/admin/help/save/', this.save())
}
Here we register the admin panel routes that are available.
Now we will be using the following code for the next section: Help.js
.
main (app) {
app.get('/help/', (req, res) => {
res.render(fs.path.join(__dirname, '/view/help.html'))
})
}
}
This portion of the module registers the Help routes that into the main interface.
The final portion of code exports our module objects so they can be used to
register into the application. Help.js
.
Help.HelpModel = HelpModel
Help.Model = Help.HelpModel
module.exports = Help