Send tasks by email

This commit is contained in:
Frederic Guillot
2017-02-18 20:21:48 -05:00
parent 93c05371a8
commit 11a774e555
8 changed files with 164 additions and 0 deletions

View File

@@ -4,6 +4,7 @@ Version 1.0.40 (unreleased)
New features:
* Send comments by email
* Send tasks by email
* Add Reply-To header to emails sent from Kanboard
* Upload Sqlite database from user interface

View File

@@ -0,0 +1,55 @@
<?php
namespace Kanboard\Controller;
/**
* Class TaskMailController
*
* @package Kanboard\Controller
* @author Frederic Guillot
*/
class TaskMailController extends BaseController
{
public function create(array $values = array(), array $errors = array())
{
$project = $this->getProject();
$task = $this->getTask();
$this->response->html($this->helper->layout->task('task_mail/create', array(
'values' => $values,
'errors' => $errors,
'task' => $task,
'project' => $project,
)));
}
public function send()
{
$task = $this->getTask();
$values = $this->request->getValues();
list($valid, $errors) = $this->taskValidator->validateEmailCreation($values);
if ($valid) {
$this->sendByEmail($values, $task);
$this->flash->success(t('Task sent by email successfully.'));
$this->response->redirect($this->helper->url->to('TaskViewController', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id']), 'comments'), true);
} else {
$this->create($values, $errors);
}
}
protected function sendByEmail(array $values, array $task)
{
$html = $this->template->render('task_mail/email', array(
'task' => $task,
));
$this->emailClient->send(
$values['email'],
$values['email'],
$values['subject'],
$html
);
}
}

View File

@@ -85,6 +85,7 @@ class AuthenticationProvider implements ServiceProviderInterface
$acl->add('ColumnController', '*', Role::PROJECT_MANAGER);
$acl->add('CommentController', array('create', 'save', 'edit', 'update', 'confirm', 'remove'), Role::PROJECT_MEMBER);
$acl->add('CommentListController', array('save'), Role::PROJECT_MEMBER);
$acl->add('CommentMailController', '*', Role::PROJECT_MEMBER);
$acl->add('CustomFilterController', '*', Role::PROJECT_MEMBER);
$acl->add('ExportController', '*', Role::PROJECT_MANAGER);
$acl->add('TaskFileController', array('screenshot', 'create', 'save', 'remove', 'confirm'), Role::PROJECT_MEMBER);
@@ -110,6 +111,7 @@ class AuthenticationProvider implements ServiceProviderInterface
$acl->add('TaskExternalLinkController', '*', Role::PROJECT_MEMBER);
$acl->add('TaskModificationController', '*', Role::PROJECT_MEMBER);
$acl->add('TaskStatusController', '*', Role::PROJECT_MEMBER);
$acl->add('TaskMailController', '*', Role::PROJECT_MEMBER);
$acl->add('UserAjaxController', array('mention'), Role::PROJECT_MEMBER);
return $acl;

View File

@@ -36,6 +36,9 @@
<li>
<?= $this->modal->small('clone', t('Move to another project'), 'TaskDuplicationController', 'move', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) ?>
</li>
<li>
<?= $this->modal->small('paper-plane', t('Send by email'), 'TaskMailController', 'create', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) ?>
</li>
<?php if ($this->projectRole->canRemoveTask($task)): ?>
<li>
<?= $this->modal->confirm('trash-o', t('Remove'), 'TaskSuppressionController', 'confirm', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) ?>

View File

@@ -0,0 +1,17 @@
<div class="page-header">
<h2><?= $this->text->e($task['title']) ?> &gt; <?= t('Send by email') ?></h2>
</div>
<form method="post" action="<?= $this->url->href('TaskMailController', 'send', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) ?>" autocomplete="off">
<?= $this->form->csrf() ?>
<?= $this->form->label(t('Email'), 'email') ?>
<?= $this->form->email('email', $values, $errors, array('autofocus', 'required', 'tabindex="1"')) ?>
<?= $this->form->label(t('Subject'), 'subject') ?>
<?= $this->form->text('subject', $values, $errors, array('required', 'tabindex="2"')) ?>
<?= $this->modal->submitButtons(array(
'submitLabel' => t('Send by email'),
'tabindex' => 3,
)) ?>
</form>

View File

@@ -0,0 +1,46 @@
<h2><?= $this->text->e($task['title']) ?> (#<?= $task['id'] ?>)</h2>
<ul>
<li>
<?= t('Project: %s', $task['project_name']) ?>
</li>
<li>
<?= t('Created:').' '.$this->dt->datetime($task['date_creation']) ?>
</li>
<?php if ($task['date_due']): ?>
<li>
<strong><?= t('Due date:').' '.$this->dt->date($task['date_due']) ?></strong>
</li>
<?php endif ?>
<?php if (! empty($task['creator_username'])): ?>
<li>
<?= t('Created by %s', $task['creator_name'] ?: $task['creator_username']) ?>
</li>
<?php endif ?>
<li>
<strong>
<?php if (! empty($task['assignee_username'])): ?>
<?= t('Assigned to %s', $task['assignee_name'] ?: $task['assignee_username']) ?>
<?php else: ?>
<?= t('There is nobody assigned') ?>
<?php endif ?>
</strong>
</li>
<li>
<?= t('Column on the board:') ?>
<strong><?= $this->text->e($task['column_title']) ?></strong>
</li>
<li><?= t('Task position:').' '.$this->text->e($task['position']) ?></li>
<?php if (! empty($task['category_name'])): ?>
<li>
<?= t('Category:') ?> <strong><?= $this->text->e($task['category_name']) ?></strong>
</li>
<?php endif ?>
</ul>
<?php if (! empty($task['description'])): ?>
<h2><?= t('Description') ?></h2>
<?= $this->text->markdown($task['description'], true) ?>
<?php endif ?>
<?= $this->render('notification/footer', array('task' => $task, 'application_url' => $this->app->config('application_url'))) ?>

View File

@@ -204,4 +204,27 @@ class TaskValidator extends BaseValidator
$v->getErrors()
);
}
/**
* Validate task email creation
*
* @access public
* @param array $values Required parameters to save an action
* @return array $valid, $errors [0] = Success or not, [1] = List of errors
*/
public function validateEmailCreation(array $values)
{
$rules = array(
new Validators\Required('subject', t('This field is required')),
new Validators\Required('email', t('This field is required')),
new Validators\Email('email', t('Email address invalid')),
);
$v = new Validator($values, $rules);
return array(
$v->execute(),
$v->getErrors()
);
}
}

View File

@@ -6,6 +6,23 @@ use Kanboard\Validator\TaskValidator;
class TaskValidatorTest extends Base
{
public function testValidationEmailCreation()
{
$taskValidator = new TaskValidator($this->container);
$result = $taskValidator->validateEmailCreation(array('email' => 'test@localhost', 'subject' => 'test'));
$this->assertTrue($result[0]);
$result = $taskValidator->validateEmailCreation(array('email' => 'test', 'subject' => 'test'));
$this->assertFalse($result[0]);
$result = $taskValidator->validateEmailCreation(array('subject' => 'test'));
$this->assertFalse($result[0]);
$result = $taskValidator->validateEmailCreation(array('email' => 'test@localhost'));
$this->assertFalse($result[0]);
}
public function testRequiredFields()
{
$taskValidator = new TaskValidator($this->container);