Add basic functionality
This commit is contained in:
126
server/router/account/index.js
Normal file
126
server/router/account/index.js
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
/**
|
||||||
|
* This router handles things related to the web browser experience...
|
||||||
|
*/
|
||||||
|
|
||||||
|
// This is the mock data we working with...
|
||||||
|
module.exports = function (options) {
|
||||||
|
var express = options.express;
|
||||||
|
var db = options.db;
|
||||||
|
var passport = options.passport;
|
||||||
|
|
||||||
|
var router = express.Router();
|
||||||
|
|
||||||
|
router.route('/')
|
||||||
|
.get(function(request, response, next) {
|
||||||
|
if (request.user) {
|
||||||
|
response.display("account", {
|
||||||
|
user: request.user,
|
||||||
|
pageTitle: "Home - Mantra"
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
router.route('/authenticate') // TODO: Might have a unique identifier for this endpoint...
|
||||||
|
.get(function (request, response, next) {
|
||||||
|
if (request.user == null) {
|
||||||
|
response.display("login-username", {
|
||||||
|
user: request.user,
|
||||||
|
pageTitle: "Login - Mantra",
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
response.redirect('/');
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.post(function (request, response, next) {
|
||||||
|
if (request.user == null) {
|
||||||
|
var username = "" + request.body.username;
|
||||||
|
username = username.trim().toLowerCase();
|
||||||
|
if(request.body.password == null) {
|
||||||
|
const email = db.Email.build({
|
||||||
|
address: username
|
||||||
|
})
|
||||||
|
email.validate()
|
||||||
|
.then((email)=> {
|
||||||
|
response.display("login-password", {
|
||||||
|
user: request.user,
|
||||||
|
username: email.address,
|
||||||
|
pageTitle: "Login - Mantra",
|
||||||
|
});
|
||||||
|
}).catch(error => {
|
||||||
|
response.display("login-username", {
|
||||||
|
user: request.user,
|
||||||
|
username: username,
|
||||||
|
pageTitle: "Login - Mantra",
|
||||||
|
data: {
|
||||||
|
message: "Enter a valid email"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
passport.authenticate('local', (error, user, info) => {
|
||||||
|
console.error("Error: ", error)
|
||||||
|
if(info) {
|
||||||
|
console.log("Info: ", info)
|
||||||
|
response.display("login-username", {
|
||||||
|
user: request.user,
|
||||||
|
username: username,
|
||||||
|
pageTitle: "Login - Mantra",
|
||||||
|
data: info
|
||||||
|
})
|
||||||
|
} else if(user) {
|
||||||
|
|
||||||
|
if(request.body.rememberMe) {
|
||||||
|
var now = new Date();
|
||||||
|
var expiresAt = new Date();
|
||||||
|
expiresAt.setFullYear(expiresAt.getFullYear()+5);
|
||||||
|
// request.session.cookie.expires = expiresAt;
|
||||||
|
request.session.cookie.maxAge = expiresAt;
|
||||||
|
|
||||||
|
// TODO: Add the remember me cookie...
|
||||||
|
} else {
|
||||||
|
// TODO: Set that the remember me cookie wasn't selected...
|
||||||
|
}
|
||||||
|
|
||||||
|
request.logIn(user, function(err) {
|
||||||
|
if (err) { return next(err); }
|
||||||
|
return response.redirect('/');
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
response.redirect('/account/authenticate')
|
||||||
|
}
|
||||||
|
})(request, response, next);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
response.redirect("/");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
router.route('/logout')
|
||||||
|
.post(function(request, response, next) {
|
||||||
|
if (request.user) {
|
||||||
|
request.logout();
|
||||||
|
return db.Session.destroy({
|
||||||
|
where: {
|
||||||
|
sid: request.sessionID
|
||||||
|
}
|
||||||
|
}).then(result => {
|
||||||
|
response.redirect('/');
|
||||||
|
}).catch(error => {
|
||||||
|
response.redirect('/');
|
||||||
|
console.error("Log out error: ", error);
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
response.redirect('/');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// var passwordResetRouter = require('./password-reset/')(options);
|
||||||
|
var libraryRouter = require('../library')(options);
|
||||||
|
|
||||||
|
// router.use('/password-reset', passwordResetRouter);
|
||||||
|
router.use('/library', libraryRouter);
|
||||||
|
|
||||||
|
return router;
|
||||||
|
};
|
||||||
182
server/router/account/password-reset/index.js
Normal file
182
server/router/account/password-reset/index.js
Normal file
@@ -0,0 +1,182 @@
|
|||||||
|
const express = require('express')
|
||||||
|
const emailAPI = require('../../../email/email-api')
|
||||||
|
|
||||||
|
module.exports = function (options) {
|
||||||
|
const db = options.db;
|
||||||
|
var router = express.Router();
|
||||||
|
|
||||||
|
router.route('/')
|
||||||
|
.get(function(request, response, next) {
|
||||||
|
response.display("password-reset-initiation", {
|
||||||
|
user: request.user,
|
||||||
|
pageTitle: "Password Reset - Mantra"
|
||||||
|
})
|
||||||
|
}).post(function(request, response, next) {
|
||||||
|
// TODO: Create UserPasswordReset object.
|
||||||
|
// TODO: Send email with link to /account/password-reset/:id
|
||||||
|
db.User.findOne({
|
||||||
|
include: [
|
||||||
|
{
|
||||||
|
association: db.User.UserEmails,
|
||||||
|
required: true,
|
||||||
|
where: {
|
||||||
|
emailAddress: request.body.email
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
association: db.User.UserPasswordReset
|
||||||
|
}
|
||||||
|
// TODO: Include user.UserPasswordReset
|
||||||
|
]
|
||||||
|
}).then(user => {
|
||||||
|
if (user) {
|
||||||
|
// TODO: Check if user already created a password reset entry to save on a db transaction
|
||||||
|
return Promise.all([
|
||||||
|
user.userEmails[0],
|
||||||
|
user.userPasswordReset ? user.userPasswordReset : db.UserPasswordReset.create({
|
||||||
|
userId: user.id
|
||||||
|
})
|
||||||
|
])
|
||||||
|
} else {
|
||||||
|
return [null, null]
|
||||||
|
}
|
||||||
|
}).then(async (results) => {
|
||||||
|
userEmail = results[0]
|
||||||
|
userPasswordReset = results[1]
|
||||||
|
if (userPasswordReset) {
|
||||||
|
await userPasswordReset.increment('sent')
|
||||||
|
// Send password reset email...
|
||||||
|
return emailAPI.sendPasswordResetEmail(userPasswordReset.token, userEmail.emailAddress)
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}).then(emailResult => {
|
||||||
|
if (emailResult) {
|
||||||
|
response.display("password-reset-initiated", {
|
||||||
|
user: request.user,
|
||||||
|
pageTitle: "Password Reset Initiated - Mantra"
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
// TODO: Check if email is an immigrant
|
||||||
|
db.Immigrant.findOne({
|
||||||
|
where: {
|
||||||
|
emailAddress: request.body.email
|
||||||
|
},
|
||||||
|
include: [
|
||||||
|
{
|
||||||
|
association: db.Immigrant.User,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
association: db.Immigrant.Email,
|
||||||
|
required: true,
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}).then(async (immigrant) => {
|
||||||
|
if (immigrant && immigrant.user == null) {
|
||||||
|
// Resend invitation
|
||||||
|
await emailAPI.sendImmigrationInvitationEmail(
|
||||||
|
immigrant.id, immigrant.emailAddress, immigrant.displayName
|
||||||
|
)
|
||||||
|
|
||||||
|
response.display("password-reset-initiated", {
|
||||||
|
user: request.user,
|
||||||
|
pageTitle: "Password Reset Initiated - Mantra"
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
next(`Failed to create a user password reset entry (user ${request.body.email} doesn't exist)`)
|
||||||
|
}
|
||||||
|
}).catch (error => {
|
||||||
|
next(error)
|
||||||
|
})
|
||||||
|
// TODO: Create password reset error page with possible reasons...
|
||||||
|
|
||||||
|
}
|
||||||
|
}).catch(reason => {
|
||||||
|
console.error("Something went wrong with reset: ", reason)
|
||||||
|
// TODO: Tell user
|
||||||
|
next(reason)
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
router.route('/:token')
|
||||||
|
.get(function(request, response, next) {
|
||||||
|
if (request.user) {
|
||||||
|
// TODO:
|
||||||
|
response.display("logout-to-continue", {
|
||||||
|
user: request.user,
|
||||||
|
pageTitle: "Logout Before Continue - Mantra"
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
db.UserPasswordReset.findByPk(request.params.token, {
|
||||||
|
include: [
|
||||||
|
{
|
||||||
|
association: db.UserPasswordReset.User
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
.then(userPasswordReset => {
|
||||||
|
if (userPasswordReset) {
|
||||||
|
response.display("password-reset", {
|
||||||
|
user: request.user,
|
||||||
|
pageTitle: "Password Reset - Mantra",
|
||||||
|
userPasswordReset: userPasswordReset
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
next()
|
||||||
|
}
|
||||||
|
}).catch(error => {
|
||||||
|
next(error)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}).post(function(request, response, next) {
|
||||||
|
if (Boolean(request.body.password) && request.body.password == request.body.confirmPassword) {
|
||||||
|
db.UserPasswordReset.findByPk(request.params.token, {
|
||||||
|
include: [
|
||||||
|
{
|
||||||
|
association: db.UserPasswordReset.User,
|
||||||
|
required: true,
|
||||||
|
include: [
|
||||||
|
{
|
||||||
|
association: db.User.Passwords,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}).then(userPasswordReset => {
|
||||||
|
if (userPasswordReset) {
|
||||||
|
var password = userPasswordReset.user.passwords[0]
|
||||||
|
password.password = request.body.password // Password will be hashed...
|
||||||
|
return Promise.all([userPasswordReset, password.save()])
|
||||||
|
} else {
|
||||||
|
return [null, null]
|
||||||
|
}
|
||||||
|
}).then(results => {
|
||||||
|
userPasswordReset = results[0]
|
||||||
|
password = results[1]
|
||||||
|
if (password) {
|
||||||
|
// Password reset success invite user to reset...
|
||||||
|
response.redirect("/account")
|
||||||
|
// Cleanup...
|
||||||
|
userPasswordReset.destroy({
|
||||||
|
force: true
|
||||||
|
}).then(() => {})
|
||||||
|
.catch(reason => console.error("Failed to destroy userPasswordReset", reason))
|
||||||
|
} else {
|
||||||
|
// TODO: Give user failed password page...
|
||||||
|
next("Failed to reset password")
|
||||||
|
}
|
||||||
|
}).catch(error => {
|
||||||
|
next(error)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
// TODO: Tell user password reset failed..
|
||||||
|
next("Passwords do not match")
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
return router;
|
||||||
|
};
|
||||||
15
server/router/campaigns/index.js
Normal file
15
server/router/campaigns/index.js
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
const express = require('express')
|
||||||
|
|
||||||
|
module.exports = function (options) {
|
||||||
|
const db = options.db;
|
||||||
|
var router = express.Router();
|
||||||
|
|
||||||
|
router.route('/')
|
||||||
|
.get(function(request, response, next) {
|
||||||
|
response.display("campaigns", {
|
||||||
|
user: request.user,
|
||||||
|
pageTitle: "Library - Mantra"
|
||||||
|
})
|
||||||
|
})
|
||||||
|
return router;
|
||||||
|
};
|
||||||
@@ -17,5 +17,15 @@ module.exports = function (options) {
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var accountRouter = require('./account/')(options);
|
||||||
|
var libraryRouter = require('./library')(options);
|
||||||
|
var pledgesRouter = require('./pledges/')(options);
|
||||||
|
var campaignsRouter = require('./campaigns/')(options);
|
||||||
|
|
||||||
|
router.use('/library', libraryRouter);
|
||||||
|
router.use('/pledges', pledgesRouter);
|
||||||
|
router.use('/campaigns', campaignsRouter);
|
||||||
|
router.use('/account', accountRouter);
|
||||||
|
|
||||||
return router;
|
return router;
|
||||||
};
|
};
|
||||||
88
server/router/library/index.js
Normal file
88
server/router/library/index.js
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
const express = require('express');
|
||||||
|
const req = require('express/lib/request');
|
||||||
|
|
||||||
|
module.exports = function (options) {
|
||||||
|
const db = options.db;
|
||||||
|
var router = express.Router();
|
||||||
|
|
||||||
|
router.route('/')
|
||||||
|
.get(function(request, response, next) {
|
||||||
|
db.Entry.findAll({
|
||||||
|
|
||||||
|
}).then(entries => {
|
||||||
|
response.display("library", {
|
||||||
|
user: request.user,
|
||||||
|
pageTitle: "Library - Mantra",
|
||||||
|
entries: entries
|
||||||
|
})
|
||||||
|
}).catch(error => {
|
||||||
|
next(error)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
router.route('/add')
|
||||||
|
.get(function(request, response, next) {
|
||||||
|
if (request.user) {
|
||||||
|
response.display("library-form", {
|
||||||
|
user: request.user,
|
||||||
|
pageTitle: "Add Library - Mantra",
|
||||||
|
entry: { }
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
next()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.post(function(request, response, next) {
|
||||||
|
if (request.user) {
|
||||||
|
db.Dialect.findOne({
|
||||||
|
where: {
|
||||||
|
languageId: "en",
|
||||||
|
countryId: "int"
|
||||||
|
}
|
||||||
|
}).then(dialect => {
|
||||||
|
if (dialect) {
|
||||||
|
return db.Entry.create({
|
||||||
|
name: request.body.name,
|
||||||
|
url: request.body.url,
|
||||||
|
dialectId: dialect.id,
|
||||||
|
licenseId: "copyright"
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
response.redirect("/library/add") // TODO: Show error message on missing dialect...
|
||||||
|
}
|
||||||
|
|
||||||
|
}).then(entry => {
|
||||||
|
if (entry) {
|
||||||
|
response.redirect(`/library/${entry.id}`)
|
||||||
|
} else {
|
||||||
|
next()
|
||||||
|
}
|
||||||
|
}).catch(error => {
|
||||||
|
next(error)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
next()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
router.route('/:id')
|
||||||
|
.get(function(request, response, next) {
|
||||||
|
db.Entry.findByPk(request.params.id, {
|
||||||
|
include: [
|
||||||
|
{
|
||||||
|
association: db.Entry.EntryApproval
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}).then(entry => {
|
||||||
|
response.display("entry", {
|
||||||
|
user: request.user,
|
||||||
|
pageTitle: "Library - Mantra",
|
||||||
|
entry: entry
|
||||||
|
})
|
||||||
|
}).catch(error => {
|
||||||
|
next(error)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
return router;
|
||||||
|
};
|
||||||
15
server/router/pledges/index.js
Normal file
15
server/router/pledges/index.js
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
const express = require('express')
|
||||||
|
|
||||||
|
module.exports = function (options) {
|
||||||
|
const db = options.db;
|
||||||
|
var router = express.Router();
|
||||||
|
|
||||||
|
router.route('/')
|
||||||
|
.get(function(request, response, next) {
|
||||||
|
response.display("pledges", {
|
||||||
|
user: request.user,
|
||||||
|
pageTitle: "Library - Mantra"
|
||||||
|
})
|
||||||
|
})
|
||||||
|
return router;
|
||||||
|
};
|
||||||
@@ -115,12 +115,12 @@ module.exports = function () {
|
|||||||
include: [
|
include: [
|
||||||
{
|
{
|
||||||
association: db.UserRole.Role,
|
association: db.UserRole.Role,
|
||||||
required: true,
|
// required: true,
|
||||||
where: {
|
// where: {
|
||||||
type: {
|
// type: {
|
||||||
[db.Sequelize.Op.or]: roles
|
// [db.Sequelize.Op.or]: roles
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -172,12 +172,12 @@ module.exports = function () {
|
|||||||
include: [
|
include: [
|
||||||
{
|
{
|
||||||
association: db.UserRole.Role,
|
association: db.UserRole.Role,
|
||||||
required: true,
|
// required: true,
|
||||||
where: {
|
// where: {
|
||||||
type: {
|
// type: {
|
||||||
[db.Sequelize.Op.or]: roles
|
// [db.Sequelize.Op.or]: roles
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
6
server/views/account.pug
Normal file
6
server/views/account.pug
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
extend templates/layout.pug
|
||||||
|
|
||||||
|
block content
|
||||||
|
.container
|
||||||
|
.center
|
||||||
|
h1 Account
|
||||||
6
server/views/campaigns.pug
Normal file
6
server/views/campaigns.pug
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
extend templates/layout.pug
|
||||||
|
|
||||||
|
block content
|
||||||
|
.container
|
||||||
|
.center
|
||||||
|
h1 Campaigns
|
||||||
@@ -1,14 +1,18 @@
|
|||||||
|
html {
|
||||||
|
font-family: courier;
|
||||||
|
}
|
||||||
|
|
||||||
/* Color scheme from https://material.io/resources/color/#!/?view.left=0&view.right=1&primary.color=212121&secondary.color=263238 */
|
/* Color scheme from https://material.io/resources/color/#!/?view.left=0&view.right=1&primary.color=212121&secondary.color=263238 */
|
||||||
.primary-color {
|
.primary-color {
|
||||||
background-color: #683400 !important;
|
background-color: #f9fbff !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.primary-color-light {
|
.primary-color-light {
|
||||||
background-color: #9a5e2c !important;
|
background-color: #ffffff !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.primary-color-dark {
|
.primary-color-dark {
|
||||||
background-color: #3d0b00 !important;
|
background-color: #c6c8cc !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.secondary-color {
|
.secondary-color {
|
||||||
|
|||||||
6
server/views/entry.pug
Normal file
6
server/views/entry.pug
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
extend templates/layout.pug
|
||||||
|
|
||||||
|
block content
|
||||||
|
.container
|
||||||
|
.center
|
||||||
|
h1= entry.name
|
||||||
@@ -7,6 +7,6 @@ block content
|
|||||||
|
|
||||||
p.flow-text A home for translation projects.
|
p.flow-text A home for translation projects.
|
||||||
p.flow-text Give translators the abilitiy to crowd fund for their work.
|
p.flow-text Give translators the abilitiy to crowd fund for their work.
|
||||||
p.flow-text Gives authors/publishers the option to crowd fund for rights to their literature.
|
p.flow-text Gives authors/publishers the option to crowd fund digital rights to their literature.
|
||||||
p.flow-text Give the community the ability to bid for translations of their choice.
|
p.flow-text Give the community the ability to pledge for library of their choice.
|
||||||
p.flow-text Open source by default.
|
p.flow-text Open source open literature.
|
||||||
18
server/views/library-form.pug
Normal file
18
server/views/library-form.pug
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
extend templates/layout.pug
|
||||||
|
|
||||||
|
block content
|
||||||
|
.container
|
||||||
|
.center
|
||||||
|
h1 Library
|
||||||
|
|
||||||
|
.row
|
||||||
|
.col.s12
|
||||||
|
form.row(action="/library/add", method="post")
|
||||||
|
.col.s12.input-field
|
||||||
|
input#name(type="text", name="name", value=entry.name)
|
||||||
|
label(for="name") Entry Name
|
||||||
|
.col.s12.input-field
|
||||||
|
input#url(type="text", name="url", value=entry.url)
|
||||||
|
label(for="url") Entry Url
|
||||||
|
.col.s12
|
||||||
|
button.btn.black(type="submit") add entry
|
||||||
17
server/views/library.pug
Normal file
17
server/views/library.pug
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
extend templates/layout.pug
|
||||||
|
|
||||||
|
block content
|
||||||
|
.container
|
||||||
|
.center
|
||||||
|
h1 Library
|
||||||
|
|
||||||
|
a.btn.black(href="/library/add") add entry
|
||||||
|
if entries.length == 0
|
||||||
|
p.flow-text No Literature currently on the system
|
||||||
|
else
|
||||||
|
.row
|
||||||
|
each entry in entries
|
||||||
|
.col.s12
|
||||||
|
a(href=`/library/${entry.id}`)
|
||||||
|
.card-panel
|
||||||
|
p.flow-text= entry.name
|
||||||
39
server/views/login-password.pug
Normal file
39
server/views/login-password.pug
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
extend templates/layout.pug
|
||||||
|
|
||||||
|
block content
|
||||||
|
-
|
||||||
|
if (data)
|
||||||
|
var message = data.message
|
||||||
|
data = data == null ? {} : data;
|
||||||
|
.container
|
||||||
|
.row
|
||||||
|
.col.s12.l4.m3
|
||||||
|
p
|
||||||
|
.col.s12.l4.m6
|
||||||
|
.center
|
||||||
|
h2.flow-text Password
|
||||||
|
if message
|
||||||
|
p.flow-text.red-text= message
|
||||||
|
form(action="/account/authenticate" method="POST")
|
||||||
|
<input type="hidden" name="username" value="#{username}"/>
|
||||||
|
.row
|
||||||
|
.col.s12
|
||||||
|
<label for="password">Password:</label>
|
||||||
|
<input id="password" type="password" name="password" autofocus/>
|
||||||
|
.col.s12
|
||||||
|
p
|
||||||
|
label
|
||||||
|
input(type="checkbox", name="rememberMe", checked="checked" )
|
||||||
|
span Remember Me
|
||||||
|
.row
|
||||||
|
|
||||||
|
<div class="col s12 center">
|
||||||
|
//- <button class="btn waves-effect waves-light" v-on:click="attemptLogin">Log In</button>
|
||||||
|
<button class="btn blue waves-effect waves-light" type="submit" name="action">Login
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col s12 center">
|
||||||
|
<a class="btn-flat waves-effect waves-light" href="/account/password-recovery">forgot password</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
44
server/views/login-username.pug
Normal file
44
server/views/login-username.pug
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
extend templates/layout.pug
|
||||||
|
|
||||||
|
block content
|
||||||
|
-
|
||||||
|
if (data)
|
||||||
|
var message = data.message
|
||||||
|
data = data == null ? {} : data;
|
||||||
|
|
||||||
|
.container
|
||||||
|
.row
|
||||||
|
.col.s12
|
||||||
|
.row
|
||||||
|
.col.s12.l4.m3
|
||||||
|
p
|
||||||
|
.col.s12.l4.m6
|
||||||
|
.center
|
||||||
|
h2.flow-text Login/Register
|
||||||
|
if message
|
||||||
|
p.flow-text.red-text= message
|
||||||
|
form(action="/account/authenticate" method="POST")
|
||||||
|
.row
|
||||||
|
<label for="email">Email:</label>
|
||||||
|
<input id="email" type="text" name="username" value="#{data.username}" autofocus/>
|
||||||
|
.row
|
||||||
|
|
||||||
|
<div class="col s12 center">
|
||||||
|
//- <button class="btn waves-effect waves-light" v-on:click="attemptLogin">Log In</button>
|
||||||
|
<button class="btn blue waves-effect waves-light" type="submit" name="action">Login/Register
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
.col.s12
|
||||||
|
p.center
|
||||||
|
a.center(href="/account/password-reset") forgot password
|
||||||
|
p.center
|
||||||
|
a.center(href="/account/creation") create a new account
|
||||||
|
.col.s12.l4.m3
|
||||||
|
.row
|
||||||
|
|
||||||
|
//- .col.s12
|
||||||
|
.center
|
||||||
|
p
|
||||||
|
strong OR
|
||||||
|
a.btn.blue(href="/account/oauth/google") LOGIN VIA GOOGLE
|
||||||
|
|
||||||
6
server/views/pledges.pug
Normal file
6
server/views/pledges.pug
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
extend templates/layout.pug
|
||||||
|
|
||||||
|
block content
|
||||||
|
.container
|
||||||
|
.center
|
||||||
|
h1 Pledges
|
||||||
@@ -25,16 +25,29 @@ html(lang="en" dir="ltr")
|
|||||||
body
|
body
|
||||||
ul.sidenav.sidenav-fixed#slide-out
|
ul.sidenav.sidenav-fixed#slide-out
|
||||||
li
|
li
|
||||||
.user-view.primary-color-light
|
.user-view.primary-color-light.z-depth-2
|
||||||
.background
|
.background
|
||||||
a#name
|
a#name
|
||||||
p.flow-text.white-text.name Mantra
|
p.flow-text.black-text.name Mantra.
|
||||||
a#bio
|
//- a(href="#bio")
|
||||||
span.white-text Mantra Mantra Mantra
|
span.black-text Open source open literature
|
||||||
a#email
|
a(href="#email")
|
||||||
span.white-text.email mantra@exonumia.africa
|
span.email mantra@exonumia.africa
|
||||||
|
|
||||||
if user
|
if user
|
||||||
|
li
|
||||||
|
a(href="/library")
|
||||||
|
i.material-icons.black-text person
|
||||||
|
span library
|
||||||
|
li
|
||||||
|
a(href="/campaigns")
|
||||||
|
i.material-icons.black-text person
|
||||||
|
span campaigns
|
||||||
|
|
||||||
|
li
|
||||||
|
a(href="/pledges")
|
||||||
|
i.material-icons.black-text person
|
||||||
|
span pledges
|
||||||
li
|
li
|
||||||
.divider
|
.divider
|
||||||
li
|
li
|
||||||
@@ -60,7 +73,7 @@ html(lang="en" dir="ltr")
|
|||||||
block navigation
|
block navigation
|
||||||
nav.primary-color
|
nav.primary-color
|
||||||
.nav-wrapper
|
.nav-wrapper
|
||||||
a.brand-logo.center.hide-on-small-only(href="/") Mantra
|
a.brand-logo.black-text.center.hide-on-small-only(href="/") Mantra
|
||||||
ul.left
|
ul.left
|
||||||
li
|
li
|
||||||
a.sidenav-trigger(href="#", data-target="slide-out")
|
a.sidenav-trigger(href="#", data-target="slide-out")
|
||||||
@@ -79,34 +92,34 @@ html(lang="en" dir="ltr")
|
|||||||
//- I just need some space at the bottom...
|
//- I just need some space at the bottom...
|
||||||
|
|
||||||
block footer
|
block footer
|
||||||
footer.primary-color.page-footer(role="footer")
|
footer.primary-color.page-footer.z-depth-3(role="footer")
|
||||||
.container
|
.container
|
||||||
.row
|
.row
|
||||||
.col.s12.m6
|
.col.s12.m6
|
||||||
p.flow-text Follow
|
p.flow-text.black-text Follow
|
||||||
ul
|
ul
|
||||||
li
|
li
|
||||||
a.white-text(href="https://www.twitter.com/exonumia280") Twitter
|
a.black-text(href="https://www.twitter.com/exonumia280") Twitter
|
||||||
li
|
li
|
||||||
a.white-text(href="https://www.facebook.com/exonumia.africa") Facebook
|
a.black-text(href="https://www.facebook.com/exonumia.africa") Facebook
|
||||||
li
|
li
|
||||||
a.white-text(href="https://www.instagram.com/exonumia.africa") Instagram
|
a.black-text(href="https://www.instagram.com/exonumia.africa") Instagram
|
||||||
li
|
li
|
||||||
a.white-text(href="https://www.linkedin.com/company/exonumia-africa") LinkedIn
|
a.black-text(href="https://www.linkedin.com/company/exonumia-africa") LinkedIn
|
||||||
|
|
||||||
.col.s12.m6
|
.col.s12.m6
|
||||||
//- p.flow-text Links
|
//- p.flow-text Links
|
||||||
//- ul
|
//- ul
|
||||||
li
|
li
|
||||||
a.white-text(href="/faq") FAQ
|
a.black-text(href="/faq") FAQ
|
||||||
li
|
li
|
||||||
a.white-text(href="/privacy") Privacy Policy
|
a.black-text(href="/privacy") Privacy Policy
|
||||||
li
|
li
|
||||||
a.white-text(href="/compliance") Compliance
|
a.black-text(href="/compliance") Compliance
|
||||||
li
|
li
|
||||||
a.white-text(href="/terms") Terms
|
a.black-text(href="/terms") Terms
|
||||||
li
|
li
|
||||||
a.white-text(href="/contact") Contact
|
a.black-text(href="/contact") Contact
|
||||||
|
|
||||||
.footer-copyright.primary-color-dark
|
.footer-copyright.primary-color-dark
|
||||||
.container
|
.container
|
||||||
|
|||||||
Reference in New Issue
Block a user