Add Slack integration
This commit is contained in:
@@ -97,6 +97,7 @@ Documentation
|
|||||||
- [Bitbucket webhooks](docs/bitbucket-webhooks.markdown)
|
- [Bitbucket webhooks](docs/bitbucket-webhooks.markdown)
|
||||||
- [Github webhooks](docs/github-webhooks.markdown)
|
- [Github webhooks](docs/github-webhooks.markdown)
|
||||||
- [Gitlab webhooks](docs/gitlab-webhooks.markdown)
|
- [Gitlab webhooks](docs/gitlab-webhooks.markdown)
|
||||||
|
- [Slack](docs/slack.markdown)
|
||||||
|
|
||||||
#### More
|
#### More
|
||||||
|
|
||||||
|
|||||||
@@ -43,6 +43,9 @@ class Config extends Base
|
|||||||
if ($redirect === 'board') {
|
if ($redirect === 'board') {
|
||||||
$values += array('subtask_restriction' => 0, 'subtask_time_tracking' => 0, 'subtask_forecast' => 0);
|
$values += array('subtask_restriction' => 0, 'subtask_time_tracking' => 0, 'subtask_forecast' => 0);
|
||||||
}
|
}
|
||||||
|
else if ($redirect === 'integrations') {
|
||||||
|
$values += array('integration_slack_webhook' => 0);
|
||||||
|
}
|
||||||
|
|
||||||
if ($this->config->save($values)) {
|
if ($this->config->save($values)) {
|
||||||
$this->config->reload();
|
$this->config->reload();
|
||||||
@@ -101,6 +104,20 @@ class Config extends Base
|
|||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display the integration settings page
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function integrations()
|
||||||
|
{
|
||||||
|
$this->common('integrations');
|
||||||
|
|
||||||
|
$this->response->html($this->layout('config/integrations', array(
|
||||||
|
'title' => t('Settings').' > '.t('Integrations'),
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Display the webhook settings page
|
* Display the webhook settings page
|
||||||
*
|
*
|
||||||
|
|||||||
67
app/Core/HttpClient.php
Normal file
67
app/Core/HttpClient.php
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Core;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HTTP client
|
||||||
|
*
|
||||||
|
* @package core
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
class HttpClient
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* HTTP connection timeout in seconds
|
||||||
|
*
|
||||||
|
* @var integer
|
||||||
|
*/
|
||||||
|
const HTTP_TIMEOUT = 2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of maximum redirections for the HTTP client
|
||||||
|
*
|
||||||
|
* @var integer
|
||||||
|
*/
|
||||||
|
const HTTP_MAX_REDIRECTS = 2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HTTP client user agent
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
const HTTP_USER_AGENT = 'Kanboard Webhook';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a POST HTTP request
|
||||||
|
*
|
||||||
|
* @static
|
||||||
|
* @access public
|
||||||
|
* @param string $url
|
||||||
|
* @param array $data
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function post($url, array $data)
|
||||||
|
{
|
||||||
|
if (empty($url)) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
$headers = array(
|
||||||
|
'Connection: close',
|
||||||
|
'User-Agent: '.self::HTTP_USER_AGENT,
|
||||||
|
);
|
||||||
|
|
||||||
|
$context = stream_context_create(array(
|
||||||
|
'http' => array(
|
||||||
|
'method' => 'POST',
|
||||||
|
'protocol_version' => 1.1,
|
||||||
|
'timeout' => self::HTTP_TIMEOUT,
|
||||||
|
'max_redirects' => self::HTTP_MAX_REDIRECTS,
|
||||||
|
'header' => implode("\r\n", $headers),
|
||||||
|
'content' => json_encode($data)
|
||||||
|
)
|
||||||
|
));
|
||||||
|
|
||||||
|
return @file_get_contents(trim($url), false, $context);
|
||||||
|
}
|
||||||
|
}
|
||||||
43
app/Integration/SlackWebhook.php
Normal file
43
app/Integration/SlackWebhook.php
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Integration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Slack Webhook
|
||||||
|
*
|
||||||
|
* @package integration
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
class SlackWebhook extends Base
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Send message to the incoming Slack webhook
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param integer $project_id Project id
|
||||||
|
* @param integer $task_id Task id
|
||||||
|
* @param string $event_name Event name
|
||||||
|
* @param array $data Event data
|
||||||
|
*/
|
||||||
|
public function notify($project_id, $task_id, $event_name, array $event)
|
||||||
|
{
|
||||||
|
$project = $this->project->getbyId($project_id);
|
||||||
|
|
||||||
|
$event['event_name'] = $event_name;
|
||||||
|
$event['author'] = $this->user->getFullname($this->session['user']);
|
||||||
|
|
||||||
|
$payload = array(
|
||||||
|
'text' => '*['.$project['name'].']* '.str_replace('"', '"', $this->projectActivity->getTitle($event)),
|
||||||
|
'username' => 'Kanboard',
|
||||||
|
'icon_url' => 'http://kanboard.net/assets/img/favicon.png',
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($this->config->get('application_url')) {
|
||||||
|
$payload['text'] .= ' - <'.$this->config->get('application_url');
|
||||||
|
$payload['text'] .= $this->helper->u('task', 'show', array('task_id' => $task_id, 'project_id' => $project_id));
|
||||||
|
$payload['text'] .= '|'.t('view the task on Kanboard').'>';
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->httpClient->post($this->config->get('integration_slack_webhook_url'), $payload);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -823,4 +823,8 @@ return array(
|
|||||||
// 'Reference currency' => '',
|
// 'Reference currency' => '',
|
||||||
// 'The currency rate have been added successfully.' => '',
|
// 'The currency rate have been added successfully.' => '',
|
||||||
// 'Unable to add this currency rate.' => '',
|
// 'Unable to add this currency rate.' => '',
|
||||||
|
// 'Send notifications to a Slack channel' => '',
|
||||||
|
// 'Webhook URL' => '',
|
||||||
|
// 'Help on Slack integration' => '',
|
||||||
|
// '%s remove the assignee of the task %s' => '',
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -823,4 +823,8 @@ return array(
|
|||||||
// 'Reference currency' => '',
|
// 'Reference currency' => '',
|
||||||
// 'The currency rate have been added successfully.' => '',
|
// 'The currency rate have been added successfully.' => '',
|
||||||
// 'Unable to add this currency rate.' => '',
|
// 'Unable to add this currency rate.' => '',
|
||||||
|
// 'Send notifications to a Slack channel' => '',
|
||||||
|
// 'Webhook URL' => '',
|
||||||
|
// 'Help on Slack integration' => '',
|
||||||
|
// '%s remove the assignee of the task %s' => '',
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -823,4 +823,8 @@ return array(
|
|||||||
// 'Reference currency' => '',
|
// 'Reference currency' => '',
|
||||||
// 'The currency rate have been added successfully.' => '',
|
// 'The currency rate have been added successfully.' => '',
|
||||||
// 'Unable to add this currency rate.' => '',
|
// 'Unable to add this currency rate.' => '',
|
||||||
|
// 'Send notifications to a Slack channel' => '',
|
||||||
|
// 'Webhook URL' => '',
|
||||||
|
// 'Help on Slack integration' => '',
|
||||||
|
// '%s remove the assignee of the task %s' => '',
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -823,4 +823,8 @@ return array(
|
|||||||
// 'Reference currency' => '',
|
// 'Reference currency' => '',
|
||||||
// 'The currency rate have been added successfully.' => '',
|
// 'The currency rate have been added successfully.' => '',
|
||||||
// 'Unable to add this currency rate.' => '',
|
// 'Unable to add this currency rate.' => '',
|
||||||
|
// 'Send notifications to a Slack channel' => '',
|
||||||
|
// 'Webhook URL' => '',
|
||||||
|
// 'Help on Slack integration' => '',
|
||||||
|
// '%s remove the assignee of the task %s' => '',
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -825,4 +825,8 @@ return array(
|
|||||||
'Reference currency' => 'Devise de référence',
|
'Reference currency' => 'Devise de référence',
|
||||||
'The currency rate have been added successfully.' => 'Le taux de change a été ajouté avec succès.',
|
'The currency rate have been added successfully.' => 'Le taux de change a été ajouté avec succès.',
|
||||||
'Unable to add this currency rate.' => 'Impossible d\'ajouter ce taux de change',
|
'Unable to add this currency rate.' => 'Impossible d\'ajouter ce taux de change',
|
||||||
|
'Send notifications to a Slack channel' => 'Envoyer des notifications sur un channel Slack',
|
||||||
|
'Webhook URL' => 'URL du webhook',
|
||||||
|
'Help on Slack integration' => 'Aide sur l\'intégration avec Slack',
|
||||||
|
'%s remove the assignee of the task %s' => '%s a enlevé la personne assignée à la tâche %s',
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -823,4 +823,8 @@ return array(
|
|||||||
// 'Reference currency' => '',
|
// 'Reference currency' => '',
|
||||||
// 'The currency rate have been added successfully.' => '',
|
// 'The currency rate have been added successfully.' => '',
|
||||||
// 'Unable to add this currency rate.' => '',
|
// 'Unable to add this currency rate.' => '',
|
||||||
|
// 'Send notifications to a Slack channel' => '',
|
||||||
|
// 'Webhook URL' => '',
|
||||||
|
// 'Help on Slack integration' => '',
|
||||||
|
// '%s remove the assignee of the task %s' => '',
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -823,4 +823,8 @@ return array(
|
|||||||
// 'Reference currency' => '',
|
// 'Reference currency' => '',
|
||||||
// 'The currency rate have been added successfully.' => '',
|
// 'The currency rate have been added successfully.' => '',
|
||||||
// 'Unable to add this currency rate.' => '',
|
// 'Unable to add this currency rate.' => '',
|
||||||
|
// 'Send notifications to a Slack channel' => '',
|
||||||
|
// 'Webhook URL' => '',
|
||||||
|
// 'Help on Slack integration' => '',
|
||||||
|
// '%s remove the assignee of the task %s' => '',
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -823,4 +823,8 @@ return array(
|
|||||||
// 'Reference currency' => '',
|
// 'Reference currency' => '',
|
||||||
// 'The currency rate have been added successfully.' => '',
|
// 'The currency rate have been added successfully.' => '',
|
||||||
// 'Unable to add this currency rate.' => '',
|
// 'Unable to add this currency rate.' => '',
|
||||||
|
// 'Send notifications to a Slack channel' => '',
|
||||||
|
// 'Webhook URL' => '',
|
||||||
|
// 'Help on Slack integration' => '',
|
||||||
|
// '%s remove the assignee of the task %s' => '',
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -823,4 +823,8 @@ return array(
|
|||||||
// 'Reference currency' => '',
|
// 'Reference currency' => '',
|
||||||
// 'The currency rate have been added successfully.' => '',
|
// 'The currency rate have been added successfully.' => '',
|
||||||
// 'Unable to add this currency rate.' => '',
|
// 'Unable to add this currency rate.' => '',
|
||||||
|
// 'Send notifications to a Slack channel' => '',
|
||||||
|
// 'Webhook URL' => '',
|
||||||
|
// 'Help on Slack integration' => '',
|
||||||
|
// '%s remove the assignee of the task %s' => '',
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -823,4 +823,8 @@ return array(
|
|||||||
// 'Reference currency' => '',
|
// 'Reference currency' => '',
|
||||||
// 'The currency rate have been added successfully.' => '',
|
// 'The currency rate have been added successfully.' => '',
|
||||||
// 'Unable to add this currency rate.' => '',
|
// 'Unable to add this currency rate.' => '',
|
||||||
|
// 'Send notifications to a Slack channel' => '',
|
||||||
|
// 'Webhook URL' => '',
|
||||||
|
// 'Help on Slack integration' => '',
|
||||||
|
// '%s remove the assignee of the task %s' => '',
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -823,4 +823,8 @@ return array(
|
|||||||
// 'Reference currency' => '',
|
// 'Reference currency' => '',
|
||||||
// 'The currency rate have been added successfully.' => '',
|
// 'The currency rate have been added successfully.' => '',
|
||||||
// 'Unable to add this currency rate.' => '',
|
// 'Unable to add this currency rate.' => '',
|
||||||
|
// 'Send notifications to a Slack channel' => '',
|
||||||
|
// 'Webhook URL' => '',
|
||||||
|
// 'Help on Slack integration' => '',
|
||||||
|
// '%s remove the assignee of the task %s' => '',
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -823,4 +823,8 @@ return array(
|
|||||||
// 'Reference currency' => '',
|
// 'Reference currency' => '',
|
||||||
// 'The currency rate have been added successfully.' => '',
|
// 'The currency rate have been added successfully.' => '',
|
||||||
// 'Unable to add this currency rate.' => '',
|
// 'Unable to add this currency rate.' => '',
|
||||||
|
// 'Send notifications to a Slack channel' => '',
|
||||||
|
// 'Webhook URL' => '',
|
||||||
|
// 'Help on Slack integration' => '',
|
||||||
|
// '%s remove the assignee of the task %s' => '',
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -823,4 +823,8 @@ return array(
|
|||||||
// 'Reference currency' => '',
|
// 'Reference currency' => '',
|
||||||
// 'The currency rate have been added successfully.' => '',
|
// 'The currency rate have been added successfully.' => '',
|
||||||
// 'Unable to add this currency rate.' => '',
|
// 'Unable to add this currency rate.' => '',
|
||||||
|
// 'Send notifications to a Slack channel' => '',
|
||||||
|
// 'Webhook URL' => '',
|
||||||
|
// 'Help on Slack integration' => '',
|
||||||
|
// '%s remove the assignee of the task %s' => '',
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -823,4 +823,8 @@ return array(
|
|||||||
// 'Reference currency' => '',
|
// 'Reference currency' => '',
|
||||||
// 'The currency rate have been added successfully.' => '',
|
// 'The currency rate have been added successfully.' => '',
|
||||||
// 'Unable to add this currency rate.' => '',
|
// 'Unable to add this currency rate.' => '',
|
||||||
|
// 'Send notifications to a Slack channel' => '',
|
||||||
|
// 'Webhook URL' => '',
|
||||||
|
// 'Help on Slack integration' => '',
|
||||||
|
// '%s remove the assignee of the task %s' => '',
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -823,4 +823,8 @@ return array(
|
|||||||
// 'Reference currency' => '',
|
// 'Reference currency' => '',
|
||||||
// 'The currency rate have been added successfully.' => '',
|
// 'The currency rate have been added successfully.' => '',
|
||||||
// 'Unable to add this currency rate.' => '',
|
// 'Unable to add this currency rate.' => '',
|
||||||
|
// 'Send notifications to a Slack channel' => '',
|
||||||
|
// 'Webhook URL' => '',
|
||||||
|
// 'Help on Slack integration' => '',
|
||||||
|
// '%s remove the assignee of the task %s' => '',
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -823,4 +823,8 @@ return array(
|
|||||||
// 'Reference currency' => '',
|
// 'Reference currency' => '',
|
||||||
// 'The currency rate have been added successfully.' => '',
|
// 'The currency rate have been added successfully.' => '',
|
||||||
// 'Unable to add this currency rate.' => '',
|
// 'Unable to add this currency rate.' => '',
|
||||||
|
// 'Send notifications to a Slack channel' => '',
|
||||||
|
// 'Webhook URL' => '',
|
||||||
|
// 'Help on Slack integration' => '',
|
||||||
|
// '%s remove the assignee of the task %s' => '',
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -823,4 +823,8 @@ return array(
|
|||||||
// 'Reference currency' => '',
|
// 'Reference currency' => '',
|
||||||
// 'The currency rate have been added successfully.' => '',
|
// 'The currency rate have been added successfully.' => '',
|
||||||
// 'Unable to add this currency rate.' => '',
|
// 'Unable to add this currency rate.' => '',
|
||||||
|
// 'Send notifications to a Slack channel' => '',
|
||||||
|
// 'Webhook URL' => '',
|
||||||
|
// 'Help on Slack integration' => '',
|
||||||
|
// '%s remove the assignee of the task %s' => '',
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -162,7 +162,13 @@ class ProjectActivity extends Base
|
|||||||
{
|
{
|
||||||
switch ($event['event_name']) {
|
switch ($event['event_name']) {
|
||||||
case Task::EVENT_ASSIGNEE_CHANGE:
|
case Task::EVENT_ASSIGNEE_CHANGE:
|
||||||
return t('%s change the assignee of the task #%d to %s', $event['author'], $event['task']['id'], $event['task']['assignee_name'] ?: $event['task']['assignee_username']);
|
$assignee = $event['task']['assignee_name'] ?: $event['task']['assignee_username'];
|
||||||
|
|
||||||
|
if (! empty($assignee)) {
|
||||||
|
return t('%s change the assignee of the task #%d to %s', $event['author'], $event['task']['id'], $assignee);
|
||||||
|
}
|
||||||
|
|
||||||
|
return t('%s remove the assignee of the task %s', $event['author'], e('#%d', $event['task']['id']));
|
||||||
case Task::EVENT_UPDATE:
|
case Task::EVENT_UPDATE:
|
||||||
return t('%s updated the task #%d', $event['author'], $event['task']['id']);
|
return t('%s updated the task #%d', $event['author'], $event['task']['id']);
|
||||||
case Task::EVENT_CREATE:
|
case Task::EVENT_CREATE:
|
||||||
|
|||||||
@@ -10,27 +10,6 @@ namespace Model;
|
|||||||
*/
|
*/
|
||||||
class Webhook extends Base
|
class Webhook extends Base
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* HTTP connection timeout in seconds
|
|
||||||
*
|
|
||||||
* @var integer
|
|
||||||
*/
|
|
||||||
const HTTP_TIMEOUT = 1;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Number of maximum redirections for the HTTP client
|
|
||||||
*
|
|
||||||
* @var integer
|
|
||||||
*/
|
|
||||||
const HTTP_MAX_REDIRECTS = 3;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* HTTP client user agent
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
const HTTP_USER_AGENT = 'Kanboard Webhook';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Call the external URL
|
* Call the external URL
|
||||||
*
|
*
|
||||||
@@ -42,22 +21,6 @@ class Webhook extends Base
|
|||||||
{
|
{
|
||||||
$token = $this->config->get('webhook_token');
|
$token = $this->config->get('webhook_token');
|
||||||
|
|
||||||
$headers = array(
|
|
||||||
'Connection: close',
|
|
||||||
'User-Agent: '.self::HTTP_USER_AGENT,
|
|
||||||
);
|
|
||||||
|
|
||||||
$context = stream_context_create(array(
|
|
||||||
'http' => array(
|
|
||||||
'method' => 'POST',
|
|
||||||
'protocol_version' => 1.1,
|
|
||||||
'timeout' => self::HTTP_TIMEOUT,
|
|
||||||
'max_redirects' => self::HTTP_MAX_REDIRECTS,
|
|
||||||
'header' => implode("\r\n", $headers),
|
|
||||||
'content' => json_encode($task)
|
|
||||||
)
|
|
||||||
));
|
|
||||||
|
|
||||||
if (strpos($url, '?') !== false) {
|
if (strpos($url, '?') !== false) {
|
||||||
$url .= '&token='.$token;
|
$url .= '&token='.$token;
|
||||||
}
|
}
|
||||||
@@ -65,6 +28,6 @@ class Webhook extends Base
|
|||||||
$url .= '?token='.$token;
|
$url .= '?token='.$token;
|
||||||
}
|
}
|
||||||
|
|
||||||
@file_get_contents($url, false, $context);
|
return $this->httpClient->post($url, $task);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,14 @@ use PDO;
|
|||||||
use Core\Security;
|
use Core\Security;
|
||||||
use Model\Link;
|
use Model\Link;
|
||||||
|
|
||||||
const VERSION = 57;
|
const VERSION = 58;
|
||||||
|
|
||||||
|
function version_58($pdo)
|
||||||
|
{
|
||||||
|
$rq = $pdo->prepare('INSERT INTO settings VALUES (?, ?)');
|
||||||
|
$rq->execute(array('integration_slack_webhook', '0'));
|
||||||
|
$rq->execute(array('integration_slack_webhook_url', ''));
|
||||||
|
}
|
||||||
|
|
||||||
function version_57($pdo)
|
function version_57($pdo)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,7 +6,14 @@ use PDO;
|
|||||||
use Core\Security;
|
use Core\Security;
|
||||||
use Model\Link;
|
use Model\Link;
|
||||||
|
|
||||||
const VERSION = 38;
|
const VERSION = 39;
|
||||||
|
|
||||||
|
function version_39($pdo)
|
||||||
|
{
|
||||||
|
$rq = $pdo->prepare('INSERT INTO settings VALUES (?, ?)');
|
||||||
|
$rq->execute(array('integration_slack_webhook', '0'));
|
||||||
|
$rq->execute(array('integration_slack_webhook_url', ''));
|
||||||
|
}
|
||||||
|
|
||||||
function version_38($pdo)
|
function version_38($pdo)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,7 +6,14 @@ use Core\Security;
|
|||||||
use PDO;
|
use PDO;
|
||||||
use Model\Link;
|
use Model\Link;
|
||||||
|
|
||||||
const VERSION = 56;
|
const VERSION = 57;
|
||||||
|
|
||||||
|
function version_57($pdo)
|
||||||
|
{
|
||||||
|
$rq = $pdo->prepare('INSERT INTO settings VALUES (?, ?)');
|
||||||
|
$rq->execute(array('integration_slack_webhook', '0'));
|
||||||
|
$rq->execute(array('integration_slack_webhook_url', ''));
|
||||||
|
}
|
||||||
|
|
||||||
function version_56($pdo)
|
function version_56($pdo)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -69,11 +69,13 @@ class ClassProvider implements ServiceProviderInterface
|
|||||||
'MemoryCache',
|
'MemoryCache',
|
||||||
'FileCache',
|
'FileCache',
|
||||||
'Request',
|
'Request',
|
||||||
|
'HttpClient',
|
||||||
),
|
),
|
||||||
'Integration' => array(
|
'Integration' => array(
|
||||||
'GitlabWebhook',
|
'GitlabWebhook',
|
||||||
'GithubWebhook',
|
'GithubWebhook',
|
||||||
'BitbucketWebhook',
|
'BitbucketWebhook',
|
||||||
|
'SlackWebhook',
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -41,6 +41,15 @@ class ProjectActivitySubscriber extends Base implements EventSubscriberInterface
|
|||||||
$event_name,
|
$event_name,
|
||||||
$values
|
$values
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if ($this->config->get('integration_slack_webhook') == 1) {
|
||||||
|
$this->slackWebhook->notify(
|
||||||
|
$values['task']['project_id'],
|
||||||
|
$values['task']['id'],
|
||||||
|
$event_name,
|
||||||
|
$values
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
22
app/Template/config/integrations.php
Normal file
22
app/Template/config/integrations.php
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<div class="page-header">
|
||||||
|
<h2><?= t('Integration with third-party services') ?></h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form method="post" action="<?= $this->u('config', 'integrations') ?>" autocomplete="off">
|
||||||
|
|
||||||
|
<?= $this->formCsrf() ?>
|
||||||
|
|
||||||
|
<h3><i class="fa fa-slack fa-fw"></i> <?= t('Slack') ?></h3>
|
||||||
|
<div class="listing">
|
||||||
|
<?= $this->formCheckbox('integration_slack_webhook', t('Send notifications to a Slack channel'), 1, $values['integration_slack_webhook'] == 1) ?>
|
||||||
|
|
||||||
|
<?= $this->formLabel(t('Webhook URL'), 'integration_slack_webhook_url') ?>
|
||||||
|
<?= $this->formText('integration_slack_webhook_url', $values, $errors) ?>
|
||||||
|
|
||||||
|
<p class="form-help"><a href="http://kanboard.net/documentation/slack" target="_blank"><?= t('Help on Slack integration') ?></a></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-actions">
|
||||||
|
<input type="submit" value="<?= t('Save') ?>" class="btn btn-blue"/>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
@@ -16,6 +16,9 @@
|
|||||||
<li>
|
<li>
|
||||||
<?= $this->a(t('Currency rates'), 'currency', 'index') ?>
|
<?= $this->a(t('Currency rates'), 'currency', 'index') ?>
|
||||||
</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
<?= $this->a(t('Integrations'), 'config', 'integrations') ?>
|
||||||
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<?= $this->a(t('Webhooks'), 'config', 'webhook') ?>
|
<?= $this->a(t('Webhooks'), 'config', 'webhook') ?>
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
@@ -1,9 +1,15 @@
|
|||||||
<p class="activity-title">
|
<p class="activity-title">
|
||||||
<?= e('%s changed the assignee of the task %s to %s',
|
<?php $assignee = $task['assignee_name'] ?: $task['assignee_username'] ?>
|
||||||
$this->e($author),
|
|
||||||
$this->a(t('#%d', $task['id']), 'task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])),
|
<?php if (! empty($assignee)): ?>
|
||||||
$this->e($task['assignee_name'] ?: $task['assignee_username'])
|
<?= e('%s changed the assignee of the task %s to %s',
|
||||||
) ?>
|
$this->e($author),
|
||||||
|
$this->a(t('#%d', $task['id']), 'task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])),
|
||||||
|
$this->e($assignee)
|
||||||
|
) ?>
|
||||||
|
<?php else: ?>
|
||||||
|
<?= e('%s remove the assignee of the task %s', $this->e($author), $this->a(t('#%d', $task['id']), 'task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id']))) ?>
|
||||||
|
<?php endif ?>
|
||||||
</p>
|
</p>
|
||||||
<p class="activity-description">
|
<p class="activity-description">
|
||||||
<em><?= $this->e($task['title']) ?></em>
|
<em><?= $this->e($task['title']) ?></em>
|
||||||
|
|||||||
21
docs/slack.markdown
Normal file
21
docs/slack.markdown
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
Slack integration
|
||||||
|
=================
|
||||||
|
|
||||||
|
Send notifications to a channel
|
||||||
|
-------------------------------
|
||||||
|
|
||||||
|
Example of notifications:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
This feature use the [Incoming webhook](https://api.slack.com/incoming-webhooks) system of Slack.
|
||||||
|
|
||||||
|
### Configure Slack
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
1. Click on the Team dropdown and choose **Configure Integrations**
|
||||||
|
2. On the list of services, scroll-down and choose **DIY Integrations & Customizations > Incoming WebHooks**
|
||||||
|
3. Copy the webhook url to the Kanboard settings page: **Settings > Integrations > Slack**
|
||||||
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user