{
"site_url": "https://www.ndcode.org",
"site_title": "NDCODE",
- "contact_from": "NDCODE Contact <contact@ndcode.org>",
+ "contact_from": "NDCODE contact <contact@ndcode.org>",
"contact_to": "Nick Downing <nick@ndcode.org>",
- "feedback_from": "NDCODE Feedback <feedback@ndcode.org>",
+ "feedback_from": "NDCODE feedback <feedback@ndcode.org>",
"feedback_to": "Nick Downing <nick@ndcode.org>",
"noreply_from": "NDCODE <noreply@ndcode.org>",
"noreply_signature": "NDCODE Team",
"secure": false,
"auth": {
"user": "feedback@ndcode.org",
- "pass": "XXXFeedback12",
+ "pass": "XXXFeedback12"
},
"requireTLS": true
}
div.row {
div.col-md-12 {
div.form-group {
- label(for="feedback-message") {'Message *'}
- textarea.form-control#feedback-message(placeholder="Please tell us your thoughts" rows="4" required="required" data-error="Please, leave us a message.") {}
- div.help-block.with-errors {}
- }
- }
- }
- p {} // fix this later
- div.row {
- div.col-md-12 {
- p.text-muted {
- strong {'*'}
- 'These fields are required.'
- //'Contact form template by '
- //a(href="https://bootstrapious.com/p/how-to-build-a-working-bootstrap-feedback-form" target="_blank") {'Bootstrapious'}
- //'.'
+ label.form-label(for="feedback-message") {'Message'}
+ textarea.form-control#feedback-message(placeholder="Please tell us your thoughts" rows="4" required="required") {}
}
}
}
'/api/sign_out.json',
...arguments
)
+ let feedback = async (...arguments) => api_call(
+ '/api/feedback.json',
+ ...arguments
+ )
// this function can be overridden in a further script
function sign_in_out(status) {
document.getElementById('feedback-submit').addEventListener(
'click',
- () => {
- $.ajax(
- {
- url: '/api/feedback.html',
- type: 'POST',
- data: {
- page: window.location.href,
- message: $('#feedback-message').val()
- },
- success: (data, textStatus, jqXHR) => {
- $('#feedback-modal').modal('hide')
- document.getElementById('message-modal-message').textContent = data
- $('#message-modal-message').text(data)
- $('#message-modal').modal('show')
- },
- error: (jqXHR, textStatus, errorThrown) => {
- $('#feedback-modal').modal('hide')
- document.getElementById('message-modal-message').textContent = errorThrown
- $('#message-modal').modal('show')
- }
- }
- )
+ async () => {
+ try {
+ await feedback(
+ location.href,
+ document.getElementById('feedback-message').value.slice(0, 65536)
+ )
+ }
+ catch (error) {
+ let problem =
+ error instanceof Problem ?
+ error :
+ new Problem(
+ // title
+ 'Bad request',
+ // details
+ (error.stack || error.message).toString()
+ // status
+ 400
+ )
+
+ document.getElementById('message-modal-message').textContent = problem.detail
+ $('#feedback-modal').modal('hide')
+ $('#message-modal').modal('show')
+ return
+ }
+
+ document.getElementById('message-modal-message').textContent = 'Thanks! We have received your feedback.'
+ $('#feedback-modal').modal('hide')
+ $('#message-modal').modal('show')
}
)
}
+++ /dev/null
-let querystring = require('querystring')
-let stream_buffers = require('stream-buffers')
-let XDate = require('xdate')
-
-return async env => {
- let globals = await env.site.get_json('/_config/globals.json')
- let nodemailer_feedback = await env.site.get_nodemailer(
- '/_config/email_feedback.json'
- )
-
- let message
- if (env.request.method === 'POST') {
- let write_stream = new stream_buffers.WritableStreamBuffer()
- let data = new Promise(
- (resolve, reject) => {
- write_stream.
- on('finish', () => {resolve(write_stream.getContents())}).
- on('error', () => {reject()})
- }
- )
- env.request.pipe(write_stream)
- let query = querystring.parse((await data).toString())
- console.log('received feedback form:', query.page)
-
- // save the form contents in a dated logfile, so that we can
- // recover manually if the email doesn't send for some reason
- date = new XDate()
- query.date = date.toUTCString()
-
- let transaction = await env.site.database.Transaction()
- ;(
- await (
- await (
- await (
- await transaction.get({})
- ).get('logs', {})
- ).get(date.toUTCString('yyyyMMdd'), {})
- ).get('feedback', [])
- ).push(transaction.json_to_logjson(query))
- transaction.commit()
-
- // send email (asynchronously)
- nodemailer_feedback.sendMail(
- {
- from: globals.feedback_from,
- to: globals.feedback_to,
- subject: 'Page: ' + query.page,
- text: query.message,
- },
- (err, message) => {
- if (err)
- console.error(err.stack || err.message)
- else
- console.log('sent feedback email:', query.page)
- }
- )
-
- message = 'Thanks!'
- }
- else
- message = 'Please POST.'
-
- env.site.serve(env, 200, Buffer.from(message), 'feedback.html.jst')
-}
--- /dev/null
+let logjson = (await import('@ndcode/logjson')).default
+let XDate = require('xdate')
+
+return async env => {
+ let globals = await env.site.get_json('/_config/globals.json')
+ let nodemailer_feedback = await env.site.get_nodemailer(
+ '/_config/nodemailer_feedback.json'
+ )
+ let post_request = await _require('/_lib/post_request.jst')
+ let session_cookie = await _require('/_lib/session_cookie.jst')
+
+ await post_request(
+ // env
+ env,
+ // endpoint
+ '/api/feedback.json',
+ // handler
+ async (page, message) => {
+ // coerce and/or validate
+ page = page.slice(0, 256)
+ mesage = message.slice(0, 65536)
+ if (page.length === 0 || message.length === 0)
+ throw new Problem(
+ 'Bad request',
+ 'Minimum length check failed',
+ 400
+ )
+
+ let transaction = await env.site.database.Transaction()
+ try {
+ // initialize env.session_key, set cookie in env.response
+ await session_cookie(env, transaction)
+ await transaction.commit()
+ }
+ catch (error) {
+ transaction.rollback()
+ throw error
+ }
+
+ await nodemailer_feedback.sendMail(
+ {
+ from: globals.feedback_from,
+ to: globals.feedback_to,
+ subject: 'Page: ' + page,
+ text: message
+ }
+ )
+ }
+ )
+}
let session_cookie = await _require('/_lib/session_cookie.jst')
let Problem = await _require('/_lib/Problem.jst')
- post_request(
+ await post_request(
// env
env,
// endpoint
let session_cookie = await _require('/_lib/session_cookie.jst')
let Problem = await _require('/_lib/Problem.jst')
- post_request(
+ await post_request(
// env
env,
// endpoint
let session_cookie = await _require('/_lib/session_cookie.jst')
let Problem = await _require('/_lib/Problem.jst')
- post_request(
+ await post_request(
// env
env,
// endpoint
let session_cookie = await _require('/_lib/session_cookie.jst')
let Problem = await _require('/_lib/Problem.jst')
- post_request(
+ await post_request(
// env
env,
// endpoint
let session_cookie = await _require('/_lib/session_cookie.jst')
let Problem = await _require('/_lib/Problem.jst')
- post_request(
+ await post_request(
// env
env,
// endpoint
let session_cookie = await _require('/_lib/session_cookie.jst')
let Problem = await _require('/_lib/Problem.jst')
- post_request(
+ await post_request(
// env
env,
// endpoint
let session_cookie = await _require('/_lib/session_cookie.jst')
let Problem = await _require('/_lib/Problem.jst')
- post_request(
+ await post_request(
// env
env,
// endpoint
let session_cookie = await _require('/_lib/session_cookie.jst')
let Problem = await _require('/_lib/Problem.jst')
- post_request(
+ await post_request(
// env
env,
// endpoint
let session_cookie = await _require('/_lib/session_cookie.jst')
let Problem = await _require('/_lib/Problem.jst')
- post_request(
+ await post_request(
// env
env,
// endpoint