Move notifications outside of dashboard

This commit is contained in:
Frederic Guillot 2017-03-11 19:01:40 -05:00
parent bb9e791657
commit cfd3000d83
34 changed files with 134 additions and 122 deletions

View File

@ -7,6 +7,7 @@ New features:
Improvements:
* Move notifications outside of dashboard
* Render QR code for TwoFactor authentication without Google Chart API
* Add toggle button to show/hide subtasks in task list view
* Use same layout as task listing for task search

View File

@ -106,20 +106,4 @@ class DashboardController extends BaseController
'user' => $user,
)));
}
/**
* My notifications
*
* @access public
*/
public function notifications()
{
$user = $this->getUser();
$this->response->html($this->helper->layout->dashboard('dashboard/notifications', array(
'title' => t('Notifications for %s', $this->helper->user->getFullname($user)),
'notifications' => $this->userUnreadNotificationModel->getAll($user['id']),
'user' => $user,
)));
}
}

View File

@ -10,6 +10,23 @@ namespace Kanboard\Controller;
*/
class WebNotificationController extends BaseController
{
/**
* My notifications
*
* @access public
*/
public function show()
{
$user = $this->getUser();
$notifications = $this->userUnreadNotificationModel->getAll($user['id']);
$this->response->html($this->template->render('web_notification/show', array(
'notifications' => $notifications,
'nb_notifications' => count($notifications),
'user' => $user,
)));
}
/**
* Mark all notifications as read
*
@ -17,10 +34,9 @@ class WebNotificationController extends BaseController
*/
public function flush()
{
$user_id = $this->getUserId();
$this->userUnreadNotificationModel->markAllAsRead($user_id);
$this->response->redirect($this->helper->url->to('DashboardController', 'notifications', array('user_id' => $user_id)));
$userId = $this->getUserId();
$this->userUnreadNotificationModel->markAllAsRead($userId);
$this->show();
}
/**
@ -32,9 +48,8 @@ class WebNotificationController extends BaseController
{
$user_id = $this->getUserId();
$notification_id = $this->request->getIntegerParam('notification_id');
$this->userUnreadNotificationModel->markAsRead($user_id, $notification_id);
$this->response->redirect($this->helper->url->to('DashboardController', 'notifications', array('user_id' => $user_id)));
$this->show();
}
/**
@ -49,7 +64,7 @@ class WebNotificationController extends BaseController
$this->userUnreadNotificationModel->markAsRead($user_id, $notification_id);
if (empty($notification)) {
$this->response->redirect($this->helper->url->to('DashboardController', 'notifications', array('user_id' => $user_id)));
$this->show();
} elseif ($this->helper->text->contains($notification['event_name'], 'comment')) {
$this->response->redirect($this->helper->url->to(
'TaskViewController',

View File

@ -65,6 +65,12 @@ class ModalHelper extends Base
return $this->helper->url->link($html, $controller, $action, $params, false, 'js-modal-medium btn');
}
public function mediumIcon($icon, $label, $controller, $action, array $params = array())
{
$html = '<i class="fa fa-'.$icon.' fa-fw js-modal-medium" aria-hidden="true"></i>';
return $this->helper->url->link($html, $controller, $action, $params, false, 'js-modal-medium', $label);
}
public function confirm($icon, $label, $controller, $action, array $params = array())
{
$html = '<i class="fa fa-'.$icon.' fa-fw js-modal-confirm" aria-hidden="true"></i>'.$label;
@ -80,4 +86,10 @@ class ModalHelper extends Base
{
return $this->helper->url->link($label, $controller, $action, $params, false, 'js-modal-replace');
}
public function replaceIconLink($icon, $label, $controller, $action, array $params = array())
{
$html = '<i class="fa fa-'.$icon.' fa-fw" aria-hidden="true"></i>'.$label;
return $this->helper->url->link($html, $controller, $action, $params, false, 'js-modal-replace');
}
}

View File

@ -808,7 +808,7 @@ return array(
'Assignee changed on task #%d' => 'Promijenjen izvršilac na zadatku #%d',
'%d overdue tasks' => '%d zadataka kasni',
'Task #%d is overdue' => 'Zadatak #%d kasni',
'No new notifications.' => 'Nema novih obavještenja.',
'No notification.' => 'Nema novih obavještenja.',
'Mark all as read' => 'Označi sve kao pročitano',
'Mark as read' => 'Označi kao pročitano',
'Total number of tasks in this column across all swimlanes' => 'Ukupan broj zadataka u ovoj koloni u svim swimlane trakama',

View File

@ -808,7 +808,7 @@ return array(
// 'Assignee changed on task #%d' => '',
// '%d overdue tasks' => '',
// 'Task #%d is overdue' => '',
// 'No new notifications.' => '',
// 'No notification.' => '',
// 'Mark all as read' => '',
// 'Mark as read' => '',
// 'Total number of tasks in this column across all swimlanes' => '',

View File

@ -808,7 +808,7 @@ return array(
// 'Assignee changed on task #%d' => '',
// '%d overdue tasks' => '',
// 'Task #%d is overdue' => '',
// 'No new notifications.' => '',
// 'No notification.' => '',
// 'Mark all as read' => '',
// 'Mark as read' => '',
// 'Total number of tasks in this column across all swimlanes' => '',

View File

@ -808,7 +808,7 @@ return array(
'Assignee changed on task #%d' => 'Neue Zuordnung für Aufgabe #%d ',
'%d overdue tasks' => '%d überfällige Aufgaben',
'Task #%d is overdue' => 'Aufgabe #%d ist überfällig',
'No new notifications.' => 'Keine neuen Benachrichtigungen',
'No notification.' => 'Keine neuen Benachrichtigungen',
'Mark all as read' => 'Alles als gelesen markieren',
'Mark as read' => 'Als gelesen markieren',
'Total number of tasks in this column across all swimlanes' => 'Anzahl an Aufgaben in dieser Spalte über alle Swimlanes',

View File

@ -808,7 +808,7 @@ return array(
'Assignee changed on task #%d' => 'Η ανάθεση άλλαξε για την εργασία n°%d',
'%d overdue tasks' => '%d εκπρόθεσμες εργασίες',
'Task #%d is overdue' => 'Η εργασία n°%d είναι εκπρόθεσμη',
'No new notifications.' => 'Χωρίς νέες ειδοποιήσεις.',
'No notification.' => 'Χωρίς νέες ειδοποιήσεις.',
'Mark all as read' => 'Μαρκάρισμα όλων ως διαβασμένα',
'Mark as read' => 'Μαρκάρισμα ως διαβασμένο',
'Total number of tasks in this column across all swimlanes' => 'Συνολικός αριθμός εργασιών σε αυτήν τη στήλη σε όλες τις λωρίδες',

View File

@ -808,7 +808,7 @@ return array(
// 'Assignee changed on task #%d' => '',
// '%d overdue tasks' => '',
// 'Task #%d is overdue' => '',
// 'No new notifications.' => '',
// 'No notification.' => '',
// 'Mark all as read' => '',
// 'Mark as read' => '',
// 'Total number of tasks in this column across all swimlanes' => '',

View File

@ -808,7 +808,7 @@ return array(
// 'Assignee changed on task #%d' => '',
// '%d overdue tasks' => '',
// 'Task #%d is overdue' => '',
// 'No new notifications.' => '',
// 'No notification.' => '',
// 'Mark all as read' => '',
// 'Mark as read' => '',
// 'Total number of tasks in this column across all swimlanes' => '',

View File

@ -808,7 +808,7 @@ return array(
'Assignee changed on task #%d' => 'Changement de l\'assigné pour la tâche n°%d',
'%d overdue tasks' => '%d tâches en retard',
'Task #%d is overdue' => 'La tâche n°%d est en retard',
'No new notifications.' => 'Aucune notification.',
'No notification.' => 'Aucune notification.',
'Mark all as read' => 'Tout marquer comme lu',
'Mark as read' => 'Marquer comme lu',
'Total number of tasks in this column across all swimlanes' => 'Nombre total de tâches dans cette colonne pour toutes les swimlanes',

View File

@ -808,7 +808,7 @@ return array(
// 'Assignee changed on task #%d' => '',
// '%d overdue tasks' => '',
// 'Task #%d is overdue' => '',
// 'No new notifications.' => '',
// 'No notification.' => '',
// 'Mark all as read' => '',
// 'Mark as read' => '',
// 'Total number of tasks in this column across all swimlanes' => '',

View File

@ -808,7 +808,7 @@ return array(
'Assignee changed on task #%d' => 'A #%d számú feladat felelőse megváltozott',
'%d overdue tasks' => '%d db feladatnál van határidő túllépés',
'Task #%d is overdue' => 'A #%d számú feladat határideje lejárt',
'No new notifications.' => 'Nincs új emlékeztető.',
'No notification.' => 'Nincs új emlékeztető.',
'Mark all as read' => 'Az összes megjelölése olvasottként',
'Mark as read' => 'Megjelölés olvasottként',
'Total number of tasks in this column across all swimlanes' => 'Az ebben az oszlopban, az összes sávban lévő feladatok száma',

View File

@ -808,7 +808,7 @@ return array(
'Assignee changed on task #%d' => 'Orang yang ditugaskan diganti pada tugas #%d',
'%d overdue tasks' => '%d tugas kadaluarsa',
'Task #%d is overdue' => 'Tugas #%d sudah kadaluarsa',
'No new notifications.' => 'Tidak ada notifikasi baru',
'No notification.' => 'Tidak ada notifikasi baru',
'Mark all as read' => 'Tandai semua sebagai sudah dibaca',
'Mark as read' => 'Tandai sebagai sudah dibaca',
'Total number of tasks in this column across all swimlanes' => 'Total tugas di kolom ini untuk semua swimlane',

View File

@ -808,7 +808,7 @@ return array(
'Assignee changed on task #%d' => 'Assegnatario modificato per il task #%d',
'%d overdue tasks' => '%d task scaduti',
'Task #%d is overdue' => 'Il task #%d è scaduto',
'No new notifications.' => 'Nessuna nuova notifica.',
'No notification.' => 'Nessuna nuova notifica.',
'Mark all as read' => 'Segna tutti come letti',
'Mark as read' => 'Segna come letto',
'Total number of tasks in this column across all swimlanes' => 'Numero totale di task in questa colonna per tutte le corsie',

View File

@ -808,7 +808,7 @@ return array(
// 'Assignee changed on task #%d' => '',
// '%d overdue tasks' => '',
// 'Task #%d is overdue' => '',
// 'No new notifications.' => '',
// 'No notification.' => '',
// 'Mark all as read' => '',
// 'Mark as read' => '',
// 'Total number of tasks in this column across all swimlanes' => '',

View File

@ -808,7 +808,7 @@ return array(
'Assignee changed on task #%d' => '#%d 할일의 담당자가 변경됩니다',
'%d overdue tasks' => '할일의 기한이 %d일 지났습니다',
'Task #%d is overdue' => '#%d 할일의 기한이 지났습니다',
'No new notifications.' => '알림이 없습니다',
'No notification.' => '알림이 없습니다',
'Mark all as read' => '모두 읽음',
'Mark as read' => '읽음',
'Total number of tasks in this column across all swimlanes' => '모든 스웜라인 칼럼의 할일 수',

View File

@ -808,7 +808,7 @@ return array(
// 'Assignee changed on task #%d' => '',
// '%d overdue tasks' => '',
// 'Task #%d is overdue' => '',
// 'No new notifications.' => '',
// 'No notification.' => '',
// 'Mark all as read' => '',
// 'Mark as read' => '',
// 'Total number of tasks in this column across all swimlanes' => '',

View File

@ -808,7 +808,7 @@ return array(
// 'Assignee changed on task #%d' => '',
// '%d overdue tasks' => '',
// 'Task #%d is overdue' => '',
// 'No new notifications.' => '',
// 'No notification.' => '',
// 'Mark all as read' => '',
// 'Mark as read' => '',
// 'Total number of tasks in this column across all swimlanes' => '',

View File

@ -808,7 +808,7 @@ return array(
// 'Assignee changed on task #%d' => '',
// '%d overdue tasks' => '',
// 'Task #%d is overdue' => '',
// 'No new notifications.' => '',
// 'No notification.' => '',
// 'Mark all as read' => '',
// 'Mark as read' => '',
// 'Total number of tasks in this column across all swimlanes' => '',

View File

@ -808,7 +808,7 @@ return array(
'Assignee changed on task #%d' => 'Zmieniono osobę odpowiedzialną dla zadania #%d',
'%d overdue tasks' => '%d zaległych zadań',
'Task #%d is overdue' => 'Zadanie #%d jest zaległe',
'No new notifications.' => 'Brak nowych powiadomień.',
'No notification.' => 'Brak nowych powiadomień.',
'Mark all as read' => 'Oznacz wszystkie jako przeczytane',
'Mark as read' => 'Oznacz jako przeczytane',
'Total number of tasks in this column across all swimlanes' => 'Całkowita liczba zadań z tej kolumny z wszystkich torów',

View File

@ -808,7 +808,7 @@ return array(
'Assignee changed on task #%d' => 'Designação alterada na tarefa #%d',
'%d overdue tasks' => '%d tarefas atrasadas',
'Task #%d is overdue' => 'Tarefa #%d está atrasada',
'No new notifications.' => 'Nenhuma notificação nova.',
'No notification.' => 'Nenhuma notificação nova.',
'Mark all as read' => 'Marcar todas como lidas',
'Mark as read' => 'Marcar como lida',
'Total number of tasks in this column across all swimlanes' => 'Número total de tarefas nesta coluna através de todas as swimlanes',

View File

@ -808,7 +808,7 @@ return array(
'Assignee changed on task #%d' => 'Assignado alterado na tarefa #%d',
'%d overdue tasks' => '%d tarefas em atraso',
'Task #%d is overdue' => 'Tarefa #%d está em atraso',
'No new notifications.' => 'Sem novas notificações.',
'No notification.' => 'Sem novas notificações.',
'Mark all as read' => 'Marcar tudo como lido',
'Mark as read' => 'Marcar como lido',
'Total number of tasks in this column across all swimlanes' => 'Número total de tarefas nesta coluna em todas as swimlanes',

View File

@ -808,7 +808,7 @@ return array(
'Assignee changed on task #%d' => 'Изменён назначенный у задачи #%d',
'%d overdue tasks' => '%d просроченных задач',
'Task #%d is overdue' => 'Задача #%d просрочена',
'No new notifications.' => 'Нет новых уведомлений.',
'No notification.' => 'Нет новых уведомлений.',
'Mark all as read' => 'Пометить все прочитанными',
'Mark as read' => 'Пометить прочитанным',
'Total number of tasks in this column across all swimlanes' => 'Общее число задач в этой колонке на всех дорожках',

View File

@ -808,7 +808,7 @@ return array(
// 'Assignee changed on task #%d' => '',
// '%d overdue tasks' => '',
// 'Task #%d is overdue' => '',
// 'No new notifications.' => '',
// 'No notification.' => '',
// 'Mark all as read' => '',
// 'Mark as read' => '',
// 'Total number of tasks in this column across all swimlanes' => '',

View File

@ -808,7 +808,7 @@ return array(
// 'Assignee changed on task #%d' => '',
// '%d overdue tasks' => '',
// 'Task #%d is overdue' => '',
// 'No new notifications.' => '',
// 'No notification.' => '',
// 'Mark all as read' => '',
// 'Mark as read' => '',
// 'Total number of tasks in this column across all swimlanes' => '',

View File

@ -808,7 +808,7 @@ return array(
'Assignee changed on task #%d' => 'เปลี่ยนผู้รับผิดชอบงาน #%d',
'%d overdue tasks' => '%d งานเกินกำหนด',
'Task #%d is overdue' => 'งาน #%d เกินกำหนด',
'No new notifications.' => 'ไม่มีการแจ้งเตือนใหม่',
'No notification.' => 'ไม่มีการแจ้งเตือนใหม่',
'Mark all as read' => 'มาร์คทั้งหมดว่าอ่านแล้ว',
'Mark as read' => 'มาร์คว่าอ่านแล้ว',
// 'Total number of tasks in this column across all swimlanes' => '',

View File

@ -808,7 +808,7 @@ return array(
'Assignee changed on task #%d' => '#%d görevine atanan değişti',
'%d overdue tasks' => '%d gecikmiş görev',
'Task #%d is overdue' => '#%d görevi gecikti',
'No new notifications.' => 'Yeni bildirim yok.',
'No notification.' => 'Yeni bildirim yok.',
'Mark all as read' => 'Tümünü okunmuş olarak işaretle',
'Mark as read' => 'Okunmuş olarak işaretle',
'Total number of tasks in this column across all swimlanes' => 'Bu sutündaki görev sayısının tüm kulvarlardaki toplamı',

View File

@ -808,7 +808,7 @@ return array(
'Assignee changed on task #%d' => '任务#%d的指派人已改变',
'%d overdue tasks' => '%d条超期任务',
'Task #%d is overdue' => '任务#%d已超期',
'No new notifications.' => '没有新通知',
'No notification.' => '没有新通知',
'Mark all as read' => '标记所有为已读',
'Mark as read' => '标记为已读',
'Total number of tasks in this column across all swimlanes' => '此任务栏下的任务数(跨里程碑)',

View File

@ -1,67 +0,0 @@
<div class="page-header">
<h2><?= t('My notifications') ?></h2>
<?php if (empty($notifications)): ?>
</div>
<p class="alert"><?= t('No new notifications.') ?></p>
<?php else: ?>
<ul>
<li>
<?= $this->url->icon('check-square-o', t('Mark all as read'), 'WebNotificationController', 'flush', array('user_id' => $user['id'])) ?>
</li>
</ul>
</div>
<table class="table-striped table-scrolling table-small">
<tr>
<th class="column-20"><?= t('Project') ?></th>
<th><?= t('Notification') ?></th>
<th class="column-15"><?= t('Date') ?></th>
<th class="column-15"><?= t('Action') ?></th>
</tr>
<?php foreach ($notifications as $notification): ?>
<tr>
<td>
<?php if (isset($notification['event_data']['task']['project_name'])): ?>
<?= $this->url->link(
$this->text->e($notification['event_data']['task']['project_name']),
'BoardViewController',
'show',
array('project_id' => $notification['event_data']['task']['project_id'])
)
?>
<?php elseif (isset($notification['event_data']['project_name'])): ?>
<?= $this->text->e($notification['event_data']['project_name']) ?>
<?php endif ?>
</td>
<td>
<?php if ($this->text->contains($notification['event_name'], 'subtask')): ?>
<i class="fa fa-tasks fa-fw"></i>
<?php elseif ($this->text->contains($notification['event_name'], 'task.move')): ?>
<i class="fa fa-arrows-alt fa-fw"></i>
<?php elseif ($this->text->contains($notification['event_name'], 'task.overdue')): ?>
<i class="fa fa-calendar-times-o fa-fw"></i>
<?php elseif ($this->text->contains($notification['event_name'], 'task')): ?>
<i class="fa fa-newspaper-o fa-fw"></i>
<?php elseif ($this->text->contains($notification['event_name'], 'comment')): ?>
<i class="fa fa-comments-o fa-fw"></i>
<?php elseif ($this->text->contains($notification['event_name'], 'file')): ?>
<i class="fa fa-file-o fa-fw"></i>
<?php endif ?>
<?php if ($this->text->contains($notification['event_name'], 'task.overdue') && count($notification['event_data']['tasks']) > 1): ?>
<?= $notification['title'] ?>
<?php else: ?>
<?= $this->url->link($notification['title'], 'WebNotificationController', 'redirect', array('notification_id' => $notification['id'], 'user_id' => $user['id'])) ?>
<?php endif ?>
</td>
<td>
<?= $this->dt->datetime($notification['date_creation']) ?>
</td>
<td>
<?= $this->url->icon('check', t('Mark as read'), 'WebNotificationController', 'remove', array('user_id' => $user['id'], 'notification_id' => $notification['id'])) ?>
</td>
</tr>
<?php endforeach ?>
</table>
<?php endif ?>

View File

@ -18,9 +18,6 @@
<li <?= $this->app->checkMenuSelection('DashboardController', 'activity') ?>>
<?= $this->url->link(t('My activity stream'), 'DashboardController', 'activity', array('user_id' => $user['id'])) ?>
</li>
<li <?= $this->app->checkMenuSelection('DashboardController', 'notifications') ?>>
<?= $this->url->link(t('My notifications'), 'DashboardController', 'notifications', array('user_id' => $user['id'])) ?>
</li>
<?= $this->hook->render('template:dashboard:sidebar', array('user' => $user)) ?>
</ul>
</div>

View File

@ -1,5 +1,7 @@
<span class="notification">
<?php if ($this->user->hasNotifications()): ?>
<span class="notification">
<?= $this->url->link('<i class="fa fa-bell web-notification-icon"></i>', 'DashboardController', 'notifications', array('user_id' => $this->user->getId()), false, '', t('Unread notifications')) ?>
</span>
<?= $this->modal->mediumIcon('bell web-notification-icon', t('Unread notifications'), 'WebNotificationController', 'show', array('user_id' => $this->user->getId())) ?>
<?php else: ?>
<?= $this->modal->mediumIcon('bell', t('My notifications'), 'WebNotificationController', 'show', array('user_id' => $this->user->getId())) ?>
<?php endif ?>
</span>

View File

@ -0,0 +1,68 @@
<div class="page-header">
<h2><?= t('My notifications') ?></h2>
<?php if (! empty($notifications)): ?>
<ul>
<li>
<?= $this->modal->replaceIconLink('check-square-o', t('Mark all as read'), 'WebNotificationController', 'flush', array('user_id' => $user['id'])) ?>
</li>
</ul>
<?php endif ?>
</div>
<?php if (empty($notifications)): ?>
<p class="alert"><?= t('No notification.') ?></p>
<?php else: ?>
<div class="table-list">
<div class="table-list-header">
<div class="table-list-header-count">
<?php if ($nb_notifications > 1): ?>
<?= t('%d notifications', $nb_notifications) ?>
<?php else: ?>
<?= t('%d notification', $nb_notifications) ?>
<?php endif ?>
</div>
&nbsp;
</div>
<?php foreach ($notifications as $notification): ?>
<div class="table-list-row table-border-left">
<span class="table-list-title">
<?php if ($this->text->contains($notification['event_name'], 'subtask')): ?>
<i class="fa fa-tasks fa-fw"></i>
<?php elseif ($this->text->contains($notification['event_name'], 'task.move')): ?>
<i class="fa fa-arrows-alt fa-fw"></i>
<?php elseif ($this->text->contains($notification['event_name'], 'task.overdue')): ?>
<i class="fa fa-calendar-times-o fa-fw"></i>
<?php elseif ($this->text->contains($notification['event_name'], 'task')): ?>
<i class="fa fa-newspaper-o fa-fw"></i>
<?php elseif ($this->text->contains($notification['event_name'], 'comment')): ?>
<i class="fa fa-comments-o fa-fw"></i>
<?php elseif ($this->text->contains($notification['event_name'], 'file')): ?>
<i class="fa fa-file-o fa-fw"></i>
<?php endif ?>
<?php if (isset($notification['event_data']['task']['project_name'])): ?>
<?= $this->url->link(
$this->text->e($notification['event_data']['task']['project_name']),
'BoardViewController',
'show',
array('project_id' => $notification['event_data']['task']['project_id'])
) ?> &gt;
<?php elseif (isset($notification['event_data']['project_name'])): ?>
<?= $this->text->e($notification['event_data']['project_name']) ?> &gt;
<?php endif ?>
<?php if ($this->text->contains($notification['event_name'], 'task.overdue') && count($notification['event_data']['tasks']) > 1): ?>
<?= $notification['title'] ?>
<?php else: ?>
<?= $this->url->link($notification['title'], 'WebNotificationController', 'redirect', array('notification_id' => $notification['id'], 'user_id' => $user['id'])) ?>
<?php endif ?>
</span>
<div class="table-list-details">
<?= $this->dt->datetime($notification['date_creation']) ?>
<?= $this->modal->replaceIconLink('check', t('Mark as read'), 'WebNotificationController', 'remove', array('user_id' => $user['id'], 'notification_id' => $notification['id'])) ?>
</div>
</div>
<?php endforeach ?>
</div>
<?php endif ?>