Commit f61a131c authored by Stephen's avatar Stephen 💯
Browse files

Organize Admin Panel and Get Localhost up and running

parent 49f93d04
{
"extends": ["standard"]
}
/node_modules
/.idea
\ No newline at end of file
# Building A Admin Panel
# Building An Admin Panel
Building an admin panel
Now that you have completed the previous
[Hello World](https://kado.org/guide/hello-world/),
[Make a Simple Website](https://kado.org/guide/make-simple-website/) and
[Database Work Flows](https://kado.org/guide/database-work-flow/) guides,
[Database Work Flows](https://kado.org/guide/database-work-flow/) 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 folder and you will use the following code: `Admin.js`.
admin.js file and you will use the following code: `Admin.js`.
```js
'use strict'
......@@ -23,22 +23,21 @@ class Admin {
}
```
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 use static register to acquire the app. Next we const route to create
a new route for the admin , then using 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.
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 use static register to acquire the app. The next line
const route = new 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.
Under the code above you’ll be using the following code: `Admin.js`.
Beneath the code above you’ll be using the following code: `Admin.js`.
```js
index () {
return (req, res) => {
console.log(req.session.get('staff'))
if (!req.session.get('staff')) {
return res.render('admin/error', { error: 'Must be logged in' })
}
......@@ -49,14 +48,14 @@ index () {
```
The above code is for creating an index and in that we use return to get our
request and response then using console.log to print the log message. Then
using if(!req.session.get(‘staff’)) { when we 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 (‘admin/home’).
request and response. Then using `if(!req.session.get(‘staff’)) {` when we
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’)`.
You will use the next section of code for the login(): `Admin.js`.
Next, we will add a login method to handle displaying and authenticating staff
members. Adding on to Admin.js: `Admin.js`.
```js
login () {
......@@ -75,16 +74,16 @@ login () {
}
```
We will use login() and by doing so we are creating the login. Under that we
will return the req and res, then using if(req.body.email) we will get the email
body and next we will set the session so that it's for staff and get back the
email body and respond the StatusCode 302. The next line we use referer the
headers is the ‘/admin/’ and then match the referer with the admin and login
and then get the setHeader(‘location’, referer).
We will use `login()` and by doing so we are creating the login. Under that we
will return the `req` and `res`, then using `if(req.body.email)` we will get the
email body and next we will set the session so that it's for staff and get back
the email body and respond the `StatusCode 302`. The next line we use referer
the headers is the `‘/admin/’` and then match the referer with the admin and
login and then get the `setHeader(‘location’, referer)`.
The last part of code we will be using is the logout(): `Admin.js`.
Finally place this section of code to handle staff logging out of the system:
`Admin.js`.
```js
logout () {
......@@ -99,19 +98,18 @@ The last part of code we will be using is the logout(): `Admin.js`.
```
This will create the logout feature. The next line of code we route the function
and set the session for staff and undefined because it has been declared but
not assigned a value. Then we get the statusCode and that will be 302 and the
set the header and end it.
and set the session for staff and its undefined because it has been declared but
not assigned a value. Then we get the `statusCode` and that will be `302` and
the set the header and end it.
Then you will use the following code to represent the current module and exports
as a module: `Admin.js`.
```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`.
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`.
```js
'use strict'
......@@ -150,13 +148,13 @@ list () {
}
```
The above code we will create a list() and we are doing that because we can use
The above code we will create a `list()` and we are doing that because we can use
this to store multiple pieces of information at once, such as a list of records
in the database or a list of contents. On the next line we use the return async
function to create a promise that will be resolved with the returned value.
Then we use const db to get the database engine and HelpModel is used to obtain
Then we use const db to get the database engine and `HelpModel` is used to obtain
a list query from the model to pass that query to the database engine, then we
set the page title with req.locals_pageTitle, then we pass the return values
set the page title with `req.locals_pageTitle`, then we pass the return values
from the database to the template for rendering.
......@@ -177,8 +175,8 @@ Now we will be using the list action method which will be similar to the
previous code we used. We are now using the list action method and the
difference is that we are using the delete method and that will use the
delete query. The next line we are getting the route to the listAction to go to
the db, query and req.body. The next line we are saying if the variable is
deleted we get the setHeader response and redirect to (‘/admin/help’).
the db, query and `req.body`. The next line we are saying if the variable is
deleted we get the setHeader response and redirect to `(‘/admin/help’)`.
......@@ -193,8 +191,8 @@ 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’).
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`.
......@@ -212,14 +210,14 @@ edit () {
}
```
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 }).
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`.
Use the following to create the `save()`: `Help.js`.
```js
save () {
......@@ -250,7 +248,7 @@ admin (app) {
}
```
With this part of code we have the admin() and that will initiate the app and
With this part of code we have the `admin()` and that will initiate the app and
get the database engine and connect the following using the app.get.
......@@ -267,9 +265,9 @@ Now we will be using the following code for the next section: `Help.js`.
}
```
The code above will have the main(app) and you will use app.get for
(‘/help/’, (req, res) and render the filesystem and join the path to the
(_dirname, ‘/view/help/html’)).
The code above will have the `main(app)` and you will use app.get for
`(‘/help/’, (req, res)` and render the filesystem and join the path to the
`(_dirname, ‘/view/help/html’))`.
Finally the last part of code we have is the last part you will need for the
same reason as we talked about above: `Help.js`.
......
......@@ -17,7 +17,7 @@ app.database.addEngine('mysql', mysql)
// add a command to create the database schema
app.cli.command('db', 'test', {
action: () => {
console.log('hi!')
console.log('Database OK')
return 1
}
})
......@@ -26,7 +26,7 @@ app.cli.command('db', 'init', {
const db = app.database.getEngine('mysql').getEngine()
// load models
const models = [
require('./model/PetModel')
require('./model/AdmModel')
]
const promises = []
models.forEach((model) => {
......@@ -46,7 +46,7 @@ app.cli.command('db', 'init', {
const http = new Application.HyperText.HyperTextServer()
app.http.addEngine('http', http.createServer(app.router))
// add a view engine
const viewFolder = fs.path.join(__dirname, 'views')
const viewFolder = fs.path.join(__dirname, 'view')
app.view.addEngine('mustache', new Application.View.ViewMustache(viewFolder))
app.view.activateEngine('mustache')
// add a static server
......
'use strict'
const cfg = {
appTitle: 'AdminPanel',
appTitle: 'adminpanel',
main: {
host: null,
cookieSecret: null,
......@@ -8,9 +8,9 @@ const cfg = {
},
mysql: {
host: 'localhost',
user: 'ap',
password: 'ap',
database: 'ap'
user: 'adm',
password: 'adm',
database: 'adminpanel'
}
}
module.exports = cfg
\ No newline at end of file
'use strict'
const fs = require('kado/lib/FileSystem')
class Admin {
static register (app) {
const route = new Admin(fs.path.join(__dirname, '../view'))
// admin panel
app.get('/admin/', route.index)
app.get('/admin/login/', route.login)
app.post('/admin/login/', route.login)
app.get('/admin/logout/', route.logout)
}
index (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')
}
login (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')
}
logout (req, res) {
req.session.set('staff', undefined)
res.statusCode = 302
res.setHeader('Location', '/admin/login/')
return res.end()
}
}
module.exports = Admin
'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'
}
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] })
}
}
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/')
}
}
create () {
return (req, res) => {
req.locals._pagetitle = 'Create Help Article'
res.render('admin/help/create')
}
}
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 })
}
}
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/')
}
}
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())
}
main (app) {
app.get('/help/', (req, res) => {
res.render(fs.path.join(__dirname, '/view/help.html'))
})
}
}
Help.HelpModel = HelpModel
Help.Model = Help.HelpModel
module.exports = Help
\ No newline at end of file
'use strict'
class Main {
static register (app) {
const route = new Main()
app.get('/about/', route.about)
app.get('/article/:article/', route.article)
app.get('/news/', route.news)
app.get('/business-cloud/', route.businessCloud)
app.get('/cloud/', route.cloud)
app.get('/contact-us/', route.contactUs)
app.get('/features/', route.features)
app.get('/', route.index)
app.get('/login/', route.login)
app.get('/order/', route.order)
app.get('/privacy-policy/', route.privacy)
app.get('/refund_policy/', route.refundPolicy)
app.get('/terms-of-service/', route.terms)
}
about (req, res) {
req.locals._pageTitle = 'About'
res.render('about')
}
article (req, res) {
req.locals._pageTitle = 'Article'
res.render('article/' + req.params.article)
}
businessCloud (req, res) {
req.locals._pageTitle = 'Business Cloud'
res.render('business-cloud')
}
cloud (req, res) {
req.locals._pageTitle = 'Cloud'
res.render('cloud')
}
contactUs (req, res) {
req.locals._pageTitle = 'Contact Us'
res.render('contact-us')
}
features (req, res) {
req.locals._pageTitle = 'Features'
res.render('features')
}
index (req, res) {
req.locals._pageTitle = 'Home'
res.render('home')
}
login (req, res) {
req.locals._pageTitle = 'Login'
res.render('login')
}
order (req, res) {
req.locals._pageTitle = 'Order'
res.render('order')
}
news (req, res) {
req.locals._pageTitle = 'News'
res.render('news')
}
privacy (req, res) {
req.locals._pageTitle = 'Privacy'
res.render('privacy')
}
refundPolicy (req, res) {
req.locals._pageTitle = 'Refund Policy'
res.render('refund_policy')
}
terms (req, res) {
req.locals._pageTitle = 'Terms'
res.render('terms')
}
}
module.exports = Main
'use strict'
const Assert = require('kado/lib/Assert')
const KadoModel = require('kado/lib/Model')
class Model extends KadoModel {
static async listRoute (db, query) {
const rv = await db.execute(query.toString(), query.toArray())
rv[0].forEach((v) => {
v.createdAt = v.createdAt.toTimeString()
v.updatedAt = v.updatedAt.toTimeString()
})
return rv
}
static async listActionRoute (db, query, data = {}, idField = 'id') {
let rv, action
if (data.action instanceof Array) action = data.action
else action = [data.action]
if (data.delete) {
let deleted = 0
action.forEach(async (id) => {
query.where(idField).value(id)
rv = await db.execute(query.toString(), query.toArray())
Assert.isType('Array', rv)
deleted++
})
return { deleted: deleted }
}
return false
}
}
module.exports = Model
'use strict'
const Assert = require('kado/lib/Assert')
const Model = require('./Model')
const Module = require('kado/lib/Module')
const Query = require('kado/lib/Query')
const Schema = require('kado/lib/Schema')
const tableName = 'User'
const Validate = require('kado/lib/Validate')
class User extends Module {
constructor () {
super()
this.name = 'user'
this.title = 'User'
this.description = 'Manage users'
}
main (app) {
// register routes
app.post('/user/save', this.save())
app.post('/user/saveOrderPartial', this.saveOrderPartial())
app.get('/user/getOrderSession', this.getOrderSession())
app.post('/user/login', this.authorize())
app.get('/user', this.index())
app.get('/user/login', this.login())
app.get('/order', this.create())
app.get('/user/manage', this.manage())
app.get('/user/edit', this.edit())
app.get('/user/change-password', this.changePassword())
app.get('/user/change-email', this.changeEmail())
app.get('/user/cancel', this.cancel())
app.get('/user/login', this.login())
app.get('/user/logout', this.logout())
app.get('/user/:uri', this.profile())
}
authorize () {
return (req, res) => {
const data = req.body
User.findByPk(data.email, req.Q)
.then((result) => {
// login without auth for now
req.session.user = result.dataValues
req.flash('success', 'Login successful!')
res.redirect(301, '/file')
})
.catch((err) => {
res.render('error', { error: err })
})
}
}
cancel () {
return (req, res) => {
res.render('user/cancel')
}
}
changePassword () {
return (req, res) => {
res.render('user/changePassword')
}
}
changeEmail () {
return (req, res) => {
res.render('user/changeEmail')
}
}
create () {
return (req, res) => {
res.locals._asset.addScriptOnce('/js/order.js')
if (!req.session.order) req.session.order = {}
const params = {
email: req.session.order.email || ''
}
if (req.query && req.query.email !== undefined) {
if (req.query.email) req.session.order.email = req.query.email
res.redirect(301, '/order')
} else {
res.render('user/order', params)
}
}
}
getOrderSession () {
return (req, res) => {
res.setHeader('Content-Type', 'application/json')
res.end(JSON.stringify(req.session.get('order') || {}))
}
}
edit () {
return (req, res) => {
res.render('user/edit', req.session.user)
}
}
index () {
return (req, res) => {
if (req.session.user) {
res.redirect(301, '/user/manage')
} else {
res.redirect(301, '/user/login')
}
}
}
login () {
return (req, res) => {
res.render('user/login')
}
}
logout () {
return (req, res) => {
req.session.user = false
req.flash('success', 'Logout successful!')
res.redirect(301, '/')
}
}
manage () {
return (req, res) => {
res.render('user/manage', req.session.user)
}
}
profile () {