diff options
68 files changed, 544 insertions, 1644 deletions
diff --git a/app/Controller/Config.php b/app/Controller/Config.php index 9a376b36..47b844e4 100644 --- a/app/Controller/Config.php +++ b/app/Controller/Config.php @@ -44,7 +44,7 @@ class Config extends Base $values += array('subtask_restriction' => 0, 'subtask_time_tracking' => 0, 'cfd_include_closed_tasks' => 0); break; case 'integrations': - $values += array('integration_slack_webhook' => 0, 'integration_hipchat' => 0, 'integration_gravatar' => 0, 'integration_jabber' => 0); + $values += array('integration_gravatar' => 0); break; case 'calendar': $values += array('calendar_user_subtasks_time_tracking' => 0); diff --git a/app/Controller/Project.php b/app/Controller/Project.php index af01ea77..f30d70e2 100644 --- a/app/Controller/Project.php +++ b/app/Controller/Project.php @@ -89,29 +89,50 @@ class Project extends Base * * @access public */ - public function integration() + public function integrations() { $project = $this->getProject(); if ($this->request->isPost()) { - $params = $this->request->getValues(); - $params += array('hipchat' => 0, 'slack' => 0, 'jabber' => 0); - $this->projectIntegration->saveParameters($project['id'], $params); + $this->projectMetadata->save($project['id'], $this->request->getValues()); + $this->session->flash(t('Project updated successfully.')); + $this->response->redirect($this->helper->url->to('project', 'integrations', array('project_id' => $project['id']))); } - $values = $this->projectIntegration->getParameters($project['id']); - $values += array('hipchat_api_url' => 'https://api.hipchat.com'); - $this->response->html($this->projectLayout('project/integrations', array( 'project' => $project, 'title' => t('Integrations'), 'webhook_token' => $this->config->get('webhook_token'), - 'values' => $values, + 'values' => $this->projectMetadata->getAll($project['id']), 'errors' => array(), ))); } /** + * Display project notifications + * + * @access public + */ + public function notifications() + { + $project = $this->getProject(); + + if ($this->request->isPost()) { + $values = $this->request->getValues(); + $this->projectNotification->saveSettings($project['id'], $values); + $this->session->flash(t('Project updated successfully.')); + $this->response->redirect($this->helper->url->to('project', 'notifications', array('project_id' => $project['id']))); + } + + $this->response->html($this->projectLayout('project/notifications', array( + 'notifications' => $this->projectNotification->readSettings($project['id']), + 'types' => $this->projectNotificationType->getTypes(), + 'project' => $project, + 'title' => t('Notifications'), + ))); + } + + /** * Display a form to edit a project * * @access public diff --git a/app/Controller/User.php b/app/Controller/User.php index 85b80d79..b5f4edeb 100644 --- a/app/Controller/User.php +++ b/app/Controller/User.php @@ -214,6 +214,28 @@ class User extends Base } /** + * Display user integrations + * + * @access public + */ + public function integrations() + { + $user = $this->getUser(); + + if ($this->request->isPost()) { + $values = $this->request->getValues(); + $this->userMetadata->save($user['id'], $values); + $this->session->flash(t('User updated successfully.')); + $this->response->redirect($this->helper->url->to('user', 'integrations', array('user_id' => $user['id']))); + } + + $this->response->html($this->layout('user/integrations', array( + 'user' => $user, + 'values' => $this->userMetadata->getall($user['id']), + ))); + } + + /** * Display external accounts * * @access public diff --git a/app/Core/Base.php b/app/Core/Base.php index 74f29508..b7be45d1 100644 --- a/app/Core/Base.php +++ b/app/Core/Base.php @@ -27,9 +27,6 @@ use Pimple\Container; * @property \Kanboard\Integration\BitbucketWebhook $bitbucketWebhook * @property \Kanboard\Integration\GithubWebhook $githubWebhook * @property \Kanboard\Integration\GitlabWebhook $gitlabWebhook - * @property \Kanboard\Integration\HipchatWebhook $hipchatWebhook - * @property \Kanboard\Integration\Jabber $jabber - * @property \Kanboard\Integration\SlackWebhook $slackWebhook * @property \Kanboard\Formatter\ProjectGanttFormatter $projectGanttFormatter * @property \Kanboard\Formatter\TaskFilterGanttFormatter $taskFilterGanttFormatter * @property \Kanboard\Formatter\TaskFilterAutoCompleteFormatter $taskFilterAutoCompleteFormatter @@ -49,6 +46,7 @@ use Pimple\Container; * @property \Kanboard\Model\File $file * @property \Kanboard\Model\LastLogin $lastLogin * @property \Kanboard\Model\Link $link + * @property \Kanboard\Model\Notification $notification * @property \Kanboard\Model\OverdueNotification $overdueNotification * @property \Kanboard\Model\Project $project * @property \Kanboard\Model\ProjectActivity $projectActivity @@ -56,7 +54,7 @@ use Pimple\Container; * @property \Kanboard\Model\ProjectDuplication $projectDuplication * @property \Kanboard\Model\ProjectDailyColumnStats $projectDailyColumnStats * @property \Kanboard\Model\ProjectDailyStats $projectDailyStats - * @property \Kanboard\Model\ProjectIntegration $projectIntegration + * @property \Kanboard\Model\ProjectMetadata $projectMetadata * @property \Kanboard\Model\ProjectPermission $projectPermission * @property \Kanboard\Model\Subtask $subtask * @property \Kanboard\Model\SubtaskExport $subtaskExport @@ -76,6 +74,7 @@ use Pimple\Container; * @property \Kanboard\Model\TaskPosition $taskPosition * @property \Kanboard\Model\TaskStatus $taskStatus * @property \Kanboard\Model\TaskValidator $taskValidator + * @property \Kanboard\Model\TaskMetadata $taskMetadata * @property \Kanboard\Model\Transition $transition * @property \Kanboard\Model\User $user * @property \Kanboard\Model\UserImport $userImport @@ -84,6 +83,7 @@ use Pimple\Container; * @property \Kanboard\Model\UserNotificationFilter $userNotificationFilter * @property \Kanboard\Model\UserUnreadNotification $userUnreadNotification * @property \Kanboard\Model\UserSession $userSession + * @property \Kanboard\Model\UserMetadata $userMetadata * @property \Kanboard\Model\Webhook $webhook * @property \Psr\Log\LoggerInterface $logger * @property \League\HTMLToMarkdown\HtmlConverter $htmlConverter diff --git a/app/Integration/HipchatWebhook.php b/app/Integration/HipchatWebhook.php deleted file mode 100644 index 6f789718..00000000 --- a/app/Integration/HipchatWebhook.php +++ /dev/null @@ -1,93 +0,0 @@ -<?php - -namespace Kanboard\Integration; - -/** - * Hipchat webhook - * - * @package integration - * @author Frederic Guillot - */ -class HipchatWebhook extends \Kanboard\Core\Base -{ - /** - * Return true if Hipchat is enabled for this project or globally - * - * @access public - * @param integer $project_id - * @return boolean - */ - public function isActivated($project_id) - { - return $this->config->get('integration_hipchat') == 1 || $this->projectIntegration->hasValue($project_id, 'hipchat', 1); - } - - /** - * Get API parameters - * - * @access public - * @param integer $project_id - * @return array - */ - public function getParameters($project_id) - { - if ($this->config->get('integration_hipchat') == 1) { - return array( - 'api_url' => $this->config->get('integration_hipchat_api_url'), - 'room_id' => $this->config->get('integration_hipchat_room_id'), - 'room_token' => $this->config->get('integration_hipchat_room_token'), - ); - } - - $options = $this->projectIntegration->getParameters($project_id); - - return array( - 'api_url' => $options['hipchat_api_url'], - 'room_id' => $options['hipchat_room_id'], - 'room_token' => $options['hipchat_room_token'], - ); - } - - /** - * Send the notification if activated - * - * @access public - * @param integer $project_id Project id - * @param integer $task_id Task id - * @param string $event_name Event name - * @param array $event Event data - */ - public function notify($project_id, $task_id, $event_name, array $event) - { - if ($this->isActivated($project_id)) { - $params = $this->getParameters($project_id); - $project = $this->project->getbyId($project_id); - - $event['event_name'] = $event_name; - $event['author'] = $this->user->getFullname($this->session['user']); - - $html = '<img src="http://kanboard.net/assets/img/favicon-32x32.png"/>'; - $html .= '<strong>'.$project['name'].'</strong>'.(isset($event['task']['title']) ? '<br/>'.$event['task']['title'] : '').'<br/>'; - $html .= $this->projectActivity->getTitle($event); - - if ($this->config->get('application_url')) { - $html .= '<br/><a href="'.$this->helper->url->href('task', 'show', array('task_id' => $task_id, 'project_id' => $project_id), false, '', true).'">'; - $html .= t('view the task on Kanboard').'</a>'; - } - - $payload = array( - 'message' => $html, - 'color' => 'yellow', - ); - - $url = sprintf( - '%s/v2/room/%s/notification?auth_token=%s', - $params['api_url'], - $params['room_id'], - $params['room_token'] - ); - - $this->httpClient->postJson($url, $payload); - } - } -} diff --git a/app/Integration/Jabber.php b/app/Integration/Jabber.php deleted file mode 100644 index d776e560..00000000 --- a/app/Integration/Jabber.php +++ /dev/null @@ -1,126 +0,0 @@ -<?php - -namespace Kanboard\Integration; - -use Exception; -use Fabiang\Xmpp\Options; -use Fabiang\Xmpp\Client; -use Fabiang\Xmpp\Protocol\Message; -use Fabiang\Xmpp\Protocol\Presence; - -/** - * Jabber - * - * @package integration - * @author Frederic Guillot - */ -class Jabber extends \Kanboard\Core\Base -{ - /** - * Return true if Jabber is enabled for this project or globally - * - * @access public - * @param integer $project_id - * @return boolean - */ - public function isActivated($project_id) - { - return $this->config->get('integration_jabber') == 1 || $this->projectIntegration->hasValue($project_id, 'jabber', 1); - } - - /** - * Get connection parameters - * - * @access public - * @param integer $project_id - * @return array - */ - public function getParameters($project_id) - { - if ($this->config->get('integration_jabber') == 1) { - return array( - 'server' => $this->config->get('integration_jabber_server'), - 'domain' => $this->config->get('integration_jabber_domain'), - 'username' => $this->config->get('integration_jabber_username'), - 'password' => $this->config->get('integration_jabber_password'), - 'nickname' => $this->config->get('integration_jabber_nickname'), - 'room' => $this->config->get('integration_jabber_room'), - ); - } - - $options = $this->projectIntegration->getParameters($project_id); - - return array( - 'server' => $options['jabber_server'], - 'domain' => $options['jabber_domain'], - 'username' => $options['jabber_username'], - 'password' => $options['jabber_password'], - 'nickname' => $options['jabber_nickname'], - 'room' => $options['jabber_room'], - ); - } - - /** - * Build and send the message - * - * @access public - * @param integer $project_id Project id - * @param integer $task_id Task id - * @param string $event_name Event name - * @param array $event Event data - */ - public function notify($project_id, $task_id, $event_name, array $event) - { - if ($this->isActivated($project_id)) { - $project = $this->project->getbyId($project_id); - - $event['event_name'] = $event_name; - $event['author'] = $this->user->getFullname($this->session['user']); - - $payload = '['.$project['name'].'] '.str_replace('"', '"', $this->projectActivity->getTitle($event)).(isset($event['task']['title']) ? ' ('.$event['task']['title'].')' : ''); - - if ($this->config->get('application_url')) { - $payload .= ' '.$this->helper->url->to('task', 'show', array('task_id' => $task_id, 'project_id' => $project_id), '', true); - } - - $this->sendMessage($project_id, $payload); - } - } - - /** - * Send message to the XMPP server - * - * @access public - * @param integer $project_id - * @param string $payload - */ - public function sendMessage($project_id, $payload) - { - try { - $params = $this->getParameters($project_id); - - $options = new Options($params['server']); - $options->setUsername($params['username']); - $options->setPassword($params['password']); - $options->setTo($params['domain']); - $options->setLogger($this->container['logger']); - - $client = new Client($options); - - $channel = new Presence; - $channel->setTo($params['room'])->setNickName($params['nickname']); - $client->send($channel); - - $message = new Message; - $message->setMessage($payload) - ->setTo($params['room']) - ->setType(Message::TYPE_GROUPCHAT); - - $client->send($message); - - $client->disconnect(); - } catch (Exception $e) { - $this->container['logger']->error('Jabber error: '.$e->getMessage()); - } - } -} diff --git a/app/Integration/SlackWebhook.php b/app/Integration/SlackWebhook.php deleted file mode 100644 index 8f4eb422..00000000 --- a/app/Integration/SlackWebhook.php +++ /dev/null @@ -1,126 +0,0 @@ -<?php - -namespace Kanboard\Integration; - -/** - * Slack Webhook - * - * @package integration - * @author Frederic Guillot - */ -class SlackWebhook extends \Kanboard\Core\Base -{ - /** - * Return true if Slack is enabled for this project or globally - * - * @access public - * @param integer $project_id - * @return boolean - */ - public function isActivated($project_id) - { - return $this->config->get('integration_slack_webhook') == 1 || $this->projectIntegration->hasValue($project_id, 'slack', 1); - } - - /** - * Get wehbook url - * - * @access public - * @param integer $project_id - * @return string - */ - public function getWebhookUrl($project_id) - { - if ($this->config->get('integration_slack_webhook') == 1) { - return $this->config->get('integration_slack_webhook_url'); - } - - $options = $this->projectIntegration->getParameters($project_id); - return isset($options['slack_webhook_url']) ? $options['slack_webhook_url'] : ''; - } - - /** - * Get optional Slack channel - * - * @access public - * @param integer $project_id - * @return string - */ - public function getChannel($project_id) - { - $channel = $this->config->get('integration_slack_webhook_channel'); - - if (! empty($channel)) { - return $channel; - } - - $options = $this->projectIntegration->getParameters($project_id); - return isset($options['slack_webhook_channel']) ? $options['slack_webhook_channel'] : ''; - } - - /** - * Send notification to Slack - * - * @access public - * @param integer $project_id Project id - * @param integer $task_id Task id - * @param string $event_name Event name - * @param array $event Event data - */ - public function notify($project_id, $task_id, $event_name, array $event) - { - if ($this->isActivated($project_id)) { - $project = $this->project->getbyId($project_id); - - $event['event_name'] = $event_name; - $event['author'] = $this->user->getFullname($this->session['user']); - - $message = '*['.$project['name'].']* '; - $message .= str_replace('"', '"', $this->projectActivity->getTitle($event)); - $message .= isset($event['task']['title']) ? ' ('.$event['task']['title'].')' : ''; - - if ($this->config->get('application_url')) { - $message .= ' - <'.$this->helper->url->href('task', 'show', array('task_id' => $task_id, 'project_id' => $project_id), false, '', true); - $message .= '|'.t('view the task on Kanboard').'>'; - } - - $this->sendMessage($project_id, $message); - } - } - - /** - * Send message to Slack - * - * @access public - * @param integer $project_id - * @param string $message - */ - public function sendMessage($project_id, $message) - { - $payload = array( - 'text' => $message, - 'username' => 'Kanboard', - 'icon_url' => 'http://kanboard.net/assets/img/favicon.png', - ); - - $this->sendPayload($project_id, $payload); - } - - /** - * Send payload to Slack - * - * @access public - * @param integer $project_id - * @param array $payload - */ - public function sendPayload($project_id, array $payload) - { - $channel = $this->getChannel($project_id); - - if (! empty($channel)) { - $payload['channel'] = $channel; - } - - $this->httpClient->postJson($this->getWebhookUrl($project_id), $payload); - } -} diff --git a/app/Locale/cs_CZ/translations.php b/app/Locale/cs_CZ/translations.php index 0ea35a9b..4b872c1d 100644 --- a/app/Locale/cs_CZ/translations.php +++ b/app/Locale/cs_CZ/translations.php @@ -697,15 +697,9 @@ return array( 'Reference currency' => 'Referenční měna', 'The currency rate have been added successfully.' => 'Směnný kurz byl úspěšně přidán.', 'Unable to add this currency rate.' => 'Nelze přidat tento směnný kurz', - 'Send notifications to a Slack channel' => 'Zaslání upozornění do Slack kanálu', 'Webhook URL' => 'Webhook URL', - 'Help on Slack integration' => 'Nápověda pro Slack integraci.', '%s remove the assignee of the task %s' => '%s odstranil přiřazení úkolu %s ', - 'Send notifications to Hipchat' => 'Odeslat upozornění přes Hipchat', 'API URL' => 'API URL', - 'Room API ID or name' => 'Raum API ID oder Name', - 'Room notification token' => 'Raum Benachrichtigungstoken', - 'Help on Hipchat integration' => 'Hilfe bei Hipchat Integration', 'Enable Gravatar images' => 'Aktiviere Gravatar Bilder', 'Information' => 'Informace', 'Check two factor authentication code' => 'Prüfe Zwei-Faktor-Authentifizierungscode', @@ -768,14 +762,6 @@ return array( // 'When task is moved from first column' => '', // 'When task is moved to last column' => '', // 'Year(s)' => '', - // 'Jabber (XMPP)' => '', - // 'Send notifications to Jabber' => '', - // 'XMPP server address' => '', - // 'Jabber domain' => '', - // 'Jabber nickname' => '', - // 'Multi-user chat room' => '', - // 'Help on Jabber integration' => '', - // 'The server address must use this format: "tcp://hostname:5222"' => '', 'Calendar settings' => 'Nastavení kalendáře', // 'Project calendar view' => '', 'Project settings' => 'Nastavení projektu', @@ -820,8 +806,6 @@ return array( '%s moved the task #%d to the swimlane "%s"' => '%s hat die Aufgabe #%d in die Swimlane "%s" verschoben', // 'Swimlane' => '', // 'Gravatar' => '', - // 'Hipchat' => '', - // 'Slack' => '', '%s moved the task %s to the first swimlane' => '%s hat die Aufgabe %s in die erste Swimlane verschoben', '%s moved the task %s to the swimlane "%s"' => '%s hat die Aufgaben %s in die Swimlane "%s" verschoben', 'This report contains all subtasks information for the given date range.' => 'Report obsahuje všechny informace o dílčích úkolech pro daný časový úsek', @@ -918,7 +902,6 @@ return array( 'Help on Google authentication' => 'Nápověda k ověřování pomocí služby Google', 'Github Authentication' => 'Ověřování pomocí služby Github', 'Help on Github authentication' => 'Nápověda k ověřování pomocí služby Github', - 'Channel/Group/User (Optional)' => 'Kanál/Skupina/Uživatel (volitelně)', 'Lead time: ' => 'Dodací lhůta: ', 'Cycle time: ' => 'Doba cyklu: ', 'Time spent into each column' => 'Čas strávený v každé fázi', diff --git a/app/Locale/da_DK/translations.php b/app/Locale/da_DK/translations.php index a0578120..a8addf6f 100644 --- a/app/Locale/da_DK/translations.php +++ b/app/Locale/da_DK/translations.php @@ -697,15 +697,9 @@ return array( // 'Reference currency' => '', // 'The currency rate have been added successfully.' => '', // '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' => '', - // 'Send notifications to Hipchat' => '', // 'API URL' => '', - // 'Room API ID or name' => '', - // 'Room notification token' => '', - // 'Help on Hipchat integration' => '', // 'Enable Gravatar images' => '', // 'Information' => '', // 'Check two factor authentication code' => '', @@ -768,14 +762,6 @@ return array( // 'When task is moved from first column' => '', // 'When task is moved to last column' => '', // 'Year(s)' => '', - // 'Jabber (XMPP)' => '', - // 'Send notifications to Jabber' => '', - // 'XMPP server address' => '', - // 'Jabber domain' => '', - // 'Jabber nickname' => '', - // 'Multi-user chat room' => '', - // 'Help on Jabber integration' => '', - // 'The server address must use this format: "tcp://hostname:5222"' => '', // 'Calendar settings' => '', // 'Project calendar view' => '', // 'Project settings' => '', @@ -820,8 +806,6 @@ return array( // '%s moved the task #%d to the swimlane "%s"' => '', // 'Swimlane' => '', // 'Gravatar' => '', - // 'Hipchat' => '', - // 'Slack' => '', // '%s moved the task %s to the first swimlane' => '', // '%s moved the task %s to the swimlane "%s"' => '', // 'This report contains all subtasks information for the given date range.' => '', @@ -918,7 +902,6 @@ return array( // 'Help on Google authentication' => '', // 'Github Authentication' => '', // 'Help on Github authentication' => '', - // 'Channel/Group/User (Optional)' => '', // 'Lead time: ' => '', // 'Cycle time: ' => '', // 'Time spent into each column' => '', diff --git a/app/Locale/de_DE/translations.php b/app/Locale/de_DE/translations.php index 13d88b11..4e451f22 100644 --- a/app/Locale/de_DE/translations.php +++ b/app/Locale/de_DE/translations.php @@ -697,15 +697,9 @@ return array( 'Reference currency' => 'Referenzwährung', 'The currency rate have been added successfully.' => 'Der Währungskurs wurde erfolgreich hinzugefügt.', 'Unable to add this currency rate.' => 'Währungskurs konnte nicht hinzugefügt werden', - 'Send notifications to a Slack channel' => 'Benachrichtigung an einen Slack-Kanal senden', 'Webhook URL' => 'Webhook-URL', - 'Help on Slack integration' => 'Hilfe für Slack-Integration.', '%s remove the assignee of the task %s' => '%s Zuordnung für die Aufgabe %s entfernen', - 'Send notifications to Hipchat' => 'Sende Benachrichtigung an Hipchat', 'API URL' => 'API-URL', - 'Room API ID or name' => 'Raum-API-ID oder -Name', - 'Room notification token' => 'Raum-Benachrichtigungstoken', - 'Help on Hipchat integration' => 'Hilfe bei Hipchat-Integration', 'Enable Gravatar images' => 'Aktiviere Gravatar-Bilder', 'Information' => 'Information', 'Check two factor authentication code' => 'Prüfe Zwei-Faktor-Authentifizierungscode', @@ -768,14 +762,6 @@ return array( 'When task is moved from first column' => 'Wenn Aufgabe von erster Spalte verschoben wird', 'When task is moved to last column' => 'Wenn Aufgabe in letzte Spalte verschoben wird', 'Year(s)' => 'Jahr(e)', - 'Jabber (XMPP)' => 'Jabber (XMPP)', - 'Send notifications to Jabber' => 'Benachrichtigungen an Jabber senden', - 'XMPP server address' => 'XMPP-Server-Adresse', - 'Jabber domain' => 'Jabber-Domain', - 'Jabber nickname' => 'Jabber-Nickname', - 'Multi-user chat room' => 'Multi-User-Chatroom', - 'Help on Jabber integration' => 'Hilfe zur Jabber-Integration', - 'The server address must use this format: "tcp://hostname:5222"' => 'Die Server-Adresse muss in diesem Format sein: "tcp://hostname:5222"', 'Calendar settings' => 'Kalender-Einstellungen', 'Project calendar view' => 'Projekt-Kalendarsicht', 'Project settings' => 'Projekteinstellungen', @@ -820,8 +806,6 @@ return array( '%s moved the task #%d to the swimlane "%s"' => '%s hat die Aufgabe #%d in die Swimlane "%s" verschoben', 'Swimlane' => 'Swimlane', 'Gravatar' => 'Gravatar', - 'Hipchat' => 'Hipchat', - 'Slack' => 'Slack', '%s moved the task %s to the first swimlane' => '%s hat die Aufgabe %s in die erste Swimlane verschoben', '%s moved the task %s to the swimlane "%s"' => '%s hat die Aufgaben %s in die Swimlane "%s" verschoben', 'This report contains all subtasks information for the given date range.' => 'Der Bericht beinhaltet alle Teilaufgaben im gewählten Zeitraum', @@ -918,7 +902,6 @@ return array( 'Help on Google authentication' => 'Hilfe bei Google-Authentifizierung', 'Github Authentication' => 'Github-Authentifizierung', 'Help on Github authentication' => 'Hilfe bei Github-Authentifizierung', - 'Channel/Group/User (Optional)' => 'Kanal/Gruppe/Benutzer (optional)', 'Lead time: ' => 'Durchlaufzeit:', 'Cycle time: ' => 'Zykluszeit:', 'Time spent into each column' => 'zeit verbracht in jeder Spalte', diff --git a/app/Locale/es_ES/translations.php b/app/Locale/es_ES/translations.php index 7e951471..527151f5 100644 --- a/app/Locale/es_ES/translations.php +++ b/app/Locale/es_ES/translations.php @@ -697,15 +697,9 @@ return array( 'Reference currency' => 'Moneda de referencia', 'The currency rate have been added successfully.' => 'Se ha añadido el cambio de moneda con éxito', 'Unable to add this currency rate.' => 'No pude añadir este cambio de moneda.', - 'Send notifications to a Slack channel' => 'Enviar notificaciones a un canal Desatendido', 'Webhook URL' => 'URL de Disparador Web (webhook)', - 'Help on Slack integration' => 'Ayuda sobre integración Desatendida', '%s remove the assignee of the task %s' => '%s quita el concesionario de la tarea %s', - 'Send notifications to Hipchat' => 'Enviar notificaciones a Hipchat', 'API URL' => 'URL de API', - 'Room API ID or name' => 'ID de API de habitación o nombre', - 'Room notification token' => 'Notificación de ficha de Habitación', - 'Help on Hipchat integration' => 'Ayuda sobre integración de Hipchat', 'Enable Gravatar images' => 'Activar imágenes Gravatar', 'Information' => 'Información', 'Check two factor authentication code' => 'Revisar código de autenticación de dos factores', @@ -768,14 +762,6 @@ return array( 'When task is moved from first column' => 'Cuando la tarea es movida desde la primera columna', 'When task is moved to last column' => 'Cuando la tarea es movida a la última columna', 'Year(s)' => 'Año(s)', - 'Jabber (XMPP)' => 'Jabber (XMPP)', - 'Send notifications to Jabber' => 'Enviar notificaciones a Jabber', - 'XMPP server address' => 'Dirección del servidor XMPP', - 'Jabber domain' => 'Dominio Jabber', - 'Jabber nickname' => 'Apodo Jabber', - 'Multi-user chat room' => 'Sala de chat multiusuario', - 'Help on Jabber integration' => 'Ayuda para la integración con Jabber', - 'The server address must use this format: "tcp://hostname:5222"' => 'La dirección del servidor debe usar este formato: "tcp://hostname:5222"', 'Calendar settings' => 'Parámetros del Calendario', 'Project calendar view' => 'Vista de Calendario para el Proyecto', 'Project settings' => 'Parámetros del Proyecto', @@ -820,8 +806,6 @@ return array( '%s moved the task #%d to the swimlane "%s"' => '%s movió la tarea #%d a la calle "%s"', 'Swimlane' => 'Calle', 'Gravatar' => 'Gravatar', - 'Hipchat' => 'Hipchat', - 'Slack' => 'Desatendida', '%s moved the task %s to the first swimlane' => '%s movió la tarea %s a la primera calle', '%s moved the task %s to the swimlane "%s"' => '%s movió la tarea %s a la calle "%s"', 'This report contains all subtasks information for the given date range.' => 'Este informe contiene todas la información de las subtareas para el rango proporcionado de fechas.', @@ -918,7 +902,6 @@ return array( 'Help on Google authentication' => 'Ayuda con la aAutenticación de Google', 'Github Authentication' => 'Autenticación de Github', 'Help on Github authentication' => 'Ayuda con la autenticación de Github', - 'Channel/Group/User (Optional)' => 'Canal/Grupo/Usuario (Opcional)', 'Lead time: ' => 'Plazo de entrega: ', 'Cycle time: ' => 'Tiempo de Ciclo: ', 'Time spent into each column' => 'Tiempo empleado en cada columna', diff --git a/app/Locale/fi_FI/translations.php b/app/Locale/fi_FI/translations.php index be4d2275..3bba8bea 100644 --- a/app/Locale/fi_FI/translations.php +++ b/app/Locale/fi_FI/translations.php @@ -697,15 +697,9 @@ return array( // 'Reference currency' => '', // 'The currency rate have been added successfully.' => '', // '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' => '', - // 'Send notifications to Hipchat' => '', // 'API URL' => '', - // 'Room API ID or name' => '', - // 'Room notification token' => '', - // 'Help on Hipchat integration' => '', // 'Enable Gravatar images' => '', // 'Information' => '', // 'Check two factor authentication code' => '', @@ -768,14 +762,6 @@ return array( // 'When task is moved from first column' => '', // 'When task is moved to last column' => '', // 'Year(s)' => '', - // 'Jabber (XMPP)' => '', - // 'Send notifications to Jabber' => '', - // 'XMPP server address' => '', - // 'Jabber domain' => '', - // 'Jabber nickname' => '', - // 'Multi-user chat room' => '', - // 'Help on Jabber integration' => '', - // 'The server address must use this format: "tcp://hostname:5222"' => '', // 'Calendar settings' => '', // 'Project calendar view' => '', // 'Project settings' => '', @@ -820,8 +806,6 @@ return array( // '%s moved the task #%d to the swimlane "%s"' => '', // 'Swimlane' => '', // 'Gravatar' => '', - // 'Hipchat' => '', - // 'Slack' => '', // '%s moved the task %s to the first swimlane' => '', // '%s moved the task %s to the swimlane "%s"' => '', // 'This report contains all subtasks information for the given date range.' => '', @@ -918,7 +902,6 @@ return array( // 'Help on Google authentication' => '', // 'Github Authentication' => '', // 'Help on Github authentication' => '', - // 'Channel/Group/User (Optional)' => '', // 'Lead time: ' => '', // 'Cycle time: ' => '', // 'Time spent into each column' => '', diff --git a/app/Locale/fr_FR/translations.php b/app/Locale/fr_FR/translations.php index 1afdeab3..d7c0148a 100644 --- a/app/Locale/fr_FR/translations.php +++ b/app/Locale/fr_FR/translations.php @@ -699,15 +699,9 @@ return array( 'Reference currency' => 'Devise de référence', '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', - 'Send notifications to a Slack channel' => 'Envoyer les notifications sur un salon de discussion 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', - 'Send notifications to Hipchat' => 'Envoyer les notifications vers Hipchat', 'API URL' => 'URL de l\'api', - 'Room API ID or name' => 'Nom ou identifiant du salon de discussion', - 'Room notification token' => 'Jeton de sécurité du salon de discussion', - 'Help on Hipchat integration' => 'Aide sur l\'intégration avec Hipchat', 'Enable Gravatar images' => 'Activer les images Gravatar', 'Information' => 'Informations', 'Check two factor authentication code' => 'Vérification du code pour l\'authentification à deux-facteurs', @@ -770,14 +764,6 @@ return array( 'When task is moved from first column' => 'Lorsque la tâche est déplacée en dehors de la première colonne', 'When task is moved to last column' => 'Lorsque la tâche est déplacée dans la dernière colonne', 'Year(s)' => 'Année(s)', - 'Jabber (XMPP)' => 'Jabber (XMPP)', - 'Send notifications to Jabber' => 'Envoyer les notifications vers Jabber', - 'XMPP server address' => 'Adresse du serveur XMPP', - 'Jabber domain' => 'Nom de domaine Jabber', - 'Jabber nickname' => 'Pseudonyme Jabber', - 'Multi-user chat room' => 'Salon de discussion multi-utilisateurs', - 'Help on Jabber integration' => 'Aide sur l\'intégration avec Jabber', - 'The server address must use this format: "tcp://hostname:5222"' => 'L\'adresse du serveur doit utiliser le format suivant : « tcp://hostname:5222 »', 'Calendar settings' => 'Paramètres du calendrier', 'Project calendar view' => 'Vue en mode projet du calendrier', 'Project settings' => 'Paramètres du projet', @@ -822,8 +808,6 @@ return array( '%s moved the task #%d to the swimlane "%s"' => '%s a déplacé la tâche n°%d dans la swimlane « %s »', 'Swimlane' => 'Swimlane', 'Gravatar' => 'Gravatar', - 'Hipchat' => 'Hipchat', - 'Slack' => 'Slack', '%s moved the task %s to the first swimlane' => '%s a déplacé la tâche %s dans la première swimlane', '%s moved the task %s to the swimlane "%s"' => '%s a déplacé la tâche %s dans la swimlane « %s »', 'This report contains all subtasks information for the given date range.' => 'Ce rapport contient les informations de toutes les sous-tâches pour la période sélectionnée.', @@ -920,7 +904,6 @@ return array( 'Help on Google authentication' => 'Aide sur l\'authentification Google', 'Github Authentication' => 'Authentification Github', 'Help on Github authentication' => 'Aide sur l\'authentification Github', - 'Channel/Group/User (Optional)' => 'Canal/Groupe/Utilisateur (Optionnel)', 'Lead time: ' => 'Lead time : ', 'Cycle time: ' => 'Temps de cycle : ', 'Time spent into each column' => 'Temps passé dans chaque colonne', diff --git a/app/Locale/hu_HU/translations.php b/app/Locale/hu_HU/translations.php index bd9ac9b5..b63ce202 100644 --- a/app/Locale/hu_HU/translations.php +++ b/app/Locale/hu_HU/translations.php @@ -697,15 +697,9 @@ return array( // 'Reference currency' => '', // 'The currency rate have been added successfully.' => '', // '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' => '', - // 'Send notifications to Hipchat' => '', // 'API URL' => '', - // 'Room API ID or name' => '', - // 'Room notification token' => '', - // 'Help on Hipchat integration' => '', // 'Enable Gravatar images' => '', // 'Information' => '', // 'Check two factor authentication code' => '', @@ -768,14 +762,6 @@ return array( // 'When task is moved from first column' => '', // 'When task is moved to last column' => '', // 'Year(s)' => '', - // 'Jabber (XMPP)' => '', - // 'Send notifications to Jabber' => '', - // 'XMPP server address' => '', - // 'Jabber domain' => '', - // 'Jabber nickname' => '', - // 'Multi-user chat room' => '', - // 'Help on Jabber integration' => '', - // 'The server address must use this format: "tcp://hostname:5222"' => '', // 'Calendar settings' => '', // 'Project calendar view' => '', // 'Project settings' => '', @@ -820,8 +806,6 @@ return array( // '%s moved the task #%d to the swimlane "%s"' => '', // 'Swimlane' => '', // 'Gravatar' => '', - // 'Hipchat' => '', - // 'Slack' => '', // '%s moved the task %s to the first swimlane' => '', // '%s moved the task %s to the swimlane "%s"' => '', // 'This report contains all subtasks information for the given date range.' => '', @@ -918,7 +902,6 @@ return array( // 'Help on Google authentication' => '', // 'Github Authentication' => '', // 'Help on Github authentication' => '', - // 'Channel/Group/User (Optional)' => '', // 'Lead time: ' => '', // 'Cycle time: ' => '', // 'Time spent into each column' => '', diff --git a/app/Locale/id_ID/translations.php b/app/Locale/id_ID/translations.php index ef4eefee..a32e2a7a 100644 --- a/app/Locale/id_ID/translations.php +++ b/app/Locale/id_ID/translations.php @@ -697,15 +697,9 @@ return array( 'Reference currency' => 'Referensi mata uang', 'The currency rate have been added successfully.' => 'Nilai tukar mata uang berhasil ditambahkan.', 'Unable to add this currency rate.' => 'Tidak dapat menambahkan nilai tukar mata uang', - 'Send notifications to a Slack channel' => 'Kirim pemberitahuan ke saluran Slack', 'Webhook URL' => 'URL webhook', - 'Help on Slack integration' => 'Bantuan pada integrasi Slack', '%s remove the assignee of the task %s' => '%s menghapus penugasan dari tugas %s', - 'Send notifications to Hipchat' => 'Kirim pemberitahuan ke Hipchat', 'API URL' => 'API URL', - 'Room API ID or name' => 'Id kamar API atau nama ', - 'Room notification token' => 'Token notifikasi kamar', - 'Help on Hipchat integration' => 'Bantuan pada integrasi Hipchat', 'Enable Gravatar images' => 'Mengaktifkan gambar Gravatar', 'Information' => 'Informasi', 'Check two factor authentication code' => 'Cek dua faktor kode otentifikasi', @@ -768,14 +762,6 @@ return array( 'When task is moved from first column' => 'Ketika tugas dipindahkan dari kolom pertama', 'When task is moved to last column' => 'Ketika tugas dipindahkan ke kolom terakhir', 'Year(s)' => 'Tahun', - 'Jabber (XMPP)' => 'Jabber (XMPP)', - 'Send notifications to Jabber' => 'Kirim pemberitahuan ke Jabber', - 'XMPP server address' => 'alamat server XMPP', - 'Jabber domain' => 'Domain Jabber', - 'Jabber nickname' => 'Nickname Jabber', - 'Multi-user chat room' => 'Multi-pengguna kamar obrolan', - 'Help on Jabber integration' => 'Bantuan pada integrasi Jabber', - 'The server address must use this format: "tcp://hostname:5222"' => 'Alamat server harus menggunakan format ini : « tcp://hostname:5222 »', 'Calendar settings' => 'Pengaturan kalender', 'Project calendar view' => 'Tampilan kalender proyek', 'Project settings' => 'Pengaturan proyek', @@ -820,8 +806,6 @@ return array( '%s moved the task #%d to the swimlane "%s"' => '%s memindahkan tugas n°%d ke swimlane « %s »', 'Swimlane' => 'Swimlane', 'Gravatar' => 'Gravatar', - 'Hipchat' => 'Hipchat', - 'Slack' => 'Slack', '%s moved the task %s to the first swimlane' => '%s memindahkan tugas %s ke swimlane pertama', '%s moved the task %s to the swimlane "%s"' => '%s memindahkan tugas %s ke swimlane « %s »', 'This report contains all subtasks information for the given date range.' => 'Laporan ini berisi semua informasi subtugas untuk rentang tanggal tertentu.', @@ -918,7 +902,6 @@ return array( 'Help on Google authentication' => 'Bantuan pada otentifikasi Google', 'Github Authentication' => 'Otentifikasi Github', 'Help on Github authentication' => 'Bantuan pada otentifikasi Github', - 'Channel/Group/User (Optional)' => 'Kanal/Grup/Pengguna (pilihan)', 'Lead time: ' => 'Lead time : ', 'Cycle time: ' => 'Siklus waktu : ', 'Time spent into each column' => 'Waktu yang dihabiskan di setiap kolom', diff --git a/app/Locale/it_IT/translations.php b/app/Locale/it_IT/translations.php index e906888a..10c85548 100644 --- a/app/Locale/it_IT/translations.php +++ b/app/Locale/it_IT/translations.php @@ -697,15 +697,9 @@ return array( 'Reference currency' => 'Valuta di riferimento', 'The currency rate have been added successfully.' => 'Il tasso di cambio è stato aggiunto con successo.', 'Unable to add this currency rate.' => 'Impossibile aggiungere questo tasso di cambio.', - 'Send notifications to a Slack channel' => 'Invia notifiche al canale Slack', 'Webhook URL' => 'URL Webhook', - 'Help on Slack integration' => 'Guida all\'integrazione con Slack', '%s remove the assignee of the task %s' => '%s rimuove l\'assegnatario del compito %s', - 'Send notifications to Hipchat' => 'Invia notifiche a Hipchat', 'API URL' => 'URL API', - 'Room API ID or name' => 'Nome o ID API della Room', - 'Room notification token' => 'Token per le notifiche della Room', - 'Help on Hipchat integration' => 'Guida all\'integrazione di Hipchat', 'Enable Gravatar images' => 'Abilita immagini Gravatar', 'Information' => 'Informazioni', 'Check two factor authentication code' => 'Controlla il codice di autenticazione a due fattori', @@ -768,14 +762,6 @@ return array( // 'When task is moved from first column' => '', // 'When task is moved to last column' => '', // 'Year(s)' => '', - // 'Jabber (XMPP)' => '', - // 'Send notifications to Jabber' => '', - // 'XMPP server address' => '', - // 'Jabber domain' => '', - // 'Jabber nickname' => '', - // 'Multi-user chat room' => '', - // 'Help on Jabber integration' => '', - // 'The server address must use this format: "tcp://hostname:5222"' => '', // 'Calendar settings' => '', // 'Project calendar view' => '', // 'Project settings' => '', @@ -820,8 +806,6 @@ return array( // '%s moved the task #%d to the swimlane "%s"' => '', // 'Swimlane' => '', // 'Gravatar' => '', - // 'Hipchat' => '', - // 'Slack' => '', // '%s moved the task %s to the first swimlane' => '', // '%s moved the task %s to the swimlane "%s"' => '', // 'This report contains all subtasks information for the given date range.' => '', @@ -918,7 +902,6 @@ return array( // 'Help on Google authentication' => '', // 'Github Authentication' => '', // 'Help on Github authentication' => '', - // 'Channel/Group/User (Optional)' => '', // 'Lead time: ' => '', // 'Cycle time: ' => '', // 'Time spent into each column' => '', diff --git a/app/Locale/ja_JP/translations.php b/app/Locale/ja_JP/translations.php index 7bf174ed..b2097280 100644 --- a/app/Locale/ja_JP/translations.php +++ b/app/Locale/ja_JP/translations.php @@ -697,15 +697,9 @@ return array( 'Reference currency' => '基軸通貨', // 'The currency rate have been added successfully.' => '', 'Unable to add this currency rate.' => 'この通貨レートを追加できません。', - 'Send notifications to a Slack channel' => 'Slack チャンネルに通知を送信', 'Webhook URL' => 'Webhook URL', - 'Help on Slack integration' => 'Slack 連携のヘルプ', '%s remove the assignee of the task %s' => '%s がタスク「%s」の担当を解除しました。', - 'Send notifications to Hipchat' => 'Hipchat に通知を送信', 'API URL' => 'API URL', - 'Room API ID or name' => 'Room API ID または名前', - 'Room notification token' => 'Room 通知トークン', - 'Help on Hipchat integration' => 'Hipchat 連携のヘルプ', 'Enable Gravatar images' => 'Gravatar イメージを有効化', 'Information' => '情報 ', 'Check two factor authentication code' => '2 段認証をチェックする', @@ -768,14 +762,6 @@ return array( // 'When task is moved from first column' => '', // 'When task is moved to last column' => '', // 'Year(s)' => '', - // 'Jabber (XMPP)' => '', - // 'Send notifications to Jabber' => '', - // 'XMPP server address' => '', - // 'Jabber domain' => '', - // 'Jabber nickname' => '', - // 'Multi-user chat room' => '', - // 'Help on Jabber integration' => '', - // 'The server address must use this format: "tcp://hostname:5222"' => '', // 'Calendar settings' => '', // 'Project calendar view' => '', // 'Project settings' => '', @@ -820,8 +806,6 @@ return array( // '%s moved the task #%d to the swimlane "%s"' => '', // 'Swimlane' => '', // 'Gravatar' => '', - // 'Hipchat' => '', - // 'Slack' => '', // '%s moved the task %s to the first swimlane' => '', // '%s moved the task %s to the swimlane "%s"' => '', // 'This report contains all subtasks information for the given date range.' => '', @@ -918,7 +902,6 @@ return array( // 'Help on Google authentication' => '', // 'Github Authentication' => '', // 'Help on Github authentication' => '', - // 'Channel/Group/User (Optional)' => '', // 'Lead time: ' => '', // 'Cycle time: ' => '', // 'Time spent into each column' => '', diff --git a/app/Locale/nb_NO/translations.php b/app/Locale/nb_NO/translations.php index ba4a06d5..e329252b 100644 --- a/app/Locale/nb_NO/translations.php +++ b/app/Locale/nb_NO/translations.php @@ -697,15 +697,9 @@ return array( // 'Reference currency' => '', // 'The currency rate have been added successfully.' => '', // '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' => '', - // 'Send notifications to Hipchat' => '', // 'API URL' => '', - // 'Room API ID or name' => '', - // 'Room notification token' => '', - // 'Help on Hipchat integration' => '', // 'Enable Gravatar images' => '', // 'Information' => '', // 'Check two factor authentication code' => '', @@ -768,14 +762,6 @@ return array( 'When task is moved from first column' => 'Når oppgaven er flyttet fra første kolon', 'When task is moved to last column' => 'Når oppgaven er flyttet til siste kolonne', 'Year(s)' => 'år', - // 'Jabber (XMPP)' => '', - // 'Send notifications to Jabber' => '', - // 'XMPP server address' => '', - // 'Jabber domain' => '', - // 'Jabber nickname' => '', - // 'Multi-user chat room' => '', - // 'Help on Jabber integration' => '', - // 'The server address must use this format: "tcp://hostname:5222"' => '', 'Calendar settings' => 'Kalenderinstillinger', 'Project calendar view' => 'Visning prosjektkalender', 'Project settings' => 'Prosjektinnstillinger', @@ -820,8 +806,6 @@ return array( // '%s moved the task #%d to the swimlane "%s"' => '', 'Swimlane' => 'Svømmebane', // 'Gravatar' => '', - // 'Hipchat' => '', - // 'Slack' => '', // '%s moved the task %s to the first swimlane' => '', // '%s moved the task %s to the swimlane "%s"' => '', // 'This report contains all subtasks information for the given date range.' => '', @@ -918,7 +902,6 @@ return array( // 'Help on Google authentication' => '', // 'Github Authentication' => '', // 'Help on Github authentication' => '', - // 'Channel/Group/User (Optional)' => '', // 'Lead time: ' => '', // 'Cycle time: ' => '', // 'Time spent into each column' => '', diff --git a/app/Locale/nl_NL/translations.php b/app/Locale/nl_NL/translations.php index 09076565..cb0eb422 100644 --- a/app/Locale/nl_NL/translations.php +++ b/app/Locale/nl_NL/translations.php @@ -697,15 +697,9 @@ return array( // 'Reference currency' => '', // 'The currency rate have been added successfully.' => '', // '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' => '', - // 'Send notifications to Hipchat' => '', // 'API URL' => '', - // 'Room API ID or name' => '', - // 'Room notification token' => '', - // 'Help on Hipchat integration' => '', // 'Enable Gravatar images' => '', // 'Information' => '', // 'Check two factor authentication code' => '', @@ -768,14 +762,6 @@ return array( // 'When task is moved from first column' => '', // 'When task is moved to last column' => '', // 'Year(s)' => '', - // 'Jabber (XMPP)' => '', - // 'Send notifications to Jabber' => '', - // 'XMPP server address' => '', - // 'Jabber domain' => '', - // 'Jabber nickname' => '', - // 'Multi-user chat room' => '', - // 'Help on Jabber integration' => '', - // 'The server address must use this format: "tcp://hostname:5222"' => '', // 'Calendar settings' => '', // 'Project calendar view' => '', // 'Project settings' => '', @@ -820,8 +806,6 @@ return array( // '%s moved the task #%d to the swimlane "%s"' => '', // 'Swimlane' => '', // 'Gravatar' => '', - // 'Hipchat' => '', - // 'Slack' => '', // '%s moved the task %s to the first swimlane' => '', // '%s moved the task %s to the swimlane "%s"' => '', // 'This report contains all subtasks information for the given date range.' => '', @@ -918,7 +902,6 @@ return array( // 'Help on Google authentication' => '', // 'Github Authentication' => '', // 'Help on Github authentication' => '', - // 'Channel/Group/User (Optional)' => '', // 'Lead time: ' => '', // 'Cycle time: ' => '', // 'Time spent into each column' => '', diff --git a/app/Locale/pl_PL/translations.php b/app/Locale/pl_PL/translations.php index 92ad4c26..ffaed8bc 100644 --- a/app/Locale/pl_PL/translations.php +++ b/app/Locale/pl_PL/translations.php @@ -697,15 +697,9 @@ return array( 'Reference currency' => 'Waluta referencyjna', 'The currency rate have been added successfully.' => 'Dodano kurs waluty', 'Unable to add this currency rate.' => 'Nie można dodać kursu waluty', - // 'Send notifications to a Slack channel' => '', // 'Webhook URL' => '', - // 'Help on Slack integration' => '', '%s remove the assignee of the task %s' => '%s usunął osobę przypisaną do zadania %s', - // 'Send notifications to Hipchat' => '', // 'API URL' => '', - // 'Room API ID or name' => '', - // 'Room notification token' => '', - // 'Help on Hipchat integration' => '', // 'Enable Gravatar images' => '', 'Information' => 'Informacje', 'Check two factor authentication code' => 'Sprawdź kod weryfikujący', @@ -768,14 +762,6 @@ return array( 'When task is moved from first column' => 'Przeniesienie zadania z pierwszej kolumny', 'When task is moved to last column' => 'Przeniesienie zadania do ostatniej kolumny', 'Year(s)' => 'Lat', - // 'Jabber (XMPP)' => '', - // 'Send notifications to Jabber' => '', - // 'XMPP server address' => '', - // 'Jabber domain' => '', - // 'Jabber nickname' => '', - // 'Multi-user chat room' => '', - // 'Help on Jabber integration' => '', - // 'The server address must use this format: "tcp://hostname:5222"' => '', 'Calendar settings' => 'Ustawienia kalendarza', 'Project calendar view' => 'Widok kalendarza projektu', 'Project settings' => 'Ustawienia Projektu', @@ -820,8 +806,6 @@ return array( // '%s moved the task #%d to the swimlane "%s"' => '', // 'Swimlane' => '', // 'Gravatar' => '', - // 'Hipchat' => '', - // 'Slack' => '', // '%s moved the task %s to the first swimlane' => '', // '%s moved the task %s to the swimlane "%s"' => '', // 'This report contains all subtasks information for the given date range.' => '', @@ -918,7 +902,6 @@ return array( // 'Help on Google authentication' => '', // 'Github Authentication' => '', // 'Help on Github authentication' => '', - // 'Channel/Group/User (Optional)' => '', // 'Lead time: ' => '', // 'Cycle time: ' => '', // 'Time spent into each column' => '', diff --git a/app/Locale/pt_BR/translations.php b/app/Locale/pt_BR/translations.php index fdad50ba..0950ef35 100644 --- a/app/Locale/pt_BR/translations.php +++ b/app/Locale/pt_BR/translations.php @@ -697,15 +697,9 @@ return array( 'Reference currency' => 'Moeda de Referência', 'The currency rate have been added successfully.' => 'A taxa de câmbio foi adicionada com sucesso.', 'Unable to add this currency rate.' => 'Impossível de adicionar essa taxa de câmbio.', - 'Send notifications to a Slack channel' => 'Enviar as notificações em um canal Slack', 'Webhook URL' => 'URL do webhook', - 'Help on Slack integration' => 'Ajuda sobre integração com o Slack', '%s remove the assignee of the task %s' => '%s removeu a pessoa designada para a tarefa %s', - 'Send notifications to Hipchat' => 'Enviar as notificações para o Hipchat', 'API URL' => 'URL da API', - 'Room API ID or name' => 'Nome ou ID da sala de discussão', - 'Room notification token' => 'Código de segurança da sala de discussão', - 'Help on Hipchat integration' => 'Ajuda sobre integração com o Hipchat', 'Enable Gravatar images' => 'Ativar imagens do Gravatar', 'Information' => 'Informações', 'Check two factor authentication code' => 'Verificação do código de autenticação à fator duplo', @@ -768,14 +762,6 @@ return array( 'When task is moved from first column' => 'Quando a tarefa é movida fora da primeira coluna', 'When task is moved to last column' => 'Quando a tarefa é movida para a última coluna', 'Year(s)' => 'Ano(s)', - 'Jabber (XMPP)' => 'Jabber (XMPP)', - 'Send notifications to Jabber' => 'Enviar notificações para o Jabber', - 'XMPP server address' => 'Endereço do servidor XMPP', - 'Jabber domain' => 'Nome de domínio Jabber', - 'Jabber nickname' => 'Apelido Jabber', - 'Multi-user chat room' => 'Sala de chat multi-usuário', - 'Help on Jabber integration' => 'Ajuda sobre integração com o Jabber', - 'The server address must use this format: "tcp://hostname:5222"' => 'O endereço do servidor deve usar o seguinte formato: "tcp://hostname:5222"', 'Calendar settings' => 'Configurações do calendário', 'Project calendar view' => 'Vista em modo projeto do calendário', 'Project settings' => 'Configurações dos projetos', @@ -820,8 +806,6 @@ return array( '%s moved the task #%d to the swimlane "%s"' => '%s moveu a tarefa #%d para a swimlane "%s"', 'Swimlane' => 'Swimlane', 'Gravatar' => 'Gravatar', - 'Hipchat' => 'Hipchat', - 'Slack' => 'Slack', '%s moved the task %s to the first swimlane' => '%s moveu a tarefa %s para a primeira swimlane', '%s moved the task %s to the swimlane "%s"' => '%s moveu a tarefa %s para a swimlane "%s"', 'This report contains all subtasks information for the given date range.' => 'Este relatório contém informações de todas as sub-tarefas para o período selecionado.', @@ -918,7 +902,6 @@ return array( 'Help on Google authentication' => 'Ajuda com a autenticação Google', 'Github Authentication' => 'Autenticação Github', 'Help on Github authentication' => 'Ajuda com a autenticação Github', - 'Channel/Group/User (Optional)' => 'Canal/Grupo/Utilizador (Opcional)', 'Lead time: ' => 'Lead time: ', 'Cycle time: ' => 'Cycle time: ', 'Time spent into each column' => 'Tempo gasto em cada coluna', diff --git a/app/Locale/pt_PT/translations.php b/app/Locale/pt_PT/translations.php index 800e5ee3..24366d92 100644 --- a/app/Locale/pt_PT/translations.php +++ b/app/Locale/pt_PT/translations.php @@ -697,15 +697,9 @@ return array( 'Reference currency' => 'Moeda de Referência', 'The currency rate have been added successfully.' => 'A taxa de câmbio foi adicionada com sucesso.', 'Unable to add this currency rate.' => 'Impossível adicionar essa taxa de câmbio.', - 'Send notifications to a Slack channel' => 'Enviar as notificações por canal Slack', 'Webhook URL' => 'URL do webhook', - 'Help on Slack integration' => 'Ajuda na integração com o Slack', '%s remove the assignee of the task %s' => '%s removeu a pessoa assignada à tarefa %s', - 'Send notifications to Hipchat' => 'Enviar as notificações para o Hipchat', 'API URL' => 'URL da API', - 'Room API ID or name' => 'Nome ou ID da sala de discussão', - 'Room notification token' => 'Código de segurança da sala de discussão', - 'Help on Hipchat integration' => 'Ajuda na integração com o Hipchat', 'Enable Gravatar images' => 'Activar imagem Gravatar', 'Information' => 'Informações', 'Check two factor authentication code' => 'Verificação do código de autenticação com factor duplo', @@ -768,14 +762,6 @@ return array( 'When task is moved from first column' => 'Quando a tarefa é movida fora da primeira coluna', 'When task is moved to last column' => 'Quando a tarefa é movida para a última coluna', 'Year(s)' => 'Ano(s)', - 'Jabber (XMPP)' => 'Jabber (XMPP)', - 'Send notifications to Jabber' => 'Enviar notificações para o Jabber', - 'XMPP server address' => 'Endereço do servidor XMPP', - 'Jabber domain' => 'Nome de domínio Jabber', - 'Jabber nickname' => 'Apelido Jabber', - 'Multi-user chat room' => 'Sala de chat multi-utilizador', - 'Help on Jabber integration' => 'Ajuda na integração com Jabber', - 'The server address must use this format: "tcp://hostname:5222"' => 'O endereço do servidor deve usar o seguinte formato: "tcp://hostname:5222"', 'Calendar settings' => 'Configurações do calendário', 'Project calendar view' => 'Vista em modo projecto do calendário', 'Project settings' => 'Configurações dos projectos', @@ -820,8 +806,6 @@ return array( '%s moved the task #%d to the swimlane "%s"' => '%s moveu a tarefa n° %d no swimlane "%s"', 'Swimlane' => 'Swimlane', 'Gravatar' => 'Gravatar', - 'Hipchat' => 'Hipchat', - 'Slack' => 'Slack', '%s moved the task %s to the first swimlane' => '%s moveu a tarefa %s no primeiro swimlane', '%s moved the task %s to the swimlane "%s"' => '%s moveu a tarefa %s no swimlane "%s"', 'This report contains all subtasks information for the given date range.' => 'Este relatório contém informações de todas as sub-tarefas para o período selecionado.', @@ -918,7 +902,6 @@ return array( 'Help on Google authentication' => 'Ajuda com autenticação Google', 'Github Authentication' => 'Autenticação Github', 'Help on Github authentication' => 'Ajuda com autenticação Github', - 'Channel/Group/User (Optional)' => 'Canal/Grupo/Utilizador (Opcional)', 'Lead time: ' => 'Tempo de Espera: ', 'Cycle time: ' => 'Tempo de Ciclo: ', 'Time spent into each column' => 'Tempo gasto em cada coluna', diff --git a/app/Locale/ru_RU/translations.php b/app/Locale/ru_RU/translations.php index fd0540e0..d16e95f3 100644 --- a/app/Locale/ru_RU/translations.php +++ b/app/Locale/ru_RU/translations.php @@ -697,15 +697,9 @@ return array( 'Reference currency' => 'Справочник валют', 'The currency rate have been added successfully.' => 'Курс валюты был успешно добавлен.', 'Unable to add this currency rate.' => 'Невозможно добавить этот курс валюты.', - 'Send notifications to a Slack channel' => 'Отправлять уведомления в канал Slack', 'Webhook URL' => 'Webhook URL', - 'Help on Slack integration' => 'Помощь по интеграции Slack', '%s remove the assignee of the task %s' => '%s удалить назначенную задачу %s', - 'Send notifications to Hipchat' => 'Отправлять уведомления в Hipchat', 'API URL' => 'API URL', - 'Room API ID or name' => 'API ID комнаты или имя', - 'Room notification token' => 'Ключь комнаты для уведомлений', - 'Help on Hipchat integration' => 'Помощь по интеграции Hipchat', 'Enable Gravatar images' => 'Включить Gravatar изображения', 'Information' => 'Информация', 'Check two factor authentication code' => 'Проверка кода двухфакторной авторизации', @@ -768,14 +762,6 @@ return array( 'When task is moved from first column' => 'Когда задача перемещается из первой колонки', 'When task is moved to last column' => 'Когда задача перемещается в последнюю колонку', 'Year(s)' => 'Год(а)', - 'Jabber (XMPP)' => 'Jabber (XMPP)', - 'Send notifications to Jabber' => 'Отправлять уведомления в Jabber', - 'XMPP server address' => 'Адрес Jabber сервера', - 'Jabber domain' => 'Домен Jabber', - 'Jabber nickname' => 'Имя пользователя Jabber', - 'Multi-user chat room' => 'Многопользовательский чат', - 'Help on Jabber integration' => 'Помощь по интеграции Jabber', - 'The server address must use this format: "tcp://hostname:5222"' => 'Адрес сервера должен быть в формате: tcp://hostname:5222', 'Calendar settings' => 'Настройки календаря', 'Project calendar view' => 'Вид календаря проекта', 'Project settings' => 'Настройки проекта', @@ -820,8 +806,6 @@ return array( '%s moved the task #%d to the swimlane "%s"' => '%s задач перемещено #%d в дорожке "%s"', 'Swimlane' => 'Дорожки', 'Gravatar' => 'Граватар', - 'Hipchat' => 'Hipchat', - 'Slack' => 'Slack', // '%s moved the task %s to the first swimlane' => '', // '%s moved the task %s to the swimlane "%s"' => '', 'This report contains all subtasks information for the given date range.' => 'Этот отчет содержит всю информацию подзадач в заданном диапазоне дат.', @@ -918,7 +902,6 @@ return array( 'Help on Google authentication' => 'Помощь в авторизации Google', 'Github Authentication' => 'Авторизация Github', 'Help on Github authentication' => 'Помощь в авторизации Github', - 'Channel/Group/User (Optional)' => 'Канал/Группа/Пользователь (опционально)', 'Lead time: ' => 'Время выполнения:', 'Cycle time: ' => 'Время цикла:', 'Time spent into each column' => 'Время, проведенное в каждой колонке', diff --git a/app/Locale/sr_Latn_RS/translations.php b/app/Locale/sr_Latn_RS/translations.php index a1eac165..34dca50b 100644 --- a/app/Locale/sr_Latn_RS/translations.php +++ b/app/Locale/sr_Latn_RS/translations.php @@ -697,15 +697,9 @@ return array( // 'Reference currency' => '', // 'The currency rate have been added successfully.' => '', // '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' => '', - // 'Send notifications to Hipchat' => '', // 'API URL' => '', - // 'Room API ID or name' => '', - // 'Room notification token' => '', - // 'Help on Hipchat integration' => '', // 'Enable Gravatar images' => '', // 'Information' => '', // 'Check two factor authentication code' => '', @@ -768,14 +762,6 @@ return array( // 'When task is moved from first column' => '', // 'When task is moved to last column' => '', // 'Year(s)' => '', - // 'Jabber (XMPP)' => '', - // 'Send notifications to Jabber' => '', - // 'XMPP server address' => '', - // 'Jabber domain' => '', - // 'Jabber nickname' => '', - // 'Multi-user chat room' => '', - // 'Help on Jabber integration' => '', - // 'The server address must use this format: "tcp://hostname:5222"' => '', // 'Calendar settings' => '', // 'Project calendar view' => '', // 'Project settings' => '', @@ -820,8 +806,6 @@ return array( // '%s moved the task #%d to the swimlane "%s"' => '', // 'Swimlane' => '', // 'Gravatar' => '', - // 'Hipchat' => '', - // 'Slack' => '', // '%s moved the task %s to the first swimlane' => '', // '%s moved the task %s to the swimlane "%s"' => '', // 'This report contains all subtasks information for the given date range.' => '', @@ -918,7 +902,6 @@ return array( // 'Help on Google authentication' => '', // 'Github Authentication' => '', // 'Help on Github authentication' => '', - // 'Channel/Group/User (Optional)' => '', // 'Lead time: ' => '', // 'Cycle time: ' => '', // 'Time spent into each column' => '', diff --git a/app/Locale/sv_SE/translations.php b/app/Locale/sv_SE/translations.php index 6faf7f60..aac3fac7 100644 --- a/app/Locale/sv_SE/translations.php +++ b/app/Locale/sv_SE/translations.php @@ -697,15 +697,9 @@ return array( 'Reference currency' => 'Referensvaluta', 'The currency rate have been added successfully.' => 'Valutakursen har lagts till.', 'Unable to add this currency rate.' => 'Kunde inte lägga till valutakursen.', - 'Send notifications to a Slack channel' => 'Skicka notiser till en Slack kanal', 'Webhook URL' => 'Webhook URL', - 'Help on Slack integration' => 'Hjälp för Slack integration', '%s remove the assignee of the task %s' => '%s ta bort tilldelningen av uppgiften %s', - 'Send notifications to Hipchat' => 'Skicka notiser till Hipchat', 'API URL' => 'API URL', - 'Room API ID or name' => 'Room API ID eller namn', - 'Room notification token' => 'Room notistoken', - 'Help on Hipchat integration' => 'Hjälp för Hipchat integration', 'Enable Gravatar images' => 'Aktivera Gravatar bilder', 'Information' => 'Information', 'Check two factor authentication code' => 'Kolla tvåfaktorsverifieringskod', @@ -768,14 +762,6 @@ return array( 'When task is moved from first column' => 'När uppgiften flyttas från första kolumnen', 'When task is moved to last column' => 'När uppgiften flyttas till sista kolumnen', 'Year(s)' => 'År', - 'Jabber (XMPP)' => 'Jabber (XMPP)', - 'Send notifications to Jabber' => 'Skicka notiser till Jabber', - 'XMPP server address' => 'XMPP serveradress', - 'Jabber domain' => 'Jabber domän', - 'Jabber nickname' => 'Jabber smeknamn', - 'Multi-user chat room' => 'Multi-user chatrum', - 'Help on Jabber integration' => 'Hjälp för Jabber integration', - 'The server address must use this format: "tcp://hostname:5222"' => 'Serveradressen måste använda detta format: "tcp://hostname:5222"', 'Calendar settings' => 'Inställningar för kalendern', 'Project calendar view' => 'Projektkalendervy', 'Project settings' => 'Projektinställningar', @@ -820,8 +806,6 @@ return array( '%s moved the task #%d to the swimlane "%s"' => '%s flyttade uppgiften #%d till swimlane "%s"', 'Swimlane' => 'Swimlane', 'Gravatar' => 'Gravatar', - 'Hipchat' => 'Hipchat', - 'Slack' => 'Slack', '%s moved the task %s to the first swimlane' => '%s flyttade uppgiften %s till första swimlane', '%s moved the task %s to the swimlane "%s"' => '%s flyttade uppgiften %s till swimlane "%s"', 'This report contains all subtasks information for the given date range.' => 'Denna rapport innehåller all deluppgiftsinformation för det givna datumintervallet.', @@ -918,7 +902,6 @@ return array( 'Help on Google authentication' => 'Hjälp för Google autentisering', 'Github Authentication' => 'Github autentisering', 'Help on Github authentication' => 'Hjälp för Github autentisering', - 'Channel/Group/User (Optional)' => 'Kanal/Grupp/Användare (valfri)', 'Lead time: ' => 'Ledtid', 'Cycle time: ' => 'Cykeltid', 'Time spent into each column' => 'Tidsåtgång per kolumn', diff --git a/app/Locale/th_TH/translations.php b/app/Locale/th_TH/translations.php index b2918ae2..1f7f2dd4 100644 --- a/app/Locale/th_TH/translations.php +++ b/app/Locale/th_TH/translations.php @@ -697,15 +697,9 @@ return array( // 'Reference currency' => '', // 'The currency rate have been added successfully.' => '', // 'Unable to add this currency rate.' => '', - 'Send notifications to a Slack channel' => 'ส่งการแจ้งเตือนไปทาง Slack channel', // 'Webhook URL' => '', - // 'Help on Slack integration' => '', // '%s remove the assignee of the task %s' => '', - // 'Send notifications to Hipchat' => '', // 'API URL' => '', - // 'Room API ID or name' => '', - // 'Room notification token' => '', - // 'Help on Hipchat integration' => '', 'Enable Gravatar images' => 'สามารถใช้งานภาพ Gravatar', 'Information' => 'ข้อมูลสารสนเทศ', // 'Check two factor authentication code' => '', @@ -768,14 +762,6 @@ return array( 'When task is moved from first column' => 'เมื่องานถูกย้ายจากคอลัมน์แรก', 'When task is moved to last column' => 'เมื่องานถูกย้ายไปคอลัมน์สุดท้าย', 'Year(s)' => 'ปี', - // 'Jabber (XMPP)' => '', - // 'Send notifications to Jabber' => '', - // 'XMPP server address' => '', - // 'Jabber domain' => '', - // 'Jabber nickname' => '', - // 'Multi-user chat room' => '', - // 'Help on Jabber integration' => '', - // 'The server address must use this format: "tcp://hostname:5222"' => '', 'Calendar settings' => 'ตั้งค่าปฏิทิน', 'Project calendar view' => 'มุมมองปฏิทินของโปรเจค', 'Project settings' => 'ตั้งค่าโปรเจค', @@ -820,8 +806,6 @@ return array( // '%s moved the task #%d to the swimlane "%s"' => '', // 'Swimlane' => '', // 'Gravatar' => '', - // 'Hipchat' => '', - // 'Slack' => '', // '%s moved the task %s to the first swimlane' => '', // '%s moved the task %s to the swimlane "%s"' => '', // 'This report contains all subtasks information for the given date range.' => '', @@ -918,7 +902,6 @@ return array( // 'Help on Google authentication' => '', // 'Github Authentication' => '', // 'Help on Github authentication' => '', - // 'Channel/Group/User (Optional)' => '', // 'Lead time: ' => '', // 'Cycle time: ' => '', // 'Time spent into each column' => '', diff --git a/app/Locale/tr_TR/translations.php b/app/Locale/tr_TR/translations.php index 54cb165d..47afc9a5 100644 --- a/app/Locale/tr_TR/translations.php +++ b/app/Locale/tr_TR/translations.php @@ -697,15 +697,9 @@ return array( // 'Reference currency' => '', // 'The currency rate have been added successfully.' => '', // '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' => '', - // 'Send notifications to Hipchat' => '', // 'API URL' => '', - // 'Room API ID or name' => '', - // 'Room notification token' => '', - // 'Help on Hipchat integration' => '', // 'Enable Gravatar images' => '', // 'Information' => '', // 'Check two factor authentication code' => '', @@ -768,14 +762,6 @@ return array( // 'When task is moved from first column' => '', // 'When task is moved to last column' => '', // 'Year(s)' => '', - // 'Jabber (XMPP)' => '', - // 'Send notifications to Jabber' => '', - // 'XMPP server address' => '', - // 'Jabber domain' => '', - // 'Jabber nickname' => '', - // 'Multi-user chat room' => '', - // 'Help on Jabber integration' => '', - // 'The server address must use this format: "tcp://hostname:5222"' => '', // 'Calendar settings' => '', // 'Project calendar view' => '', // 'Project settings' => '', @@ -820,8 +806,6 @@ return array( // '%s moved the task #%d to the swimlane "%s"' => '', // 'Swimlane' => '', // 'Gravatar' => '', - // 'Hipchat' => '', - // 'Slack' => '', // '%s moved the task %s to the first swimlane' => '', // '%s moved the task %s to the swimlane "%s"' => '', // 'This report contains all subtasks information for the given date range.' => '', @@ -918,7 +902,6 @@ return array( // 'Help on Google authentication' => '', // 'Github Authentication' => '', // 'Help on Github authentication' => '', - // 'Channel/Group/User (Optional)' => '', // 'Lead time: ' => '', // 'Cycle time: ' => '', // 'Time spent into each column' => '', diff --git a/app/Locale/zh_CN/translations.php b/app/Locale/zh_CN/translations.php index 02e0572c..22612b59 100644 --- a/app/Locale/zh_CN/translations.php +++ b/app/Locale/zh_CN/translations.php @@ -697,15 +697,9 @@ return array( 'Reference currency' => '参考货币', 'The currency rate have been added successfully.' => '成功添加汇率。', 'Unable to add this currency rate.' => '无法添加此汇率', - 'Send notifications to a Slack channel' => '发送通知到 Slack 频道', 'Webhook URL' => '网络钩子 URL', - 'Help on Slack integration' => 'Slack 整合帮助', '%s remove the assignee of the task %s' => '%s删除了任务%s的负责人', - 'Send notifications to Hipchat' => '发送通知到 Hipchat', 'API URL' => 'API URL', - 'Room API ID or name' => '房间 API ID 或名称', - 'Room notification token' => '房间通知令牌', - 'Help on Hipchat integration' => 'Hipchat 整合帮助', 'Enable Gravatar images' => '启用 Gravatar 图像', 'Information' => '信息', 'Check two factor authentication code' => '检查双重认证码', @@ -768,14 +762,6 @@ return array( // 'When task is moved from first column' => '', // 'When task is moved to last column' => '', // 'Year(s)' => '', - // 'Jabber (XMPP)' => '', - // 'Send notifications to Jabber' => '', - // 'XMPP server address' => '', - // 'Jabber domain' => '', - // 'Jabber nickname' => '', - 'Multi-user chat room' => '多用户聊天室', - // 'Help on Jabber integration' => '', - // 'The server address must use this format: "tcp://hostname:5222"' => '', 'Calendar settings' => '日程设置', // 'Project calendar view' => '', 'Project settings' => '项目设置', @@ -820,8 +806,6 @@ return array( // '%s moved the task #%d to the swimlane "%s"' => '', // 'Swimlane' => '', // 'Gravatar' => '', - // 'Hipchat' => '', - // 'Slack' => '', // '%s moved the task %s to the first swimlane' => '', // '%s moved the task %s to the swimlane "%s"' => '', // 'This report contains all subtasks information for the given date range.' => '', @@ -918,7 +902,6 @@ return array( // 'Help on Google authentication' => '', // 'Github Authentication' => '', // 'Help on Github authentication' => '', - // 'Channel/Group/User (Optional)' => '', // 'Lead time: ' => '', // 'Cycle time: ' => '', // 'Time spent into each column' => '', diff --git a/app/Model/Acl.php b/app/Model/Acl.php index 92ce0c5a..62f850cb 100644 --- a/app/Model/Acl.php +++ b/app/Model/Acl.php @@ -64,7 +64,7 @@ class Acl extends Base 'column' => '*', 'export' => '*', 'taskimport' => '*', - 'project' => array('edit', 'update', 'share', 'integration', 'users', 'alloweverybody', 'allow', 'setowner', 'revoke', 'duplicate', 'disable', 'enable'), + 'project' => array('edit', 'update', 'share', 'integrations', 'notifications', 'users', 'alloweverybody', 'allow', 'setowner', 'revoke', 'duplicate', 'disable', 'enable'), 'swimlane' => '*', 'gantt' => array('project', 'savetaskdate', 'task', 'savetask'), ); diff --git a/app/Model/Notification.php b/app/Model/Notification.php new file mode 100644 index 00000000..f1122993 --- /dev/null +++ b/app/Model/Notification.php @@ -0,0 +1,142 @@ +<?php + +namespace Kanboard\Model; + +/** + * Notification + * + * @package model + * @author Frederic Guillot + */ +class Notification extends Base +{ + /** + * Get the event title with author + * + * @access public + * @param string $event_author + * @param string $event_name + * @param array $event_data + * @return string + */ + public function getTitleWithAuthor($event_author, $event_name, array $event_data) + { + switch ($event_name) { + case Task::EVENT_ASSIGNEE_CHANGE: + $assignee = $event_data['task']['assignee_name'] ?: $event_data['task']['assignee_username']; + + if (! empty($assignee)) { + return e('%s change the assignee of the task #%d to %s', $event_author, $event_data['task']['id'], $assignee); + } + + return e('%s remove the assignee of the task %s', $event_author, e('#%d', $event_data['task']['id'])); + case Task::EVENT_UPDATE: + return e('%s updated the task #%d', $event_author, $event_data['task']['id']); + case Task::EVENT_CREATE: + return e('%s created the task #%d', $event_author, $event_data['task']['id']); + case Task::EVENT_CLOSE: + return e('%s closed the task #%d', $event_author, $event_data['task']['id']); + case Task::EVENT_OPEN: + return e('%s open the task #%d', $event_author, $event_data['task']['id']); + case Task::EVENT_MOVE_COLUMN: + return e( + '%s moved the task #%d to the column "%s"', + $event_author, + $event_data['task']['id'], + $event_data['task']['column_title'] + ); + case Task::EVENT_MOVE_POSITION: + return e( + '%s moved the task #%d to the position %d in the column "%s"', + $event_author, + $event_data['task']['id'], + $event_data['task']['position'], + $event_data['task']['column_title'] + ); + case Task::EVENT_MOVE_SWIMLANE: + if ($event_data['task']['swimlane_id'] == 0) { + return e('%s moved the task #%d to the first swimlane', $event_author, $event_data['task']['id']); + } + + return e( + '%s moved the task #%d to the swimlane "%s"', + $event_author, + $event_data['task']['id'], + $event_data['task']['swimlane_name'] + ); + case Subtask::EVENT_UPDATE: + return e('%s updated a subtask for the task #%d', $event_author, $event_data['task']['id']); + case Subtask::EVENT_CREATE: + return e('%s created a subtask for the task #%d', $event_author, $event_data['task']['id']); + case Comment::EVENT_UPDATE: + return e('%s updated a comment on the task #%d', $event_author, $event_data['task']['id']); + case Comment::EVENT_CREATE: + return e('%s commented on the task #%d', $event_author, $event_data['task']['id']); + case File::EVENT_CREATE: + return e('%s attached a file to the task #%d', $event_author, $event_data['task']['id']); + default: + return e('Notification'); + } + } + + /** + * Get the event title without author + * + * @access public + * @param string $event_name + * @param array $event_data + * @return string + */ + public function getTitleWithoutAuthor($event_name, array $event_data) + { + switch ($event_name) { + case File::EVENT_CREATE: + $title = e('New attachment on task #%d: %s', $event_data['file']['task_id'], $event_data['file']['name']); + break; + case Comment::EVENT_CREATE: + $title = e('New comment on task #%d', $event_data['comment']['task_id']); + break; + case Comment::EVENT_UPDATE: + $title = e('Comment updated on task #%d', $event_data['comment']['task_id']); + break; + case Subtask::EVENT_CREATE: + $title = e('New subtask on task #%d', $event_data['subtask']['task_id']); + break; + case Subtask::EVENT_UPDATE: + $title = e('Subtask updated on task #%d', $event_data['subtask']['task_id']); + break; + case Task::EVENT_CREATE: + $title = e('New task #%d: %s', $event_data['task']['id'], $event_data['task']['title']); + break; + case Task::EVENT_UPDATE: + $title = e('Task updated #%d', $event_data['task']['id']); + break; + case Task::EVENT_CLOSE: + $title = e('Task #%d closed', $event_data['task']['id']); + break; + case Task::EVENT_OPEN: + $title = e('Task #%d opened', $event_data['task']['id']); + break; + case Task::EVENT_MOVE_COLUMN: + $title = e('Column changed for task #%d', $event_data['task']['id']); + break; + case Task::EVENT_MOVE_POSITION: + $title = e('New position for task #%d', $event_data['task']['id']); + break; + case Task::EVENT_MOVE_SWIMLANE: + $title = e('Swimlane changed for task #%d', $event_data['task']['id']); + break; + case Task::EVENT_ASSIGNEE_CHANGE: + $title = e('Assignee changed on task #%d', $event_data['task']['id']); + break; + case Task::EVENT_OVERDUE: + $nb = count($event_data['tasks']); + $title = $nb > 1 ? e('%d overdue tasks', $nb) : e('Task #%d is overdue', $event_data['tasks'][0]['id']); + break; + default: + $title = e('Notification'); + } + + return $title; + } +} diff --git a/app/Model/NotificationType.php b/app/Model/NotificationType.php index e05cc686..bc9c6fdc 100644 --- a/app/Model/NotificationType.php +++ b/app/Model/NotificationType.php @@ -108,4 +108,20 @@ abstract class NotificationType extends Base { return $this->hiddens; } + + /** + * Keep only loaded notification types + * + * @access public + * @param string[] $types + * @return array + */ + public function filterTypes(array $types) + { + $classes = $this->classes; + + return array_filter($types, function($type) use ($classes) { + return isset($classes[$type]); + }); + } } diff --git a/app/Model/ProjectActivity.php b/app/Model/ProjectActivity.php index 032c1fa6..309bab9a 100644 --- a/app/Model/ProjectActivity.php +++ b/app/Model/ProjectActivity.php @@ -153,7 +153,7 @@ class ProjectActivity extends Base unset($event['data']); $event['author'] = $event['author_name'] ?: $event['author_username']; - $event['event_title'] = $this->getTitle($event); + $event['event_title'] = $this->notification->getTitleWithAuthor($event['author'], $event['event_name'], $event); $event['event_content'] = $this->getContent($event); } @@ -196,56 +196,6 @@ class ProjectActivity extends Base } /** - * Get the event title (translated) - * - * @access public - * @param array $event Event properties - * @return string - */ - public function getTitle(array $event) - { - switch ($event['event_name']) { - case Task::EVENT_ASSIGNEE_CHANGE: - $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: - return t('%s updated the task #%d', $event['author'], $event['task']['id']); - case Task::EVENT_CREATE: - return t('%s created the task #%d', $event['author'], $event['task']['id']); - case Task::EVENT_CLOSE: - return t('%s closed the task #%d', $event['author'], $event['task']['id']); - case Task::EVENT_OPEN: - return t('%s open the task #%d', $event['author'], $event['task']['id']); - case Task::EVENT_MOVE_COLUMN: - return t('%s moved the task #%d to the column "%s"', $event['author'], $event['task']['id'], $event['task']['column_title']); - case Task::EVENT_MOVE_POSITION: - return t('%s moved the task #%d to the position %d in the column "%s"', $event['author'], $event['task']['id'], $event['task']['position'], $event['task']['column_title']); - case Task::EVENT_MOVE_SWIMLANE: - if ($event['task']['swimlane_id'] == 0) { - return t('%s moved the task #%d to the first swimlane', $event['author'], $event['task']['id']); - } - return t('%s moved the task #%d to the swimlane "%s"', $event['author'], $event['task']['id'], $event['task']['swimlane_name']); - case Subtask::EVENT_UPDATE: - return t('%s updated a subtask for the task #%d', $event['author'], $event['task']['id']); - case Subtask::EVENT_CREATE: - return t('%s created a subtask for the task #%d', $event['author'], $event['task']['id']); - case Comment::EVENT_UPDATE: - return t('%s updated a comment on the task #%d', $event['author'], $event['task']['id']); - case Comment::EVENT_CREATE: - return t('%s commented on the task #%d', $event['author'], $event['task']['id']); - case File::EVENT_CREATE: - return t('%s attached a file to the task #%d', $event['author'], $event['task']['id']); - default: - return ''; - } - } - - /** * Decode event data, supports unserialize() and json_decode() * * @access public diff --git a/app/Model/ProjectIntegration.php b/app/Model/ProjectIntegration.php deleted file mode 100644 index d07e4167..00000000 --- a/app/Model/ProjectIntegration.php +++ /dev/null @@ -1,66 +0,0 @@ -<?php - -namespace Kanboard\Model; - -/** - * Project integration - * - * @package model - * @author Frederic Guillot - */ -class ProjectIntegration extends Base -{ - /** - * SQL table name - * - * @var string - */ - const TABLE = 'project_integrations'; - - /** - * Get all parameters for a project - * - * @access public - * @param integer $project_id - * @return array - */ - public function getParameters($project_id) - { - return $this->db->table(self::TABLE)->eq('project_id', $project_id)->findOne() ?: array(); - } - - /** - * Save parameters for a project - * - * @access public - * @param integer $project_id - * @param array $values - * @return boolean - */ - public function saveParameters($project_id, array $values) - { - if ($this->db->table(self::TABLE)->eq('project_id', $project_id)->exists()) { - return $this->db->table(self::TABLE)->eq('project_id', $project_id)->update($values); - } - - return $this->db->table(self::TABLE)->insert($values + array('project_id' => $project_id)); - } - - /** - * Check if a project has the given parameter/value - * - * @access public - * @param integer $project_id - * @param string $option - * @param string $value - * @return boolean - */ - public function hasValue($project_id, $option, $value) - { - return $this->db - ->table(self::TABLE) - ->eq('project_id', $project_id) - ->eq($option, $value) - ->exists(); - } -} diff --git a/app/Model/ProjectNotification.php b/app/Model/ProjectNotification.php index 49fcc61d..a355902f 100644 --- a/app/Model/ProjectNotification.php +++ b/app/Model/ProjectNotification.php @@ -22,8 +22,44 @@ class ProjectNotification extends Base { $project = $this->project->getById($project_id); - foreach ($this->projectNotificationType->getSelectedTypes($project_id) as $type) { + $types = array_merge( + $this->projectNotificationType->getHiddenTypes(), + $this->projectNotificationType->getSelectedTypes($project_id) + ); + + foreach ($types as $type) { $this->projectNotificationType->getType($type)->notifyProject($project, $event_name, $event_data); } } + + /** + * Save settings for the given project + * + * @access public + * @param integer $project_id + * @param array $values + */ + public function saveSettings($project_id, array $values) + { + $this->db->startTransaction(); + + $types = empty($values['notification_types']) ? array() : array_keys($values['notification_types']); + $this->projectNotificationType->saveSelectedTypes($project_id, $types); + + $this->db->closeTransaction(); + } + + /** + * Read user settings to display the form + * + * @access public + * @param integer $project_id + * @return array + */ + public function readSettings($project_id) + { + return array( + 'notification_types' => $this->projectNotificationType->getSelectedTypes($project_id), + ); + } } diff --git a/app/Model/ProjectNotificationType.php b/app/Model/ProjectNotificationType.php index d8568589..a4719598 100644 --- a/app/Model/ProjectNotificationType.php +++ b/app/Model/ProjectNotificationType.php @@ -26,13 +26,13 @@ class ProjectNotificationType extends NotificationType */ public function getSelectedTypes($project_id) { - $selectedTypes = $this->db + $types = $this->db ->table(self::TABLE) ->eq('project_id', $project_id) ->asc('notification_type') ->findAllByColumn('notification_type'); - return array_merge($this->getHiddenTypes(), $selectedTypes); + return $this->filterTypes($types); } /** @@ -52,6 +52,6 @@ class ProjectNotificationType extends NotificationType $results[] = $this->db->table(self::TABLE)->insert(array('project_id' => $project_id, 'notification_type' => $type)); } - return ! in_array(false, $results); + return ! in_array(false, $results, true); } } diff --git a/app/Model/UserNotificationType.php b/app/Model/UserNotificationType.php index d2613440..89beb480 100644 --- a/app/Model/UserNotificationType.php +++ b/app/Model/UserNotificationType.php @@ -26,7 +26,8 @@ class UserNotificationType extends NotificationType */ public function getSelectedTypes($user_id) { - return $this->db->table(self::TABLE)->eq('user_id', $user_id)->asc('notification_type')->findAllByColumn('notification_type'); + $types = $this->db->table(self::TABLE)->eq('user_id', $user_id)->asc('notification_type')->findAllByColumn('notification_type'); + return $this->filterTypes($types); } /** @@ -46,6 +47,6 @@ class UserNotificationType extends NotificationType $results[] = $this->db->table(self::TABLE)->insert(array('user_id' => $user_id, 'notification_type' => $type)); } - return ! in_array(false, $results); + return ! in_array(false, $results, true); } } diff --git a/app/Model/UserUnreadNotification.php b/app/Model/UserUnreadNotification.php index 98a337a2..cc0f326a 100644 --- a/app/Model/UserUnreadNotification.php +++ b/app/Model/UserUnreadNotification.php @@ -48,7 +48,7 @@ class UserUnreadNotification extends Base foreach ($events as &$event) { $event['event_data'] = json_decode($event['event_data'], true); - $event['title'] = $this->getTitleFromEvent($event['event_name'], $event['event_data']); + $event['title'] = $this->notification->getTitleWithoutAuthor($event['event_name'], $event['event_data']); } return $events; @@ -90,65 +90,4 @@ class UserUnreadNotification extends Base { return $this->db->table(self::TABLE)->eq('user_id', $user_id)->exists(); } - - /** - * Get title from event - * - * @access public - * @param string $event_name - * @param array $event_data - * @return string - */ - public function getTitleFromEvent($event_name, array $event_data) - { - switch ($event_name) { - case File::EVENT_CREATE: - $title = t('New attachment on task #%d: %s', $event_data['file']['task_id'], $event_data['file']['name']); - break; - case Comment::EVENT_CREATE: - $title = t('New comment on task #%d', $event_data['comment']['task_id']); - break; - case Comment::EVENT_UPDATE: - $title = t('Comment updated on task #%d', $event_data['comment']['task_id']); - break; - case Subtask::EVENT_CREATE: - $title = t('New subtask on task #%d', $event_data['subtask']['task_id']); - break; - case Subtask::EVENT_UPDATE: - $title = t('Subtask updated on task #%d', $event_data['subtask']['task_id']); - break; - case Task::EVENT_CREATE: - $title = t('New task #%d: %s', $event_data['task']['id'], $event_data['task']['title']); - break; - case Task::EVENT_UPDATE: - $title = t('Task updated #%d', $event_data['task']['id']); - break; - case Task::EVENT_CLOSE: - $title = t('Task #%d closed', $event_data['task']['id']); - break; - case Task::EVENT_OPEN: - $title = t('Task #%d opened', $event_data['task']['id']); - break; - case Task::EVENT_MOVE_COLUMN: - $title = t('Column changed for task #%d', $event_data['task']['id']); - break; - case Task::EVENT_MOVE_POSITION: - $title = t('New position for task #%d', $event_data['task']['id']); - break; - case Task::EVENT_MOVE_SWIMLANE: - $title = t('Swimlane changed for task #%d', $event_data['task']['id']); - break; - case Task::EVENT_ASSIGNEE_CHANGE: - $title = t('Assignee changed on task #%d', $event_data['task']['id']); - break; - case Task::EVENT_OVERDUE: - $nb = count($event_data['tasks']); - $title = $nb > 1 ? t('%d overdue tasks', $nb) : t('Task #%d is overdue', $event_data['tasks'][0]['id']); - break; - default: - $title = e('Notification'); - } - - return $title; - } } diff --git a/app/Notification/ActivityStream.php b/app/Notification/ActivityStream.php index 65ae64b1..325732ec 100644 --- a/app/Notification/ActivityStream.php +++ b/app/Notification/ActivityStream.php @@ -35,7 +35,6 @@ class ActivityStream extends Base implements NotificationInterface public function notifyProject(array $project, $event_name, array $event_data) { if ($this->userSession->isLogged()) { - $this->projectActivity->createEvent( $project['id'], $event_data['task']['id'], @@ -43,16 +42,6 @@ class ActivityStream extends Base implements NotificationInterface $event_name, $event_data ); - - // TODO: need to be moved to external plugins - foreach (array('slackWebhook', 'hipchatWebhook', 'jabber') as $model) { - $this->$model->notify( - $project['id'], - $event_data['task']['id'], - $event_name, - $event_data - ); - } } } } diff --git a/app/Schema/Mysql.php b/app/Schema/Mysql.php index b85c185e..d3c0d3b6 100644 --- a/app/Schema/Mysql.php +++ b/app/Schema/Mysql.php @@ -39,6 +39,23 @@ function version_93($pdo) UNIQUE(task_id, name) ) ENGINE=InnoDB CHARSET=utf8 "); + + $pdo->exec("DROP TABLE project_integrations"); + + $pdo->exec("DELETE FROM settings WHERE `option`='integration_jabber'"); + $pdo->exec("DELETE FROM settings WHERE `option`='integration_jabber_server'"); + $pdo->exec("DELETE FROM settings WHERE `option`='integration_jabber_domain'"); + $pdo->exec("DELETE FROM settings WHERE `option`='integration_jabber_username'"); + $pdo->exec("DELETE FROM settings WHERE `option`='integration_jabber_password'"); + $pdo->exec("DELETE FROM settings WHERE `option`='integration_jabber_nickname'"); + $pdo->exec("DELETE FROM settings WHERE `option`='integration_jabber_room'"); + $pdo->exec("DELETE FROM settings WHERE `option`='integration_hipchat'"); + $pdo->exec("DELETE FROM settings WHERE `option`='integration_hipchat_api_url'"); + $pdo->exec("DELETE FROM settings WHERE `option`='integration_hipchat_room_id'"); + $pdo->exec("DELETE FROM settings WHERE `option`='integration_hipchat_room_token'"); + $pdo->exec("DELETE FROM settings WHERE `option`='integration_slack_webhook'"); + $pdo->exec("DELETE FROM settings WHERE `option`='integration_slack_webhook_url'"); + $pdo->exec("DELETE FROM settings WHERE `option`='integration_slack_webhook_channel'"); } function version_92($pdo) diff --git a/app/Schema/Postgres.php b/app/Schema/Postgres.php index 1a399cfc..165b11d2 100644 --- a/app/Schema/Postgres.php +++ b/app/Schema/Postgres.php @@ -39,6 +39,23 @@ function version_73($pdo) UNIQUE(task_id, name) ) "); + + $pdo->exec("DROP TABLE project_integrations"); + + $pdo->exec("DELETE FROM settings WHERE \"option\"='integration_jabber'"); + $pdo->exec("DELETE FROM settings WHERE \"option\"='integration_jabber_server'"); + $pdo->exec("DELETE FROM settings WHERE \"option\"='integration_jabber_domain'"); + $pdo->exec("DELETE FROM settings WHERE \"option\"='integration_jabber_username'"); + $pdo->exec("DELETE FROM settings WHERE \"option\"='integration_jabber_password'"); + $pdo->exec("DELETE FROM settings WHERE \"option\"='integration_jabber_nickname'"); + $pdo->exec("DELETE FROM settings WHERE \"option\"='integration_jabber_room'"); + $pdo->exec("DELETE FROM settings WHERE \"option\"='integration_hipchat'"); + $pdo->exec("DELETE FROM settings WHERE \"option\"='integration_hipchat_api_url'"); + $pdo->exec("DELETE FROM settings WHERE \"option\"='integration_hipchat_room_id'"); + $pdo->exec("DELETE FROM settings WHERE \"option\"='integration_hipchat_room_token'"); + $pdo->exec("DELETE FROM settings WHERE \"option\"='integration_slack_webhook'"); + $pdo->exec("DELETE FROM settings WHERE \"option\"='integration_slack_webhook_url'"); + $pdo->exec("DELETE FROM settings WHERE \"option\"='integration_slack_webhook_channel'"); } function version_72($pdo) diff --git a/app/Schema/Sqlite.php b/app/Schema/Sqlite.php index 1a60443f..e8dcf50e 100644 --- a/app/Schema/Sqlite.php +++ b/app/Schema/Sqlite.php @@ -39,6 +39,23 @@ function version_88($pdo) UNIQUE(task_id, name) ) "); + + $pdo->exec("DROP TABLE project_integrations"); + + $pdo->exec("DELETE FROM settings WHERE \"option\"='integration_jabber'"); + $pdo->exec("DELETE FROM settings WHERE \"option\"='integration_jabber_server'"); + $pdo->exec("DELETE FROM settings WHERE \"option\"='integration_jabber_domain'"); + $pdo->exec("DELETE FROM settings WHERE \"option\"='integration_jabber_username'"); + $pdo->exec("DELETE FROM settings WHERE \"option\"='integration_jabber_password'"); + $pdo->exec("DELETE FROM settings WHERE \"option\"='integration_jabber_nickname'"); + $pdo->exec("DELETE FROM settings WHERE \"option\"='integration_jabber_room'"); + $pdo->exec("DELETE FROM settings WHERE \"option\"='integration_hipchat'"); + $pdo->exec("DELETE FROM settings WHERE \"option\"='integration_hipchat_api_url'"); + $pdo->exec("DELETE FROM settings WHERE \"option\"='integration_hipchat_room_id'"); + $pdo->exec("DELETE FROM settings WHERE \"option\"='integration_hipchat_room_token'"); + $pdo->exec("DELETE FROM settings WHERE \"option\"='integration_slack_webhook'"); + $pdo->exec("DELETE FROM settings WHERE \"option\"='integration_slack_webhook_url'"); + $pdo->exec("DELETE FROM settings WHERE \"option\"='integration_slack_webhook_channel'"); } function version_87($pdo) diff --git a/app/ServiceProvider/ClassProvider.php b/app/ServiceProvider/ClassProvider.php index e50a6297..c103d639 100644 --- a/app/ServiceProvider/ClassProvider.php +++ b/app/ServiceProvider/ClassProvider.php @@ -31,6 +31,7 @@ class ClassProvider implements ServiceProviderInterface 'File', 'LastLogin', 'Link', + 'Notification', 'OverdueNotification', 'Project', 'ProjectActivity', @@ -38,7 +39,6 @@ class ClassProvider implements ServiceProviderInterface 'ProjectDuplication', 'ProjectDailyColumnStats', 'ProjectDailyStats', - 'ProjectIntegration', 'ProjectPermission', 'ProjectNotification', 'ProjectMetadata', @@ -98,9 +98,6 @@ class ClassProvider implements ServiceProviderInterface 'BitbucketWebhook', 'GithubWebhook', 'GitlabWebhook', - 'HipchatWebhook', - 'Jabber', - 'SlackWebhook', ) ); diff --git a/app/Template/config/integrations.php b/app/Template/config/integrations.php index b454fa86..bba85672 100644 --- a/app/Template/config/integrations.php +++ b/app/Template/config/integrations.php @@ -31,60 +31,6 @@ <?= $this->form->checkbox('integration_gravatar', t('Enable Gravatar images'), 1, $values['integration_gravatar'] == 1) ?> </div> - <h3><img src="<?= $this->url->dir() ?>assets/img/jabber-icon.png"/> <?= t('Jabber (XMPP)') ?></h3> - <div class="listing"> - <?= $this->form->checkbox('integration_jabber', t('Send notifications to Jabber'), 1, $values['integration_jabber'] == 1) ?> - - <?= $this->form->label(t('XMPP server address'), 'integration_jabber_server') ?> - <?= $this->form->text('integration_jabber_server', $values, $errors, array('placeholder="tcp://myserver:5222"')) ?> - <p class="form-help"><?= t('The server address must use this format: "tcp://hostname:5222"') ?></p> - - <?= $this->form->label(t('Jabber domain'), 'integration_jabber_domain') ?> - <?= $this->form->text('integration_jabber_domain', $values, $errors, array('placeholder="example.com"')) ?> - - <?= $this->form->label(t('Username'), 'integration_jabber_username') ?> - <?= $this->form->text('integration_jabber_username', $values, $errors) ?> - - <?= $this->form->label(t('Password'), 'integration_jabber_password') ?> - <?= $this->form->password('integration_jabber_password', $values, $errors) ?> - - <?= $this->form->label(t('Jabber nickname'), 'integration_jabber_nickname') ?> - <?= $this->form->text('integration_jabber_nickname', $values, $errors) ?> - - <?= $this->form->label(t('Multi-user chat room'), 'integration_jabber_room') ?> - <?= $this->form->text('integration_jabber_room', $values, $errors, array('placeholder="myroom@conference.example.com"')) ?> - - <p class="form-help"><?= $this->url->doc(t('Help on Jabber integration'), 'jabber') ?></p> - </div> - - <h3><img src="<?= $this->url->dir() ?>assets/img/hipchat-icon.png"/> <?= t('Hipchat') ?></h3> - <div class="listing"> - <?= $this->form->checkbox('integration_hipchat', t('Send notifications to Hipchat'), 1, $values['integration_hipchat'] == 1) ?> - - <?= $this->form->label(t('API URL'), 'integration_hipchat_api_url') ?> - <?= $this->form->text('integration_hipchat_api_url', $values, $errors) ?> - - <?= $this->form->label(t('Room API ID or name'), 'integration_hipchat_room_id') ?> - <?= $this->form->text('integration_hipchat_room_id', $values, $errors) ?> - - <?= $this->form->label(t('Room notification token'), 'integration_hipchat_room_token') ?> - <?= $this->form->text('integration_hipchat_room_token', $values, $errors) ?> - - <p class="form-help"><?= $this->url->doc(t('Help on Hipchat integration'), 'hipchat') ?></p> - </div> - - <h3><i class="fa fa-slack fa-fw"></i> <?= t('Slack') ?></h3> - <div class="listing"> - <?= $this->form->checkbox('integration_slack_webhook', t('Send notifications to a Slack channel'), 1, $values['integration_slack_webhook'] == 1) ?> - - <?= $this->form->label(t('Webhook URL'), 'integration_slack_webhook_url') ?> - <?= $this->form->text('integration_slack_webhook_url', $values, $errors) ?> - <?= $this->form->label(t('Channel/Group/User (Optional)'), 'integration_slack_webhook_channel') ?> - <?= $this->form->text('integration_slack_webhook_channel', $values, $errors) ?> - - <p class="form-help"><?= $this->url->doc(t('Help on Slack integration'), 'slack') ?></p> - </div> - <div class="form-actions"> <input type="submit" value="<?= t('Save') ?>" class="btn btn-blue"/> </div> diff --git a/app/Template/project/integrations.php b/app/Template/project/integrations.php index eb5faddf..c4d9385b 100644 --- a/app/Template/project/integrations.php +++ b/app/Template/project/integrations.php @@ -2,9 +2,10 @@ <h2><?= t('Integration with third-party services') ?></h2> </div> -<form method="post" action="<?= $this->url->href('project', 'integration', array('project_id' => $project['id'])) ?>" autocomplete="off"> +<form method="post" action="<?= $this->url->href('project', 'integrations', array('project_id' => $project['id'])) ?>" autocomplete="off"> <?= $this->form->csrf() ?> + <?= $this->hook->render('template:project:integrations', array('values' => $values)) ?> <h3><i class="fa fa-github fa-fw"></i> <?= t('Github webhooks') ?></h3> <div class="listing"> @@ -12,86 +13,15 @@ <p class="form-help"><?= $this->url->doc(t('Help on Github webhooks'), 'github-webhooks') ?></p> </div> - <h3><img src="<?= $this->url->dir() ?>assets/img/gitlab-icon.png"/> <?= t('Gitlab webhooks') ?></h3> <div class="listing"> <input type="text" class="auto-select" readonly="readonly" value="<?= $this->url->href('webhook', 'gitlab', array('token' => $webhook_token, 'project_id' => $project['id']), false, '', true) ?>"/><br/> <p class="form-help"><?= $this->url->doc(t('Help on Gitlab webhooks'), 'gitlab-webhooks') ?></p> </div> - <h3><i class="fa fa-bitbucket fa-fw"></i> <?= t('Bitbucket webhooks') ?></h3> <div class="listing"> <input type="text" class="auto-select" readonly="readonly" value="<?= $this->url->href('webhook', 'bitbucket', array('token' => $webhook_token, 'project_id' => $project['id']), false, '', true) ?>"/><br/> <p class="form-help"><?= $this->url->doc(t('Help on Bitbucket webhooks'), 'bitbucket-webhooks') ?></p> </div> - - - <h3><img src="<?= $this->url->dir() ?>assets/img/jabber-icon.png"/> <?= t('Jabber (XMPP)') ?></h3> - <div class="listing"> - <?= $this->form->checkbox('jabber', t('Send notifications to Jabber'), 1, isset($values['jabber']) && $values['jabber'] == 1) ?> - - <?= $this->form->label(t('XMPP server address'), 'jabber_server') ?> - <?= $this->form->text('jabber_server', $values, $errors, array('placeholder="tcp://myserver:5222"')) ?> - <p class="form-help"><?= t('The server address must use this format: "tcp://hostname:5222"') ?></p> - - <?= $this->form->label(t('Jabber domain'), 'jabber_domain') ?> - <?= $this->form->text('jabber_domain', $values, $errors, array('placeholder="example.com"')) ?> - - <?= $this->form->label(t('Username'), 'jabber_username') ?> - <?= $this->form->text('jabber_username', $values, $errors) ?> - - <?= $this->form->label(t('Password'), 'jabber_password') ?> - <?= $this->form->password('jabber_password', $values, $errors) ?> - - <?= $this->form->label(t('Jabber nickname'), 'jabber_nickname') ?> - <?= $this->form->text('jabber_nickname', $values, $errors) ?> - - <?= $this->form->label(t('Multi-user chat room'), 'jabber_room') ?> - <?= $this->form->text('jabber_room', $values, $errors, array('placeholder="myroom@conference.example.com"')) ?> - - <p class="form-help"><?= $this->url->doc(t('Help on Jabber integration'), 'jabber') ?></p> - - <div class="form-actions"> - <input type="submit" value="<?= t('Save') ?>" class="btn btn-blue"/> - </div> - </div> - - - <h3><img src="<?= $this->url->dir() ?>assets/img/hipchat-icon.png"/> <?= t('Hipchat') ?></h3> - <div class="listing"> - <?= $this->form->checkbox('hipchat', t('Send notifications to Hipchat'), 1, isset($values['hipchat']) && $values['hipchat'] == 1) ?> - - <?= $this->form->label(t('API URL'), 'hipchat_api_url') ?> - <?= $this->form->text('hipchat_api_url', $values, $errors) ?> - - <?= $this->form->label(t('Room API ID or name'), 'hipchat_room_id') ?> - <?= $this->form->text('hipchat_room_id', $values, $errors) ?> - - <?= $this->form->label(t('Room notification token'), 'hipchat_room_token') ?> - <?= $this->form->text('hipchat_room_token', $values, $errors) ?> - - <p class="form-help"><?= $this->url->doc(t('Help on Hipchat integration'), 'hipchat') ?></a></p> - - <div class="form-actions"> - <input type="submit" value="<?= t('Save') ?>" class="btn btn-blue"/> - </div> - </div> - - - <h3><i class="fa fa-slack fa-fw"></i> <?= t('Slack') ?></h3> - <div class="listing"> - <?= $this->form->checkbox('slack', t('Send notifications to a Slack channel'), 1, isset($values['slack']) && $values['slack'] == 1) ?> - - <?= $this->form->label(t('Webhook URL'), 'slack_webhook_url') ?> - <?= $this->form->text('slack_webhook_url', $values, $errors) ?> - <?= $this->form->label(t('Channel/Group/User (Optional)'), 'slack_webhook_channel') ?> - <?= $this->form->text('slack_webhook_channel', $values, $errors) ?> - - <p class="form-help"><?= $this->url->doc(t('Help on Slack integration'), 'slack') ?></p> - - <div class="form-actions"> - <input type="submit" value="<?= t('Save') ?>" class="btn btn-blue"/> - </div> - </div> </form>
\ No newline at end of file diff --git a/app/Template/project/notifications.php b/app/Template/project/notifications.php new file mode 100644 index 00000000..ac743087 --- /dev/null +++ b/app/Template/project/notifications.php @@ -0,0 +1,20 @@ +<div class="page-header"> + <h2><?= t('Notifications') ?></h2> +</div> +<?php if (empty($types)): ?> + <p class="alert"><?= t('There is no notification method registered.') ?></p> +<?php else: ?> + <form method="post" action="<?= $this->url->href('project', 'notifications', array('project_id' => $project['id'])) ?>" autocomplete="off"> + + <?= $this->form->csrf() ?> + + <h4><?= t('Notification methods:') ?></h4> + <?= $this->form->checkboxes('notification_types', $types, $notifications) ?> + + <div class="form-actions"> + <input type="submit" value="<?= t('Save') ?>" class="btn btn-blue"/> + <?= t('or') ?> + <?= $this->url->link(t('cancel'), 'project', 'show', array('project_id' => $project['id'])) ?> + </div> + </form> +<?php endif ?>
\ No newline at end of file diff --git a/app/Template/project/sidebar.php b/app/Template/project/sidebar.php index 971ed950..fb5dd3bd 100644 --- a/app/Template/project/sidebar.php +++ b/app/Template/project/sidebar.php @@ -12,8 +12,11 @@ <li <?= $this->app->getRouterController() === 'project' && $this->app->getRouterAction() === 'share' ? 'class="active"' : '' ?>> <?= $this->url->link(t('Public access'), 'project', 'share', array('project_id' => $project['id'])) ?> </li> - <li <?= $this->app->getRouterController() === 'project' && $this->app->getRouterAction() === 'integration' ? 'class="active"' : '' ?>> - <?= $this->url->link(t('Integrations'), 'project', 'integration', array('project_id' => $project['id'])) ?> + <li <?= $this->app->getRouterController() === 'project' && $this->app->getRouterAction() === 'notifications' ? 'class="active"' : '' ?>> + <?= $this->url->link(t('Notifications'), 'project', 'notifications', array('project_id' => $project['id'])) ?> + </li> + <li <?= $this->app->getRouterController() === 'project' && $this->app->getRouterAction() === 'integrations' ? 'class="active"' : '' ?>> + <?= $this->url->link(t('Integrations'), 'project', 'integrations', array('project_id' => $project['id'])) ?> </li> <li <?= $this->app->getRouterController() === 'project' && $this->app->getRouterAction() === 'edit' ? 'class="active"' : '' ?>> <?= $this->url->link(t('Edit project'), 'project', 'edit', array('project_id' => $project['id'])) ?> diff --git a/app/Template/user/integrations.php b/app/Template/user/integrations.php new file mode 100644 index 00000000..ef9d8e71 --- /dev/null +++ b/app/Template/user/integrations.php @@ -0,0 +1,13 @@ +<div class="page-header"> + <h2><?= t('Integrations') ?></h2> +</div> + +<form method="post" action="<?= $this->url->href('user', 'integrations', array('user_id' => $user['id'])) ?>" autocomplete="off"> + <?= $this->form->csrf() ?> + <?php $hooks = $this->hook->render('template:user:integrations', array('values' => $values)) ?> + <?php if (! empty($hooks)): ?> + <?= $hooks ?> + <?php else: ?> + <p class="alert"><?= t('No external integration registered.') ?></p> + <?php endif ?> +</form> diff --git a/app/Template/user/sidebar.php b/app/Template/user/sidebar.php index ca1e0621..167c8054 100644 --- a/app/Template/user/sidebar.php +++ b/app/Template/user/sidebar.php @@ -56,6 +56,9 @@ <li <?= $this->app->getRouterController() === 'user' && $this->app->getRouterAction() === 'external' ? 'class="active"' : '' ?>> <?= $this->url->link(t('External accounts'), 'user', 'external', array('user_id' => $user['id'])) ?> </li> + <li <?= $this->app->getRouterController() === 'user' && $this->app->getRouterAction() === 'integrations' ? 'class="active"' : '' ?>> + <?= $this->url->link(t('Integrations'), 'user', 'integrations', array('user_id' => $user['id'])) ?> + </li> <?php endif ?> <?php if ($this->user->isAdmin()): ?> diff --git a/assets/img/hipchat-icon.png b/assets/img/hipchat-icon.png Binary files differdeleted file mode 100644 index 1b0a825f..00000000 --- a/assets/img/hipchat-icon.png +++ /dev/null diff --git a/assets/img/jabber-icon.png b/assets/img/jabber-icon.png Binary files differdeleted file mode 100644 index 00832279..00000000 --- a/assets/img/jabber-icon.png +++ /dev/null diff --git a/doc/fr/notifications.markdown b/doc/fr/notifications.markdown index 7d85087a..2190f317 100644 --- a/doc/fr/notifications.markdown +++ b/doc/fr/notifications.markdown @@ -4,12 +4,9 @@ Notifications Kanboard est capable d'envoyer des notifications via différents canaux : - Email -- Jabber/XMPP -- Hipchat -- Slack +- Web (Liste de message non lus) -En fait, pour Jabber/Hipchat/Slack les notifications sont envoyées dans des salons de discussion car ils sont configurés au niveau projet. -Cependant, les notifications par email sont envoyées à un individu. +Vous pouvez ajouter d'autres cannaux an ajoutant des extensions comme par exemple Hipchat, Slack ou encore Jabber. Configuration -------------- @@ -26,7 +23,7 @@ Vous pouvez choisir votre méthode favorite de notification : - Web Pour chaque projet dont vous êtes membre, vous pouvez choisir de recevoir des notifications pour : - + - Toutes les tâches - Seulement les tâches qui vous sont assignées - Seulement les tâches que vous avez créées @@ -41,7 +38,7 @@ Les notifications web sont accéssibles depuis le tableau de bord ou depuis l'ic ![Icône des notifications web](http://kanboard.net/screenshots/documentation/web-notifications-icon.png) -Les notifications sont affichés sous forme de liste. Vous pouvez marquer comme lu chacune d'entre-elle ou toutes en même temps. +Les notifications sont affichés sous forme de liste. Vous pouvez marquer comme lu chacune d'entre-elle ou toutes en même temps. ![Notifications web](http://kanboard.net/screenshots/documentation/web-notifications.png) diff --git a/doc/hipchat.markdown b/doc/hipchat.markdown deleted file mode 100644 index 66cf9fdc..00000000 --- a/doc/hipchat.markdown +++ /dev/null @@ -1,38 +0,0 @@ -Hipchat integration -=================== - -You can send notifications to Hipchat for all projects or only for specific projects. - -- To send notifications for all projects, go to **Settings > Integrations > Hipchat** -- To send notifications for only some projects, go to **Project settings > Integrations > Hipchat** - -Each project can send notifications to a separate room. - -Send notifications to a room ------------------------------ - -Example of notifications: - -![Hipchat notification](http://kanboard.net/screenshots/documentation/hipchat-notification.png) - -This feature use the room notification token system of Hipchat. - -### Hipchat configuration - -![Hipchat room token](http://kanboard.net/screenshots/documentation/hipchat-room-token.png) - -1. Go to to **My account** -2. Click on the tab **Rooms** and select the room you want to send the notifications -3. On the left, choose **Tokens** -4. Enter a label, by example "Kanboard" and save - -### Kanboard configuration - -![Hipchat settings](http://kanboard.net/screenshots/documentation/hipchat-settings.png) - -1. Go to **Settings > Integrations > Hipchat** or **Project settings > Integrations > Hipchat** -2. Replace the API url if you use the self-hosted version of Hipchat -3. Set the room name or the room API ID -4. Copy and paste the token generated previously - -Now, Kanboard events will be sent to the Hipchat room. diff --git a/doc/index.markdown b/doc/index.markdown index 86b5b7fc..3c0cae97 100644 --- a/doc/index.markdown +++ b/doc/index.markdown @@ -66,9 +66,6 @@ Using Kanboard - [Bitbucket webhooks](bitbucket-webhooks.markdown) - [Github webhooks](github-webhooks.markdown) - [Gitlab webhooks](gitlab-webhooks.markdown) -- [Hipchat](hipchat.markdown) -- [Jabber](jabber.markdown) -- [Slack](slack.markdown) - [iCalendar subscriptions](ical.markdown) - [RSS/Atom subscriptions](rss.markdown) - [Json-RPC API](api-json-rpc.markdown) diff --git a/doc/jabber.markdown b/doc/jabber.markdown deleted file mode 100644 index fe365168..00000000 --- a/doc/jabber.markdown +++ /dev/null @@ -1,34 +0,0 @@ -Jabber/XMPP integration -======================= - -You can send notifications to a Jabber room for all projects or only for specific projects. - -- To send notifications for all projects, go to **Settings > Integrations > Jabber** -- To send notifications for only some projects, go to **Project settings > Integrations > Jabber** - -Each project can send notifications to a separate room. - -## Example of notification - -Here an example with the Jabber client Adium: - -![Jabber notification](http://kanboard.net/screenshots/documentation/jabber-notification.png) - -## Configuration - -![Jabber settings](http://kanboard.net/screenshots/documentation/jabber-settings.png) - -1. Go to **Settings > Integrations > Jabber** or **Project settings > Integrations > Jabber** -2. **XMPP server address**: URL of the XMPP server, example: **tcp://172.28.128.3:5222** -3. **Jabber domain**: The **"to"** attribute of the XMPP protocol, example: **example.com** -4. **Username**: The Jabber username used by Kanboard, example: **kanboard** -5. **Password**: The Jabber password -6. **Jabber nickname**: The nickname used to connect to the room -7. **Multi-user chat room**: The address of the room, example: **demo@conference.example.com** - -Now, Kanboard events will be sent to the Jabber conference room. - -## Troubleshooting - -- Enable the debug mode -- All connection errors with the XMPP server are recorded in the log files `data/debug.log` or syslog diff --git a/doc/notifications.markdown b/doc/notifications.markdown index 937060da..55ba94bb 100644 --- a/doc/notifications.markdown +++ b/doc/notifications.markdown @@ -4,14 +4,9 @@ Notifications Kanboard is able to send notifications through several channels: - Email -- Web -- Jabber/XMPP -- Hipchat -- Slack +- Web (List of unread messages) -Actually, Jabber/Hipchat/Slack notifications are sent to a room or group channel because they are configured at the project level. - -However, email or web notifications are sent to an individual person. +External plugins allow you to send notifications to Slack, Hipchat, Jabber or any chat system. Configuration ------------- diff --git a/doc/plugin-hooks.markdown b/doc/plugin-hooks.markdown index eca8c14a..95d1a55f 100644 --- a/doc/plugin-hooks.markdown +++ b/doc/plugin-hooks.markdown @@ -134,6 +134,8 @@ List of template hooks: - `template:dashboard:sidebar` - `template:config:sidebar` - `template:config:integrations` +- `template:project:integrations` +- `template:user:integrations` - `template:export:sidebar` - `template:layout:head` - `template:layout:top` diff --git a/doc/plugin-notifications.markdown b/doc/plugin-notifications.markdown new file mode 100644 index 00000000..83fdb5e3 --- /dev/null +++ b/doc/plugin-notifications.markdown @@ -0,0 +1,60 @@ +Add Notification Types with Plugins +=================================== + +You can send notifications to almost any system by adding a new type. +There are two kinds of notifications: project and user. + +- Project: Notifications configured at the project level +- User: Notifications sent individually and configured at the user profile + +Register a new notification type +-------------------------------- + +In your plugin registration file call the method `setType()`: + +```php +$this->userNotificationType->setType('irc', t('IRC'), '\Kanboard\Plugin\IRC\Notification\IrcHandler'); +$this->projectNotificationType->setType('irc', t('IRC'), '\Kanboard\Plugin\IRC\Notification\IrcHandler'); +``` + +Your handler can be registered for user or project notification. You don't necessary need to support both. + +When your handler is registered, the end-user can choose to receive the new notification type or not. + +Notification Handler +-------------------- + +Your notification handler must implements the interface `Kanboard\Notification\NotificationInterface`: + +```php +interface NotificationInterface +{ + /** + * Send notification to a user + * + * @access public + * @param array $user + * @param string $event_name + * @param array $event_data + */ + public function notifyUser(array $user, $event_name, array $event_data); + + /** + * Send notification to a project + * + * @access public + * @param array $project + * @param string $event_name + * @param array $event_data + */ + public function notifyProject(array $project, $event_name, array $event_data); +} +``` + +Example of notification plugins +------------------------------- + +- [Slack](https://github.com/kanboard/plugin-slack) +- [Hipchat](https://github.com/kanboard/plugin-hipchat) +- [Jabber](https://github.com/kanboard/plugin-jabber) + diff --git a/doc/plugin-registration.markdown b/doc/plugin-registration.markdown index 50bfaff2..312f61b9 100644 --- a/doc/plugin-registration.markdown +++ b/doc/plugin-registration.markdown @@ -156,8 +156,8 @@ class Plugin extends Base public function initialize() { $this->action->extendActions( - '\Kanboard\Plugin\AutomaticAction\Action\SendSlackMessage', // Use absolute namespace - t('Send a message to Slack when the task color change') + '\Kanboard\Plugin\AutomaticAction\Action\DoSomething', // Use absolute namespace + t('Do something when the task color change') ); } } diff --git a/doc/plugins.markdown b/doc/plugins.markdown index 39a1caec..89629a35 100644 --- a/doc/plugins.markdown +++ b/doc/plugins.markdown @@ -12,10 +12,14 @@ Plugin creators should specify explicitly the compatible versions of Kanboard. I - [Override default application behaviors](plugin-overrides.markdown) - [Add schema migrations for plugins](plugin-schema-migrations.markdown) - [Add mail transports](plugin-mail-transports.markdown) +- [Add notification types](plugin-notifications.markdown) Examples of plugins ------------------- +- [Slack](https://github.com/kanboard/plugin-slack) +- [Hipchat](https://github.com/kanboard/plugin-hipchat) +- [Jabber](https://github.com/kanboard/plugin-jabber) - [Sendgrid](https://github.com/kanboard/plugin-sendgrid) - [Mailgun](https://github.com/kanboard/plugin-mailgun) - [Postmark](https://github.com/kanboard/plugin-postmark) diff --git a/doc/slack.markdown b/doc/slack.markdown deleted file mode 100644 index f90464e8..00000000 --- a/doc/slack.markdown +++ /dev/null @@ -1,38 +0,0 @@ -Slack integration -================= - -You can send notifications to Slack for all projects or only for specific projects. - -- To send notifications for all projects, go to **Settings > Integrations > Slack** -- To send notifications for only some projects, go to **Project settings > Integrations > Slack** - -Each project can send notifications to a separate channel. - -Send notifications to a channel -------------------------------- - -Example of notifications: - -![Slack notification](http://kanboard.net/screenshots/documentation/slack-notification.png) - -This feature use the [Incoming webhook](https://api.slack.com/incoming-webhooks) system of Slack. - -### Slack configuration - -![Slack webhook creation](http://kanboard.net/screenshots/documentation/slack-add-incoming-webhook.png) - -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** or **Project settings > Integrations > Slack** - -Now, Kanboard events will be sent to the Slack channel. - -### Overriding Channel (Optional) - -Optionally you can override the channel, private group or send direct messages by filling up **Channel/Group/User** text box. Leaving it empty will post to the channel configured during webhook configuration. - -Examples: - -- Send messages to another channel: **#mychannel1** -- Send messages to a private group: **#myprivategroup1** -- Send messages directly to someone: **@anotheruser1** diff --git a/tests/units/Base.php b/tests/units/Base.php index 4a5b303f..89d0e2bf 100644 --- a/tests/units/Base.php +++ b/tests/units/Base.php @@ -91,7 +91,7 @@ abstract class Base extends PHPUnit_Framework_TestCase $this->container['userNotificationType'] = $this ->getMockBuilder('\Kanboard\Model\UserNotificationType') ->setConstructorArgs(array($this->container)) - ->setMethods(array('getType')) + ->setMethods(array('getType', 'getSelectedTypes')) ->getMock(); } diff --git a/tests/units/Integration/SlackWebhookTest.php b/tests/units/Integration/SlackWebhookTest.php deleted file mode 100644 index cf8c8645..00000000 --- a/tests/units/Integration/SlackWebhookTest.php +++ /dev/null @@ -1,377 +0,0 @@ -<?php - -require_once __DIR__.'/../Base.php'; - -use Kanboard\Integration\SlackWebhook; -use Kanboard\Model\Project; -use Kanboard\Model\Task; - -class SlackWebhookTest extends Base -{ - public function testIsActivatedFromGlobalConfig() - { - $slack = new SlackWebhook($this->container); - - $this->container['config'] = $this - ->getMockBuilder('\Kanboard\Model\Config') - ->setConstructorArgs(array($this->container)) - ->setMethods(array( - 'get', - )) - ->getMock(); - - $this->container['config'] - ->expects($this->once()) - ->method('get') - ->with($this->equalTo('integration_slack_webhook')) - ->will($this->returnValue(1)); - - $this->assertTrue($slack->isActivated(1)); - } - - public function testIsActivatedFromProjectConfig() - { - $slack = new SlackWebhook($this->container); - - $this->container['config'] = $this - ->getMockBuilder('\Kanboard\Model\Config') - ->setConstructorArgs(array($this->container)) - ->setMethods(array( - 'get', - )) - ->getMock(); - - $this->container['projectIntegration'] = $this - ->getMockBuilder('\Kanboard\Model\ProjectIntegration') - ->setConstructorArgs(array($this->container)) - ->setMethods(array( - 'hasValue', - )) - ->getMock(); - - $this->container['config'] - ->expects($this->once()) - ->method('get') - ->with($this->equalTo('integration_slack_webhook')) - ->will($this->returnValue(0)); - - $this->container['projectIntegration'] - ->expects($this->once()) - ->method('hasValue') - ->with( - $this->equalTo(1), - $this->equalTo('slack'), - $this->equalTo(1) - ) - ->will($this->returnValue(true)); - - $this->assertTrue($slack->isActivated(1)); - } - - public function testIsNotActivated() - { - $slack = new SlackWebhook($this->container); - - $this->container['config'] = $this - ->getMockBuilder('\Kanboard\Model\Config') - ->setConstructorArgs(array($this->container)) - ->setMethods(array( - 'get', - )) - ->getMock(); - - $this->container['projectIntegration'] = $this - ->getMockBuilder('\Kanboard\Model\ProjectIntegration') - ->setConstructorArgs(array($this->container)) - ->setMethods(array( - 'hasValue', - )) - ->getMock(); - - $this->container['config'] - ->expects($this->once()) - ->method('get') - ->with($this->equalTo('integration_slack_webhook')) - ->will($this->returnValue(0)); - - $this->container['projectIntegration'] - ->expects($this->once()) - ->method('hasValue') - ->with( - $this->equalTo(1), - $this->equalTo('slack'), - $this->equalTo(1) - ) - ->will($this->returnValue(false)); - - $this->assertFalse($slack->isActivated(1)); - } - - public function testGetChannelFromGlobalConfig() - { - $slack = new SlackWebhook($this->container); - - $this->container['config'] = $this - ->getMockBuilder('\Kanboard\Model\Config') - ->setConstructorArgs(array($this->container)) - ->setMethods(array( - 'get', - )) - ->getMock(); - - $this->container['config'] - ->expects($this->once()) - ->method('get') - ->with($this->equalTo('integration_slack_webhook_channel')) - ->will($this->returnValue('mychannel')); - - $this->assertEquals('mychannel', $slack->getChannel(1)); - } - - public function testGetChannelFromProjectConfig() - { - $slack = new SlackWebhook($this->container); - - $this->container['config'] = $this - ->getMockBuilder('\Kanboard\Model\Config') - ->setConstructorArgs(array($this->container)) - ->setMethods(array( - 'get', - )) - ->getMock(); - - $this->container['projectIntegration'] = $this - ->getMockBuilder('\Kanboard\Model\ProjectIntegration') - ->setConstructorArgs(array($this->container)) - ->setMethods(array( - 'getParameters', - )) - ->getMock(); - - $this->container['config'] - ->expects($this->once()) - ->method('get') - ->with($this->equalTo('integration_slack_webhook_channel')) - ->will($this->returnValue('')); - - $this->container['projectIntegration'] - ->expects($this->once()) - ->method('getParameters') - ->with($this->equalTo(1)) - ->will($this->returnValue(array('slack_webhook_channel' => 'my_project_channel'))); - - $this->assertEquals('my_project_channel', $slack->getChannel(1)); - } - - public function testGetWebhoookUrlFromGlobalConfig() - { - $slack = new SlackWebhook($this->container); - - $this->container['config'] = $this - ->getMockBuilder('\Kanboard\Model\Config') - ->setConstructorArgs(array($this->container)) - ->setMethods(array( - 'get', - )) - ->getMock(); - - $this->container['config'] - ->expects($this->at(0)) - ->method('get') - ->with($this->equalTo('integration_slack_webhook')) - ->will($this->returnValue(1)); - - $this->container['config'] - ->expects($this->at(1)) - ->method('get') - ->with($this->equalTo('integration_slack_webhook_url')) - ->will($this->returnValue('url')); - - $this->assertEquals('url', $slack->getWebhookUrl(1)); - } - - public function testGetWebhookUrlFromProjectConfig() - { - $slack = new SlackWebhook($this->container); - - $this->container['config'] = $this - ->getMockBuilder('\Kanboard\Model\Config') - ->setConstructorArgs(array($this->container)) - ->setMethods(array( - 'get', - )) - ->getMock(); - - $this->container['projectIntegration'] = $this - ->getMockBuilder('\Kanboard\Model\ProjectIntegration') - ->setConstructorArgs(array($this->container)) - ->setMethods(array( - 'getParameters', - )) - ->getMock(); - - $this->container['config'] - ->expects($this->once()) - ->method('get') - ->with($this->equalTo('integration_slack_webhook')) - ->will($this->returnValue(0)); - - $this->container['projectIntegration'] - ->expects($this->once()) - ->method('getParameters') - ->with($this->equalTo(1)) - ->will($this->returnValue(array('slack_webhook_url' => 'my_project_url'))); - - $this->assertEquals('my_project_url', $slack->getWebhookUrl(1)); - } - - public function testSendPayloadWithChannel() - { - $this->container['httpClient'] = $this - ->getMockBuilder('\Kanboard\Core\HttpClient') - ->setConstructorArgs(array($this->container)) - ->setMethods(array( - 'postJson', - )) - ->getMock(); - - $slack = $this - ->getMockBuilder('\Kanboard\Integration\SlackWebhook') - ->setConstructorArgs(array($this->container)) - ->setMethods(array( - 'getChannel', - 'getWebhookUrl', - )) - ->getMock(); - - $slack - ->expects($this->at(0)) - ->method('getChannel') - ->with( - $this->equalTo(1) - ) - ->will($this->returnValue('mychannel')); - - $slack - ->expects($this->at(1)) - ->method('getWebhookUrl') - ->with( - $this->equalTo(1) - ) - ->will($this->returnValue('url')); - - $this->container['httpClient'] - ->expects($this->once()) - ->method('postJson') - ->with( - $this->equalTo('url'), - $this->equalTo(array('text' => 'test', 'channel' => 'mychannel')) - ); - - $slack->sendPayload(1, array('text' => 'test')); - } - - public function testSendPayloadWithoutChannel() - { - $this->container['httpClient'] = $this - ->getMockBuilder('\Kanboard\Core\HttpClient') - ->setConstructorArgs(array($this->container)) - ->setMethods(array( - 'postJson', - )) - ->getMock(); - - $slack = $this - ->getMockBuilder('\Kanboard\Integration\SlackWebhook') - ->setConstructorArgs(array($this->container)) - ->setMethods(array( - 'getChannel', - 'getWebhookUrl', - )) - ->getMock(); - - $slack - ->expects($this->at(0)) - ->method('getChannel') - ->with( - $this->equalTo(1) - ) - ->will($this->returnValue('')); - - $slack - ->expects($this->at(1)) - ->method('getWebhookUrl') - ->with( - $this->equalTo(1) - ) - ->will($this->returnValue('url')); - - $this->container['httpClient'] - ->expects($this->once()) - ->method('postJson') - ->with( - $this->equalTo('url'), - $this->equalTo(array('text' => 'test')) - ); - - $slack->sendPayload(1, array('text' => 'test')); - } - - public function testSendMessage() - { - $message = 'test'; - - $payload = array( - 'text' => $message, - 'username' => 'Kanboard', - 'icon_url' => 'http://kanboard.net/assets/img/favicon.png', - ); - - $slack = $this - ->getMockBuilder('\Kanboard\Integration\SlackWebhook') - ->setConstructorArgs(array($this->container)) - ->setMethods(array( - 'sendPayload', - )) - ->getMock(); - - $slack - ->expects($this->once()) - ->method('sendPayload') - ->with( - $this->equalTo(1), - $this->equalTo($payload) - ); - - $slack->sendMessage(1, $message); - } - - public function testNotify() - { - $message = '*[foobar]* FooBar created the task #1 (task #1)'; - - $this->container['session']['user'] = array('username' => 'foobar', 'name' => 'FooBar'); - - $p = new Project($this->container); - $this->assertEquals(1, $p->create(array('name' => 'foobar'))); - $this->assertTrue($this->container['config']->save(array('integration_slack_webhook' => 1))); - - $slack = $this - ->getMockBuilder('\Kanboard\Integration\SlackWebhook') - ->setConstructorArgs(array($this->container)) - ->setMethods(array( - 'sendMessage', - )) - ->getMock(); - - $slack - ->expects($this->once()) - ->method('sendMessage') - ->with( - $this->equalTo(1), - $this->equalTo($message) - ); - - $slack->notify(1, 1, Task::EVENT_CREATE, array('task' => array('id' => 1, 'title' => 'task #1'))); - } -} diff --git a/tests/units/Model/NotificationTest.php b/tests/units/Model/NotificationTest.php new file mode 100644 index 00000000..7f9977ce --- /dev/null +++ b/tests/units/Model/NotificationTest.php @@ -0,0 +1,69 @@ +<?php + +require_once __DIR__.'/../Base.php'; + +use Kanboard\Model\TaskFinder; +use Kanboard\Model\TaskCreation; +use Kanboard\Model\Subtask; +use Kanboard\Model\Comment; +use Kanboard\Model\User; +use Kanboard\Model\File; +use Kanboard\Model\Task; +use Kanboard\Model\Project; +use Kanboard\Model\Notification; +use Kanboard\Subscriber\NotificationSubscriber; + +class NotificationTest extends Base +{ + public function testGetTitle() + { + $wn = new Notification($this->container); + $p = new Project($this->container); + $tf = new TaskFinder($this->container); + $tc = new TaskCreation($this->container); + $s = new Subtask($this->container); + $c = new Comment($this->container); + $f = new File($this->container); + + $this->assertEquals(1, $p->create(array('name' => 'test'))); + $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1))); + $this->assertEquals(1, $s->create(array('title' => 'test', 'task_id' => 1))); + $this->assertEquals(1, $c->create(array('comment' => 'test', 'task_id' => 1, 'user_id' => 1))); + $this->assertEquals(1, $f->create(1, 'test', 'blah', 123)); + + $task = $tf->getDetails(1); + $subtask = $s->getById(1, true); + $comment = $c->getById(1); + $file = $c->getById(1); + + $this->assertNotEmpty($task); + $this->assertNotEmpty($subtask); + $this->assertNotEmpty($comment); + $this->assertNotEmpty($file); + + foreach (NotificationSubscriber::getSubscribedEvents() as $event_name => $values) { + $title = $wn->getTitleWithoutAuthor($event_name, array( + 'task' => $task, + 'comment' => $comment, + 'subtask' => $subtask, + 'file' => $file, + 'changes' => array() + )); + + $this->assertNotEmpty($title); + + $title = $wn->getTitleWithAuthor('foobar', $event_name, array( + 'task' => $task, + 'comment' => $comment, + 'subtask' => $subtask, + 'file' => $file, + 'changes' => array() + )); + + $this->assertNotEmpty($title); + } + + $this->assertNotEmpty($wn->getTitleWithoutAuthor(Task::EVENT_OVERDUE, array('tasks' => array(array('id' => 1))))); + $this->assertNotEmpty($wn->getTitleWithoutAuthor('unkown', array())); + } +} diff --git a/tests/units/Model/ProjectActivityTest.php b/tests/units/Model/ProjectActivityTest.php index ead74e08..5a242cb2 100644 --- a/tests/units/Model/ProjectActivityTest.php +++ b/tests/units/Model/ProjectActivityTest.php @@ -10,49 +10,9 @@ use Kanboard\Model\Project; use Kanboard\Model\Subtask; use Kanboard\Model\Comment; use Kanboard\Model\File; -use Kanboard\Subscriber\NotificationSubscriber; class ProjectActivityTest extends Base { - public function testGetTitle() - { - $pa = new ProjectActivity($this->container); - $p = new Project($this->container); - $tf = new TaskFinder($this->container); - $tc = new TaskCreation($this->container); - $s = new Subtask($this->container); - $c = new Comment($this->container); - $f = new File($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'test'))); - $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1))); - $this->assertEquals(1, $s->create(array('title' => 'test', 'task_id' => 1))); - $this->assertEquals(1, $c->create(array('comment' => 'test', 'task_id' => 1, 'user_id' => 1))); - $this->assertEquals(1, $f->create(1, 'test', 'blah', 123)); - - $task = $tf->getDetails(1); - $subtask = $s->getById(1, true); - $comment = $c->getById(1); - $file = $c->getById(1); - - $this->assertNotEmpty($task); - $this->assertNotEmpty($subtask); - $this->assertNotEmpty($comment); - $this->assertNotEmpty($file); - - foreach (NotificationSubscriber::getSubscribedEvents() as $event_name => $listeners) { - $this->assertNotEmpty($pa->getTitle(array( - 'event_name' => $event_name, - 'task' => $task, - 'comment' => $comment, - 'subtask' => $subtask, - 'file' => $file, - 'author' => 'bob', - 'changes' => array()) - )); - } - } - public function testDecode() { $e = new ProjectActivity($this->container); diff --git a/tests/units/Model/ProjectNotificationTypeTest.php b/tests/units/Model/ProjectNotificationTypeTest.php index d03bffe0..71e2b964 100644 --- a/tests/units/Model/ProjectNotificationTypeTest.php +++ b/tests/units/Model/ProjectNotificationTypeTest.php @@ -32,10 +32,15 @@ class ProjectNotificationTypeTest extends Base // Hidden type $nt->setType('baz', 'Baz', 'Something3', true); - $this->assertEquals(array('baz'), $nt->getSelectedTypes(1)); + $this->assertEmpty($nt->getSelectedTypes(1)); - // User defined types + // User defined types but not registered $this->assertTrue($nt->saveSelectedTypes(1, array('foo', 'bar'))); - $this->assertEquals(array('baz', 'bar', 'foo'), $nt->getSelectedTypes(1)); + $this->assertEmpty($nt->getSelectedTypes(1)); + + // User defined types and registered + $nt->setType('bar', 'Bar', 'Something4'); + $nt->setType('foo', 'Foo', 'Something3'); + $this->assertEquals(array('bar', 'foo'), $nt->getSelectedTypes(1)); } } diff --git a/tests/units/Model/UserNotificationTest.php b/tests/units/Model/UserNotificationTest.php index 8d7dec60..729667de 100644 --- a/tests/units/Model/UserNotificationTest.php +++ b/tests/units/Model/UserNotificationTest.php @@ -50,6 +50,22 @@ class UserNotificationTest extends Base 'notification_projects' => array(), )); + $this->container['userNotificationType'] + ->expects($this->at(0)) + ->method('getSelectedTypes') + ->will($this->returnValue(array('email'))); + + $this->container['userNotificationType'] + ->expects($this->at(1)) + ->method('getSelectedTypes') + ->will($this->returnValue(array('email'))); + + $this->container['userNotificationType'] + ->expects($this->at(2)) + ->method('getSelectedTypes') + ->with($this->equalTo(1)) + ->will($this->returnValue(array('email', 'web'))); + $settings = $n->readSettings(1); $this->assertNotEmpty($settings); $this->assertEquals(1, $settings['notifications_enabled']); @@ -183,12 +199,17 @@ class UserNotificationTest extends Base $this->container['userNotificationType'] ->expects($this->at(0)) + ->method('getSelectedTypes') + ->will($this->returnValue(array('email', 'web'))); + + $this->container['userNotificationType'] + ->expects($this->at(1)) ->method('getType') ->with($this->equalTo('email')) ->will($this->returnValue($notifier)); $this->container['userNotificationType'] - ->expects($this->at(1)) + ->expects($this->at(2)) ->method('getType') ->with($this->equalTo('web')) ->will($this->returnValue($notifier)); diff --git a/tests/units/Model/UserNotificationTypeTest.php b/tests/units/Model/UserNotificationTypeTest.php index 6982e890..da22afef 100644 --- a/tests/units/Model/UserNotificationTypeTest.php +++ b/tests/units/Model/UserNotificationTypeTest.php @@ -19,12 +19,21 @@ class UserNotificationTypeTest extends Base public function testGetSelectedTypes() { $nt = new UserNotificationType($this->container); - $types = $nt->getSelectedTypes(1); - $this->assertEmpty($types); - $this->assertTrue($nt->saveSelectedTypes(1, array('email', 'web'))); - $types = $nt->getSelectedTypes(1); - $this->assertNotEmpty($types); - $this->assertEquals(array('email', 'web'), $types); + // No type defined + $this->assertEmpty($nt->getSelectedTypes(1)); + + // Hidden type + $nt->setType('baz', 'Baz', 'Something3', true); + $this->assertEmpty($nt->getSelectedTypes(1)); + + // User defined types but not registered + $this->assertTrue($nt->saveSelectedTypes(1, array('foo', 'bar'))); + $this->assertEmpty($nt->getSelectedTypes(1)); + + // User defined types and registered + $nt->setType('bar', 'Bar', 'Something4'); + $nt->setType('foo', 'Foo', 'Something3'); + $this->assertEquals(array('bar', 'foo'), $nt->getSelectedTypes(1)); } } diff --git a/tests/units/Model/UserUnreadNotificationTest.php b/tests/units/Model/UserUnreadNotificationTest.php index 130a6eba..bf274d95 100644 --- a/tests/units/Model/UserUnreadNotificationTest.php +++ b/tests/units/Model/UserUnreadNotificationTest.php @@ -11,52 +11,9 @@ use Kanboard\Model\File; use Kanboard\Model\Task; use Kanboard\Model\Project; use Kanboard\Model\UserUnreadNotification; -use Kanboard\Subscriber\NotificationSubscriber; class UserUnreadNotificationTest extends Base { - public function testGetTitle() - { - $wn = new UserUnreadNotification($this->container); - $p = new Project($this->container); - $tf = new TaskFinder($this->container); - $tc = new TaskCreation($this->container); - $s = new Subtask($this->container); - $c = new Comment($this->container); - $f = new File($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'test'))); - $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1))); - $this->assertEquals(1, $s->create(array('title' => 'test', 'task_id' => 1))); - $this->assertEquals(1, $c->create(array('comment' => 'test', 'task_id' => 1, 'user_id' => 1))); - $this->assertEquals(1, $f->create(1, 'test', 'blah', 123)); - - $task = $tf->getDetails(1); - $subtask = $s->getById(1, true); - $comment = $c->getById(1); - $file = $c->getById(1); - - $this->assertNotEmpty($task); - $this->assertNotEmpty($subtask); - $this->assertNotEmpty($comment); - $this->assertNotEmpty($file); - - foreach (NotificationSubscriber::getSubscribedEvents() as $event_name => $values) { - $title = $wn->getTitleFromEvent($event_name, array( - 'task' => $task, - 'comment' => $comment, - 'subtask' => $subtask, - 'file' => $file, - 'changes' => array() - )); - - $this->assertNotEmpty($title); - } - - $this->assertNotEmpty($wn->getTitleFromEvent(Task::EVENT_OVERDUE, array('tasks' => array(array('id' => 1))))); - $this->assertNotEmpty($wn->getTitleFromEvent('unkown', array())); - } - public function testHasNotification() { $wn = new UserUnreadNotification($this->container); |