Works with the Form plugin
This commit is contained in:
parent
6ce186584e
commit
5f50c08970
|
@ -45,9 +45,9 @@ For example, in Antimatter, in `templates/item.html.twig`:
|
||||||
|
|
||||||
The comment form will appear to the blog post items.
|
The comment form will appear to the blog post items.
|
||||||
|
|
||||||
# Enable the Captcha anti-spam filter
|
# Enabling Recaptcha
|
||||||
|
|
||||||
To reduce spam in your comments, enable the Google Recaptcha integration we added. Copy the plugin's `comments.yaml` to `user/config/plugins/comments.yaml` and enable `use_captcha`. Also add the Google Recaptcha API keys to allow it to work correctly.
|
The plugin comes with Recaptcha integration. To make it work, add your own Recaptcha `site` and `secret` keys the the plugin yaml config file.
|
||||||
|
|
||||||
# Where are the comments stored?
|
# Where are the comments stored?
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ Further improvements to the comments visualization will be added in the next rel
|
||||||
|
|
||||||
# Email notifications
|
# Email notifications
|
||||||
|
|
||||||
Upon receiving a comment, if `enable_email_notifications` is enabled, the Comments plugin will send an email to the `notifications_email_to` address set in the plugin options.
|
The plugin interacts with the Email plugin to send emails upon receiving a comment.
|
||||||
|
|
||||||
# Things still missing
|
# Things still missing
|
||||||
|
|
||||||
|
|
|
@ -105,6 +105,33 @@
|
||||||
<p class="center">Showing <span class="totalRetrieved">{{grav.twig.comments.totalRetrieved}}</span> comments of <span class="totalAvailable">{{grav.twig.comments.totalAvailable}}</span></p>
|
<p class="center">Showing <span class="totalRetrieved">{{grav.twig.comments.totalRetrieved}}</span> comments of <span class="totalAvailable">{{grav.twig.comments.totalAvailable}}</span></p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<h1>Recently commented pages</h1>
|
||||||
|
|
||||||
|
<div class="admin-block">
|
||||||
|
<table>
|
||||||
|
<tbody class="js__pages-container">
|
||||||
|
<tr class="h">
|
||||||
|
<th class="page">Page</th>
|
||||||
|
<th class="number-of-comments">Number of comments</th>
|
||||||
|
<th class="last-comment-date">Last commented on</th>
|
||||||
|
</tr>
|
||||||
|
{% for page in grav.twig.pages %}
|
||||||
|
<tr>
|
||||||
|
<td class="page">{{page.title}}</td>
|
||||||
|
<td class="number-of-comments">{{page.commentsCount}}</td>
|
||||||
|
<td class="last-comment-date"><strong>Page</strong>: {{page.lastCommentDate}}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
{% if grav.twig.comments.totalRetrieved < grav.twig.comments.totalAvailable %}
|
||||||
|
<button type="button" class="button center js__load-more">
|
||||||
|
Load more
|
||||||
|
</button>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
name: Comments
|
||||||
|
version: 0.1.0
|
||||||
|
description: Adds a commenting functionality to your site
|
||||||
|
icon: comment
|
||||||
|
author:
|
||||||
|
name: Team Grav
|
||||||
|
email: devs@getgrav.org
|
||||||
|
url: http://getgrav.org
|
||||||
|
homepage: https://github.com/getgrav/grav-plugin-comments
|
||||||
|
keywords: guestbook, plugin
|
||||||
|
bugs: https://github.com/getgrav/grav-plugin-comments/issues
|
||||||
|
readme: https://github.com/getgrav/grav-plugin-comments/blob/develop/README.md
|
||||||
|
license: MIT
|
||||||
|
|
||||||
|
dependencies:
|
||||||
|
- form
|
||||||
|
- email
|
||||||
|
|
||||||
|
form:
|
||||||
|
validation: loose
|
||||||
|
fields:
|
||||||
|
enabled:
|
||||||
|
type: toggle
|
||||||
|
label: Plugin status
|
||||||
|
highlight: 1
|
||||||
|
default: 0
|
||||||
|
options:
|
||||||
|
1: Enabled
|
||||||
|
0: Disabled
|
||||||
|
validate:
|
||||||
|
type: bool
|
170
comments.php
170
comments.php
|
@ -23,9 +23,27 @@ class CommentsPlugin extends Plugin
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'onPluginsInitialized' => ['onPluginsInitialized', 0],
|
'onPluginsInitialized' => ['onPluginsInitialized', 0],
|
||||||
|
'onFormProcessed' => ['onFormProcessed', 0],
|
||||||
|
'onPageInitialized' => ['onPageInitialized', 0],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize form if the page has one. Also catches form processing if user posts the form.
|
||||||
|
*/
|
||||||
|
public function onPageInitialized()
|
||||||
|
{
|
||||||
|
/** @var Page $page */
|
||||||
|
$page = $this->grav['page'];
|
||||||
|
if (!$page) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$header = $page->header();
|
||||||
|
$header->form = $this->grav['config']->get('plugins.comments.form');
|
||||||
|
$page->header($header);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
public function onPluginsInitialized()
|
public function onPluginsInitialized()
|
||||||
|
@ -36,15 +54,7 @@ class CommentsPlugin extends Plugin
|
||||||
'onTwigTemplatePaths' => ['onTwigTemplatePaths', 0],
|
'onTwigTemplatePaths' => ['onTwigTemplatePaths', 0],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$this->addCommentURL = $this->config->get('plugins.comments.addCommentURL', '/add-comment');
|
$this->grav['twig']->comments = $this->fetchComments();
|
||||||
|
|
||||||
if ($this->addCommentURL && $this->addCommentURL == $this->grav['uri']->path()) {
|
|
||||||
$this->enable([
|
|
||||||
'onPagesInitialized' => ['addComment', 0]
|
|
||||||
]);
|
|
||||||
} else {
|
|
||||||
$this->grav['twig']->comments = $this->fetchComments();
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
@ -74,94 +84,65 @@ class CommentsPlugin extends Plugin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function addComment()
|
/**
|
||||||
|
* Handle form processing instructions.
|
||||||
|
*
|
||||||
|
* @param Event $event
|
||||||
|
*/
|
||||||
|
public function onFormProcessed(Event $event)
|
||||||
{
|
{
|
||||||
$post = !empty($_POST) ? $_POST : [];
|
$form = $event['form'];
|
||||||
|
$action = $event['action'];
|
||||||
|
$params = $event['params'];
|
||||||
|
|
||||||
$lang = filter_var(urldecode($post['lang']), FILTER_SANITIZE_STRING);
|
if (!$this->active) {
|
||||||
$path = filter_var(urldecode($post['path']), FILTER_SANITIZE_STRING);
|
return;
|
||||||
$text = filter_var(urldecode($post['text']), FILTER_SANITIZE_STRING);
|
|
||||||
$name = filter_var(urldecode($post['name']), FILTER_SANITIZE_STRING);
|
|
||||||
$email = filter_var(urldecode($post['email']), FILTER_SANITIZE_STRING);
|
|
||||||
$title = filter_var(urldecode($post['title']), FILTER_SANITIZE_STRING);
|
|
||||||
|
|
||||||
if ($this->config->get('plugins.comments.use_captcha')) {
|
|
||||||
//Validate the captcha
|
|
||||||
$recaptchaResponse = filter_var(urldecode($post['recaptchaResponse']), FILTER_SANITIZE_STRING);
|
|
||||||
|
|
||||||
$url = 'https://www.google.com/recaptcha/api/siteverify?secret=';
|
|
||||||
$url .= $this->config->get('plugins.comments.recatpcha_secret');
|
|
||||||
$url .= '&response=' . $recaptchaResponse;
|
|
||||||
$response = json_decode(file_get_contents($url), true);
|
|
||||||
|
|
||||||
if ($response['success'] == false) {
|
|
||||||
throw new \RuntimeException('Error validating the Captcha');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$filename = DATA_DIR . 'comments';
|
switch ($action) {
|
||||||
$filename .= ($lang ? '/' . $lang : '');
|
case 'addComment':
|
||||||
$filename .= $path . '.yaml';
|
$post = !empty($_POST) ? $_POST : [];
|
||||||
$file = File::instance($filename);
|
|
||||||
|
|
||||||
if (file_exists($filename)) {
|
$lang = filter_var(urldecode($post['lang']), FILTER_SANITIZE_STRING);
|
||||||
$data = Yaml::parse($file->content());
|
$path = filter_var(urldecode($post['path']), FILTER_SANITIZE_STRING);
|
||||||
|
$text = filter_var(urldecode($post['text']), FILTER_SANITIZE_STRING);
|
||||||
|
$name = filter_var(urldecode($post['name']), FILTER_SANITIZE_STRING);
|
||||||
|
$email = filter_var(urldecode($post['email']), FILTER_SANITIZE_STRING);
|
||||||
|
$title = filter_var(urldecode($post['title']), FILTER_SANITIZE_STRING);
|
||||||
|
/** @var Language $language */
|
||||||
|
$language = $this->grav['language'];
|
||||||
|
$lang = $language->getLanguage();
|
||||||
|
|
||||||
$data['comments'][] = [
|
$filename = DATA_DIR . 'comments';
|
||||||
'text' => $text,
|
$filename .= ($lang ? '/' . $lang : '');
|
||||||
'date' => gmdate('D, d M Y H:i:s', time()),
|
$filename .= $path . '.yaml';
|
||||||
'author' => $name,
|
$file = File::instance($filename);
|
||||||
'email' => $email
|
|
||||||
];
|
if (file_exists($filename)) {
|
||||||
} else {
|
$data = Yaml::parse($file->content());
|
||||||
$data = array(
|
|
||||||
'title' => $title,
|
$data['comments'][] = [
|
||||||
'lang' => $lang,
|
'text' => $text,
|
||||||
'comments' => array([
|
'date' => gmdate('D, d M Y H:i:s', time()),
|
||||||
'text' => $text,
|
'author' => $name,
|
||||||
'date' => gmdate('D, d M Y H:i:s', time()),
|
'email' => $email
|
||||||
'author' => $name,
|
];
|
||||||
'email' => $email
|
} else {
|
||||||
])
|
$data = array(
|
||||||
);
|
'title' => $title,
|
||||||
|
'lang' => $lang,
|
||||||
|
'comments' => array([
|
||||||
|
'text' => $text,
|
||||||
|
'date' => gmdate('D, d M Y H:i:s', time()),
|
||||||
|
'author' => $name,
|
||||||
|
'email' => $email
|
||||||
|
])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$file->save(Yaml::dump($data));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
$file->save(Yaml::dump($data));
|
|
||||||
|
|
||||||
if (isset($this->grav['Email']) && $this->grav['config']->get('plugins.comments.enable_email_notifications')) {
|
|
||||||
$this->sendEmailNotification(array(
|
|
||||||
'title' => $title,
|
|
||||||
'comment' => array(
|
|
||||||
'text' => $text,
|
|
||||||
'date' => gmdate('D, d M Y H:i:s', time()),
|
|
||||||
'author' => $name,
|
|
||||||
'email' => $email
|
|
||||||
)
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
exit();
|
|
||||||
}
|
|
||||||
|
|
||||||
private function sendEmailNotification($comment) {
|
|
||||||
/** @var Language $l */
|
|
||||||
$l = $this->grav['language'];
|
|
||||||
|
|
||||||
$sitename = $this->grav['config']->get('site.title', 'Website');
|
|
||||||
$from = $this->grav['config']->get('plugins.email.from', 'noreply@getgrav.org');
|
|
||||||
$to = $this->grav['config']->get('plugins.email.email');
|
|
||||||
|
|
||||||
$subject = $l->translate(['PLUGIN_COMMENTS.NEW_COMMENT_EMAIL_SUBJECT', $sitename]);
|
|
||||||
$content = $l->translate(['PLUGIN_COMMENTS.NEW_COMMENT_EMAIL_BODY', $sitename, $comment['title'], $comment['comment']['text'], $comment['comment']['author'], $comment['comment']['email']]);
|
|
||||||
|
|
||||||
$twig = $this->grav['twig'];
|
|
||||||
$body = $twig->processTemplate('email/base.html.twig', ['content' => $content]);
|
|
||||||
|
|
||||||
$message = $this->grav['Email']->message($subject, $body, 'text/html')
|
|
||||||
->setFrom($from)
|
|
||||||
->setTo($to);
|
|
||||||
|
|
||||||
$sent = $this->grav['Email']->send($message);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getFilesOrderedByModifiedDate($path = '') {
|
private function getFilesOrderedByModifiedDate($path = '') {
|
||||||
|
@ -242,15 +223,8 @@ class CommentsPlugin extends Plugin
|
||||||
});
|
});
|
||||||
|
|
||||||
$totalAvailable = count($comments);
|
$totalAvailable = count($comments);
|
||||||
|
|
||||||
$comments = array_slice($comments, $page * $number, $number);
|
$comments = array_slice($comments, $page * $number, $number);
|
||||||
|
|
||||||
$totalRetrieved = count($comments);
|
$totalRetrieved = count($comments);
|
||||||
$hasMore = false;
|
|
||||||
|
|
||||||
if ($totalAvailable > $totalRetrieved) {
|
|
||||||
$hasMore = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (object)array(
|
return (object)array(
|
||||||
"comments" => $comments,
|
"comments" => $comments,
|
||||||
|
@ -264,7 +238,7 @@ class CommentsPlugin extends Plugin
|
||||||
* Return the comments associated to the current route
|
* Return the comments associated to the current route
|
||||||
*/
|
*/
|
||||||
private function fetchComments() {
|
private function fetchComments() {
|
||||||
$lang = $this->grav['language']->getActive();
|
$lang = $this->grav['language']->getLanguage();
|
||||||
$filename = $lang ? '/' . $lang : '';
|
$filename = $lang ? '/' . $lang : '';
|
||||||
$filename .= $this->grav['uri']->path() . '.yaml';
|
$filename .= $this->grav['uri']->path() . '.yaml';
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,68 @@
|
||||||
enabled: true
|
enabled: true
|
||||||
use_captcha: false
|
form:
|
||||||
recatpcha_site_key: ''
|
name: comments
|
||||||
recatpcha_secret: ''
|
fields:
|
||||||
enable_email_notifications: false
|
- name: name
|
||||||
notifications_email_to: 'noreply@getgrav.org'
|
label: Name
|
||||||
|
placeholder: Enter your name
|
||||||
|
autofocus: on
|
||||||
|
autocomplete: on
|
||||||
|
type: text
|
||||||
|
validate:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- name: email
|
||||||
|
label: Email
|
||||||
|
placeholder: Enter your email address
|
||||||
|
type: email
|
||||||
|
validate:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- name: text
|
||||||
|
label: Message
|
||||||
|
placeholder: Enter your message
|
||||||
|
type: textarea
|
||||||
|
validate:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- name: date
|
||||||
|
type: hidden
|
||||||
|
process:
|
||||||
|
fillWithCurrentDateTime: true
|
||||||
|
|
||||||
|
- name: title
|
||||||
|
type: hidden
|
||||||
|
evaluateDefault: grav.page.header.title
|
||||||
|
|
||||||
|
- name: lang
|
||||||
|
type: hidden
|
||||||
|
evaluateDefault: grav.language.getLanguage
|
||||||
|
|
||||||
|
- name: path
|
||||||
|
type: hidden
|
||||||
|
evaluateDefault: grav.uri.path
|
||||||
|
|
||||||
|
# - name: g-recaptcha-response
|
||||||
|
# label: Captcha
|
||||||
|
# type: captcha
|
||||||
|
# recatpcha_site_key: 6Lde4gwTAAAAAAZuv4z2AgVU6Xamn5twDYzQr8hv
|
||||||
|
# recaptcha_not_validated: 'Captcha not valid!'
|
||||||
|
# validate:
|
||||||
|
# required: true
|
||||||
|
# process:
|
||||||
|
# ignore: true
|
||||||
|
|
||||||
|
buttons:
|
||||||
|
- type: submit
|
||||||
|
value: Submit
|
||||||
|
|
||||||
|
process:
|
||||||
|
# - email:
|
||||||
|
# subject: "[Site Guestbook] {{ form.value.name|e }}"
|
||||||
|
# body: "{% include 'forms/data.html.twig' %}"
|
||||||
|
# - captcha:
|
||||||
|
# recatpcha_secret: 6Lde4gwTAAAAAPpwVKuaYm53n2bWfFfxcDxSlI54
|
||||||
|
- addComment:
|
||||||
|
- message: Thank you for writing your comment!
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
en:
|
en:
|
||||||
PLUGIN_COMMENTS:
|
PLUGIN_COMMENTS:
|
||||||
|
ADD_COMMENT: Add a comment
|
||||||
COMMENTS: Comments
|
COMMENTS: Comments
|
||||||
EMAIL_NOT_CONFIGURED: Email not configured
|
EMAIL_NOT_CONFIGURED: Email not configured
|
||||||
NEW_COMMENT_EMAIL_SUBJECT: 'New comment on %1$s'
|
NEW_COMMENT_EMAIL_SUBJECT: 'New comment on %1$s'
|
||||||
|
@ -11,6 +12,7 @@ en:
|
||||||
BY: by
|
BY: by
|
||||||
it:
|
it:
|
||||||
PLUGIN_COMMENTS:
|
PLUGIN_COMMENTS:
|
||||||
|
ADD_COMMENT: Aggiungi un commento
|
||||||
COMMENTS: Commenti
|
COMMENTS: Commenti
|
||||||
EMAIL_NOT_CONFIGURED: Email non configurata
|
EMAIL_NOT_CONFIGURED: Email non configurata
|
||||||
NEW_COMMENT_EMAIL_SUBJECT: 'Nuovo commento su %1$s'
|
NEW_COMMENT_EMAIL_SUBJECT: 'Nuovo commento su %1$s'
|
||||||
|
|
|
@ -1,194 +0,0 @@
|
||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
|
||||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
|
||||||
<head>
|
|
||||||
<meta name="viewport" content="width=device-width" />
|
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
|
||||||
<title>Comments Email Template</title>
|
|
||||||
<style>
|
|
||||||
/* -------------------------------------
|
|
||||||
GLOBAL
|
|
||||||
------------------------------------- */
|
|
||||||
* {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif;
|
|
||||||
font-size: 100%;
|
|
||||||
line-height: 1.6;
|
|
||||||
}
|
|
||||||
img {
|
|
||||||
max-width: 100%;
|
|
||||||
}
|
|
||||||
body {
|
|
||||||
-webkit-font-smoothing: antialiased;
|
|
||||||
-webkit-text-size-adjust: none;
|
|
||||||
width: 100%!important;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
/* -------------------------------------
|
|
||||||
ELEMENTS
|
|
||||||
------------------------------------- */
|
|
||||||
a {
|
|
||||||
color: #348eda;
|
|
||||||
}
|
|
||||||
.btn-primary {
|
|
||||||
text-decoration: none;
|
|
||||||
color: #FFF;
|
|
||||||
background-color: #348eda;
|
|
||||||
border: solid #348eda;
|
|
||||||
border-width: 10px 20px;
|
|
||||||
line-height: 2;
|
|
||||||
font-weight: bold;
|
|
||||||
margin-right: 10px;
|
|
||||||
text-align: center;
|
|
||||||
cursor: pointer;
|
|
||||||
display: inline-block;
|
|
||||||
border-radius: 25px;
|
|
||||||
}
|
|
||||||
.btn-secondary {
|
|
||||||
text-decoration: none;
|
|
||||||
color: #FFF;
|
|
||||||
background-color: #aaa;
|
|
||||||
border: solid #aaa;
|
|
||||||
border-width: 10px 20px;
|
|
||||||
line-height: 2;
|
|
||||||
font-weight: bold;
|
|
||||||
margin-right: 10px;
|
|
||||||
text-align: center;
|
|
||||||
cursor: pointer;
|
|
||||||
display: inline-block;
|
|
||||||
border-radius: 25px;
|
|
||||||
}
|
|
||||||
.last {
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
.first {
|
|
||||||
margin-top: 0;
|
|
||||||
}
|
|
||||||
.padding {
|
|
||||||
padding: 10px 0;
|
|
||||||
}
|
|
||||||
/* -------------------------------------
|
|
||||||
BODY
|
|
||||||
------------------------------------- */
|
|
||||||
table.body-wrap {
|
|
||||||
width: 100%;
|
|
||||||
padding: 20px;
|
|
||||||
}
|
|
||||||
table.body-wrap .container {
|
|
||||||
border: 1px solid #f0f0f0;
|
|
||||||
}
|
|
||||||
/* -------------------------------------
|
|
||||||
FOOTER
|
|
||||||
------------------------------------- */
|
|
||||||
table.footer-wrap {
|
|
||||||
width: 100%;
|
|
||||||
clear: both!important;
|
|
||||||
}
|
|
||||||
.footer-wrap .container p {
|
|
||||||
font-size: 12px;
|
|
||||||
color: #666;
|
|
||||||
|
|
||||||
}
|
|
||||||
table.footer-wrap a {
|
|
||||||
color: #999;
|
|
||||||
}
|
|
||||||
/* -------------------------------------
|
|
||||||
TYPOGRAPHY
|
|
||||||
------------------------------------- */
|
|
||||||
h1, h2, h3 {
|
|
||||||
font-family: "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
|
|
||||||
color: #000;
|
|
||||||
margin: 40px 0 10px;
|
|
||||||
line-height: 1.2;
|
|
||||||
font-weight: 200;
|
|
||||||
}
|
|
||||||
h1 {
|
|
||||||
font-size: 36px;
|
|
||||||
}
|
|
||||||
h2 {
|
|
||||||
font-size: 28px;
|
|
||||||
}
|
|
||||||
h3 {
|
|
||||||
font-size: 22px;
|
|
||||||
}
|
|
||||||
p, ul, ol {
|
|
||||||
margin-bottom: 10px;
|
|
||||||
font-weight: normal;
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
ul li, ol li {
|
|
||||||
margin-left: 5px;
|
|
||||||
list-style-position: inside;
|
|
||||||
}
|
|
||||||
/* ---------------------------------------------------
|
|
||||||
RESPONSIVENESS
|
|
||||||
Nuke it from orbit. It's the only way to be sure.
|
|
||||||
------------------------------------------------------ */
|
|
||||||
/* Set a max-width, and make it display as block so it will automatically stretch to that width, but will also shrink down on a phone or something */
|
|
||||||
.container {
|
|
||||||
display: block!important;
|
|
||||||
max-width: 600px!important;
|
|
||||||
margin: 0 auto!important; /* makes it centered */
|
|
||||||
clear: both!important;
|
|
||||||
}
|
|
||||||
/* Set the padding on the td rather than the div for Outlook compatibility */
|
|
||||||
.body-wrap .container {
|
|
||||||
padding: 20px;
|
|
||||||
}
|
|
||||||
/* This should also be a block element, so that it will fill 100% of the .container */
|
|
||||||
.content {
|
|
||||||
max-width: 600px;
|
|
||||||
margin: 0 auto;
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
/* Let's make sure tables in the content area are 100% wide */
|
|
||||||
.content table {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body bgcolor="#f6f6f6">
|
|
||||||
|
|
||||||
<!-- body -->
|
|
||||||
<table class="body-wrap" bgcolor="#f6f6f6">
|
|
||||||
<tr>
|
|
||||||
<td></td>
|
|
||||||
<td class="container" bgcolor="#FFFFFF">
|
|
||||||
<div class="content">
|
|
||||||
<table>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
{{ content }}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<!-- /body -->
|
|
||||||
|
|
||||||
<!-- footer -->
|
|
||||||
<table class="footer-wrap">
|
|
||||||
<tr>
|
|
||||||
<td></td>
|
|
||||||
<td class="container">
|
|
||||||
<div class="content">
|
|
||||||
<table>
|
|
||||||
<tr>
|
|
||||||
<td align="center">
|
|
||||||
{{ 'PLUGIN_COMMENTS.EMAIL_FOOTER'|tu }}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<!-- /footer -->
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -1,113 +1,28 @@
|
||||||
{% set use_captcha = grav.config.plugins.comments.use_captcha %}
|
<h3>{{'PLUGIN_COMMENTS.ADD_COMMENT'|t}}</h3>
|
||||||
|
|
||||||
<h3>Add a Comment</h3>
|
<form name="{{ grav.config.plugins.comments.form.name }}"
|
||||||
|
action="{{ uri.rootUrl ~ (grav.config.plugins.comments.form.action|default(page.route)) }}/processform:true"
|
||||||
|
method="{{ grav.config.plugins.comments.form.method|upper|default('POST') }}">
|
||||||
|
{% for field in grav.config.plugins.comments.form.fields %}
|
||||||
|
|
||||||
<script>
|
{% set value = form.value(field.name) %}
|
||||||
$(function() {
|
{% if field.evaluateDefault %}
|
||||||
function validateEmail(email) {
|
{% set value = evaluate(field.evaluateDefault) %}
|
||||||
var re = /^([\w-]+(?:\.[\w-]+)*)@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$/i;
|
|
||||||
return re.test(email);
|
|
||||||
}
|
|
||||||
|
|
||||||
$(document).on('click tap', '.js__add-new-comment', function(event) {
|
|
||||||
event.preventDefault();
|
|
||||||
|
|
||||||
var text = $('.js__new-comment-text').val();
|
|
||||||
var name = $('.js__new-comment-name').val();
|
|
||||||
var email = $('.js__new-comment-email').val();
|
|
||||||
var captcha = $('#g-recaptcha-response').val();
|
|
||||||
|
|
||||||
if (text.length == 0 || email.length == 0 || name.length == 0) {
|
|
||||||
$('.alert').html('Please fill all the fields');
|
|
||||||
$('.alert-container').show();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!validateEmail(email)) {
|
|
||||||
$('.alert').html('Please enter a valid email');
|
|
||||||
$('.alert-container').show();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
{% if use_captcha %}
|
|
||||||
if (!captcha) {
|
|
||||||
$('.alert').html("Error validating the security code");
|
|
||||||
$('.alert-container').show();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
$.ajax({
|
|
||||||
url: "{{ grav.uri.rootUrl }}/add-comment",
|
|
||||||
data: {
|
|
||||||
text: $('.js__new-comment-text').val(),
|
|
||||||
name: $('.js__new-comment-name').val(),
|
|
||||||
email: $('.js__new-comment-email').val(),
|
|
||||||
title: "{{ grav.page.header.title }}",
|
|
||||||
lang: "{{ grav.language.getActive }}",
|
|
||||||
path: "{{ grav.uri.path }}",
|
|
||||||
{% if use_captcha %}recaptchaResponse: captcha{% endif %}
|
|
||||||
},
|
|
||||||
type: 'POST'
|
|
||||||
})
|
|
||||||
.success(function() {
|
|
||||||
$('.alert-container').hide();
|
|
||||||
window.location.reload();
|
|
||||||
})
|
|
||||||
.error(function() {
|
|
||||||
$('.alert').html("Error while posting the comment");
|
|
||||||
$('.alert-container').show();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
{% if use_captcha %}
|
|
||||||
<script src="https://www.google.com/recaptcha/api.js?onload=captchaOnloadCallback&render=explicit" async defer></script>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
$(function() {
|
|
||||||
var captchaOnloadCallback = function captchaOnloadCallback() {
|
|
||||||
grecaptcha.render('g-recaptcha', {
|
|
||||||
'sitekey': "{{grav.config.plugins.comments.recatpcha_site_key}}",
|
|
||||||
'callback': captchaValidatedCallback,
|
|
||||||
'expired-callback': captchaExpiredCallback
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
var captchaValidatedCallback = function captchaValidatedCallback() {
|
|
||||||
};
|
|
||||||
|
|
||||||
var captchaExpiredCallback = function captchaExpiredCallback() {
|
|
||||||
grecaptcha.reset();
|
|
||||||
};
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
<div class="alert-container" style="display: none">
|
|
||||||
<blockquote>
|
|
||||||
<blockquote>
|
|
||||||
<blockquote>
|
|
||||||
<blockquote>
|
|
||||||
<p class="alert"></p>
|
|
||||||
</blockquote>
|
|
||||||
</blockquote>
|
|
||||||
</blockquote>
|
|
||||||
</blockquote>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<form>
|
|
||||||
<textarea class="js__new-comment-text"></textarea>
|
|
||||||
{{'PLUGIN_COMMENTS.NAME'|t}} <input type="text" class="js__new-comment-name" />
|
|
||||||
{{'PLUGIN_COMMENTS.EMAIL'|t}} <input type="email" class="js__new-comment-email" />
|
|
||||||
{% if use_captcha %}
|
|
||||||
<div class="g-recaptcha" id="g-recaptcha"></div>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
<div>
|
||||||
|
{% include "forms/fields/#{field.type}/#{field.type}.html.twig" %}
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
<input type="submit" class="js__add-new-comment" />
|
<div class="buttons">
|
||||||
|
{% for button in grav.config.plugins.comments.form.buttons %}
|
||||||
|
<button class="button" type="{{ button.type|default('submit') }}">{{ button.value|default('Submit') }}</button>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
<div class="alert">{{ form.message }}</div>
|
||||||
|
|
||||||
{% if grav.twig.comments|length %}
|
{% if grav.twig.comments|length %}
|
||||||
|
|
||||||
<h3>{{'PLUGIN_COMMENTS.COMMENTS'|t}}</h3>
|
<h3>{{'PLUGIN_COMMENTS.COMMENTS'|t}}</h3>
|
||||||
|
|
Loading…
Reference in New Issue