summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rw-r--r--app/Api/Procedure/TaskMetadataProcedure.php38
-rw-r--r--app/Api/Procedure/TaskProcedure.php2
-rw-r--r--app/Controller/ActivityController.php1
-rw-r--r--app/Controller/BoardAjaxController.php9
-rw-r--r--app/Controller/BoardTooltipController.php5
-rw-r--r--app/Controller/CommentController.php20
-rw-r--r--app/Controller/TaskCreationController.php52
-rw-r--r--app/Controller/TaskGanttCreationController.php18
-rw-r--r--app/Controller/TaskModificationController.php21
-rw-r--r--app/Controller/TaskViewController.php18
-rw-r--r--app/Core/Base.php2
-rw-r--r--app/Core/Cache/BaseCache.php (renamed from app/Core/Cache/Base.php)6
-rw-r--r--app/Core/Cache/CacheInterface.php14
-rw-r--r--app/Core/Cache/FileCache.php98
-rw-r--r--app/Core/Cache/MemoryCache.php10
-rw-r--r--app/Core/Filter/LexerBuilder.php2
-rw-r--r--app/Core/Mail/Transport/Smtp.php9
-rw-r--r--app/Core/Plugin/Hook.php17
-rw-r--r--app/Core/Plugin/Installer.php27
-rw-r--r--app/Core/Tool.php28
-rw-r--r--app/Core/User/UserSession.php46
-rw-r--r--app/Decorator/MetadataCacheDecorator.php96
-rw-r--r--app/Formatter/BoardFormatter.php11
-rw-r--r--app/Helper/BoardHelper.php3
-rw-r--r--app/Helper/FormHelper.php42
-rw-r--r--app/Helper/HookHelper.php53
-rw-r--r--app/Helper/SubtaskHelper.php5
-rw-r--r--app/Helper/TaskHelper.php27
-rw-r--r--app/Locale/bs_BA/translations.php2
-rw-r--r--app/Locale/cs_CZ/translations.php2
-rw-r--r--app/Locale/da_DK/translations.php2
-rw-r--r--app/Locale/de_DE/translations.php2
-rw-r--r--app/Locale/el_GR/translations.php2
-rw-r--r--app/Locale/es_ES/translations.php2
-rw-r--r--app/Locale/fi_FI/translations.php2
-rw-r--r--app/Locale/fr_FR/translations.php2
-rw-r--r--app/Locale/hu_HU/translations.php2
-rw-r--r--app/Locale/id_ID/translations.php318
-rw-r--r--app/Locale/it_IT/translations.php2
-rw-r--r--app/Locale/ja_JP/translations.php2
-rw-r--r--app/Locale/ko_KR/translations.php194
-rw-r--r--app/Locale/my_MY/translations.php2
-rw-r--r--app/Locale/nb_NO/translations.php2
-rw-r--r--app/Locale/nl_NL/translations.php2
-rw-r--r--app/Locale/pl_PL/translations.php2
-rw-r--r--app/Locale/pt_BR/translations.php2
-rw-r--r--app/Locale/pt_PT/translations.php4
-rw-r--r--app/Locale/ru_RU/translations.php60
-rw-r--r--app/Locale/sr_Latn_RS/translations.php2
-rw-r--r--app/Locale/sv_SE/translations.php2
-rw-r--r--app/Locale/th_TH/translations.php126
-rw-r--r--app/Locale/tr_TR/translations.php2
-rw-r--r--app/Locale/zh_CN/translations.php2
-rw-r--r--app/Model/TaskCreationModel.php2
-rw-r--r--app/Model/TaskFinderModel.php78
-rw-r--r--app/Model/TaskModificationModel.php2
-rw-r--r--app/Model/UserMetadataModel.php3
-rw-r--r--app/Notification/MailNotification.php2
-rw-r--r--app/Pagination/SubtaskPagination.php5
-rw-r--r--app/Pagination/TaskPagination.php5
-rw-r--r--app/ServiceProvider/ApiProvider.php2
-rw-r--r--app/ServiceProvider/CacheProvider.php51
-rw-r--r--app/ServiceProvider/ClassProvider.php3
-rw-r--r--app/Template/action/index.php2
-rw-r--r--app/Template/activity/task.php11
-rw-r--r--app/Template/analytic/avg_time_columns.php2
-rw-r--r--app/Template/analytic/compare_hours.php2
-rw-r--r--app/Template/analytic/tasks.php2
-rw-r--r--app/Template/analytic/users.php2
-rw-r--r--app/Template/board/table_column.php4
-rw-r--r--app/Template/board/tooltip_external_links.php2
-rw-r--r--app/Template/board/tooltip_files.php2
-rw-r--r--app/Template/board/tooltip_subtasks.php2
-rw-r--r--app/Template/board/tooltip_tasklinks.php2
-rw-r--r--app/Template/category/index.php2
-rw-r--r--app/Template/column/index.php2
-rw-r--r--app/Template/comment/show.php4
-rw-r--r--app/Template/comments/show.php6
-rw-r--r--app/Template/currency/index.php2
-rw-r--r--app/Template/custom_filter/index.php2
-rw-r--r--app/Template/dashboard/notifications.php18
-rw-r--r--app/Template/dashboard/projects.php4
-rw-r--r--app/Template/dashboard/show.php11
-rw-r--r--app/Template/dashboard/sidebar.php2
-rw-r--r--app/Template/dashboard/subtasks.php2
-rw-r--r--app/Template/dashboard/tasks.php4
-rw-r--r--app/Template/event/comment_create.php2
-rw-r--r--app/Template/event/comment_delete.php2
-rw-r--r--app/Template/event/comment_update.php2
-rw-r--r--app/Template/event/subtask_create.php2
-rw-r--r--app/Template/event/subtask_delete.php2
-rw-r--r--app/Template/event/subtask_update.php2
-rw-r--r--app/Template/event/task_assignee_change.php2
-rw-r--r--app/Template/event/task_close.php2
-rw-r--r--app/Template/event/task_create.php2
-rw-r--r--app/Template/event/task_file_create.php2
-rw-r--r--app/Template/event/task_internal_link_create_update.php2
-rw-r--r--app/Template/event/task_internal_link_delete.php2
-rw-r--r--app/Template/event/task_move_column.php2
-rw-r--r--app/Template/event/task_move_position.php2
-rw-r--r--app/Template/event/task_move_swimlane.php2
-rw-r--r--app/Template/event/task_open.php2
-rw-r--r--app/Template/event/task_update.php2
-rw-r--r--app/Template/group/index.php2
-rw-r--r--app/Template/group/users.php2
-rw-r--r--app/Template/header.php139
-rw-r--r--app/Template/header/board_selector.php13
-rw-r--r--app/Template/header/creation_dropdown.php22
-rw-r--r--app/Template/header/title.php17
-rw-r--r--app/Template/header/user_dropdown.php49
-rw-r--r--app/Template/header/user_notifications.php5
-rw-r--r--app/Template/layout.php1
-rw-r--r--app/Template/link/index.php2
-rw-r--r--app/Template/project_header/header.php26
-rw-r--r--app/Template/project_header/search.php77
-rw-r--r--app/Template/project_list/show.php14
-rw-r--r--app/Template/project_overview/columns.php4
-rw-r--r--app/Template/project_overview/files.php2
-rw-r--r--app/Template/project_permission/index.php4
-rw-r--r--app/Template/project_tag/index.php2
-rw-r--r--app/Template/project_user_overview/roles.php2
-rw-r--r--app/Template/project_user_overview/tasks.php2
-rw-r--r--app/Template/project_user_overview/tooltip_users.php2
-rw-r--r--app/Template/project_view/show.php2
-rw-r--r--app/Template/search/activity.php9
-rw-r--r--app/Template/search/index.php9
-rw-r--r--app/Template/search/results.php2
-rw-r--r--app/Template/subtask/table.php2
-rw-r--r--app/Template/swimlane/table.php2
-rw-r--r--app/Template/tag/index.php2
-rw-r--r--app/Template/task/analytics.php12
-rw-r--r--app/Template/task/details.php19
-rw-r--r--app/Template/task/show.php74
-rw-r--r--app/Template/task/time_tracking_details.php11
-rw-r--r--app/Template/task/transitions.php11
-rw-r--r--app/Template/task_bulk/show.php2
-rw-r--r--app/Template/task_creation/show.php2
-rw-r--r--app/Template/task_external_link/table.php2
-rw-r--r--app/Template/task_file/files.php2
-rw-r--r--app/Template/task_gantt_creation/show.php4
-rw-r--r--app/Template/task_internal_link/table.php2
-rw-r--r--app/Template/task_list/show.php2
-rw-r--r--app/Template/task_modification/show.php2
-rw-r--r--app/Template/user_list/show.php2
-rw-r--r--app/Template/user_view/last.php4
-rw-r--r--app/Template/user_view/password_reset.php4
-rw-r--r--app/Template/user_view/sessions.php2
-rw-r--r--app/Template/user_view/timesheet.php2
-rw-r--r--app/common.php1
-rw-r--r--app/constants.php6
150 files changed, 1338 insertions, 944 deletions
diff --git a/app/Api/Procedure/TaskMetadataProcedure.php b/app/Api/Procedure/TaskMetadataProcedure.php
new file mode 100644
index 00000000..169482f5
--- /dev/null
+++ b/app/Api/Procedure/TaskMetadataProcedure.php
@@ -0,0 +1,38 @@
+<?php
+
+namespace Kanboard\Api\Procedure;
+
+use Kanboard\Api\Authorization\TaskAuthorization;
+
+/**
+ * Class TaskMetadataProcedure
+ *
+ * @package Kanboard\Api\Procedure
+ * @author Frederic Guillot
+ */
+class TaskMetadataProcedure extends BaseProcedure
+{
+ public function getTaskMetadata($task_id)
+ {
+ TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'getTask', $task_id);
+ return $this->taskMetadataModel->getAll($task_id);
+ }
+
+ public function getTaskMetadataByName($task_id, $name)
+ {
+ TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'getTask', $task_id);
+ return $this->taskMetadataModel->get($task_id, $name);
+ }
+
+ public function saveTaskMetadata($task_id, array $values)
+ {
+ TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'updateTask', $task_id);
+ return $this->taskMetadataModel->save($task_id, $values);
+ }
+
+ public function removeTaskMetadata($task_id, $name)
+ {
+ TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'updateTask', $task_id);
+ return $this->taskMetadataModel->remove($task_id, $name);
+ }
+}
diff --git a/app/Api/Procedure/TaskProcedure.php b/app/Api/Procedure/TaskProcedure.php
index 8661deef..ee9242d1 100644
--- a/app/Api/Procedure/TaskProcedure.php
+++ b/app/Api/Procedure/TaskProcedure.php
@@ -92,7 +92,7 @@ class TaskProcedure extends BaseProcedure
$recurrence_basedate = 0, $reference = '')
{
ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'createTask', $project_id);
-
+
if ($owner_id !== 0 && ! $this->projectPermissionModel->isAssignable($project_id, $owner_id)) {
return false;
}
diff --git a/app/Controller/ActivityController.php b/app/Controller/ActivityController.php
index 9f9841af..476e4aac 100644
--- a/app/Controller/ActivityController.php
+++ b/app/Controller/ActivityController.php
@@ -40,6 +40,7 @@ class ActivityController extends BaseController
'task' => $task,
'project' => $this->projectModel->getById($task['project_id']),
'events' => $this->helper->projectActivity->getTaskEvents($task['id']),
+ 'tags' => $this->taskTagModel->getList($task['id']),
)));
}
}
diff --git a/app/Controller/BoardAjaxController.php b/app/Controller/BoardAjaxController.php
index 9b721f06..ccd47667 100644
--- a/app/Controller/BoardAjaxController.php
+++ b/app/Controller/BoardAjaxController.php
@@ -4,6 +4,7 @@ namespace Kanboard\Controller;
use Kanboard\Core\Controller\AccessForbiddenException;
use Kanboard\Formatter\BoardFormatter;
+use Kanboard\Model\UserMetadataModel;
/**
* Class BoardAjaxController
@@ -88,7 +89,7 @@ class BoardAjaxController extends BaseController
*/
public function collapse()
{
- $this->changeDisplayMode(true);
+ $this->changeDisplayMode(1);
}
/**
@@ -98,19 +99,19 @@ class BoardAjaxController extends BaseController
*/
public function expand()
{
- $this->changeDisplayMode(false);
+ $this->changeDisplayMode(0);
}
/**
* Change display mode
*
* @access private
- * @param boolean $mode
+ * @param int $mode
*/
private function changeDisplayMode($mode)
{
$project_id = $this->request->getIntegerParam('project_id');
- $this->userSession->setBoardDisplayMode($project_id, $mode);
+ $this->userMetadataCacheDecorator->set(UserMetadataModel::KEY_BOARD_COLLAPSED.$project_id, $mode);
if ($this->request->isAjax()) {
$this->response->html($this->renderBoard($project_id));
diff --git a/app/Controller/BoardTooltipController.php b/app/Controller/BoardTooltipController.php
index 134d728e..79b9b509 100644
--- a/app/Controller/BoardTooltipController.php
+++ b/app/Controller/BoardTooltipController.php
@@ -2,6 +2,8 @@
namespace Kanboard\Controller;
+use Kanboard\Model\UserMetadataModel;
+
/**
* Board Tooltip
*
@@ -75,10 +77,11 @@ class BoardTooltipController extends BaseController
public function comments()
{
$task = $this->getTask();
+ $commentSortingDirection = $this->userMetadataCacheDecorator->get(UserMetadataModel::KEY_COMMENT_SORTING_DIRECTION, 'ASC');
$this->response->html($this->template->render('board/tooltip_comments', array(
'task' => $task,
- 'comments' => $this->commentModel->getAll($task['id'], $this->userSession->getCommentSorting())
+ 'comments' => $this->commentModel->getAll($task['id'], $commentSortingDirection)
)));
}
diff --git a/app/Controller/CommentController.php b/app/Controller/CommentController.php
index 2a8c258a..c61a0602 100644
--- a/app/Controller/CommentController.php
+++ b/app/Controller/CommentController.php
@@ -4,6 +4,7 @@ namespace Kanboard\Controller;
use Kanboard\Core\Controller\AccessForbiddenException;
use Kanboard\Core\Controller\PageNotFoundException;
+use Kanboard\Model\UserMetadataModel;
/**
* Comment Controller
@@ -82,10 +83,10 @@ class CommentController extends BaseController
$this->flash->failure(t('Unable to create your comment.'));
}
- return $this->response->redirect($this->helper->url->to('TaskViewController', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id']), 'comments'), true);
+ $this->response->redirect($this->helper->url->to('TaskViewController', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id']), 'comments'), true);
+ } else {
+ $this->create($values, $errors);
}
-
- return $this->create($values, $errors);
}
/**
@@ -183,9 +184,16 @@ class CommentController extends BaseController
{
$task = $this->getTask();
- $order = $this->userSession->getCommentSorting() === 'ASC' ? 'DESC' : 'ASC';
- $this->userSession->setCommentSorting($order);
+ $oldDirection = $this->userMetadataCacheDecorator->get(UserMetadataModel::KEY_COMMENT_SORTING_DIRECTION, 'ASC');
+ $newDirection = $oldDirection === 'ASC' ? 'DESC' : 'ASC';
- $this->response->redirect($this->helper->url->to('TaskViewController', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id']), 'comments'));
+ $this->userMetadataCacheDecorator->set(UserMetadataModel::KEY_COMMENT_SORTING_DIRECTION, $newDirection);
+
+ $this->response->redirect($this->helper->url->to(
+ 'TaskViewController',
+ 'show',
+ array('task_id' => $task['id'], 'project_id' => $task['project_id']),
+ 'comments'
+ ));
}
}
diff --git a/app/Controller/TaskCreationController.php b/app/Controller/TaskCreationController.php
index 073b31b0..5f1337e5 100644
--- a/app/Controller/TaskCreationController.php
+++ b/app/Controller/TaskCreationController.php
@@ -2,6 +2,8 @@
namespace Kanboard\Controller;
+use Kanboard\Core\Controller\PageNotFoundException;
+
/**
* Task Creation Controller
*
@@ -14,9 +16,9 @@ class TaskCreationController extends BaseController
* Display a form to create a new task
*
* @access public
- * @param array $values
- * @param array $errors
- * @throws \Kanboard\Core\Controller\PageNotFoundException
+ * @param array $values
+ * @param array $errors
+ * @throws PageNotFoundException
*/
public function show(array $values = array(), array $errors = array())
{
@@ -24,15 +26,7 @@ class TaskCreationController extends BaseController
$swimlanes_list = $this->swimlaneModel->getList($project['id'], false, true);
if (empty($values)) {
- $values = array(
- 'swimlane_id' => $this->request->getIntegerParam('swimlane_id', key($swimlanes_list)),
- 'column_id' => $this->request->getIntegerParam('column_id'),
- 'color_id' => $this->colorModel->getDefaultColor(),
- 'owner_id' => $this->userSession->getId(),
- );
-
- $values = $this->hook->merge('controller:task:form:default', $values, array('default_values' => $values));
- $values = $this->hook->merge('controller:task-creation:form:default', $values, array('default_values' => $values));
+ $values = $this->prepareValues($swimlanes_list);
}
$this->response->html($this->template->render('task_creation/show', array(
@@ -43,7 +37,6 @@ class TaskCreationController extends BaseController
'users_list' => $this->projectUserRoleModel->getAssignableUsersList($project['id'], true, false, true),
'categories_list' => $this->categoryModel->getList($project['id']),
'swimlanes_list' => $swimlanes_list,
- 'title' => $project['name'].' &gt; '.t('New task')
)));
}
@@ -61,17 +54,17 @@ class TaskCreationController extends BaseController
if ($valid && $this->taskCreationModel->create($values)) {
$this->flash->success(t('Task created successfully.'));
- return $this->afterSave($project, $values);
+ $this->afterSave($project, $values);
+ } else {
+ $this->flash->failure(t('Unable to create your task.'));
+ $this->show($values, $errors);
}
-
- $this->flash->failure(t('Unable to create your task.'));
- return $this->show($values, $errors);
}
private function afterSave(array $project, array &$values)
{
if (isset($values['another_task']) && $values['another_task'] == 1) {
- return $this->show(array(
+ $this->show(array(
'owner_id' => $values['owner_id'],
'color_id' => $values['color_id'],
'category_id' => isset($values['category_id']) ? $values['category_id'] : 0,
@@ -79,8 +72,29 @@ class TaskCreationController extends BaseController
'swimlane_id' => isset($values['swimlane_id']) ? $values['swimlane_id'] : 0,
'another_task' => 1,
));
+ } else {
+ $this->response->redirect($this->helper->url->to('BoardViewController', 'show', array('project_id' => $project['id'])), true);
}
+ }
+
+ /**
+ * Prepare form values
+ *
+ * @access protected
+ * @param array $swimlanes_list
+ * @return array
+ */
+ protected function prepareValues(array $swimlanes_list)
+ {
+ $values = array(
+ 'swimlane_id' => $this->request->getIntegerParam('swimlane_id', key($swimlanes_list)),
+ 'column_id' => $this->request->getIntegerParam('column_id'),
+ 'color_id' => $this->colorModel->getDefaultColor(),
+ 'owner_id' => $this->userSession->getId(),
+ );
- return $this->response->redirect($this->helper->url->to('BoardViewController', 'show', array('project_id' => $project['id'])), true);
+ $values = $this->hook->merge('controller:task:form:default', $values, array('default_values' => $values));
+ $values = $this->hook->merge('controller:task-creation:form:default', $values, array('default_values' => $values));
+ return $values;
}
}
diff --git a/app/Controller/TaskGanttCreationController.php b/app/Controller/TaskGanttCreationController.php
index 07b74a49..0fbac8bb 100644
--- a/app/Controller/TaskGanttCreationController.php
+++ b/app/Controller/TaskGanttCreationController.php
@@ -38,7 +38,6 @@ class TaskGanttCreationController extends BaseController
'users_list' => $this->projectUserRoleModel->getAssignableUsersList($project['id'], true, false, true),
'categories_list' => $this->categoryModel->getList($project['id']),
'swimlanes_list' => $this->swimlaneModel->getList($project['id'], false, true),
- 'title' => $project['name'].' &gt; '.t('New task')
)));
}
@@ -54,17 +53,12 @@ class TaskGanttCreationController extends BaseController
list($valid, $errors) = $this->taskValidator->validateCreation($values);
- if ($valid) {
- $task_id = $this->taskCreationModel->create($values);
-
- if ($task_id !== false) {
- $this->flash->success(t('Task created successfully.'));
- return $this->response->redirect($this->helper->url->to('TaskGanttController', 'show', array('project_id' => $project['id'])));
- } else {
- $this->flash->failure(t('Unable to create your task.'));
- }
+ if ($valid && $this->taskCreationModel->create($values)) {
+ $this->flash->success(t('Task created successfully.'));
+ $this->response->redirect($this->helper->url->to('TaskGanttController', 'show', array('project_id' => $project['id'])));
+ } else {
+ $this->flash->failure(t('Unable to create your task.'));
+ $this->show($values, $errors);
}
-
- return $this->show($values, $errors);
}
}
diff --git a/app/Controller/TaskModificationController.php b/app/Controller/TaskModificationController.php
index b064123a..cbc3777a 100644
--- a/app/Controller/TaskModificationController.php
+++ b/app/Controller/TaskModificationController.php
@@ -37,11 +37,7 @@ class TaskModificationController extends BaseController
$project = $this->projectModel->getById($task['project_id']);
if (empty($values)) {
- $values = $task;
- $values = $this->hook->merge('controller:task:form:default', $values, array('default_values' => $values));
- $values = $this->hook->merge('controller:task-modification:form:default', $values, array('default_values' => $values));
- $values = $this->dateParser->format($values, array('date_due'), $this->dateParser->getUserDateFormat());
- $values = $this->dateParser->format($values, array('date_started'), $this->dateParser->getUserDateTimeFormat());
+ $values = $this->prepareValues($task);
}
$this->response->html($this->template->render('task_modification/show', array(
@@ -75,4 +71,19 @@ class TaskModificationController extends BaseController
$this->edit($values, $errors);
}
}
+
+ /**
+ * Prepare form values
+ *
+ * @access protected
+ * @param array $task
+ * @return array
+ */
+ protected function prepareValues(array $task)
+ {
+ $values = $task;
+ $values = $this->hook->merge('controller:task:form:default', $values, array('default_values' => $values));
+ $values = $this->hook->merge('controller:task-modification:form:default', $values, array('default_values' => $values));
+ return $values;
+ }
}
diff --git a/app/Controller/TaskViewController.php b/app/Controller/TaskViewController.php
index f40f8bea..31b9de11 100644
--- a/app/Controller/TaskViewController.php
+++ b/app/Controller/TaskViewController.php
@@ -4,6 +4,7 @@ namespace Kanboard\Controller;
use Kanboard\Core\Controller\AccessForbiddenException;
use Kanboard\Core\Controller\PageNotFoundException;
+use Kanboard\Model\UserMetadataModel;
/**
* Task Controller
@@ -22,7 +23,6 @@ class TaskViewController extends BaseController
{
$project = $this->projectModel->getByToken($this->request->getStringParam('token'));
- // Token verification
if (empty($project)) {
throw AccessForbiddenException::getInstance()->withoutLayout();
}
@@ -62,23 +62,14 @@ class TaskViewController extends BaseController
{
$task = $this->getTask();
$subtasks = $this->subtaskModel->getAll($task['id']);
-
- $values = array(
- 'id' => $task['id'],
- 'date_started' => $task['date_started'],
- 'time_estimated' => $task['time_estimated'] ?: '',
- 'time_spent' => $task['time_spent'] ?: '',
- );
-
- $values = $this->dateParser->format($values, array('date_started'), $this->dateParser->getUserDateTimeFormat());
+ $commentSortingDirection = $this->userMetadataCacheDecorator->get(UserMetadataModel::KEY_COMMENT_SORTING_DIRECTION, 'ASC');
$this->response->html($this->helper->layout->task('task/show', array(
'task' => $task,
'project' => $this->projectModel->getById($task['project_id']),
- 'values' => $values,
'files' => $this->taskFileModel->getAllDocuments($task['id']),
'images' => $this->taskFileModel->getAllImages($task['id']),
- 'comments' => $this->commentModel->getAll($task['id'], $this->userSession->getCommentSorting()),
+ 'comments' => $this->commentModel->getAll($task['id'], $commentSortingDirection),
'subtasks' => $subtasks,
'internal_links' => $this->taskLinkModel->getAllGroupedByLabel($task['id']),
'external_links' => $this->taskExternalLinkModel->getAll($task['id']),
@@ -102,6 +93,7 @@ class TaskViewController extends BaseController
'lead_time' => $this->taskAnalyticModel->getLeadTime($task),
'cycle_time' => $this->taskAnalyticModel->getCycleTime($task),
'time_spent_columns' => $this->taskAnalyticModel->getTimeSpentByColumn($task),
+ 'tags' => $this->taskTagModel->getList($task['id']),
)));
}
@@ -126,6 +118,7 @@ class TaskViewController extends BaseController
'task' => $task,
'project' => $this->projectModel->getById($task['project_id']),
'subtask_paginator' => $subtask_paginator,
+ 'tags' => $this->taskTagModel->getList($task['id']),
)));
}
@@ -142,6 +135,7 @@ class TaskViewController extends BaseController
'task' => $task,
'project' => $this->projectModel->getById($task['project_id']),
'transitions' => $this->transitionModel->getAllByTask($task['id']),
+ 'tags' => $this->taskTagModel->getList($task['id']),
)));
}
}
diff --git a/app/Core/Base.php b/app/Core/Base.php
index 68604785..3b7c5e66 100644
--- a/app/Core/Base.php
+++ b/app/Core/Base.php
@@ -18,6 +18,7 @@ use Pimple\Container;
* @property \Kanboard\Core\Action\ActionManager $actionManager
* @property \Kanboard\Core\ExternalLink\ExternalLinkManager $externalLinkManager
* @property \Kanboard\Core\Cache\MemoryCache $memoryCache
+ * @property \Kanboard\Core\Cache\BaseCache $cacheDriver
* @property \Kanboard\Core\Event\EventManager $eventManager
* @property \Kanboard\Core\Group\GroupManager $groupManager
* @property \Kanboard\Core\Http\Client $httpClient
@@ -55,6 +56,7 @@ use Pimple\Container;
* @property \Kanboard\Core\Helper $helper
* @property \Kanboard\Core\Paginator $paginator
* @property \Kanboard\Core\Template $template
+ * @property \Kanboard\Decorator\MetadataCacheDecorator $userMetadataCacheDecorator
* @property \Kanboard\Model\ActionModel $actionModel
* @property \Kanboard\Model\ActionParameterModel $actionParameterModel
* @property \Kanboard\Model\AvatarFileModel $avatarFileModel
diff --git a/app/Core/Cache/Base.php b/app/Core/Cache/BaseCache.php
index d62b8507..b51c4c0c 100644
--- a/app/Core/Cache/Base.php
+++ b/app/Core/Cache/BaseCache.php
@@ -3,12 +3,12 @@
namespace Kanboard\Core\Cache;
/**
- * Base class for cache drivers
+ * Base Class for Cache Drivers
*
- * @package cache
+ * @package Kanboard\Core\Cache
* @author Frederic Guillot
*/
-abstract class Base
+abstract class BaseCache implements CacheInterface
{
/**
* Proxy cache
diff --git a/app/Core/Cache/CacheInterface.php b/app/Core/Cache/CacheInterface.php
index d9e9747a..19bd6ef7 100644
--- a/app/Core/Cache/CacheInterface.php
+++ b/app/Core/Cache/CacheInterface.php
@@ -3,15 +3,15 @@
namespace Kanboard\Core\Cache;
/**
- * Cache Interface
+ * Interface CacheInterface
*
- * @package cache
- * @author Frederic Guillot
+ * @package Kanboard\Core\Cache
+ * @author Frederic Guillot
*/
interface CacheInterface
{
/**
- * Save a new value in the cache
+ * Store an item in the cache
*
* @access public
* @param string $key
@@ -20,7 +20,7 @@ interface CacheInterface
public function set($key, $value);
/**
- * Fetch value from cache
+ * Retrieve an item from the cache by key
*
* @access public
* @param string $key
@@ -29,14 +29,14 @@ interface CacheInterface
public function get($key);
/**
- * Clear all cache
+ * Remove all items from the cache
*
* @access public
*/
public function flush();
/**
- * Remove cached value
+ * Remove an item from the cache
*
* @access public
* @param string $key
diff --git a/app/Core/Cache/FileCache.php b/app/Core/Cache/FileCache.php
new file mode 100644
index 00000000..d477a1f3
--- /dev/null
+++ b/app/Core/Cache/FileCache.php
@@ -0,0 +1,98 @@
+<?php
+
+namespace Kanboard\Core\Cache;
+
+use Kanboard\Core\Tool;
+use LogicException;
+
+/**
+ * Class FileCache
+ *
+ * @package Kanboard\Core\Cache
+ */
+class FileCache extends BaseCache
+{
+ /**
+ * Store an item in the cache
+ *
+ * @access public
+ * @param string $key
+ * @param string $value
+ */
+ public function set($key, $value)
+ {
+ $this->createCacheFolder();
+ file_put_contents($this->getFilenameFromKey($key), serialize($value));
+ }
+
+ /**
+ * Retrieve an item from the cache by key
+ *
+ * @access public
+ * @param string $key
+ * @return mixed Null when not found, cached value otherwise
+ */
+ public function get($key)
+ {
+ $filename = $this->getFilenameFromKey($key);
+
+ if (file_exists($filename)) {
+ return unserialize(file_get_contents($filename));
+ }
+
+ return null;
+ }
+
+ /**
+ * Remove all items from the cache
+ *
+ * @access public
+ */
+ public function flush()
+ {
+ $this->createCacheFolder();
+ Tool::removeAllFiles(CACHE_DIR, false);
+ }
+
+ /**
+ * Remove an item from the cache
+ *
+ * @access public
+ * @param string $key
+ */
+ public function remove($key)
+ {
+ $filename = $this->getFilenameFromKey($key);
+
+ if (file_exists($filename)) {
+ unlink($filename);
+ }
+ }
+
+ /**
+ * Get absolute filename from the key
+ *
+ * @access protected
+ * @param string $key
+ * @return string
+ */
+ protected function getFilenameFromKey($key)
+ {
+ return CACHE_DIR.DIRECTORY_SEPARATOR.$key;
+ }
+
+ /**
+ * Create cache folder if missing
+ *
+ * @access protected
+ * @throws LogicException
+ */
+ protected function createCacheFolder()
+ {
+ if (! is_dir(CACHE_DIR)) {
+ if (! mkdir(CACHE_DIR, 0755)) {
+ throw new LogicException('Unable to create cache directory: '.CACHE_DIR);
+ }
+ }
+ }
+}
diff --git a/app/Core/Cache/MemoryCache.php b/app/Core/Cache/MemoryCache.php
index 39e3947b..4fb94728 100644
--- a/app/Core/Cache/MemoryCache.php
+++ b/app/Core/Cache/MemoryCache.php
@@ -3,12 +3,12 @@
namespace Kanboard\Core\Cache;
/**
- * Memory Cache
+ * Memory Cache Driver
*
- * @package cache
+ * @package Kanboard\Core\Cache
* @author Frederic Guillot
*/
-class MemoryCache extends Base implements CacheInterface
+class MemoryCache extends BaseCache
{
/**
* Container
@@ -19,7 +19,7 @@ class MemoryCache extends Base implements CacheInterface
private $storage = array();
/**
- * Save a new value in the cache
+ * Store an item in the cache
*
* @access public
* @param string $key
@@ -31,7 +31,7 @@ class MemoryCache extends Base implements CacheInterface
}
/**
- * Fetch value from cache
+ * Retrieve an item from the cache by key
*
* @access public
* @param string $key
diff --git a/app/Core/Filter/LexerBuilder.php b/app/Core/Filter/LexerBuilder.php
index 626d7614..e3ab725b 100644
--- a/app/Core/Filter/LexerBuilder.php
+++ b/app/Core/Filter/LexerBuilder.php
@@ -51,7 +51,7 @@ class LexerBuilder
*/
public function __construct()
{
- $this->lexer = new Lexer;
+ $this->lexer = new Lexer();
$this->queryBuilder = new QueryBuilder();
}
diff --git a/app/Core/Mail/Transport/Smtp.php b/app/Core/Mail/Transport/Smtp.php
index 66f0a3aa..1f4e54ce 100644
--- a/app/Core/Mail/Transport/Smtp.php
+++ b/app/Core/Mail/Transport/Smtp.php
@@ -24,6 +24,15 @@ class Smtp extends Mail
$transport->setUsername(MAIL_SMTP_USERNAME);
$transport->setPassword(MAIL_SMTP_PASSWORD);
$transport->setEncryption(MAIL_SMTP_ENCRYPTION);
+ if (HTTP_VERIFY_SSL_CERTIFICATE === false) {
+ $transport->setStreamOptions(array(
+ 'ssl' => array(
+ 'allow_self_signed' => true,
+ 'verify_peer' => false,
+ 'verify_peer_name' => false,
+ )
+ ));
+ }
return $transport;
}
diff --git a/app/Core/Plugin/Hook.php b/app/Core/Plugin/Hook.php
index ade69150..ca197937 100644
--- a/app/Core/Plugin/Hook.php
+++ b/app/Core/Plugin/Hook.php
@@ -96,4 +96,21 @@ class Hook
return null;
}
+
+ /**
+ * Hook with reference
+ *
+ * @access public
+ * @param string $hook
+ * @param mixed $param
+ * @return mixed
+ */
+ public function reference($hook, &$param)
+ {
+ foreach ($this->getListeners($hook) as $listener) {
+ $listener($param);
+ }
+
+ return $param;
+ }
}
diff --git a/app/Core/Plugin/Installer.php b/app/Core/Plugin/Installer.php
index 48c4d978..b3618aeb 100644
--- a/app/Core/Plugin/Installer.php
+++ b/app/Core/Plugin/Installer.php
@@ -2,9 +2,8 @@
namespace Kanboard\Core\Plugin;
-use RecursiveDirectoryIterator;
-use RecursiveIteratorIterator;
use ZipArchive;
+use Kanboard\Core\Tool;
/**
* Class Installer
@@ -64,7 +63,7 @@ class Installer extends \Kanboard\Core\Base
throw new PluginInstallerException(e('You don\'t have the permission to remove this plugin.'));
}
- $this->removeAllDirectories($pluginFolder);
+ Tool::removeAllFiles($pluginFolder);
}
/**
@@ -137,26 +136,4 @@ class Installer extends \Kanboard\Core\Base
unlink($zip->filename);
$zip->close();
}
-
- /**
- * Remove recursively a directory
- *
- * @access protected
- * @param string $directory
- */
- protected function removeAllDirectories($directory)
- {
- $it = new RecursiveDirectoryIterator($directory, RecursiveDirectoryIterator::SKIP_DOTS);
- $files = new RecursiveIteratorIterator($it, RecursiveIteratorIterator::CHILD_FIRST);
-
- foreach ($files as $file) {
- if ($file->isDir()) {
- rmdir($file->getRealPath());
- } else {
- unlink($file->getRealPath());
- }
- }
-
- rmdir($directory);
- }
}
diff --git a/app/Core/Tool.php b/app/Core/Tool.php
index bfa6c955..9b8820eb 100644
--- a/app/Core/Tool.php
+++ b/app/Core/Tool.php
@@ -3,6 +3,8 @@
namespace Kanboard\Core;
use Pimple\Container;
+use RecursiveDirectoryIterator;
+use RecursiveIteratorIterator;
/**
* Tool class
@@ -13,6 +15,32 @@ use Pimple\Container;
class Tool
{
/**
+ * Remove recursively a directory
+ *
+ * @static
+ * @access public
+ * @param string $directory
+ * @param bool $removeDirectory
+ */
+ public static function removeAllFiles($directory, $removeDirectory = true)
+ {
+ $it = new RecursiveDirectoryIterator($directory, RecursiveDirectoryIterator::SKIP_DOTS);
+ $files = new RecursiveIteratorIterator($it, RecursiveIteratorIterator::CHILD_FIRST);
+
+ foreach ($files as $file) {
+ if ($file->isDir()) {
+ rmdir($file->getRealPath());
+ } else {
+ unlink($file->getRealPath());
+ }
+ }
+
+ if ($removeDirectory) {
+ rmdir($directory);
+ }
+ }
+
+ /**
* Build dependency injection container from an array
*
* @static
diff --git a/app/Core/User/UserSession.php b/app/Core/User/UserSession.php
index 9c63f07a..7917b223 100644
--- a/app/Core/User/UserSession.php
+++ b/app/Core/User/UserSession.php
@@ -179,50 +179,4 @@ class UserSession extends Base
{
$this->sessionStorage->filters[$project_id] = $filters;
}
-
- /**
- * Is board collapsed or expanded
- *
- * @access public
- * @param integer $project_id
- * @return boolean
- */
- public function isBoardCollapsed($project_id)
- {
- return ! empty($this->sessionStorage->boardCollapsed[$project_id]) ? $this->sessionStorage->boardCollapsed[$project_id] : false;
- }
-
- /**
- * Set board display mode
- *
- * @access public
- * @param integer $project_id
- * @param boolean $is_collapsed
- */
- public function setBoardDisplayMode($project_id, $is_collapsed)
- {
- $this->sessionStorage->boardCollapsed[$project_id] = $is_collapsed;
- }
-
- /**
- * Set comments sorting
- *
- * @access public
- * @param string $order
- */
- public function setCommentSorting($order)
- {
- $this->sessionStorage->commentSorting = $order;
- }
-
- /**
- * Get comments sorting direction
- *
- * @access public
- * @return string
- */
- public function getCommentSorting()
- {
- return empty($this->sessionStorage->commentSorting) ? 'ASC' : $this->sessionStorage->commentSorting;
- }
}
diff --git a/app/Decorator/MetadataCacheDecorator.php b/app/Decorator/MetadataCacheDecorator.php
new file mode 100644
index 00000000..0897b51c
--- /dev/null
+++ b/app/Decorator/MetadataCacheDecorator.php
@@ -0,0 +1,96 @@
+<?php
+
+namespace Kanboard\Decorator;
+
+use Kanboard\Core\Cache\CacheInterface;
+use Kanboard\Model\MetadataModel;
+
+/**
+ * Class MetadataCacheDecorator
+ *
+ * @package Kanboard\Decorator
+ * @author Frederic Guillot
+ */
+class MetadataCacheDecorator
+{
+ /**
+ * @var CacheInterface
+ */
+ protected $cache;
+
+ /**
+ * @var MetadataModel
+ */
+ protected $metadataModel;
+
+ /**
+ * @var string
+ */
+ protected $cachePrefix;
+
+ /**
+ * @var int
+ */
+ protected $entityId;
+
+ /**
+ * Constructor
+ *
+ * @param CacheInterface $cache
+ * @param MetadataModel $metadataModel
+ * @param string $cachePrefix
+ * @param integer $entityId
+ */
+ public function __construct(CacheInterface $cache, MetadataModel $metadataModel, $cachePrefix, $entityId)
+ {
+ $this->cache = $cache;
+ $this->metadataModel = $metadataModel;
+ $this->cachePrefix = $cachePrefix;
+ $this->entityId = $entityId;
+ }
+
+ /**
+ * Get metadata value by key
+ *
+ * @param string $key
+ * @param mixed $default
+ * @return mixed
+ */
+ public function get($key, $default)
+ {
+ $metadata = $this->cache->get($this->getCacheKey());
+
+ if ($metadata === null) {
+ $metadata = $this->metadataModel->getAll($this->entityId);
+ $this->cache->set($this->getCacheKey(), $metadata);
+ }
+
+ return isset($metadata[$key]) ? $metadata[$key] : $default;
+ }
+
+ /**
+ * Set new metadata value
+ *
+ * @param $key
+ * @param $value
+ */
+ public function set($key, $value)
+ {
+ $this->metadataModel->save($this->entityId, array(
+ $key => $value,
+ ));
+
+ $metadata = $this->metadataModel->getAll($this->entityId);
+ $this->cache->set($this->getCacheKey(), $metadata);
+ }
+
+ /**
+ * Get cache key
+ *
+ * @return string
+ */
+ protected function getCacheKey()
+ {
+ return $this->cachePrefix.$this->entityId;
+ }
+}
diff --git a/app/Formatter/BoardFormatter.php b/app/Formatter/BoardFormatter.php
index 350dde6c..df443a52 100644
--- a/app/Formatter/BoardFormatter.php
+++ b/app/Formatter/BoardFormatter.php
@@ -44,6 +44,13 @@ class BoardFormatter extends BaseFormatter implements FormatterInterface
{
$swimlanes = $this->swimlaneModel->getSwimlanes($this->projectId);
$columns = $this->columnModel->getAll($this->projectId);
+
+ if (empty($swimlanes) || empty($columns)) {
+ return array();
+ }
+
+ $this->hook->reference('formatter:board:query', $this->query);
+
$tasks = $this->query
->eq(TaskModel::TABLE.'.project_id', $this->projectId)
->asc(TaskModel::TABLE.'.position')
@@ -52,10 +59,6 @@ class BoardFormatter extends BaseFormatter implements FormatterInterface
$task_ids = array_column($tasks, 'id');
$tags = $this->taskTagModel->getTagsByTasks($task_ids);
- if (empty($swimlanes) || empty($columns)) {
- return array();
- }
-
return BoardSwimlaneFormatter::getInstance($this->container)
->withSwimlanes($swimlanes)
->withColumns($columns)
diff --git a/app/Helper/BoardHelper.php b/app/Helper/BoardHelper.php
index a86a6c18..f5df3db2 100644
--- a/app/Helper/BoardHelper.php
+++ b/app/Helper/BoardHelper.php
@@ -3,6 +3,7 @@
namespace Kanboard\Helper;
use Kanboard\Core\Base;
+use Kanboard\Model\UserMetadataModel;
/**
* Board Helper
@@ -21,6 +22,6 @@ class BoardHelper extends Base
*/
public function isCollapsed($project_id)
{
- return $this->userSession->isBoardCollapsed($project_id);
+ return $this->userMetadataCacheDecorator->get(UserMetadataModel::KEY_BOARD_COLLAPSED.$project_id, 0) == 1;
}
}
diff --git a/app/Helper/FormHelper.php b/app/Helper/FormHelper.php
index c2ea1d72..0bb94d39 100644
--- a/app/Helper/FormHelper.php
+++ b/app/Helper/FormHelper.php
@@ -307,6 +307,48 @@ class FormHelper extends Base
}
/**
+ * Date field
+ *
+ * @access public
+ * @param string $label
+ * @param string $name
+ * @param array $values
+ * @param array $errors
+ * @param array $attributes
+ * @return string
+ */
+ public function date($label, $name, array $values, array $errors = array(), array $attributes = array())
+ {
+ $userFormat = $this->dateParser->getUserDateFormat();
+ $values = $this->dateParser->format($values, array($name), $userFormat);
+ $attributes = array_merge(array('placeholder="'.date($userFormat).'"'), $attributes);
+
+ return $this->helper->form->label($label, $name) .
+ $this->helper->form->text($name, $values, $errors, $attributes, 'form-date');
+ }
+
+ /**
+ * Datetime field
+ *
+ * @access public
+ * @param string $label
+ * @param string $name
+ * @param array $values
+ * @param array $errors
+ * @param array $attributes
+ * @return string
+ */
+ public function datetime($label, $name, array $values, array $errors = array(), array $attributes = array())
+ {
+ $userFormat = $this->dateParser->getUserDateTimeFormat();
+ $values = $this->dateParser->format($values, array($name), $userFormat);
+ $attributes = array_merge(array('placeholder="'.date($userFormat).'"'), $attributes);
+
+ return $this->helper->form->label($label, $name) .
+ $this->helper->form->text($name, $values, $errors, $attributes, 'form-datetime');
+ }
+
+ /**
* Display the form error class
*
* @access private
diff --git a/app/Helper/HookHelper.php b/app/Helper/HookHelper.php
index cb4dc1ef..24b7d00a 100644
--- a/app/Helper/HookHelper.php
+++ b/app/Helper/HookHelper.php
@@ -2,6 +2,7 @@
namespace Kanboard\Helper;
+use Closure;
use Kanboard\Core\Base;
/**
@@ -24,8 +25,8 @@ class HookHelper extends Base
{
$buffer = '';
- foreach ($this->hook->getListeners($hook) as $file) {
- $buffer .= $this->helper->asset->$type($file);
+ foreach ($this->hook->getListeners($hook) as $params) {
+ $buffer .= $this->helper->asset->$type($params['template']);
}
return $buffer;
@@ -43,8 +44,18 @@ class HookHelper extends Base
{
$buffer = '';
- foreach ($this->hook->getListeners($hook) as $template) {
- $buffer .= $this->template->render($template, $variables);
+ foreach ($this->hook->getListeners($hook) as $params) {
+ if (! empty($params['variables'])) {
+ $variables = array_merge($variables, $params['variables']);
+ } elseif (! empty($params['callable'])) {
+ $result = call_user_func_array($params['callable'], $variables);
+
+ if (is_array($result)) {
+ $variables = array_merge($variables, $result);
+ }
+ }
+
+ $buffer .= $this->template->render($params['template'], $variables);
}
return $buffer;
@@ -54,13 +65,39 @@ class HookHelper extends Base
* Attach a template to a hook
*
* @access public
- * @param string $hook
- * @param string $template
+ * @param string $hook
+ * @param string $template
+ * @param array $variables
* @return $this
*/
- public function attach($hook, $template)
+ public function attach($hook, $template, array $variables = array())
{
- $this->hook->on($hook, $template);
+ $this->hook->on($hook, array(
+ 'template' => $template,
+ 'variables' => $variables,
+ ));
+
+ return $this;
+ }
+
+ /**
+ * Attach a template to a hook with a callable
+ *
+ * Arguments passed to the callback are the one passed to the hook
+ *
+ * @access public
+ * @param string $hook
+ * @param string $template
+ * @param Closure $callable
+ * @return $this
+ */
+ public function attachCallable($hook, $template, Closure $callable)
+ {
+ $this->hook->on($hook, array(
+ 'template' => $template,
+ 'callable' => $callable,
+ ));
+
return $this;
}
}
diff --git a/app/Helper/SubtaskHelper.php b/app/Helper/SubtaskHelper.php
index dac71203..833544a7 100644
--- a/app/Helper/SubtaskHelper.php
+++ b/app/Helper/SubtaskHelper.php
@@ -66,7 +66,10 @@ class SubtaskHelper extends Base
$html = $this->helper->form->label(t('Assignee'), 'user_id');
$html .= $this->helper->form->select('user_id', $users, $values, $errors, $attributes);
- $html .= '&nbsp;<a href="#" class="assign-me" data-target-id="form-user_id" data-current-id="'.$this->userSession->getId().'" title="'.t('Assign to me').'">'.t('Me').'</a>';
+ $html .= '&nbsp;';
+ $html .= '<small>';
+ $html .= '<a href="#" class="assign-me" data-target-id="form-user_id" data-current-id="'.$this->userSession->getId().'" title="'.t('Assign to me').'">'.t('Me').'</a>';
+ $html .= '</small>';
return $html;
}
diff --git a/app/Helper/TaskHelper.php b/app/Helper/TaskHelper.php
index 481a5efb..678b4bed 100644
--- a/app/Helper/TaskHelper.php
+++ b/app/Helper/TaskHelper.php
@@ -103,7 +103,10 @@ class TaskHelper extends Base
$html = $this->helper->form->label(t('Assignee'), 'owner_id');
$html .= $this->helper->form->select('owner_id', $users, $values, $errors, $attributes);
- $html .= '&nbsp;<a href="#" class="assign-me" data-target-id="form-owner_id" data-current-id="'.$this->userSession->getId().'" title="'.t('Assign to me').'">'.t('Me').'</a>';
+ $html .= '&nbsp;';
+ $html .= '<small>';
+ $html .= '<a href="#" class="assign-me" data-target-id="form-owner_id" data-current-id="'.$this->userSession->getId().'" title="'.t('Assign to me').'">'.t('Me').'</a>';
+ $html .= '</small>';
return $html;
}
@@ -148,7 +151,7 @@ class TaskHelper extends Base
{
$html = '';
- if ($project['priority_end'] > $project['priority_start']) {
+ if ($project['priority_end'] != $project['priority_start']) {
$range = range($project['priority_start'], $project['priority_end']);
$options = array_combine($range, $range);
$values += array('priority' => $project['priority_default']);
@@ -204,31 +207,21 @@ class TaskHelper extends Base
public function selectStartDate(array $values, array $errors = array(), array $attributes = array())
{
- $placeholder = date($this->configModel->get('application_date_format', 'm/d/Y H:i'));
- $attributes = array_merge(array('tabindex="12"', 'placeholder="'.$placeholder.'"'), $attributes);
-
- $html = $this->helper->form->label(t('Start Date'), 'date_started');
- $html .= $this->helper->form->text('date_started', $values, $errors, $attributes, 'form-datetime');
-
- return $html;
+ $attributes = array_merge(array('tabindex="12"'), $attributes);
+ return $this->helper->form->datetime(t('Start Date'), 'date_started', $values, $errors, $attributes);
}
public function selectDueDate(array $values, array $errors = array(), array $attributes = array())
{
- $placeholder = date($this->configModel->get('application_date_format', 'm/d/Y'));
- $attributes = array_merge(array('tabindex="13"', 'placeholder="'.$placeholder.'"'), $attributes);
-
- $html = $this->helper->form->label(t('Due Date'), 'date_due');
- $html .= $this->helper->form->text('date_due', $values, $errors, $attributes, 'form-date');
-
- return $html;
+ $attributes = array_merge(array('tabindex="13"'), $attributes);
+ return $this->helper->form->date(t('Due Date'), 'date_due', $values, $errors, $attributes);
}
public function formatPriority(array $project, array $task)
{
$html = '';
- if ($project['priority_end'] > $project['priority_start']) {
+ if ($project['priority_end'] != $project['priority_start']) {
$html .= '<span class="task-board-priority" title="'.t('Task priority').'">';
$html .= $task['priority'] >= 0 ? 'P'.$task['priority'] : '-P'.abs($task['priority']);
$html .= '</span>';
diff --git a/app/Locale/bs_BA/translations.php b/app/Locale/bs_BA/translations.php
index 898e4d66..e17a3cdf 100644
--- a/app/Locale/bs_BA/translations.php
+++ b/app/Locale/bs_BA/translations.php
@@ -68,7 +68,6 @@ return array(
'Do you really want to remove this project: "%s"?' => 'Da li želiš da ukloniš projekat: "%s"?',
'Remove project' => 'Ukloni projekat',
'Edit the board for "%s"' => 'Uredi ploču za "%s"',
- 'All projects' => 'Svi projekti',
'Add a new column' => 'Dodaj novu kolonu',
'Title' => 'Naslov',
'Assigned to %s' => 'Dodijeljen korisniku %s',
@@ -88,7 +87,6 @@ return array(
'(VACUUM command)' => '(Naredba VACUUM)',
'(Gzip compressed Sqlite file)' => '(Sqlite baza spakovana Gzip-om)',
'Close a task' => 'Zatvori zadatak',
- 'Edit a task' => 'Uredi zadatak',
'Column' => 'Kolona',
'Color' => 'Boja',
'Assignee' => 'Izvršilac',
diff --git a/app/Locale/cs_CZ/translations.php b/app/Locale/cs_CZ/translations.php
index 565f92f5..277ddecc 100644
--- a/app/Locale/cs_CZ/translations.php
+++ b/app/Locale/cs_CZ/translations.php
@@ -68,7 +68,6 @@ return array(
'Do you really want to remove this project: "%s"?' => 'Opravdu chcete vyjmout projekt: "%s"?',
'Remove project' => 'Vyjmout projekt',
'Edit the board for "%s"' => 'Editace nástěnky pro "%s" ',
- 'All projects' => 'Všechny projekty',
'Add a new column' => 'Přidat nový sloupec',
'Title' => 'Název',
'Assigned to %s' => 'Přiřazeno uživateli: %s',
@@ -88,7 +87,6 @@ return array(
'(VACUUM command)' => '(Vyčištění)',
'(Gzip compressed Sqlite file)' => '(Gzip )',
'Close a task' => 'Uzavřít úkol',
- 'Edit a task' => 'Editovat úkol',
'Column' => 'Sloupec',
'Color' => 'Barva',
'Assignee' => 'Přiřazeno uživateli',
diff --git a/app/Locale/da_DK/translations.php b/app/Locale/da_DK/translations.php
index 0ff4253e..c4bf55ff 100644
--- a/app/Locale/da_DK/translations.php
+++ b/app/Locale/da_DK/translations.php
@@ -68,7 +68,6 @@ return array(
'Do you really want to remove this project: "%s"?' => 'Vil du virkelig fjerne dette projekt: "%s"?',
'Remove project' => 'Fjern projekt',
'Edit the board for "%s"' => 'Rediger boardet for "%s"',
- 'All projects' => 'Alle Projekter',
'Add a new column' => 'Tilføj en ny kolonne',
'Title' => 'Titel',
'Assigned to %s' => 'Ansvarlig: %s',
@@ -88,7 +87,6 @@ return array(
'(VACUUM command)' => '(VACUUM kommando)',
'(Gzip compressed Sqlite file)' => '(Gzip-komprimeret Sqlite fil)',
'Close a task' => 'Luk en opgave',
- 'Edit a task' => 'Rediger en opgave',
'Column' => 'Kolonne',
'Color' => 'Farve',
'Assignee' => 'Ansvarlig',
diff --git a/app/Locale/de_DE/translations.php b/app/Locale/de_DE/translations.php
index 59de2956..a2a1c17a 100644
--- a/app/Locale/de_DE/translations.php
+++ b/app/Locale/de_DE/translations.php
@@ -68,7 +68,6 @@ return array(
'Do you really want to remove this project: "%s"?' => 'Soll dieses Projekt wirklich gelöscht werden: "%s"?',
'Remove project' => 'Projekt löschen',
'Edit the board for "%s"' => 'Pinnwand für "%s" bearbeiten',
- 'All projects' => 'Alle Projekte',
'Add a new column' => 'Neue Spalte hinzufügen',
'Title' => 'Titel',
'Assigned to %s' => 'Zuständig: %s',
@@ -88,7 +87,6 @@ return array(
'(VACUUM command)' => '(VACUUM Befehl)',
'(Gzip compressed Sqlite file)' => '(Gzip-komprimierte SQLite-Datei)',
'Close a task' => 'Aufgabe abschließen',
- 'Edit a task' => 'Aufgabe bearbeiten',
'Column' => 'Spalte',
'Color' => 'Farbe',
'Assignee' => 'Zuständiger',
diff --git a/app/Locale/el_GR/translations.php b/app/Locale/el_GR/translations.php
index cf3bb588..30143ac5 100644
--- a/app/Locale/el_GR/translations.php
+++ b/app/Locale/el_GR/translations.php
@@ -68,7 +68,6 @@ return array(
'Do you really want to remove this project: "%s"?' => 'Αφαίρεση του έργου: « %s » ?',
'Remove project' => 'Αφαίρεση του έργου',
'Edit the board for "%s"' => 'Διόρθωση πίνακα από « %s »',
- 'All projects' => 'Όλα τα έργα',
'Add a new column' => 'Πρόσθήκη στήλης',
'Title' => 'Τίτλος',
'Assigned to %s' => 'Ανατιθεμένο στον %s',
@@ -88,7 +87,6 @@ return array(
'(VACUUM command)' => '(VACUUM command)',
'(Gzip compressed Sqlite file)' => '(Gzip compressed Sqlite file)',
'Close a task' => 'Κλείσιμο εργασίας',
- 'Edit a task' => 'Διόρθωση εργασίας',
'Column' => 'Στήλη',
'Color' => 'Χρώμα',
'Assignee' => 'Ανατεθιμένο στον χρήστη',
diff --git a/app/Locale/es_ES/translations.php b/app/Locale/es_ES/translations.php
index 5a2c16c0..be603eeb 100644
--- a/app/Locale/es_ES/translations.php
+++ b/app/Locale/es_ES/translations.php
@@ -68,7 +68,6 @@ return array(
'Do you really want to remove this project: "%s"?' => '¿Realmente desea eliminar este proyecto: «%s»?',
'Remove project' => 'Eliminar el proyecto',
'Edit the board for "%s"' => 'Modificar el tablero para «%s»',
- 'All projects' => 'Todos los proyectos',
'Add a new column' => 'Añadir una nueva columna',
'Title' => 'Título',
'Assigned to %s' => 'Asignada a %s',
@@ -88,7 +87,6 @@ return array(
'(VACUUM command)' => '(comando VACUUM)',
'(Gzip compressed Sqlite file)' => '(archivo Sqlite comprimido en Gzip)',
'Close a task' => 'Cerrar una tarea',
- 'Edit a task' => 'Modificar una tarea',
'Column' => 'Columna',
'Color' => 'Color',
'Assignee' => 'Responsable',
diff --git a/app/Locale/fi_FI/translations.php b/app/Locale/fi_FI/translations.php
index ed38fb56..7ce7fc5f 100644
--- a/app/Locale/fi_FI/translations.php
+++ b/app/Locale/fi_FI/translations.php
@@ -68,7 +68,6 @@ return array(
'Do you really want to remove this project: "%s"?' => 'Haluatko varmasti poistaa projektin: "%s"?',
'Remove project' => 'Poista projekti',
'Edit the board for "%s"' => 'Muokkaa taulua projektille "%s"',
- 'All projects' => 'Kaikki projektit',
'Add a new column' => 'Lisää uusi sarake',
'Title' => 'Nimi',
'Assigned to %s' => 'Tekijä: %s',
@@ -88,7 +87,6 @@ return array(
'(VACUUM command)' => '(VACUUM-komento)',
'(Gzip compressed Sqlite file)' => '(Gzip-pakattu Sqlite-tiedosto)',
'Close a task' => 'Sulje tehtävä',
- 'Edit a task' => 'Muokkaa tehtävää',
'Column' => 'Sarake',
'Color' => 'Väri',
'Assignee' => 'Suorittaja',
diff --git a/app/Locale/fr_FR/translations.php b/app/Locale/fr_FR/translations.php
index e7184949..71b8ace5 100644
--- a/app/Locale/fr_FR/translations.php
+++ b/app/Locale/fr_FR/translations.php
@@ -68,7 +68,6 @@ return array(
'Do you really want to remove this project: "%s"?' => 'Voulez-vous vraiment supprimer ce projet : « %s » ?',
'Remove project' => 'Supprimer le projet',
'Edit the board for "%s"' => 'Modifier le tableau pour « %s »',
- 'All projects' => 'Tous les projets',
'Add a new column' => 'Ajouter une nouvelle colonne',
'Title' => 'Titre',
'Assigned to %s' => 'Assigné à %s',
@@ -88,7 +87,6 @@ return array(
'(VACUUM command)' => '(Commande VACUUM)',
'(Gzip compressed Sqlite file)' => '(Fichier Sqlite compressé en Gzip)',
'Close a task' => 'Fermer une tâche',
- 'Edit a task' => 'Modifier une tâche',
'Column' => 'Colonne',
'Color' => 'Couleur',
'Assignee' => 'Personne assignée',
diff --git a/app/Locale/hu_HU/translations.php b/app/Locale/hu_HU/translations.php
index 32e34857..c5900fb5 100644
--- a/app/Locale/hu_HU/translations.php
+++ b/app/Locale/hu_HU/translations.php
@@ -68,7 +68,6 @@ return array(
'Do you really want to remove this project: "%s"?' => 'Valóban törölni akarja ezt a projektet: "%s"?',
'Remove project' => 'Projekt törlése',
'Edit the board for "%s"' => 'Tábla szerkesztése: "%s"',
- 'All projects' => 'Minden projekt',
'Add a new column' => 'Új oszlop',
'Title' => 'Cím',
'Assigned to %s' => 'Felelős: %s',
@@ -88,7 +87,6 @@ return array(
'(VACUUM command)' => '(VACUUM parancs)',
'(Gzip compressed Sqlite file)' => '(Gzip tömörített SQLite fájl)',
'Close a task' => 'Feladat lezárása',
- 'Edit a task' => 'Feladat módosítása',
'Column' => 'Oszlop',
'Color' => 'Szín',
'Assignee' => 'Felelős',
diff --git a/app/Locale/id_ID/translations.php b/app/Locale/id_ID/translations.php
index 28f590a9..22b6a75e 100644
--- a/app/Locale/id_ID/translations.php
+++ b/app/Locale/id_ID/translations.php
@@ -68,7 +68,6 @@ return array(
'Do you really want to remove this project: "%s"?' => 'Apakah anda yakin akan menghapus proyek ini : « %s » ?',
'Remove project' => 'Hapus proyek',
'Edit the board for "%s"' => 'Rubah papan untuk « %s »',
- 'All projects' => 'Semua proyek',
'Add a new column' => 'Tambah kolom baru',
'Title' => 'Judul',
'Assigned to %s' => 'Ditugaskan ke %s',
@@ -88,7 +87,6 @@ return array(
'(VACUUM command)' => '(perintah VACUUM)',
'(Gzip compressed Sqlite file)' => '(File Sqlite yang terkompress Gzip)',
'Close a task' => 'Tutup tugas',
- 'Edit a task' => 'Edit tugas',
'Column' => 'Kolom',
'Color' => 'Warna',
'Assignee' => 'Orang yang ditugaskan',
@@ -813,166 +811,166 @@ return array(
'Documentation' => 'Dokumentasi',
'Table of contents' => 'Daftar isi',
'Gantt' => 'Gantt',
- // 'Author' => '',
- // 'Version' => '',
- // 'Plugins' => '',
- // 'There is no plugin loaded.' => '',
- // 'My notifications' => '',
- // 'Custom filters' => '',
- // 'Your custom filter have been created successfully.' => '',
- // 'Unable to create your custom filter.' => '',
- // 'Custom filter removed successfully.' => '',
- // 'Unable to remove this custom filter.' => '',
- // 'Edit custom filter' => '',
- // 'Your custom filter have been updated successfully.' => '',
- // 'Unable to update custom filter.' => '',
- // 'Web' => '',
- // 'New attachment on task #%d: %s' => '',
- // 'New comment on task #%d' => '',
- // 'Comment updated on task #%d' => '',
- // 'New subtask on task #%d' => '',
- // 'Subtask updated on task #%d' => '',
- // 'New task #%d: %s' => '',
- // 'Task updated #%d' => '',
- // 'Task #%d closed' => '',
- // 'Task #%d opened' => '',
- // 'Column changed for task #%d' => '',
- // 'New position for task #%d' => '',
- // 'Swimlane changed for task #%d' => '',
- // 'Assignee changed on task #%d' => '',
- // '%d overdue tasks' => '',
- // 'Task #%d is overdue' => '',
- // 'No new notifications.' => '',
- // 'Mark all as read' => '',
- // 'Mark as read' => '',
- // 'Total number of tasks in this column across all swimlanes' => '',
- // 'Collapse swimlane' => '',
- // 'Expand swimlane' => '',
- // 'Add a new filter' => '',
- // 'Share with all project members' => '',
- // 'Shared' => '',
- // 'Owner' => '',
- // 'Unread notifications' => '',
- // 'Notification methods:' => '',
- // 'Import tasks from CSV file' => '',
- // 'Unable to read your file' => '',
- // '%d task(s) have been imported successfully.' => '',
- // 'Nothing have been imported!' => '',
- // 'Import users from CSV file' => '',
- // '%d user(s) have been imported successfully.' => '',
- // 'Comma' => '',
- // 'Semi-colon' => '',
- // 'Tab' => '',
- // 'Vertical bar' => '',
- // 'Double Quote' => '',
- // 'Single Quote' => '',
- // '%s attached a file to the task #%d' => '',
- // 'There is no column or swimlane activated in your project!' => '',
- // 'Append filter (instead of replacement)' => '',
- // 'Append/Replace' => '',
- // 'Append' => '',
- // 'Replace' => '',
- // 'Import' => '',
- // 'change sorting' => '',
- // 'Tasks Importation' => '',
- // 'Delimiter' => '',
- // 'Enclosure' => '',
- // 'CSV File' => '',
- // 'Instructions' => '',
- // 'Your file must use the predefined CSV format' => '',
- // 'Your file must be encoded in UTF-8' => '',
- // 'The first row must be the header' => '',
- // 'Duplicates are not verified for you' => '',
- // 'The due date must use the ISO format: YYYY-MM-DD' => '',
- // 'Download CSV template' => '',
- // 'No external integration registered.' => '',
- // 'Duplicates are not imported' => '',
- // 'Usernames must be lowercase and unique' => '',
- // 'Passwords will be encrypted if present' => '',
- // '%s attached a new file to the task %s' => '',
+ 'Author' => 'Penulis',
+ 'Version' => 'Versi',
+ 'Plugins' => 'Plugin',
+ 'There is no plugin loaded.' => 'Tidak ada plugin yang dimuat',
+ 'My notifications' => 'Notifikasi saya',
+ 'Custom filters' => 'Filter kustom',
+ 'Your custom filter have been created successfully.' => 'Filter kustom anda telah berhasil dibuat',
+ 'Unable to create your custom filter.' => 'Tidak dapat membuat filter kustom',
+ 'Custom filter removed successfully.' => 'Filter kustom berhail dihapus',
+ 'Unable to remove this custom filter.' => 'Tidak dapat menghapus filter kustom',
+ 'Edit custom filter' => 'Modifikasi filter kustom',
+ 'Your custom filter have been updated successfully.' => 'Filter kustom anda telah berhasil diperbaharui',
+ 'Unable to update custom filter.' => 'Tidak dapat memperbaharui filter kustom',
+ 'Web' => 'Web',
+ 'New attachment on task #%d: %s' => 'Lampiran baru pada tugas #%d: %s',
+ 'New comment on task #%d' => 'Komentar baru pada tugas #%d',
+ 'Comment updated on task #%d' => 'Komentar diperbaharui pada tugas #%d',
+ 'New subtask on task #%d' => 'Subtask baru pada tugas #%d',
+ 'Subtask updated on task #%d' => 'Subtask diperbaharui pada tugas #%d',
+ 'New task #%d: %s' => 'Tugas baru #%d: %s',
+ 'Task updated #%d' => 'Tugas diperbaharui #%d',
+ 'Task #%d closed' => 'Tugas #%d ditutup',
+ 'Task #%d opened' => 'Tugas #%d dibuka',
+ 'Column changed for task #%d' => 'Kolom berubah untuk tugas #%d',
+ 'New position for task #%d' => 'Posisi baru untuk tugas #%d',
+ 'Swimlane changed for task #%d' => 'Swimlane berubah untuk tugas #%d',
+ 'Assignee changed on task #%d' => 'Orang yang ditugaskan berubah pada tugas #%d',
+ '%d overdue tasks' => '%d tugas terlambat',
+ 'Task #%d is overdue' => 'Tugas #%d terlambat',
+ 'No new notifications.' => '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 jumlah tugas di kolom ini di semua swimlanes',
+ 'Collapse swimlane' => 'Lipat swimlane',
+ 'Expand swimlane' => 'Perluas swimlane',
+ 'Add a new filter' => 'Tambah filter baru',
+ 'Share with all project members' => 'Bagikan dengan semua member proyek',
+ 'Shared' => 'Dibagikan',
+ 'Owner' => 'Pemilik',
+ 'Unread notifications' => 'Notifikasi belum terbaca',
+ 'Notification methods:' => 'Metode pemberitahuan',
+ 'Import tasks from CSV file' => 'Impor tugas dari berkas CSV',
+ 'Unable to read your file' => 'Tidak dapat membaca berkas anda',
+ '%d task(s) have been imported successfully.' => '%d tugas telah berhasil di impor',
+ 'Nothing have been imported!' => 'Tidak ada yang dapat di impor',
+ 'Import users from CSV file' => 'Impor pengguna dari berkas CSV',
+ '%d user(s) have been imported successfully.' => '%d pengguna telah berhasil di impor',
+ 'Comma' => 'Koma',
+ 'Semi-colon' => 'Titik Koma',
+ 'Tab' => 'Tab',
+ 'Vertical bar' => 'Bar vertikal',
+ 'Double Quote' => 'Kutip Ganda',
+ 'Single Quote' => 'Kutip Satu',
+ '%s attached a file to the task #%d' => '%s berkas dilampirkan untuk tugas #%d',
+ 'There is no column or swimlane activated in your project!' => 'Tidak ada kolom atau swimlane aktif untuk proyek anda',
+ 'Append filter (instead of replacement)' => 'Tambahkan filter (bukan pengganti)',
+ 'Append/Replace' => 'Tambah/Ganti',
+ 'Append' => 'Tambahkan',
+ 'Replace' => 'Ganti',
+ 'Import' => 'Impor',
+ 'change sorting' => 'rubah sortir',
+ 'Tasks Importation' => 'Tugas Impor',
+ 'Delimiter' => 'Pembatas',
+ 'Enclosure' => 'Lampiran',
+ 'CSV File' => 'Berkas CSV',
+ 'Instructions' => 'Intruksi',
+ 'Your file must use the predefined CSV format' => 'Berkas Anda harus menggunakan format CSV yang telah ditetapkan',
+ 'Your file must be encoded in UTF-8' => 'Berkas anda harus di kodekan dalam bentuk UTF-8',
+ 'The first row must be the header' => 'Baris pertama harus header',
+ 'Duplicates are not verified for you' => 'Duplikasi tidak diverifikasi untuk anda',
+ 'The due date must use the ISO format: YYYY-MM-DD' => 'Tanggal jatuh tempo harus menggunakan format ISO: YYYY-MM-DD',
+ 'Download CSV template' => 'Unduh template CSV',
+ 'No external integration registered.' => 'Tidak ada integrasi eksternal terdaftar',
+ 'Duplicates are not imported' => 'Duplikasi tidak diimpor',
+ 'Usernames must be lowercase and unique' => 'Username harus huruf kecil dan unik',
+ 'Passwords will be encrypted if present' => 'Kata sandi akan di enkripsi jika ada',
+ '%s attached a new file to the task %s' => '%s berkas baru dilampirkan untuk tugas %s',
'Link type' => 'Tipe tautan',
- // 'Assign automatically a category based on a link' => '',
- // 'BAM - Konvertible Mark' => '',
- // 'Assignee Username' => '',
- // 'Assignee Name' => '',
- // 'Groups' => '',
- // 'Members of %s' => '',
- // 'New group' => '',
- // 'Group created successfully.' => '',
- // 'Unable to create your group.' => '',
- // 'Edit group' => '',
- // 'Group updated successfully.' => '',
- // 'Unable to update your group.' => '',
- // 'Add group member to "%s"' => '',
- // 'Group member added successfully.' => '',
- // 'Unable to add group member.' => '',
- // 'Remove user from group "%s"' => '',
- // 'User removed successfully from this group.' => '',
- // 'Unable to remove this user from the group.' => '',
- // 'Remove group' => '',
- // 'Group removed successfully.' => '',
- // 'Unable to remove this group.' => '',
- // 'Project Permissions' => '',
- // 'Manager' => '',
- // 'Project Manager' => '',
- // 'Project Member' => '',
- // 'Project Viewer' => '',
- // 'Your account is locked for %d minutes' => '',
- // 'Invalid captcha' => '',
- // 'The name must be unique' => '',
- // 'View all groups' => '',
- // 'There is no user available.' => '',
- // 'Do you really want to remove the user "%s" from the group "%s"?' => '',
- // 'There is no group.' => '',
- // 'External Id' => '',
- // 'Add group member' => '',
- // 'Do you really want to remove this group: "%s"?' => '',
- // 'There is no user in this group.' => '',
- // 'Remove this user' => '',
- // 'Permissions' => '',
- // 'Allowed Users' => '',
- // 'No user have been allowed specifically.' => '',
- // 'Role' => '',
- // 'Enter user name...' => '',
- // 'Allowed Groups' => '',
- // 'No group have been allowed specifically.' => '',
- // 'Group' => '',
- // 'Group Name' => '',
- // 'Enter group name...' => '',
- // 'Role:' => '',
+ 'Assign automatically a category based on a link' => 'Menetapkan otomatis kategori berdasarkan tautan',
+ 'BAM - Konvertible Mark' => 'BAM - Konvertible Mark',
+ 'Assignee Username' => 'Username yang ditugaskan',
+ 'Assignee Name' => 'Nama yang ditugaskan',
+ 'Groups' => 'Grup',
+ 'Members of %s' => 'Anggota dari %s',
+ 'New group' => 'Grup baru',
+ 'Group created successfully.' => 'Grup berhasil dibuat',
+ 'Unable to create your group.' => 'Tidak dapat membuat grup anda',
+ 'Edit group' => 'Rubah grup',
+ 'Group updated successfully.' => 'Grup berhasil diperbaharui',
+ 'Unable to update your group.' => 'Tidak dapat memperbaharui grup anda',
+ 'Add group member to "%s"' => 'Tambahkan anggota grup ke "%s"',
+ 'Group member added successfully.' => 'Anggota grup berhasil ditambahkan',
+ 'Unable to add group member.' => 'Tidak dapat menambahkan anggota grup',
+ 'Remove user from group "%s"' => 'hapus pengguna dari grup "%s"',
+ 'User removed successfully from this group.' => 'Pengguna berhasil dihapus dari grup ini',
+ 'Unable to remove this user from the group.' => 'Tidak dapat menghapus pengguna dari grup',
+ 'Remove group' => 'Hapus grup',
+ 'Group removed successfully.' => 'Grup berhasil dihapus',
+ 'Unable to remove this group.' => 'Tidak dapat menghapus grup ini',
+ 'Project Permissions' => 'Izin Proyek',
+ 'Manager' => 'Manajer',
+ 'Project Manager' => 'Manajer Proyek',
+ 'Project Member' => 'Anggota Proyek',
+ 'Project Viewer' => 'Penonton Proyek',
+ 'Your account is locked for %d minutes' => 'Akun anda dikunci untuk %d menit',
+ 'Invalid captcha' => 'Captcha tidak valid',
+ 'The name must be unique' => 'Nama harus unik',
+ 'View all groups' => 'Lihat semua grup',
+ 'There is no user available.' => 'Tidak ada pengguna yang tersedia',
+ 'Do you really want to remove the user "%s" from the group "%s"?' => 'Anda yakin akan menghapus pengguna "%s" dari grup "%s"?',
+ 'There is no group.' => 'Tidak ada grup',
+ 'External Id' => 'Id Eksternal',
+ 'Add group member' => 'Tambah anggota grup',
+ 'Do you really want to remove this group: "%s"?' => 'Anda yakin akan menghapus grup ini: "%s"?',
+ 'There is no user in this group.' => 'Tidak ada pengguna dalam grup ini',
+ 'Remove this user' => 'Hapus pengguna ini',
+ 'Permissions' => 'Izin',
+ 'Allowed Users' => 'Pengguna Yang Diperbolehkan',
+ 'No user have been allowed specifically.' => 'Tidak ada user yang diperbolehkan secara khusus',
+ 'Role' => 'Peran',
+ 'Enter user name...' => 'Masukkan nama pengguna...',
+ 'Allowed Groups' => 'Grup Yang Diperbolehkan',
+ 'No group have been allowed specifically.' => 'Tidak ada grup yang diperbolehkan secara khusus',
+ 'Group' => 'Grup',
+ 'Group Name' => 'Nama Grup',
+ 'Enter group name...' => 'Masukkan nama grup...',
+ 'Role:' => 'Peran:',
'Project members' => 'Anggota proyek',
- // '%s mentioned you in the task #%d' => '',
- // '%s mentioned you in a comment on the task #%d' => '',
- // 'You were mentioned in the task #%d' => '',
- // 'You were mentioned in a comment on the task #%d' => '',
- // 'Estimated hours: ' => '',
- // 'Actual hours: ' => '',
- // 'Hours Spent' => '',
- // 'Hours Estimated' => '',
- // 'Estimated Time' => '',
- // 'Actual Time' => '',
- // 'Estimated vs actual time' => '',
- // 'RUB - Russian Ruble' => '',
- // 'Assign the task to the person who does the action when the column is changed' => '',
- // 'Close a task in a specific column' => '',
- // 'Time-based One-time Password Algorithm' => '',
- // 'Two-Factor Provider: ' => '',
- // 'Disable two-factor authentication' => '',
- // 'Enable two-factor authentication' => '',
- // 'There is no integration registered at the moment.' => '',
- // 'Password Reset for Kanboard' => '',
- // 'Forgot password?' => '',
- // 'Enable "Forget Password"' => '',
- // 'Password Reset' => '',
- // 'New password' => '',
- // 'Change Password' => '',
- // 'To reset your password click on this link:' => '',
- // 'Last Password Reset' => '',
- // 'The password has never been reinitialized.' => '',
- // 'Creation' => '',
- // 'Expiration' => '',
- // 'Password reset history' => '',
- // 'All tasks of the column "%s" and the swimlane "%s" have been closed successfully.' => '',
+ '%s mentioned you in the task #%d' => '%s menyebut anda dalam tugas #%d',
+ '%s mentioned you in a comment on the task #%d' => '%s menyebut anda dalam komentar pada tugas #%d',
+ 'You were mentioned in the task #%d' => 'Anda disebutkan dalam tugas #%d',
+ 'You were mentioned in a comment on the task #%d' => 'Anda disebutkan dalam komentar pada tugas #%d',
+ 'Estimated hours: ' => 'Estimasi jam:',
+ 'Actual hours: ' => 'Aktual jam',
+ 'Hours Spent' => 'Jam dihabiskan',
+ 'Hours Estimated' => 'Jam diperkirakan',
+ 'Estimated Time' => 'Waktu Estimasi',
+ 'Actual Time' => 'Waktu Aktual',
+ 'Estimated vs actual time' => 'Estimasi vs waktu aktual',
+ 'RUB - Russian Ruble' => 'RUB - Rusia rubel',
+ 'Assign the task to the person who does the action when the column is changed' => 'Menetapkan tugas kepada orang yang melakukan tindakan ketika kolom berubah',
+ 'Close a task in a specific column' => 'Tutup tugas di kolom tertentu',
+ 'Time-based One-time Password Algorithm' => 'Waktu berbasis Satu-waktu Algoritma Kata sandi',
+ 'Two-Factor Provider: ' => 'Provider Dua-Faktor',
+ 'Disable two-factor authentication' => 'Nonaktifkan otentikasi dua-faktor',
+ 'Enable two-factor authentication' => 'Aktifkan otentikasi dua-faktor',
+ 'There is no integration registered at the moment.' => 'Tidak ada integrasi yang diregristasi untuk saat ini',
+ 'Password Reset for Kanboard' => 'Setel ulang Kata sandi untuk Kanboard',
+ 'Forgot password?' => 'Lupa kata sandi',
+ 'Enable "Forget Password"' => 'Aktifkan "Lupa Kata Sandi"',
+ 'Password Reset' => 'Setel ulang Kata sandi',
+ 'New password' => 'Kata sandi baru',
+ 'Change Password' => 'Rubah kata sandi',
+ 'To reset your password click on this link:' => 'Untuk menyetel ulang kata sandi anda klik tautan ini:',
+ 'Last Password Reset' => 'Terakhir Setel Ulang Kata Sandi',
+ 'The password has never been reinitialized.' => 'Kata sandi tidak pernah di reinisialisasi',
+ 'Creation' => 'Kreasi',
+ 'Expiration' => 'Waktu berakhir',
+ 'Password reset history' => 'Sejarah setel ulang kata sandi',
+ 'All tasks of the column "%s" and the swimlane "%s" have been closed successfully.' => 'Semua tugas dalam kolom "%s" dan swimlane "%s" telah berhasil ditutup',
// 'Do you really want to close all tasks of this column?' => '',
// '%d task(s) in the column "%s" and the swimlane "%s" will be closed.' => '',
// 'Close all tasks of this column' => '',
diff --git a/app/Locale/it_IT/translations.php b/app/Locale/it_IT/translations.php
index b72ca181..1f6539b7 100644
--- a/app/Locale/it_IT/translations.php
+++ b/app/Locale/it_IT/translations.php
@@ -68,7 +68,6 @@ return array(
'Do you really want to remove this project: "%s"?' => 'Vuoi davvero eliminare il seguente progetto: "%s" ?',
'Remove project' => 'Cancella il progetto',
'Edit the board for "%s"' => 'Modifica la bacheca per "%s"',
- 'All projects' => 'Tutti i progetti',
'Add a new column' => 'Aggiungi una nuova colonna',
'Title' => 'Titolo',
'Assigned to %s' => 'Assegnato a %s',
@@ -88,7 +87,6 @@ return array(
'(VACUUM command)' => '(Comando VACUUM)',
'(Gzip compressed Sqlite file)' => '(File Sqlite compresso in Gzip)',
'Close a task' => 'Chiudi un task',
- 'Edit a task' => 'Modifica un task',
'Column' => 'Colonna',
'Color' => 'Colore',
'Assignee' => 'Assegnatario',
diff --git a/app/Locale/ja_JP/translations.php b/app/Locale/ja_JP/translations.php
index d3a11fc8..24dae922 100644
--- a/app/Locale/ja_JP/translations.php
+++ b/app/Locale/ja_JP/translations.php
@@ -68,7 +68,6 @@ return array(
'Do you really want to remove this project: "%s"?' => 'プロジェクト「%s」を本当に削除しますか?',
'Remove project' => 'プロジェクトの削除',
'Edit the board for "%s"' => 'ボード「%s」を変更する',
- 'All projects' => 'すべてのプロジェクト',
'Add a new column' => 'カラムの追加',
'Title' => 'タイトル',
'Assigned to %s' => '%sが担当',
@@ -88,7 +87,6 @@ return array(
'(VACUUM command)' => '(VACUUM コマンド)',
'(Gzip compressed Sqlite file)' => '(GZip コマンドで圧縮された Sqlite ファイル)',
'Close a task' => 'タスクをクロースする',
- 'Edit a task' => 'タスクを変更する',
'Column' => 'カラム',
'Color' => '色',
'Assignee' => '担当',
diff --git a/app/Locale/ko_KR/translations.php b/app/Locale/ko_KR/translations.php
index b8ec0c81..19b1f5fd 100644
--- a/app/Locale/ko_KR/translations.php
+++ b/app/Locale/ko_KR/translations.php
@@ -68,14 +68,13 @@ return array(
'Do you really want to remove this project: "%s"?' => '프로젝트를 삭제하시겠습니까: "%s"?',
'Remove project' => '프로젝트의 삭제',
'Edit the board for "%s"' => '"%s"를 위한 보드 수정',
- 'All projects' => '모든 프로젝트',
- 'Add a new column' => '칼럼의 추가',
+ 'Add a new column' => '컬럼의 추가',
'Title' => '제목',
'Assigned to %s' => '담당자 %s',
- 'Remove a column' => '칼럼 삭제',
- 'Remove a column from a board' => '보드에서 칼럼 삭제',
+ 'Remove a column' => '컬럼 삭제',
+ 'Remove a column from a board' => '보드에서 컬럼 삭제',
'Unable to remove this column.' => '(※)컬럼을 삭제할 수 없었습니다.',
- 'Do you really want to remove this column: "%s"?' => '칼럼을 삭제하시겠습니까: "%s"?',
+ 'Do you really want to remove this column: "%s"?' => '컬럼을 삭제하시겠습니까: "%s"?',
'This action will REMOVE ALL TASKS associated to this column!' => '이 조작은 이 컬럼에 할당된 『 모든 할일을 삭제 』합니다!',
'Settings' => '설정',
'Application settings' => '애플리케이션의 설정',
@@ -88,8 +87,7 @@ return array(
'(VACUUM command)' => '(VACUUM명령)',
'(Gzip compressed Sqlite file)' => '(GZip명령으로 압축된 Sqlite파일)',
'Close a task' => '할일 마치기',
- 'Edit a task' => '할일 수정',
- 'Column' => '칼럼',
+ 'Column' => '컬럼',
'Color' => '색',
'Assignee' => '담당자',
'Create another task' => '다른 할일 추가',
@@ -98,7 +96,7 @@ return array(
'Do you really want to open this task: "%s"?' => '할일은 시작 하시겠습니까: "%s"?',
'Back to the board' => '보드로 돌아가기',
'There is nobody assigned' => '담당자가 없습니다',
- 'Column on the board:' => '칼럼:',
+ 'Column on the board:' => '컬럼:',
'Close this task' => '할일 마치기',
'Open this task' => '할일을 열다',
'There is no description.' => '설명이 없다',
@@ -190,12 +188,12 @@ return array(
'Assign the task to a specific user' => '할일 담당자를 할당',
'Assign the task to the person who does the action' => '액션을 일으킨 사용자를 담당자이자',
'Duplicate the task to another project' => ' 다른 프로젝트에 할일을 복제하는 ',
- 'Move a task to another column' => '할일을 다른 칼럼에 이동하는 ',
+ 'Move a task to another column' => '할일을 다른 컬럼에 이동하는 ',
'Task modification' => '할일 변경',
'Task creation' => '할일을 만들',
'Closing a task' => '할일을 닫혔다',
'Assign a color to a specific user' => '색을 사용자에 할당',
- 'Column title' => '칼럼의 제목',
+ 'Column title' => '컬럼의 제목',
'Position' => '위치',
'Duplicate to another project' => '다른 프로젝트에 복사',
'Duplicate' => '복사',
@@ -362,7 +360,7 @@ return array(
'%s updated the task %s' => '%s이 할일 %s을 갱신 하였습니다',
'%s opened the task %s' => '%s이 할일 %s을 시작시켰습니다',
'%s moved the task %s to the position #%d in the column "%s"' => '%s이 할일%s을 위치#%d컬럼%s로 옮겼습니다',
- '%s moved the task %s to the column "%s"' => '%s이 할일 %s을 칼럼 "%s" 로 옮겼습니다',
+ '%s moved the task %s to the column "%s"' => '%s이 할일 %s을 컬럼 "%s" 로 옮겼습니다',
'%s created the task %s' => '%s이 할일%s을 추가했습니다',
'%s closed the task %s' => '%s이 할일%s을 마쳤습니다',
'%s created a subtask for the task %s' => '%s이 할일%s의 서브 할일을 추가했습니다',
@@ -383,7 +381,7 @@ return array(
'%s opened the task #%d' => '%s이 할일#%d를 오픈했습니다',
'Activity' => '활동',
'Default values are "%s"' => '기본 값은 "%s" 입니다',
- 'Default columns for new projects (Comma-separated)' => '새로운 프로젝트의 기본 칼럼 (콤마(,)로 분리됨)',
+ 'Default columns for new projects (Comma-separated)' => '새로운 프로젝트의 기본 컬럼 (콤마(,)로 분리됨)',
'Task assignee change' => '담당자의 변경',
'%s changed the assignee of the task #%d to %s' => '%s이 할일 #%d의 담당을 %s로 변경합니다',
'%s changed the assignee of the task %s to %s' => '%s이 할일 %s의 담당을 %s로 변경했습니다',
@@ -428,7 +426,7 @@ return array(
'Create a comment from an external provider' => '외부 서비스로부터 의견을 작성한다',
'Project management' => '프로젝트 관리',
'My projects' => '내 프로젝트',
- 'Columns' => '칼럼',
+ 'Columns' => '컬럼',
'Task' => '할일',
'Your are not member of any project.' => '어떤 프로젝트에도 속하지 않습니다.',
'Percentage' => '비중',
@@ -486,16 +484,16 @@ return array(
'Application default' => '애플리케이션 기본',
'Language:' => '언어:',
'Timezone:' => '시간대:',
- 'All columns' => '모든 칼럼',
+ 'All columns' => '모든 컬럼',
'Calendar' => '달력',
'Next' => '다음에 ',
'#%d' => '#%d',
'All swimlanes' => '모든 스윔레인',
'All colors' => '모든 색',
- 'Moved to column %s' => '"%s" 칼럼으로 이동',
+ 'Moved to column %s' => '"%s" 컬럼으로 이동',
'User dashboard' => '대시보드',
'Allow only one subtask in progress at the same time for a user' => '한 사용자에 대한 하나의 할일만 진행 중에 가능합니다',
- 'Edit column "%s"' => '"%s" 칼럼 수정',
+ 'Edit column "%s"' => '"%s" 컬럼 수정',
'Select the new status of the subtask: "%s"' => '서브 할일의 새로운 상태 선택: "%s"',
'Subtask timesheet' => '서브 할일 타임시트',
'There is nothing to show.' => '기록이 없습니다',
@@ -506,7 +504,7 @@ return array(
'Start' => '시작',
'End' => '종료',
'Task age in days' => '할일이 생긴 시간',
- 'Days in this column' => '이 칼럼에 있는 시간',
+ 'Days in this column' => '이 컬럼에 있는 시간',
'%dd' => '%d일',
'Add a new link' => ' 새로운 링크 추가',
'Do you really want to remove this link: "%s"?' => '링크를 삭제하시겠습니까: "%s"?',
@@ -569,16 +567,16 @@ return array(
// 'NZD - New Zealand Dollar' => '',
// 'RSD - Serbian dinar' => '',
// 'USD - US Dollar' => '',
- 'Destination column' => '이동 후 칼럼',
- 'Move the task to another column when assigned to a user' => '사용자의 할당을 하면 할일을 다른 칼럼에 이동',
- 'Move the task to another column when assignee is cleared' => '사용자의 할당이 없어지면 할일을 다른 칼럼에 이동',
- 'Source column' => '이동 전 칼럼',
+ 'Destination column' => '이동 후 컬럼',
+ 'Move the task to another column when assigned to a user' => '사용자의 할당을 하면 할일을 다른 컬럼에 이동',
+ 'Move the task to another column when assignee is cleared' => '사용자의 할당이 없어지면 할일을 다른 컬럼에 이동',
+ 'Source column' => '이동 전 컬럼',
'Transitions' => '이력',
'Executer' => '실행자',
- 'Time spent in the column' => '칼럼에 있던 시간',
+ 'Time spent in the column' => '컬럼에 있던 시간',
'Task transitions' => '할일 천이',
'Task transitions export' => '할일 천이를 출력',
- 'This report contains all column moves for each task with the date, the user and the time spent for each transition.' => '이 리포트는 할일의 칼럼 간 이동을 시간, 유저, 경과 시간과 함께 기록한 것입니다.',
+ 'This report contains all column moves for each task with the date, the user and the time spent for each transition.' => '이 리포트는 할일의 컬럼 간 이동을 시간, 유저, 경과 시간과 함께 기록한 것입니다.',
'Currency rates' => '환율',
'Rate' => '레이트',
'Change reference currency' => '현재의 기축 통화',
@@ -599,7 +597,7 @@ return array(
'Check my code' => '코드 체크',
'Secret key: ' => '비밀키: ',
'Test your device' => '디바이스 테스트',
- 'Assign a color when the task is moved to a specific column' => '상세 칼럼으로 이동할 할일의 색깔을 지정하세요',
+ 'Assign a color when the task is moved to a specific column' => '상세 컬럼으로 이동할 할일의 색깔을 지정하세요',
'%s via Kanboard' => '%s via E-board',
'Burndown chart' => '번다운 차트',
// 'This chart show the task complexity over the time (Work Remaining).' => '',
@@ -639,8 +637,8 @@ return array(
'Timeframe to calculate new due date: ' => '종료날짜 계산 단위',
// 'Trigger to generate recurrent task: ' => '',
'When task is closed' => '할일을 마쳤을때',
- 'When task is moved from first column' => '할일이 첫번째 칼럼으로 옮겨졌을때',
- 'When task is moved to last column' => '할일이 마지막 칼럼으로 옮겨졌을때',
+ 'When task is moved from first column' => '할일이 첫번째 컬럼으로 옮겨졌을때',
+ 'When task is moved to last column' => '할일이 마지막 컬럼으로 옮겨졌을때',
'Year(s)' => '년',
'Calendar settings' => '달력 설정',
'Project calendar view' => '프로젝트 달력 보기',
@@ -661,8 +659,8 @@ return array(
'User that will receive the email' => '그 담당자가 이메일을 수신할 것입니다',
'Email subject' => '이메일 제목',
'Date' => '날짜',
- 'Add a comment log when moving the task between columns' => '칼럼 중간의 할일이 이동할 때 의견 달기',
- 'Move the task to another column when the category is changed' => '카테고리 변경시 할일을 다른 칼럼으로 이동',
+ 'Add a comment log when moving the task between columns' => '컬럼 중간의 할일이 이동할 때 의견 달기',
+ 'Move the task to another column when the category is changed' => '카테고리 변경시 할일을 다른 컬럼으로 이동',
'Send a task by email to someone' => '할일을 이메일로 보내기',
'Reopen a task' => '할일 다시 시작',
'Notification' => '알림',
@@ -698,7 +696,7 @@ return array(
'Only for tasks created by me' => '내가 만든 일',
'Only for tasks created by me and assigned to me' => '내가 만들었거나 내가 담당자인 일',
// '%%Y-%%m-%%d' => '',
- 'Total for all columns' => '모든 칼럼',
+ 'Total for all columns' => '모든 컬럼',
'You need at least 2 days of data to show the chart.' => '차트를 보기 위하여 최소 2일의 데이터가 필요합니다',
'<15m' => '<15분',
'<30m' => '<30분',
@@ -731,7 +729,7 @@ return array(
'Advanced search' => '검색 문법',
'Example of query: ' => '문법 예제 ',
'Search by project: ' => '프로젝트로 찾기 ',
- 'Search by column: ' => '칼럼으로 찾기 ',
+ 'Search by column: ' => '컬럼으로 찾기 ',
'Search by assignee: ' => '담당자로 찾기 ',
'Search by color: ' => '색깔로 찾기 ',
'Search by category: ' => '카테고리로 찾기 ',
@@ -739,18 +737,18 @@ return array(
'Search by due date: ' => '마감날짜로 찾기 ',
'Average time spent into each column' => '각 칼럼의 평균 소요시간',
'Average time spent' => '평균 소요시간',
- 'This chart show the average time spent into each column for the last %d tasks.' => '마지막 %d 할일의 칼럼 평균 소요시간을 차트에 표시합니다',
+ 'This chart show the average time spent into each column for the last %d tasks.' => '마지막 %d 할일의 컬럼 평균 소요시간을 차트에 표시합니다',
'Average Lead and Cycle time' => '평균 Lead and Cycle 시간',
'Average lead time: ' => '평균 lead 시간',
'Average cycle time: ' => '평균 cycle 시간',
'Cycle Time' => '사이클 시간',
'Lead Time' => '리드 시간',
'This chart show the average lead and cycle time for the last %d tasks over the time.' => '마지막 %d 할일의 평균 리드와 사이클 시간을 차트에 표시합니다',
- 'Average time into each column' => '각 칼럼의 평균 시간',
+ 'Average time into each column' => '각 컬럼의 평균 시간',
'Lead and cycle time' => '리드와 사이클 시간',
'Lead time: ' => '리드 시간: ',
'Cycle time: ' => '사이클 시간: ',
- 'Time spent into each column' => '각 칼럼에서 걸린 시간',
+ 'Time spent into each column' => '각 컬럼에서 걸린 시간',
'The lead time is the duration between the task creation and the completion.' => '리드 시간은 할일의 생성부터 완료까지의 기간입니다',
'The cycle time is the duration between the start date and the completion.' => '사이클 시간은 할일의 시작일부터 완료까지의 기간입니다',
'If the task is not closed the current time is used instead of the completion date.' => '할일이 종료되지 않았다면, 완료 시간 대신 현재 시간이 사용됩니다',
@@ -767,7 +765,7 @@ return array(
'Trigger automatically subtask time tracking' => '자동 서브 할일 시간 트래킹 트리거',
'Include closed tasks in the cumulative flow diagram' => '누적 플로우 다이어그램에 종료된 할일을 포함합니다',
'Current swimlane: %s' => '현재 스웜라인: %s',
- 'Current column: %s' => '현재 칼럼: %s',
+ 'Current column: %s' => '현재 컬럼: %s',
'Current category: %s' => '현재 카테고리: %s',
'no category' => '카테고리 아님',
'Current assignee: %s' => '현재 할당자: %s',
@@ -789,8 +787,8 @@ return array(
'People who are project managers' => '프로젝트 매니저',
'People who are project members' => '프로젝트 멤버',
// 'NOK - Norwegian Krone' => '',
- 'Show this column' => '칼럼 보이기',
- 'Hide this column' => '칼럼 숨기기',
+ 'Show this column' => '컬럼 보이기',
+ 'Hide this column' => '컬럼 숨기기',
'open file' => '열기',
'End date' => '종료 날짜',
'Users overview' => '유저 전체보기',
@@ -836,7 +834,7 @@ return array(
'Task updated #%d' => '할일 #%d이 갱신 되었습니다',
'Task #%d closed' => '할일 #%d를 마쳤습니다',
'Task #%d opened' => '할일 #%d가 시작되었습니다',
- 'Column changed for task #%d' => '할일 #%d의 칼럼이 변경되었습니다',
+ 'Column changed for task #%d' => '할일 #%d의 컬럼이 변경되었습니다',
'New position for task #%d' => '할일 #%d이 새로운 위치에 등록되었습니다',
'Swimlane changed for task #%d' => '#%d 할일의 스웜라인이 변경됩니다',
'Assignee changed on task #%d' => '#%d 할일의 담당자가 변경됩니다',
@@ -867,7 +865,7 @@ return array(
'Double Quote' => '이중 따옴표',
'Single Quote' => '따옴표',
'%s attached a file to the task #%d' => '%s가 할일 #%d에 파일을 추가하였습니다',
- 'There is no column or swimlane activated in your project!' => '프로젝트에 활성화된 칼럼이나 스웜라인이 없습니다',
+ 'There is no column or swimlane activated in your project!' => '프로젝트에 활성화된 컬럼이나 스웜라인이 없습니다',
// 'Append filter (instead of replacement)' => '',
'Append/Replace' => '추가/변경',
'Append' => '추가',
@@ -953,8 +951,8 @@ return array(
'Actual Time' => '실제 시간',
'Estimated vs actual time' => '예상 vs 실제 시간',
// 'RUB - Russian Ruble' => '',
- 'Assign the task to the person who does the action when the column is changed' => '칼럼이 변경되면 액션하지 않는 사람에게 할일을 할당합니다',
- 'Close a task in a specific column' => '상세 칼럼의 할일을 종료합니다',
+ 'Assign the task to the person who does the action when the column is changed' => '컬럼이 변경되면 액션하지 않는 사람에게 할일을 할당합니다',
+ 'Close a task in a specific column' => '상세 컬럼의 할일을 종료합니다',
'Time-based One-time Password Algorithm' => '시간에 기반한 1회용 패스워드 알고리즘',
'Two-Factor Provider: ' => '이중 인증: ',
'Disable two-factor authentication' => '이중 인증 비활성화',
@@ -972,10 +970,10 @@ return array(
'Creation' => '생성',
'Expiration' => '만료',
'Password reset history' => '비밀번호 초기화 기록',
- 'All tasks of the column "%s" and the swimlane "%s" have been closed successfully.' => '칼럼 "%s"와 스웜라인 "%s"의 모든 할일이 성공적으로 종료되었습니다',
- 'Do you really want to close all tasks of this column?' => '이 칼럼의 모든 할일을 종료 하시겠습니까?',
- '%d task(s) in the column "%s" and the swimlane "%s" will be closed.' => '칼럼 "%s"와 스웜라인 "%s"의 할일 %d가 종료될 것입니다',
- 'Close all tasks of this column' => '칼럼의 모든 할일 마치기',
+ 'All tasks of the column "%s" and the swimlane "%s" have been closed successfully.' => '컬럼 "%s"와 스웜라인 "%s"의 모든 할일이 성공적으로 종료되었습니다',
+ 'Do you really want to close all tasks of this column?' => '이 컬럼의 모든 할일을 종료 하시겠습니까?',
+ '%d task(s) in the column "%s" and the swimlane "%s" will be closed.' => '컬럼 "%s"와 스웜라인 "%s"의 할일 %d가 종료될 것입니다',
+ 'Close all tasks of this column' => '컬럼의 모든 할일 마치기',
'No plugin has registered a project notification method. You can still configure individual notifications in your user profile.' => '프로젝트 알림 방법으로 플러그인이 등록되지 않았습니다. 각각의 알림을 프로파일에서 설정하실 수 있습니다',
'My dashboard' => '대시보드',
'My profile' => '프로필',
@@ -1027,7 +1025,7 @@ return array(
'Reference:' => '참고:',
'Complexity:' => '복합:',
'Swimlane:' => '스웜라인:',
- 'Column:' => '칼럼:',
+ 'Column:' => '컬럼:',
'Position:' => '위치:',
'Creator:' => '생성자:',
'Time estimated:' => '예상 시간:',
@@ -1070,11 +1068,11 @@ return array(
'Uploaded by %s' => '%s로 올리기',
'Filename' => '파일 이름',
'Size' => '크기',
- 'Column created successfully.' => '칼럼이 성공적으로 생성되었습니다',
- 'Another column with the same name exists in the project' => '프로젝트에 동일한 이름의 칼럼이 있습니다',
+ 'Column created successfully.' => '컬럼이 성공적으로 생성되었습니다',
+ 'Another column with the same name exists in the project' => '프로젝트에 동일한 이름의 컬럼이 있습니다',
'Default filters' => '기본 필터',
- 'Your board doesn\'t have any columns!' => '보드에 칼럼이 존재하지 않습니다',
- 'Change column position' => '칼럼 위치 변경',
+ 'Your board doesn\'t have any columns!' => '보드에 컬럼이 존재하지 않습니다',
+ 'Change column position' => '컬럼 위치 변경',
'Switch to the project overview' => '프로젝트 개요로 변경',
'User filters' => '사용자 필터',
'Category filters' => '카테고리 필터',
@@ -1164,54 +1162,54 @@ return array(
'Email settings' => '이메일 설정',
'Email sender address' => '이메일 보낸이 주소',
'Email transport' => '이메일 전송',
- // 'Webhook token' => '',
+ 'Webhook token' => 'Webhook토큰',
'Imports' => '가져오기',
- // 'Project tags management' => '',
- // 'Tag created successfully.' => '',
- // 'Unable to create this tag.' => '',
- // 'Tag updated successfully.' => '',
- // 'Unable to update this tag.' => '',
- // 'Tag removed successfully.' => '',
- // 'Unable to remove this tag.' => '',
- // 'Global tags management' => '',
- // 'Tags' => '',
- // 'Tags management' => '',
- // 'Add new tag' => '',
- // 'Edit a tag' => '',
- // 'Project tags' => '',
- // 'There is no specific tag for this project at the moment.' => '',
- // 'Tag' => '',
- // 'Remove a tag' => '',
- // 'Do you really want to remove this tag: "%s"?' => '',
- // 'Global tags' => '',
- // 'There is no global tag at the moment.' => '',
- // 'This field cannot be empty' => '',
- // 'Close a task when there is no activity in an specific column' => '',
- // '%s removed a subtask for the task #%d' => '',
- // '%s removed a comment on the task #%d' => '',
- // 'Comment removed on task #%d' => '',
- // 'Subtask removed on task #%d' => '',
- // 'Hide tasks in this column in the dashboard' => '',
- // '%s removed a comment on the task %s' => '',
- // '%s removed a subtask for the task %s' => '',
- // 'Comment removed' => '',
- // 'Subtask removed' => '',
- // '%s set a new internal link for the task #%d' => '',
- // '%s removed an internal link for the task #%d' => '',
- // 'A new internal link for the task #%d have been defined' => '',
- // 'Internal link removed for the task #%d' => '',
- // '%s set a new internal link for the task %s' => '',
- // '%s removed an internal link for the task %s' => '',
- // 'Automatically set the due date on task creation' => '',
- // 'Move the task to another column when closed' => '',
- // 'Move the task to another column when not moved during a given period' => '',
- // 'Dashboard for %s' => '',
- // 'Tasks overview for %s' => '',
- // 'Subtasks overview for %s' => '',
- // 'Projects overview for %s' => '',
- // 'Activity stream for %s' => '',
- // 'Calendar for %s' => '',
- // 'Notifications for %s' => '',
- // 'Subtasks export' => '',
- // 'Tasks exportation' => '',
+ 'Project tags management' => '프로젝트 태그 관리',
+ 'Tag created successfully.' => '태그가 성공적으로 생성되었습니다.',
+ 'Unable to create this tag.' => '태그를 생성할 수 없습니다.',
+ 'Tag updated successfully.' => '태그가 성공적으로 수정되었습니다.',
+ 'Unable to update this tag.' => '태그를 수정할 수 없습니다.',
+ 'Tag removed successfully.' => '태그가 성공적으로 삭제되었습니다.',
+ 'Unable to remove this tag.' => '태그를 삭제할 수 없습니다.',
+ 'Global tags management' => '전역 태그 관리',
+ 'Tags' => '태그',
+ 'Tags management' => '태그 관리',
+ 'Add new tag' => '태그 추가',
+ 'Edit a tag' => '태그 수정',
+ 'Project tags' => '프로젝트 태그',
+ 'There is no specific tag for this project at the moment.' => '현재 이 프로젝트에는 태그가 없습니다.',
+ 'Tag' => '태그',
+ 'Remove a tag' => '태그 삭제',
+ 'Do you really want to remove this tag: "%s"?' => '태그를 삭제하시겠습니까: "%s"?',
+ 'Global tags' => '전역 태그',
+ 'There is no global tag at the moment.' => '현재 전역 태그가 없습니다.',
+ 'This field cannot be empty' => '이 필드는 비워둘 수 없습니다',
+ 'Close a task when there is no activity in an specific column' => '활동이 없는 컬럼의 할일 마치기',
+ '%s removed a subtask for the task #%d' => '%s가 할일 #%d의 서브 할일을 삭제하였습니다',
+ '%s removed a comment on the task #%d' => '%s가 할일 #%d의 댓글을 삭제하였습니다',
+ 'Comment removed on task #%d' => '할일 #%d의 댓글이 삭제되었습니다',
+ 'Subtask removed on task #%d' => '할일 #%d의 서브 할일이 삭제되었습니다',
+ 'Hide tasks in this column in the dashboard' => '대시보드 컬럼의 할일 숨기기',
+ '%s removed a comment on the task %s' => '%s가 할일 %s의 댓글을 삭제하였습니다',
+ '%s removed a subtask for the task %s' => '%s가 할일 %s의 서브 할일을 삭제하였습니다',
+ 'Comment removed' => '댓글이 삭제되었습니다',
+ 'Subtask removed' => '서브 할일이 삭제되었습니다',
+ '%s set a new internal link for the task #%d' => '%s가 할일 #%d의 새로운 내부 링크를 설정하였습니다',
+ '%s removed an internal link for the task #%d' => '%s가 할일 #%d의 새로운 내부 링크를 삭제하였습니다',
+ 'A new internal link for the task #%d have been defined' => '할일 #%d의 새로운 내부 링크가 정의되었습니다',
+ 'Internal link removed for the task #%d' => '할일 #%d의 새로운 내부 링크가 삭제되었습니다',
+ '%s set a new internal link for the task %s' => '%s가 할일 %s의 새로운 내부 링크를 설정하였습니다',
+ '%s removed an internal link for the task %s' => '%s가 할일 %s의 새로운 내부 링크를 삭제하였습니다',
+ 'Automatically set the due date on task creation' => '할일 생성시 마감일이 자동으로 설정되었습니다',
+ 'Move the task to another column when closed' => '할일을 마치면 다른 컬럼으로 이동시키기',
+ 'Move the task to another column when not moved during a given period' => '주어진 기간동안 이동하지 않으면 할일을 다른 컬럼으로 이동시키기',
+ 'Dashboard for %s' => '%s의 대시보드',
+ 'Tasks overview for %s' => '%s의 할일 개요',
+ 'Subtasks overview for %s' => '%s의 서브 할일 개요',
+ 'Projects overview for %s' => '%s의 프로젝트 개요',
+ 'Activity stream for %s' => '%s의 활동기록',
+ 'Calendar for %s' => '%s의 달력',
+ 'Notifications for %s' => '%s의 알림',
+ 'Subtasks export' => '서브할일 내보내기',
+ 'Tasks exportation' => '할일 내보내기',
);
diff --git a/app/Locale/my_MY/translations.php b/app/Locale/my_MY/translations.php
index 79baadf7..661fe5ac 100644
--- a/app/Locale/my_MY/translations.php
+++ b/app/Locale/my_MY/translations.php
@@ -68,7 +68,6 @@ return array(
'Do you really want to remove this project: "%s"?' => 'Anda yakin mahu menghapus projek ini : « %s » ?',
'Remove project' => 'Hapus projek',
'Edit the board for "%s"' => 'Ubah papan untuk « %s »',
- 'All projects' => 'Semua projek',
'Add a new column' => 'Tambah kolom baru',
'Title' => 'Judul',
'Assigned to %s' => 'Ditugaskan ke %s',
@@ -88,7 +87,6 @@ return array(
'(VACUUM command)' => '(perintah VACUUM)',
'(Gzip compressed Sqlite file)' => '(File Sqlite yang termampat Gzip)',
'Close a task' => 'Tutup tugas',
- 'Edit a task' => 'Sunting tugas',
'Column' => 'Kolom',
'Color' => 'Warna',
'Assignee' => 'Orang yang ditugaskan',
diff --git a/app/Locale/nb_NO/translations.php b/app/Locale/nb_NO/translations.php
index 3a0c3353..86fb33a9 100644
--- a/app/Locale/nb_NO/translations.php
+++ b/app/Locale/nb_NO/translations.php
@@ -68,7 +68,6 @@ return array(
'Do you really want to remove this project: "%s"?' => 'Vil du fjerne dette prosjektet: "%s"?',
'Remove project' => 'Fjern prosjekt',
'Edit the board for "%s"' => 'Endre prosjektsiden for "%s"',
- 'All projects' => 'Alle prosjekter',
'Add a new column' => 'Legg til en ny kolonne',
'Title' => 'Tittel',
'Assigned to %s' => 'Tildelt: %s',
@@ -88,7 +87,6 @@ return array(
'(VACUUM command)' => '(VACUUM kommando)',
'(Gzip compressed Sqlite file)' => '(Gzip-komprimert Sqlite fil)',
'Close a task' => 'Lukk en oppgave',
- 'Edit a task' => 'Endre en oppgave',
'Column' => 'Kolonne',
'Color' => 'Farge',
'Assignee' => 'Tildelt',
diff --git a/app/Locale/nl_NL/translations.php b/app/Locale/nl_NL/translations.php
index 5a026092..43bd32d3 100644
--- a/app/Locale/nl_NL/translations.php
+++ b/app/Locale/nl_NL/translations.php
@@ -68,7 +68,6 @@ return array(
'Do you really want to remove this project: "%s"?' => 'Weet u zeker dat u dit project wil verwijderen : « %s » ?',
'Remove project' => 'Project verwijderen',
'Edit the board for "%s"' => 'Bord bewerken voor « %s »',
- 'All projects' => 'Alle projecten',
'Add a new column' => 'Kolom toevoegen',
'Title' => 'Titel',
'Assigned to %s' => 'Toegewezen aan %s',
@@ -88,7 +87,6 @@ return array(
'(VACUUM command)' => '(VACUUM commando)',
'(Gzip compressed Sqlite file)' => '(Gzip ingepakt Sqlite bestand)',
'Close a task' => 'Taak sluiten',
- 'Edit a task' => 'Taak bewerken',
'Column' => 'Kolom',
'Color' => 'Kleur',
'Assignee' => 'Toegewezene',
diff --git a/app/Locale/pl_PL/translations.php b/app/Locale/pl_PL/translations.php
index af3bcd4e..c19ebbbe 100644
--- a/app/Locale/pl_PL/translations.php
+++ b/app/Locale/pl_PL/translations.php
@@ -68,7 +68,6 @@ return array(
'Do you really want to remove this project: "%s"?' => 'Na pewno chcesz usunąć projekt: "%s"?',
'Remove project' => 'Usuń projekt',
'Edit the board for "%s"' => 'Edytuj tablicę dla "%s"',
- 'All projects' => 'Wszystkie projekty',
'Add a new column' => 'Dodaj nową kolumnę',
'Title' => 'Nazwa',
'Assigned to %s' => 'Przypisane do %s',
@@ -88,7 +87,6 @@ return array(
'(VACUUM command)' => '(komenda VACUUM)',
'(Gzip compressed Sqlite file)' => '(baza danych spakowana Gzip)',
'Close a task' => 'Zakończ zadanie',
- 'Edit a task' => 'Edytuj zadanie',
'Column' => 'Kolumna',
'Color' => 'Kolor',
'Assignee' => 'Odpowiedzialny',
diff --git a/app/Locale/pt_BR/translations.php b/app/Locale/pt_BR/translations.php
index 2772d8bb..f4ed4f62 100644
--- a/app/Locale/pt_BR/translations.php
+++ b/app/Locale/pt_BR/translations.php
@@ -68,7 +68,6 @@ return array(
'Do you really want to remove this project: "%s"?' => 'Você realmente deseja remover este projeto: "%s"?',
'Remove project' => 'Remover projeto',
'Edit the board for "%s"' => 'Editar o board para "%s"',
- 'All projects' => 'Todos os projetos',
'Add a new column' => 'Adicionar uma nova coluna',
'Title' => 'Título',
'Assigned to %s' => 'Designado para %s',
@@ -88,7 +87,6 @@ return array(
'(VACUUM command)' => '(Comando VACUUM)',
'(Gzip compressed Sqlite file)' => '(Arquivo Sqlite comprimido com Gzip)',
'Close a task' => 'Finalizar uma tarefa',
- 'Edit a task' => 'Editar uma tarefa',
'Column' => 'Coluna',
'Color' => 'Cor',
'Assignee' => 'Designação',
diff --git a/app/Locale/pt_PT/translations.php b/app/Locale/pt_PT/translations.php
index 83670db1..1925eef2 100644
--- a/app/Locale/pt_PT/translations.php
+++ b/app/Locale/pt_PT/translations.php
@@ -68,7 +68,6 @@ return array(
'Do you really want to remove this project: "%s"?' => 'Tem a certeza que quer remover este projecto: "%s" ?',
'Remove project' => 'Remover projecto',
'Edit the board for "%s"' => 'Editar o quadro para "%s"',
- 'All projects' => 'Todos os projectos',
'Add a new column' => 'Adicionar uma nova coluna',
'Title' => 'Título',
'Assigned to %s' => 'Designado para %s',
@@ -88,7 +87,6 @@ return array(
'(VACUUM command)' => '(Comando VACUUM)',
'(Gzip compressed Sqlite file)' => '(Arquivo Sqlite comprimido com Gzip)',
'Close a task' => 'Finalizar uma tarefa',
- 'Edit a task' => 'Editar uma tarefa',
'Column' => 'Coluna',
'Color' => 'Cor',
'Assignee' => 'Assignado',
@@ -371,7 +369,7 @@ return array(
'Not assigned, estimate of %sh' => 'Não assignado, estimado em %sh',
'%s updated a comment on the task %s' => '%s actualizou o comentário na tarefa %s',
'%s commented the task %s' => '%s comentou a tarefa %s',
- '%s\'s activity' => 'Atividades de%s',
+ '%s\'s activity' => 'Atividades %s',
'RSS feed' => 'Feed RSS',
'%s updated a comment on the task #%d' => '%s actualizou um comentário sobre a tarefa #%d',
'%s commented on the task #%d' => '%s comentou sobre a tarefa #%d',
diff --git a/app/Locale/ru_RU/translations.php b/app/Locale/ru_RU/translations.php
index 1669ce9b..74563ad4 100644
--- a/app/Locale/ru_RU/translations.php
+++ b/app/Locale/ru_RU/translations.php
@@ -68,7 +68,6 @@ return array(
'Do you really want to remove this project: "%s"?' => 'Вы точно хотите удалить проект: "%s"?',
'Remove project' => 'Удалить проект',
'Edit the board for "%s"' => 'Изменить доску для "%s"',
- 'All projects' => 'Все проекты',
'Add a new column' => 'Добавить новую колонку',
'Title' => 'Название',
'Assigned to %s' => 'Назначено %s',
@@ -88,7 +87,6 @@ return array(
'(VACUUM command)' => '(Команда VACUUM)',
'(Gzip compressed Sqlite file)' => '(Сжать GZip файл SQLite)',
'Close a task' => 'Закрыть задачу',
- 'Edit a task' => 'Изменить задачу',
'Column' => 'Колонка',
'Color' => 'Цвет',
'Assignee' => 'Назначена',
@@ -1164,8 +1162,8 @@ return array(
'Email settings' => 'Настройки почты',
'Email sender address' => 'Адрес отправителя',
'Email transport' => 'Почтовый транспорт',
- // 'Webhook token' => '',
- // 'Imports' => '',
+ 'Webhook token' => 'Webhook токены',
+ 'Imports' => 'Импорт',
'Project tags management' => 'Управление метками проекта',
'Tag created successfully.' => 'Метка успешно создана.',
'Unable to create this tag.' => 'Невозможно создать эту метку.',
@@ -1186,32 +1184,32 @@ return array(
'Global tags' => 'Глобальные метка',
'There is no global tag at the moment.' => 'Нет глобальных меток.',
'This field cannot be empty' => 'Это поле не может быть пустым',
- // 'Close a task when there is no activity in an specific column' => '',
- // '%s removed a subtask for the task #%d' => '',
- // '%s removed a comment on the task #%d' => '',
- // 'Comment removed on task #%d' => '',
- // 'Subtask removed on task #%d' => '',
+ 'Close a task when there is no activity in an specific column' => 'Закрыть задачу при отсутствии активности в определенной колонке',
+ '%s removed a subtask for the task #%d' => '%s удалил подзадачу для #%d',
+ '%s removed a comment on the task #%d' => '%s удалил комментарий к задаче #%d',
+ 'Comment removed on task #%d' => 'Комментарий удален в задаче #%d',
+ 'Subtask removed on task #%d' => 'Подзадача удалена в задаче #%d',
'Hide tasks in this column in the dashboard' => 'Не показывать задачи из этой колонки в кабинете',
- // '%s removed a comment on the task %s' => '',
- // '%s removed a subtask for the task %s' => '',
- // 'Comment removed' => '',
- // 'Subtask removed' => '',
- // '%s set a new internal link for the task #%d' => '',
- // '%s removed an internal link for the task #%d' => '',
- // 'A new internal link for the task #%d have been defined' => '',
- // 'Internal link removed for the task #%d' => '',
- // '%s set a new internal link for the task %s' => '',
- // '%s removed an internal link for the task %s' => '',
- // 'Automatically set the due date on task creation' => '',
- // 'Move the task to another column when closed' => '',
- // 'Move the task to another column when not moved during a given period' => '',
- // 'Dashboard for %s' => '',
- // 'Tasks overview for %s' => '',
- // 'Subtasks overview for %s' => '',
- // 'Projects overview for %s' => '',
- // 'Activity stream for %s' => '',
- // 'Calendar for %s' => '',
- // 'Notifications for %s' => '',
- // 'Subtasks export' => '',
- // 'Tasks exportation' => '',
+ '%s removed a comment on the task %s' => '%s удалил комментарии к задаче %s',
+ '%s removed a subtask for the task %s' => '%s удалил подзадачу для %s',
+ 'Comment removed' => 'Комментарий удален',
+ 'Subtask removed' => 'Подзадача удалена',
+ '%s set a new internal link for the task #%d' => '%s добавил внутреннюю ссылку для задачи #%d',
+ '%s removed an internal link for the task #%d' => '%s удалил внутреннюю ссылку для задачи #%d',
+ 'A new internal link for the task #%d have been defined' => 'Внешняя ссылка для задачи #%d была установлена',
+ 'Internal link removed for the task #%d' => 'Внутренняя ссылка удалена для задачи #%d',
+ '%s set a new internal link for the task %s' => '%s добавил внутреннюю ссылку для задачи %s',
+ '%s removed an internal link for the task %s' => '%s удалил внутреннюю ссылку для задачи %s',
+ 'Automatically set the due date on task creation' => 'Автоматическая установка срока задачи при создании',
+ 'Move the task to another column when closed' => 'Переместить задачу в другую колонку при закрытии',
+ 'Move the task to another column when not moved during a given period' => 'Переместить задачу в другую колонку если она не был перемещен в указанный период',
+ 'Dashboard for %s' => 'Панель управления для %s',
+ 'Tasks overview for %s' => 'Обзор задач для %s',
+ 'Subtasks overview for %s' => 'Обзор подзадач для %s',
+ 'Projects overview for %s' => 'Обзор проектов для %s',
+ 'Activity stream for %s' => 'Лента активности для %s',
+ 'Calendar for %s' => 'Календарь для %s',
+ 'Notifications for %s' => 'Уведомления для %s',
+ 'Subtasks export' => 'Экспорт подзадач',
+ 'Tasks exportation' => 'Экспортирование задач',
);
diff --git a/app/Locale/sr_Latn_RS/translations.php b/app/Locale/sr_Latn_RS/translations.php
index 7e28e9a9..18dbbc65 100644
--- a/app/Locale/sr_Latn_RS/translations.php
+++ b/app/Locale/sr_Latn_RS/translations.php
@@ -68,7 +68,6 @@ return array(
'Do you really want to remove this project: "%s"?' => 'Da li želiš da ukloniš projekat: "%s"?',
'Remove project' => 'Ukloni projekat',
'Edit the board for "%s"' => 'Izmeni tablu za "%s"',
- 'All projects' => 'Svi projekti',
'Add a new column' => 'Dodaj novu kolonu',
'Title' => 'Naslov',
'Assigned to %s' => 'Dodeljen korisniku %s',
@@ -88,7 +87,6 @@ return array(
'(VACUUM command)' => '(komanda VACUUM)',
'(Gzip compressed Sqlite file)' => '(Sqlite baza spakovana Gzip-om)',
'Close a task' => 'Zatvori zadatak',
- 'Edit a task' => 'Izmeni zadatak',
'Column' => 'Kolona',
'Color' => 'Boja',
'Assignee' => 'Dodeli',
diff --git a/app/Locale/sv_SE/translations.php b/app/Locale/sv_SE/translations.php
index 5ad2938c..f7d1a4e4 100644
--- a/app/Locale/sv_SE/translations.php
+++ b/app/Locale/sv_SE/translations.php
@@ -68,7 +68,6 @@ return array(
'Do you really want to remove this project: "%s"?' => 'Vill du verkligen ta bort projektet: "%s" ?',
'Remove project' => 'Ta bort projekt',
'Edit the board for "%s"' => 'Ändra tavlan för "%s"',
- 'All projects' => 'Alla projekt',
'Add a new column' => 'Lägg till ny kolumn',
'Title' => 'Titel',
'Assigned to %s' => 'Tilldelad %s',
@@ -88,7 +87,6 @@ return array(
'(VACUUM command)' => '(Vacuum kommando)',
'(Gzip compressed Sqlite file)' => '(Gzip komprimera Sqlite filen)',
'Close a task' => 'Stäng en uppgift',
- 'Edit a task' => 'Ändra en uppgift',
'Column' => 'Kolumn',
'Color' => 'Färg',
'Assignee' => 'Uppdragsinnehavare',
diff --git a/app/Locale/th_TH/translations.php b/app/Locale/th_TH/translations.php
index 2aee696b..825dab93 100644
--- a/app/Locale/th_TH/translations.php
+++ b/app/Locale/th_TH/translations.php
@@ -42,11 +42,11 @@ return array(
'Sign in' => 'เข้าสู่ระบบ',
'Users' => 'ผู้ใช้',
'No user' => 'ไม่มีผู้ใช้',
- 'Forbidden' => 'ไม่อนุญาติ',
- 'Access Forbidden' => 'ไม่อนุญาติให้เข้า',
+ 'Forbidden' => 'ไม่อนุญาต',
+ 'Access Forbidden' => 'ไม่อนุญาตให้เข้า',
'Edit user' => 'แก้ไขผู้ใช้',
'Logout' => 'ออกจากระบบ',
- 'Bad username or password' => 'ชื่อผู้ใช่หรือรหัสผ่านผิด',
+ 'Bad username or password' => 'ชื่อผู้ใช้หรือรหัสผ่านผิด',
'Edit project' => 'แก้ไขโปรเจค',
'Name' => 'ชื่อ',
'Projects' => 'โปรเจค',
@@ -68,7 +68,6 @@ return array(
'Do you really want to remove this project: "%s"?' => 'คุณต้องการเอาโปรเจค « %s » ออกใช่หรือไม่?',
'Remove project' => 'ลบโปรเจค',
'Edit the board for "%s"' => 'แก้ไขบอร์ดสำหรับ « %s »',
- 'All projects' => 'โปรเจคทั้งหมด',
'Add a new column' => 'เพิ่มคอลัมน์ใหม่',
'Title' => 'หัวเรื่อง',
'Assigned to %s' => 'กำหนดให้ %s',
@@ -88,7 +87,6 @@ return array(
'(VACUUM command)' => '(VACUUM command)',
'(Gzip compressed Sqlite file)' => '(Gzip compressed Sqlite file)',
'Close a task' => 'ปิดงาน',
- 'Edit a task' => 'แก้ไขงาน',
'Column' => 'คอลัมน์',
'Color' => 'สี',
'Assignee' => 'กำหนดให้',
@@ -213,7 +211,7 @@ return array(
'Last logins' => 'เข้าใช้ล่าสุด',
'Login date' => 'วันที่เข้าใข้',
'Authentication method' => 'วิธีการยืนยันตัวตน',
- 'IP address' => 'ไอพี แอดเดรส',
+ 'IP address' => 'ที่อยู่ไอพี',
'User agent' => 'User agent',
'Persistent connections' => 'Persistent connections',
'No session.' => 'No session.',
@@ -230,35 +228,35 @@ return array(
'Description' => 'คำอธิบาย',
'%d comments' => '%d ความคิดเห็น',
'%d comment' => '%d ความคิดเห็น',
- 'Email address invalid' => 'อีเมลผิด',
- 'Your external account is not linked anymore to your profile.' => 'บัญชีภายนอกของคุณไม่ได้เชื่อมโยงอีกต่อไปในโปรไฟล์ของคุณ',
+ 'Email address invalid' => 'ที่อยู่อีเมลไม่ถูกต้อง',
+ 'Your external account is not linked anymore to your profile.' => 'บัญชีภายนอกของคุณไม่ได้เชื่อมโยงมายังโปรไฟล์ของคุณอีกต่อ',
'Unable to unlink your external account.' => 'ไม่สามารถยกเลิกการเชื่อมโยงบัญชีภายนอกของคุณ',
'External authentication failed' => 'การตรวจสอบภายนอกล้มเหลว',
- 'Your external account is linked to your profile successfully.' => 'บัญชีภายนอกของคุณลิงค์กับโปรไฟล์ของคุณเรียบร้อย',
+ 'Your external account is linked to your profile successfully.' => 'ทำการเชื่อมโยงบัญชีภายนอกของคุณกับโปรไฟล์ของคุณเรียบร้อย',
'Email' => 'อีเมล',
'Task removed successfully.' => 'ลบงานเรียบร้อยแล้ว',
'Unable to remove this task.' => 'ไม่สามารถลบงานนี้',
- 'Remove a task' => 'ลบงาาน',
+ 'Remove a task' => 'ลบงาน',
'Do you really want to remove this task: "%s"?' => 'คุณต้องการลบงาน "%s" ออกใช่หรือไม่?',
'Assign automatically a color based on a category' => 'กำหนดสีอัตโนมัติขึ้นอยู่กับหมวด',
'Assign automatically a category based on a color' => 'กำหนดหมวดอัตโนมัติขึ้นอยู่กับสี',
'Task creation or modification' => 'สร้างหรือแก้ไขงาน',
- 'Category' => 'หมวด',
- 'Category:' => 'หมวด:',
- 'Categories' => 'หมวด',
- 'Your category have been created successfully.' => 'สร้างหมวดเรียบร้อยแล้ว',
- 'Unable to create your category.' => 'ไม่สามารถสร้างหมวดได้',
+ 'Category' => 'หมวดหมู่',
+ 'Category:' => 'หมวดหมู่:',
+ 'Categories' => 'หมวดหมู่',
+ 'Your category have been created successfully.' => 'สร้างหมวดหมู่เรียบร้อยแล้ว',
+ 'Unable to create your category.' => 'ไม่สามารถสร้างหมวดหมู่ได้',
'Your category have been updated successfully.' => 'ปรับปรุงหมวดเรียบร้อยแล้ว',
- 'Unable to update your category.' => 'ไม่สามารถปรับปรุงหมวดได้',
- 'Remove a category' => 'ลบหมวด',
+ 'Unable to update your category.' => 'ไม่สามารถปรับปรุงหมวดหมู่ได้',
+ 'Remove a category' => 'ลบหมวดหมู่',
'Category removed successfully.' => 'ลบหมวดเรียบร้อยแล้ว',
- 'Unable to remove this category.' => 'ไม่สามารถลบหมวดได้',
- 'Category modification for the project "%s"' => 'แก้ไขหมวดสำหรับโปรเจค "%s"',
- 'Category Name' => 'ชื่อหมวด',
- 'Add a new category' => 'เพิ่มหมวดใหม่',
- 'Do you really want to remove this category: "%s"?' => 'คุณต้องการลบหมวด "%s" ใช่หรือไม่?',
- 'All categories' => 'หมวดทั้งหมด',
- 'No category' => 'ไม่มีหมวด',
+ 'Unable to remove this category.' => 'ไม่สามารถลบหมวดหมู่ได้',
+ 'Category modification for the project "%s"' => 'แก้ไขหมวดหมู่สำหรับโปรเจค "%s"',
+ 'Category Name' => 'ชื่อหมวดหมู่',
+ 'Add a new category' => 'เพิ่มหมวดหมู่ใหม่',
+ 'Do you really want to remove this category: "%s"?' => 'คุณต้องการลบหมวดหมู่ "%s" ใช่หรือไม่?',
+ 'All categories' => 'หมวดหมู่ทั้งหมด',
+ 'No category' => 'ไม่มีหมวดหมู่',
'The name is required' => 'ต้องการชื่อ',
'Remove a file' => 'ลบไฟล์',
'Unable to remove this file.' => 'ไม่สามารถลบไฟล์ได้',
@@ -294,7 +292,7 @@ return array(
'Unable to update your sub-task.' => 'ไม่สามารถปรับปรุงานย่อยได้',
'Unable to create your sub-task.' => 'ไม่สามารถสร้างงานย่อยได้',
'Sub-task added successfully.' => 'เพิ่มงานย่อยเรียบร้อยแล้ว',
- 'Maximum size: ' => 'ขนาดสูงสุด:',
+ 'Maximum size: ' => 'ขนาดไฟล์สูงสุด:',
'Unable to upload the file.' => 'ไม่สามารถอัพโหลดไฟล์ได้',
'Display another project' => 'แสดงโปรเจคอื่น',
'Created by %s' => 'สร้างโดย %s',
@@ -355,38 +353,38 @@ return array(
'Password modification' => 'แก้ไขรหัสผ่าน',
'External authentications' => 'การยืนยันภายนอก',
'Never connected.' => 'ไม่เชื่อมต่อ',
- 'No external authentication enabled.' => 'ไม่เปิดการใช้งานการยืนยันภายนอก',
- 'Password modified successfully.' => 'แก้ไขรหัสผ่านเรียบร้อยแล้ว',
+ 'No external authentication enabled.' => 'ปิดการใช้งานการยืนยันภายนอก',
+ 'Password modified successfully.' => 'แก้ไขรหัสผ่านเรียบร้อย',
'Unable to change the password.' => 'ไม่สามารถเปลี่ยนรหัสผ่านได้',
- 'Change category' => 'เปลี่ยนหมวด',
- '%s updated the task %s' => '%s ปรับปรุงงานแล้ว %s',
- '%s opened the task %s' => '%s เปิดงานแล้ว %s',
- '%s moved the task %s to the position #%d in the column "%s"' => '%s ย้ายงานแล้ว %s ไปตำแหน่ง #%d ในคอลัมน์ "%s"',
- '%s moved the task %s to the column "%s"' => '%s ย้ายงานแล้ว %s ไปคอลัมน์ "%s"',
- '%s created the task %s' => '%s สร้างงานแล้ว %s',
- '%s closed the task %s' => '%s ปิดงานแล้ว %s',
- '%s created a subtask for the task %s' => '%s สร้างงานย่อยสำหรับงานแล้ว %s',
- '%s updated a subtask for the task %s' => '%s ปรับปรุงงานย่อยสำหรับงานแล้ว %s',
- 'Assigned to %s with an estimate of %s/%sh' => 'กำหนดให้ %s โดยประมาณแล้ว %s/%sh',
- 'Not assigned, estimate of %sh' => 'ไม่กำหนดแล้ว, ประมาณเวลาที่ใช้ %s ชั่วโมง',
- '%s updated a comment on the task %s' => '%s ปรับปรุงความคิดเห็นในงานแล้ว %s',
- '%s commented the task %s' => '%s แสดงความคิดเห็นของงานแล้ว %s',
+ 'Change category' => 'เปลี่ยนหมวดหมู่',
+ '%s updated the task %s' => '%s ได้ปรับปรุงงาน %s',
+ '%s opened the task %s' => '%s ได้สร้างงาน %s',
+ '%s moved the task %s to the position #%d in the column "%s"' => '%s ได้ย้ายงาน %s ไปยังตำแหน่ง #%d ในคอลัมน์ "%s"',
+ '%s moved the task %s to the column "%s"' => '%s ได้ย้ายงาน %s ไปยังคอลัมน์ "%s"',
+ '%s created the task %s' => '%s ได้สร้างงาน %s',
+ '%s closed the task %s' => '%s ได้ปิดงาน %s',
+ '%s created a subtask for the task %s' => '%s ได้สร้างงานย่อยสำหรับงาน %s',
+ '%s updated a subtask for the task %s' => '%s ได้ปรับปรุงงานย่อยสำหรับงาน %s',
+ 'Assigned to %s with an estimate of %s/%sh' => 'มอบหมายให้ %s โดยประมาณเวลาที่ใช้ %s/%sh',
+ 'Not assigned, estimate of %sh' => 'ไม่ระบุผู้รับผิดชอบ, ประมาณเวลาที่ใช้ %s ชั่วโมง',
+ '%s updated a comment on the task %s' => '%s ได้ปรับปรุงความคิดเห็นในงาน %s',
+ '%s commented the task %s' => '%s ได้แสดงความคิดเห็นในงาน %s',
'%s\'s activity' => 'กิจกรรม %s',
'RSS feed' => 'RSS feed',
- '%s updated a comment on the task #%d' => '%s ปรับปรุงความคิดเห็นบนงานแล้ว #%d',
- '%s commented on the task #%d' => '%s แสดงความคิดเห็นบนงานแล้ว #%d',
- '%s updated a subtask for the task #%d' => '%s ปรับปรุงงานย่อยสำหรับงานแล้ว #%d',
- '%s created a subtask for the task #%d' => '%s สร้างงานย่อยสำหรับงานแล้ว #%d',
- '%s updated the task #%d' => '%s ปรับปรุงงานแล้ว #%d',
- '%s created the task #%d' => '%s สร้างงานแล้ว #%d',
- '%s closed the task #%d' => '%s ปิดงานแล้ว #%d',
- '%s opened the task #%d' => '%s เปิดงานแล้ว #%d',
+ '%s updated a comment on the task #%d' => '%s ได้ปรับปรุงความคิดเห็นในงาน #%d',
+ '%s commented on the task #%d' => '%s ได้แสดงความคิดเห็นบนงาน #%d',
+ '%s updated a subtask for the task #%d' => '%s ได้ปรับปรุงงานย่อยสำหรับงาน #%d',
+ '%s created a subtask for the task #%d' => '%s ได้สร้างงานย่อยสำหรับงาน #%d',
+ '%s updated the task #%d' => '%s ได้ปรับปรุงงาน #%d',
+ '%s created the task #%d' => '%s ได้สร้างงาน #%d',
+ '%s closed the task #%d' => '%s ได้ปิดงาน #%d',
+ '%s opened the task #%d' => '%s ได้เปิดงาน #%d',
'Activity' => 'กิจกรรม',
'Default values are "%s"' => 'ค่าเริ่มต้น "%s"',
'Default columns for new projects (Comma-separated)' => 'คอลัมน์เริ่มต้นสำหรับโปรเจคใหม่ (Comma-separated)',
'Task assignee change' => 'เปลี่ยนการกำหนดบุคคลของงาน',
- '%s changed the assignee of the task #%d to %s' => '%s เปลี่ยนผู้รับผิดชอบของงาน #%d เป็น %s',
- '%s changed the assignee of the task %s to %s' => '%s เปลี่ยนผู้รับผิดชอบของงาน %s เป็น %s',
+ '%s changed the assignee of the task #%d to %s' => '%s ได้เปลี่ยนผู้รับผิดชอบงาน #%d เป็น %s',
+ '%s changed the assignee of the task %s to %s' => '%s ได้เปลี่ยนผู้รับผิดชอบงาน %s เป็น %s',
'New password for the user "%s"' => 'รหัสผ่านใหม่สำหรับผู้ใช้ "%s"',
'Choose an event' => 'เลือกเหตุการณ์',
'Create a task from an external provider' => 'สร้างงานจากบริการภายนอก',
@@ -401,8 +399,8 @@ return array(
// 'Webhook settings' => '',
// 'Reset token' => '',
// 'API endpoint:' => '',
- 'Refresh interval for private board' => 'ระยะรีเฟรชบอร์ดส่วนตัว',
- 'Refresh interval for public board' => 'ระยะรีเฟรชบอร์ดสาธารณะ',
+ 'Refresh interval for private board' => 'ระยะเวลารีเฟรชบอร์ดส่วนตัว',
+ 'Refresh interval for public board' => 'ระยะเวลารีเฟรชบอร์ดสาธารณะ',
'Task highlight period' => 'ช่วงเวลาไฮไลต์งาน',
'Period (in second) to consider a task was modified recently (0 to disable, 2 days by default)' => 'ช่วงเวลา (เป็นวินาที) ใช้ในการตัดสินใจว่าเป็นการแก้ไขเร็วๆ นี้ (0 ไม่ใช้งาน, ค่าเริ่มต้น 2 วัน)',
'Frequency in second (60 seconds by default)' => 'ความถี่ (ค่าเริ่มต้นทุก 60 วินาที) ',
@@ -430,7 +428,7 @@ return array(
'My projects' => 'โปรเจคของฉัน',
'Columns' => 'คอลัมน์',
'Task' => 'งาน',
- 'Your are not member of any project.' => 'คุณไม่ได้เป็นสมาชิกของโปรเจค',
+ 'Your are not member of any project.' => 'คุณไม่ได้เป็นสมาชิกของโปรเจคใดๆ',
'Percentage' => 'เปอร์เซ็นต์',
'Number of tasks' => 'จำนวนงาน',
'Task distribution' => 'การกระจายงาน',
@@ -438,18 +436,18 @@ return array(
'Subtask' => 'งานย่อย',
'My subtasks' => 'งานย่อยของฉัน',
'User repartition' => 'การแบ่งงานของผู้ใช้',
- 'Clone this project' => 'เลียนแบบโปรเจคนี้',
+ 'Clone this project' => 'สำเนาโปรเจคนี้',
'Column removed successfully.' => 'ลบคอลัมน์สำเร็จ',
- 'Not enough data to show the graph.' => 'ไม่มีข้อมูลแสดงเป็นกราฟ',
+ 'Not enough data to show the graph.' => 'ไม่มีข้อมูลเพียงพอสำหรับการแสดงกราฟ',
'Previous' => 'ก่อนหน้า',
'The id must be an integer' => 'ไอดีต้องเป็นตัวเลขจำนวนเต็ม',
- 'The project id must be an integer' => 'ไอดีโปรเจคต้องเป็นตัวเลข',
- 'The status must be an integer' => 'สถานะต้องเป็นตัวเลข',
+ 'The project id must be an integer' => 'ไอดีโปรเจคต้องเป็นตัวเลขเท่านั้น',
+ 'The status must be an integer' => 'สถานะต้องเป็นตัวเลขเท่านั้น',
'The subtask id is required' => 'ต้องการงานย่อย',
- 'The subtask id must be an integer' => 'ไอดีงานย่อยต้องเป็นตัวเลข',
+ 'The subtask id must be an integer' => 'ไอดีงานย่อยต้องเป็นตัวเลขเท่านั้น',
'The task id is required' => 'ต้องการไอดีงาน',
- 'The task id must be an integer' => 'ไอดีงานต้องเป็นตัวเลข',
- 'The user id must be an integer' => 'ไอดีผู้ใช้ต้องเป็นตัวเลข',
+ 'The task id must be an integer' => 'ไอดีงานต้องเป็นตัวเลขเท่านั้น',
+ 'The user id must be an integer' => 'ไอดีผู้ใช้ต้องเป็นตัวเลขเท่านั้น',
'This value is required' => 'ต้องการค่านี้',
'This value must be numeric' => 'ค่านี้ต้องเป็นตัวเลข',
'Unable to create this task.' => 'ไม่สามารถสร้างงานนี้',
@@ -478,7 +476,7 @@ return array(
'Default categories for new projects (Comma-separated)' => 'ค่าเริ่มต้นหมวดสำหรับโปรเจคใหม่ (Comma-separated)',
'Integrations' => 'การใช้ร่วมกัน',
'Integration with third-party services' => 'การใช้งานร่วมกับบริการ third-party',
- 'Subtask Id' => 'รหัสงานย่อย',
+ 'Subtask Id' => 'ไอดีของงานย่อย',
'Subtasks' => 'งานย่อย',
'Subtasks Export' => 'ส่งออก งานย่อย',
'Task Title' => 'ชื่องาน',
@@ -511,7 +509,7 @@ return array(
'Add a new link' => 'เพิ่มลิงค์ใหม่',
'Do you really want to remove this link: "%s"?' => 'คุณต้องการลบลิงค์นี้: "%s"?',
'Do you really want to remove this link with task #%d?' => 'คุณต้องการลบลิงค์นี้ของงาน #%d?',
- 'Field required' => 'ต้องใส่',
+ 'Field required' => 'จำเป็นต้องใส่',
'Link added successfully.' => 'เพิ่มลิงค์เรียบร้อยแล้ว',
'Link updated successfully.' => 'ปรับปรุงลิงค์เรียบร้อยแล้ว',
'Link removed successfully.' => 'ลบลิงค์เรียบร้อยแล้ว',
@@ -931,11 +929,11 @@ return array(
'Remove this user' => 'เอาผู้ใช้คนนี้ออก',
'Permissions' => 'การอนุญาตใช้งาน',
'Allowed Users' => 'การอนุญาตผู้ใช้',
- 'No user have been allowed specifically.' => 'ไม่มีผู้ใช้ได้รับอนุญาติเป็นพิเศษ',
+ 'No user have been allowed specifically.' => 'ไม่มีผู้ใช้ได้รับอนุญาตเป็นพิเศษ',
'Role' => 'บทบาท',
'Enter user name...' => 'พิมพ์ชื่อผู้ใช้...',
'Allowed Groups' => 'อนุญาตกลุ่ม',
- 'No group have been allowed specifically.' => 'ไม่มีกลุ่มได้รับอนุญาติเป็นพิเศษ',
+ 'No group have been allowed specifically.' => 'ไม่มีกลุ่มได้รับอนุญาตเป็นพิเศษ',
'Group' => 'กลุ่ม',
'Group Name' => 'ชื่อกลุ่ม',
'Enter group name...' => 'พิมพ์ชื่อกลุ่ม...',
diff --git a/app/Locale/tr_TR/translations.php b/app/Locale/tr_TR/translations.php
index 69642b58..7eb5c2aa 100644
--- a/app/Locale/tr_TR/translations.php
+++ b/app/Locale/tr_TR/translations.php
@@ -68,7 +68,6 @@ return array(
'Do you really want to remove this project: "%s"?' => 'Bu projeyi gerçekten silmek istiyor musunuz: "%s"?',
'Remove project' => 'Projeyi sil',
'Edit the board for "%s"' => 'Tabloyu "%s" için güncelle',
- 'All projects' => 'Tüm projeler',
'Add a new column' => 'Yeni sütun ekle',
'Title' => 'Başlık',
'Assigned to %s' => '%s kullanıcısına atanmış',
@@ -88,7 +87,6 @@ return array(
'(VACUUM command)' => '(VACUUM komutu)',
'(Gzip compressed Sqlite file)' => '(Gzip ile sıkıştırılmış Sqlite dosyası)',
'Close a task' => 'Bir görevi kapat',
- 'Edit a task' => 'Bir görevi düzenle',
'Column' => 'Sütun',
'Color' => 'Renk',
'Assignee' => 'Atanan',
diff --git a/app/Locale/zh_CN/translations.php b/app/Locale/zh_CN/translations.php
index b4e9c063..f28434d2 100644
--- a/app/Locale/zh_CN/translations.php
+++ b/app/Locale/zh_CN/translations.php
@@ -68,7 +68,6 @@ return array(
'Do you really want to remove this project: "%s"?' => '确定要移除项目"%s"吗?',
'Remove project' => '移除项目',
'Edit the board for "%s"' => '为"%s"修改看板',
- 'All projects' => '所有项目',
'Add a new column' => '添加新栏目',
'Title' => '标题',
'Assigned to %s' => '指派给 %s',
@@ -88,7 +87,6 @@ return array(
'(VACUUM command)' => '(VACUUM 指令)',
'(Gzip compressed Sqlite file)' => '(用Gzip压缩的Sqlite文件)',
'Close a task' => '关闭一个任务',
- 'Edit a task' => '修改一个任务',
'Column' => '栏目',
'Color' => '颜色',
'Assignee' => '负责人',
diff --git a/app/Model/TaskCreationModel.php b/app/Model/TaskCreationModel.php
index 1c0fd7d9..b9b07d5e 100644
--- a/app/Model/TaskCreationModel.php
+++ b/app/Model/TaskCreationModel.php
@@ -85,5 +85,7 @@ class TaskCreationModel extends Base
$values['date_modification'] = $values['date_creation'];
$values['date_moved'] = $values['date_creation'];
$values['position'] = $this->taskFinderModel->countByColumnAndSwimlaneId($values['project_id'], $values['column_id'], $values['swimlane_id']) + 1;
+
+ $this->hook->reference('model:task:creation:prepare', $values);
}
}
diff --git a/app/Model/TaskFinderModel.php b/app/Model/TaskFinderModel.php
index 924f339b..3c32e140 100644
--- a/app/Model/TaskFinderModel.php
+++ b/app/Model/TaskFinderModel.php
@@ -2,7 +2,6 @@
namespace Kanboard\Model;
-use PDO;
use Kanboard\Core\Base;
/**
@@ -298,59 +297,30 @@ class TaskFinderModel extends Base
*/
public function getDetails($task_id)
{
- $sql = '
- SELECT
- tasks.id,
- tasks.reference,
- tasks.title,
- tasks.description,
- tasks.date_creation,
- tasks.date_completed,
- tasks.date_modification,
- tasks.date_due,
- tasks.date_started,
- tasks.time_estimated,
- tasks.time_spent,
- tasks.color_id,
- tasks.project_id,
- tasks.column_id,
- tasks.owner_id,
- tasks.creator_id,
- tasks.position,
- tasks.is_active,
- tasks.score,
- tasks.category_id,
- tasks.priority,
- tasks.swimlane_id,
- tasks.date_moved,
- tasks.recurrence_status,
- tasks.recurrence_trigger,
- tasks.recurrence_factor,
- tasks.recurrence_timeframe,
- tasks.recurrence_basedate,
- tasks.recurrence_parent,
- tasks.recurrence_child,
- project_has_categories.name AS category_name,
- swimlanes.name AS swimlane_name,
- projects.name AS project_name,
- projects.default_swimlane,
- columns.title AS column_title,
- users.username AS assignee_username,
- users.name AS assignee_name,
- creators.username AS creator_username,
- creators.name AS creator_name
- FROM tasks
- LEFT JOIN users ON users.id = tasks.owner_id
- LEFT JOIN users AS creators ON creators.id = tasks.creator_id
- LEFT JOIN project_has_categories ON project_has_categories.id = tasks.category_id
- LEFT JOIN projects ON projects.id = tasks.project_id
- LEFT JOIN columns ON columns.id = tasks.column_id
- LEFT JOIN swimlanes ON swimlanes.id = tasks.swimlane_id
- WHERE tasks.id = ?
- ';
-
- $rq = $this->db->execute($sql, array($task_id));
- return $rq->fetch(PDO::FETCH_ASSOC);
+ return $this->db->table(TaskModel::TABLE)
+ ->columns(
+ TaskModel::TABLE.'.*',
+ CategoryModel::TABLE.'.name AS category_name',
+ SwimlaneModel::TABLE.'.name AS swimlane_name',
+ ProjectModel::TABLE.'.name AS project_name',
+ ProjectModel::TABLE.'.default_swimlane',
+ ColumnModel::TABLE.'.title AS column_title',
+ UserModel::TABLE.'.username AS assignee_username',
+ UserModel::TABLE.'.name AS assignee_name',
+ 'uc.username AS creator_username',
+ 'uc.name AS creator_name',
+ CategoryModel::TABLE.'.description AS category_description',
+ ColumnModel::TABLE.'.position AS column_position',
+ ProjectModel::TABLE.'.default_swimlane'
+ )
+ ->join(UserModel::TABLE, 'id', 'owner_id', TaskModel::TABLE)
+ ->left(UserModel::TABLE, 'uc', 'id', TaskModel::TABLE, 'creator_id')
+ ->join(CategoryModel::TABLE, 'id', 'category_id', TaskModel::TABLE)
+ ->join(ColumnModel::TABLE, 'id', 'column_id', TaskModel::TABLE)
+ ->join(SwimlaneModel::TABLE, 'id', 'swimlane_id', TaskModel::TABLE)
+ ->join(ProjectModel::TABLE, 'id', 'project_id', TaskModel::TABLE)
+ ->eq(TaskModel::TABLE.'.id', $task_id)
+ ->findOne();
}
/**
diff --git a/app/Model/TaskModificationModel.php b/app/Model/TaskModificationModel.php
index 16b48f3d..6e16fbec 100644
--- a/app/Model/TaskModificationModel.php
+++ b/app/Model/TaskModificationModel.php
@@ -106,6 +106,8 @@ class TaskModificationModel extends Base
$this->helper->model->convertIntegerFields($values, array('priority', 'is_active', 'recurrence_status', 'recurrence_trigger', 'recurrence_factor', 'recurrence_timeframe', 'recurrence_basedate'));
$values['date_modification'] = time();
+
+ $this->hook->reference('model:task:modification:prepare', $values);
}
/**
diff --git a/app/Model/UserMetadataModel.php b/app/Model/UserMetadataModel.php
index e931d3ba..42fe4c6d 100644
--- a/app/Model/UserMetadataModel.php
+++ b/app/Model/UserMetadataModel.php
@@ -10,6 +10,9 @@ namespace Kanboard\Model;
*/
class UserMetadataModel extends MetadataModel
{
+ const KEY_COMMENT_SORTING_DIRECTION = 'comment.sorting.direction';
+ const KEY_BOARD_COLLAPSED = 'board.collapsed.';
+
/**
* Get the table
*
diff --git a/app/Notification/MailNotification.php b/app/Notification/MailNotification.php
index a5f51b89..9e042820 100644
--- a/app/Notification/MailNotification.php
+++ b/app/Notification/MailNotification.php
@@ -80,7 +80,7 @@ class MailNotification extends Base implements NotificationInterface
{
return sprintf(
'[%s] %s',
- $eventData['task']['project_name'],
+ isset($eventData['project_name']) ? $eventData['project_name'] : $eventData['task']['project_name'],
$this->notificationModel->getTitleWithoutAuthor($eventName, $eventData)
);
}
diff --git a/app/Pagination/SubtaskPagination.php b/app/Pagination/SubtaskPagination.php
index f0cd6148..c55d0fb4 100644
--- a/app/Pagination/SubtaskPagination.php
+++ b/app/Pagination/SubtaskPagination.php
@@ -26,11 +26,14 @@ class SubtaskPagination extends Base
*/
public function getDashboardPaginator($user_id, $method, $max)
{
+ $query = $this->subtaskModel->getUserQuery($user_id, array(SubtaskModel::STATUS_TODO, SubtaskModel::STATUS_INPROGRESS));
+ $this->hook->reference('pagination:dashboard:subtask:query', $query);
+
return $this->paginator
->setUrl('DashboardController', $method, array('pagination' => 'subtasks', 'user_id' => $user_id))
->setMax($max)
->setOrder(TaskModel::TABLE.'.id')
- ->setQuery($this->subtaskModel->getUserQuery($user_id, array(SubtaskModel::STATUS_TODO, SubtaskModel::STATUS_INPROGRESS)))
+ ->setQuery($query)
->calculateOnlyIf($this->request->getStringParam('pagination') === 'subtasks');
}
}
diff --git a/app/Pagination/TaskPagination.php b/app/Pagination/TaskPagination.php
index a395ab84..5fe986e7 100644
--- a/app/Pagination/TaskPagination.php
+++ b/app/Pagination/TaskPagination.php
@@ -25,11 +25,14 @@ class TaskPagination extends Base
*/
public function getDashboardPaginator($user_id, $method, $max)
{
+ $query = $this->taskFinderModel->getUserQuery($user_id);
+ $this->hook->reference('pagination:dashboard:task:query', $query);
+
return $this->paginator
->setUrl('DashboardController', $method, array('pagination' => 'tasks', 'user_id' => $user_id))
->setMax($max)
->setOrder(TaskModel::TABLE.'.id')
- ->setQuery($this->taskFinderModel->getUserQuery($user_id))
+ ->setQuery($query)
->calculateOnlyIf($this->request->getStringParam('pagination') === 'tasks');
}
}
diff --git a/app/ServiceProvider/ApiProvider.php b/app/ServiceProvider/ApiProvider.php
index 5cf6231c..d5d1f260 100644
--- a/app/ServiceProvider/ApiProvider.php
+++ b/app/ServiceProvider/ApiProvider.php
@@ -22,6 +22,7 @@ use Kanboard\Api\Procedure\ProjectPermissionProcedure;
use Kanboard\Api\Procedure\SubtaskProcedure;
use Kanboard\Api\Procedure\SubtaskTimeTrackingProcedure;
use Kanboard\Api\Procedure\SwimlaneProcedure;
+use Kanboard\Api\Procedure\TaskMetadataProcedure;
use Kanboard\Api\Procedure\TaskProcedure;
use Kanboard\Api\Procedure\TaskLinkProcedure;
use Kanboard\Api\Procedure\UserProcedure;
@@ -69,6 +70,7 @@ class ApiProvider implements ServiceProviderInterface
->withObject(new TaskProcedure($container))
->withObject(new TaskLinkProcedure($container))
->withObject(new TaskExternalLinkProcedure($container))
+ ->withObject(new TaskMetadataProcedure($container))
->withObject(new UserProcedure($container))
->withObject(new GroupProcedure($container))
->withObject(new GroupMemberProcedure($container))
diff --git a/app/ServiceProvider/CacheProvider.php b/app/ServiceProvider/CacheProvider.php
new file mode 100644
index 00000000..fac44d53
--- /dev/null
+++ b/app/ServiceProvider/CacheProvider.php
@@ -0,0 +1,51 @@
+<?php
+
+namespace Kanboard\ServiceProvider;
+
+use Kanboard\Core\Cache\FileCache;
+use Kanboard\Core\Cache\MemoryCache;
+use Kanboard\Decorator\MetadataCacheDecorator;
+use Pimple\Container;
+use Pimple\ServiceProviderInterface;
+
+/**
+ * Cache Provider
+ *
+ * @package Kanboard\ServiceProvider
+ * @author Frederic Guillot
+ */
+class CacheProvider implements ServiceProviderInterface
+{
+ /**
+ * Register providers
+ *
+ * @access public
+ * @param \Pimple\Container $container
+ * @return \Pimple\Container
+ */
+ public function register(Container $container)
+ {
+ $container['memoryCache'] = function() {
+ return new MemoryCache();
+ };
+
+ if (CACHE_DRIVER === 'file') {
+ $container['cacheDriver'] = function() {
+ return new FileCache();
+ };
+ } else {
+ $container['cacheDriver'] = $container['memoryCache'];
+ }
+
+ $container['userMetadataCacheDecorator'] = function($c) {
+ return new MetadataCacheDecorator(
+ $c['cacheDriver'],
+ $c['userMetadataModel'],
+ 'user.metadata.',
+ $c['userSession']->getId()
+ );
+ };
+
+ return $container;
+ }
+}
diff --git a/app/ServiceProvider/ClassProvider.php b/app/ServiceProvider/ClassProvider.php
index aab41c74..d837500a 100644
--- a/app/ServiceProvider/ClassProvider.php
+++ b/app/ServiceProvider/ClassProvider.php
@@ -140,9 +140,6 @@ class ClassProvider implements ServiceProviderInterface
'Response',
'RememberMeCookie',
),
- 'Core\Cache' => array(
- 'MemoryCache',
- ),
'Core\Plugin' => array(
'Hook',
),
diff --git a/app/Template/action/index.php b/app/Template/action/index.php
index 7140dc85..7768a0b6 100644
--- a/app/Template/action/index.php
+++ b/app/Template/action/index.php
@@ -15,7 +15,7 @@
<?php if (empty($actions)): ?>
<p class="alert"><?= t('There is no action at the moment.') ?></p>
<?php else: ?>
- <table>
+ <table class="table-scrolling">
<tr>
<th><?= t('Automatic actions') ?></th>
<th><?= t('Action parameters') ?></th>
diff --git a/app/Template/activity/task.php b/app/Template/activity/task.php
index 04c64c63..39953d1a 100644
--- a/app/Template/activity/task.php
+++ b/app/Template/activity/task.php
@@ -1,9 +1,12 @@
-<div class="task-show-title color-<?= $task['color_id'] ?>">
- <h2><?= $this->text->e($task['title']) ?></h2>
-</div>
+<?= $this->render('task/details', array(
+ 'task' => $task,
+ 'tags' => $tags,
+ 'project' => $project,
+ 'editable' => false,
+)) ?>
<div class="page-header">
<h2><?= t('Activity stream') ?></h2>
</div>
-<?= $this->render('event/events', array('events' => $events)) ?> \ No newline at end of file
+<?= $this->render('event/events', array('events' => $events)) ?>
diff --git a/app/Template/analytic/avg_time_columns.php b/app/Template/analytic/avg_time_columns.php
index 5f6c6b35..91c269fc 100644
--- a/app/Template/analytic/avg_time_columns.php
+++ b/app/Template/analytic/avg_time_columns.php
@@ -9,7 +9,7 @@
<div id="chart" data-metrics='<?= json_encode($metrics, JSON_HEX_APOS) ?>' data-label="<?= t('Average time spent') ?>"></div>
- <table class="table-stripped">
+ <table class="table-striped">
<tr>
<th><?= t('Column') ?></th>
<th><?= t('Average time spent') ?></th>
diff --git a/app/Template/analytic/compare_hours.php b/app/Template/analytic/compare_hours.php
index e4a0b60e..c0b9cfc3 100644
--- a/app/Template/analytic/compare_hours.php
+++ b/app/Template/analytic/compare_hours.php
@@ -23,7 +23,7 @@
<?php if ($paginator->isEmpty()): ?>
<p class="alert"><?= t('No tasks found.') ?></p>
<?php elseif (! $paginator->isEmpty()): ?>
- <table class="table-fixed table-small">
+ <table class="table-fixed table-small table-scrolling">
<tr>
<th class="column-5"><?= $paginator->order(t('Id'), 'tasks.id') ?></th>
<th><?= $paginator->order(t('Title'), 'tasks.title') ?></th>
diff --git a/app/Template/analytic/tasks.php b/app/Template/analytic/tasks.php
index 9e7b1fd7..4bc19784 100644
--- a/app/Template/analytic/tasks.php
+++ b/app/Template/analytic/tasks.php
@@ -9,7 +9,7 @@
<div id="chart" data-metrics='<?= json_encode($metrics, JSON_HEX_APOS) ?>'></div>
- <table>
+ <table class="table-striped">
<tr>
<th><?= t('Column') ?></th>
<th><?= t('Number of tasks') ?></th>
diff --git a/app/Template/analytic/users.php b/app/Template/analytic/users.php
index 9d1d3a1e..91bec11b 100644
--- a/app/Template/analytic/users.php
+++ b/app/Template/analytic/users.php
@@ -9,7 +9,7 @@
<div id="chart" data-metrics='<?= json_encode($metrics, JSON_HEX_APOS) ?>'></div>
- <table>
+ <table class="table-striped">
<tr>
<th><?= t('User') ?></th>
<th><?= t('Number of tasks') ?></th>
diff --git a/app/Template/board/table_column.php b/app/Template/board/table_column.php
index 75a6eb4c..c0b71eab 100644
--- a/app/Template/board/table_column.php
+++ b/app/Template/board/table_column.php
@@ -5,9 +5,9 @@
<!-- column in collapsed mode -->
<div class="board-column-collapsed">
- <span class="board-column-header-task-count" title="<?= t('Show this column') ?>">
+ <small class="board-column-header-task-count" title="<?= t('Show this column') ?>">
<span id="task-number-column-<?= $column['id'] ?>"><?= $column['nb_tasks'] ?></span>
- </span>
+ </small>
</div>
<!-- column in expanded mode -->
diff --git a/app/Template/board/tooltip_external_links.php b/app/Template/board/tooltip_external_links.php
index 65331864..a9f1fc7f 100644
--- a/app/Template/board/tooltip_external_links.php
+++ b/app/Template/board/tooltip_external_links.php
@@ -1,5 +1,5 @@
<div class="tooltip-large">
- <table>
+ <table class="table-small">
<tr>
<th class="column-20"><?= t('Type') ?></th>
<th class="column-70"><?= t('Title') ?></th>
diff --git a/app/Template/board/tooltip_files.php b/app/Template/board/tooltip_files.php
index 6f9e2640..4e704dac 100644
--- a/app/Template/board/tooltip_files.php
+++ b/app/Template/board/tooltip_files.php
@@ -1,5 +1,5 @@
<div class="tooltip-large">
- <table>
+ <table class="table-small">
<?php foreach ($files as $file): ?>
<tr>
<th>
diff --git a/app/Template/board/tooltip_subtasks.php b/app/Template/board/tooltip_subtasks.php
index 0322d373..8d5bc059 100644
--- a/app/Template/board/tooltip_subtasks.php
+++ b/app/Template/board/tooltip_subtasks.php
@@ -1,5 +1,5 @@
<div class="tooltip-large">
- <table>
+ <table class="table-small">
<tr>
<th class="column-80"><?= t('Subtask') ?></th>
<th><?= t('Assignee') ?></th>
diff --git a/app/Template/board/tooltip_tasklinks.php b/app/Template/board/tooltip_tasklinks.php
index d1156cbe..08432e71 100644
--- a/app/Template/board/tooltip_tasklinks.php
+++ b/app/Template/board/tooltip_tasklinks.php
@@ -1,5 +1,5 @@
<div class="tooltip-large">
- <table>
+ <table class="table-small">
<?php foreach ($links as $label => $grouped_links): ?>
<tr>
<th colspan="4"><?= t($label) ?></th>
diff --git a/app/Template/category/index.php b/app/Template/category/index.php
index a103d89f..ac60d9a8 100644
--- a/app/Template/category/index.php
+++ b/app/Template/category/index.php
@@ -2,7 +2,7 @@
<div class="page-header">
<h2><?= t('Categories') ?></h2>
</div>
-<table>
+<table class="table-striped">
<tr>
<th><?= t('Category Name') ?></th>
<th class="column-8"><?= t('Actions') ?></th>
diff --git a/app/Template/column/index.php b/app/Template/column/index.php
index 04760a16..66890ba5 100644
--- a/app/Template/column/index.php
+++ b/app/Template/column/index.php
@@ -12,7 +12,7 @@
<p class="alert alert-error"><?= t('Your board doesn\'t have any columns!') ?></p>
<?php else: ?>
<table
- class="columns-table table-stripped"
+ class="columns-table table-striped"
data-save-position-url="<?= $this->url->href('ColumnController', 'move', array('project_id' => $project['id'])) ?>">
<thead>
<tr>
diff --git a/app/Template/comment/show.php b/app/Template/comment/show.php
index 8419a14e..16a807bc 100644
--- a/app/Template/comment/show.php
+++ b/app/Template/comment/show.php
@@ -4,10 +4,10 @@
<div class="comment-title">
<?php if (! empty($comment['username'])): ?>
- <span class="comment-username"><?= $this->text->e($comment['name'] ?: $comment['username']) ?></span>
+ <strong class="comment-username"><?= $this->text->e($comment['name'] ?: $comment['username']) ?></strong>
<?php endif ?>
- <span class="comment-date"><?= $this->dt->datetime($comment['date_creation']) ?></span>
+ <small class="comment-date"><?= $this->dt->datetime($comment['date_creation']) ?></small>
</div>
<div class="comment-content">
diff --git a/app/Template/comments/show.php b/app/Template/comments/show.php
index 43f6b2c2..5c6d8e20 100644
--- a/app/Template/comments/show.php
+++ b/app/Template/comments/show.php
@@ -5,8 +5,10 @@
<div class="accordion-content" id="comments">
<?php if (!isset($is_public) || !$is_public): ?>
<div class="comment-sorting">
- <i class="fa fa-sort"></i>
- <?= $this->url->link(t('change sorting'), 'CommentController', 'toggleSorting', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) ?>
+ <small>
+ <i class="fa fa-sort"></i>
+ <?= $this->url->link(t('change sorting'), 'CommentController', 'toggleSorting', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) ?>
+ </small>
</div>
<?php endif ?>
<?php foreach ($comments as $comment): ?>
diff --git a/app/Template/currency/index.php b/app/Template/currency/index.php
index 9881cee5..db9b21af 100644
--- a/app/Template/currency/index.php
+++ b/app/Template/currency/index.php
@@ -4,7 +4,7 @@
<?php if (! empty($rates)): ?>
-<table class="table-stripped">
+<table class="table-striped">
<tr>
<th class="column-35"><?= t('Currency') ?></th>
<th><?= t('Rate') ?></th>
diff --git a/app/Template/custom_filter/index.php b/app/Template/custom_filter/index.php
index 08c8040c..dcab891b 100644
--- a/app/Template/custom_filter/index.php
+++ b/app/Template/custom_filter/index.php
@@ -3,7 +3,7 @@
<h2><?= t('Custom filters') ?></h2>
</div>
<div>
- <table>
+ <table class="table-striped table-scrolling">
<tr>
<th class="column-15"><?= t('Name') ?></th>
<th class="column-30"><?= t('Filter') ?></th>
diff --git a/app/Template/dashboard/notifications.php b/app/Template/dashboard/notifications.php
index 3b70b49f..4fb59e24 100644
--- a/app/Template/dashboard/notifications.php
+++ b/app/Template/dashboard/notifications.php
@@ -13,15 +13,29 @@
</ul>
</div>
- <table class="table-fixed table-small">
+ <table class="table-striped table-scrolling table-small">
<tr>
+ <th class="column-20"><?= t('Project') ?></th>
<th><?= t('Notification') ?></th>
- <th class="column-20"><?= t('Date') ?></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')): ?>
diff --git a/app/Template/dashboard/projects.php b/app/Template/dashboard/projects.php
index 3a7f1d86..f8806c01 100644
--- a/app/Template/dashboard/projects.php
+++ b/app/Template/dashboard/projects.php
@@ -4,7 +4,7 @@
<?php if ($paginator->isEmpty()): ?>
<p class="alert"><?= t('Your are not member of any project.') ?></p>
<?php else: ?>
- <table class="table-fixed table-small">
+ <table class="table-striped table-small table-scrolling">
<tr>
<th class="column-5"><?= $paginator->order('Id', \Kanboard\Model\ProjectModel::TABLE.'.id') ?></th>
<th class="column-3"><?= $paginator->order('<i class="fa fa-lock fa-fw" title="'.t('Private project').'"></i>', \Kanboard\Model\ProjectModel::TABLE.'.is_private') ?></th>
@@ -43,7 +43,7 @@
<td class="dashboard-project-stats">
<?php foreach ($project['columns'] as $column): ?>
<strong title="<?= t('Task count') ?>"><?= $column['nb_tasks'] ?></strong>
- <span><?= $this->text->e($column['title']) ?></span>
+ <small><?= $this->text->e($column['title']) ?></small>
<?php endforeach ?>
</td>
diff --git a/app/Template/dashboard/show.php b/app/Template/dashboard/show.php
index 637b60f8..aec6f591 100644
--- a/app/Template/dashboard/show.php
+++ b/app/Template/dashboard/show.php
@@ -2,11 +2,18 @@
<form method="get" action="<?= $this->url->dir() ?>" class="search">
<?= $this->form->hidden('controller', array('controller' => 'SearchController')) ?>
<?= $this->form->hidden('action', array('action' => 'index')) ?>
- <?= $this->form->text('search', array(), array(), array('placeholder="'.t('Search').'"'), 'form-input-large') ?>
- <?= $this->render('app/filters_helper') ?>
+
+ <div class="input-addon">
+ <?= $this->form->text('search', array(), array(), array('placeholder="'.t('Search').'"'), 'input-addon-field') ?>
+ <div class="input-addon-item">
+ <?= $this->render('app/filters_helper') ?>
+ </div>
+ </div>
</form>
</div>
<?= $this->render('dashboard/projects', array('paginator' => $project_paginator, 'user' => $user)) ?>
<?= $this->render('dashboard/tasks', array('paginator' => $task_paginator, 'user' => $user)) ?>
<?= $this->render('dashboard/subtasks', array('paginator' => $subtask_paginator, 'user' => $user)) ?>
+
+<?= $this->hook->render('template:dashboard:show', array('user' => $user)) ?>
diff --git a/app/Template/dashboard/sidebar.php b/app/Template/dashboard/sidebar.php
index df4e91a5..108c028a 100644
--- a/app/Template/dashboard/sidebar.php
+++ b/app/Template/dashboard/sidebar.php
@@ -21,6 +21,6 @@
<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') ?>
+ <?= $this->hook->render('template:dashboard:sidebar', array('user' => $user)) ?>
</ul>
</div>
diff --git a/app/Template/dashboard/subtasks.php b/app/Template/dashboard/subtasks.php
index ca550e4c..b71deeb9 100644
--- a/app/Template/dashboard/subtasks.php
+++ b/app/Template/dashboard/subtasks.php
@@ -4,7 +4,7 @@
<?php if ($paginator->isEmpty()): ?>
<p class="alert"><?= t('There is nothing assigned to you.') ?></p>
<?php else: ?>
- <table class="table-fixed table-small">
+ <table class="table-striped table-small table-scrolling">
<tr>
<th class="column-5"><?= $paginator->order('Id', \Kanboard\Model\TaskModel::TABLE.'.id') ?></th>
<th class="column-20"><?= $paginator->order(t('Project'), 'project_name') ?></th>
diff --git a/app/Template/dashboard/tasks.php b/app/Template/dashboard/tasks.php
index d9cb4f9e..427b903d 100644
--- a/app/Template/dashboard/tasks.php
+++ b/app/Template/dashboard/tasks.php
@@ -4,12 +4,12 @@
<?php if ($paginator->isEmpty()): ?>
<p class="alert"><?= t('There is nothing assigned to you.') ?></p>
<?php else: ?>
- <table class="table-fixed table-small">
+ <table class="table-striped table-small table-scrolling">
<tr>
<th class="column-5"><?= $paginator->order('Id', \Kanboard\Model\TaskModel::TABLE.'.id') ?></th>
<th class="column-20"><?= $paginator->order(t('Project'), 'project_name') ?></th>
<th><?= $paginator->order(t('Task'), \Kanboard\Model\TaskModel::TABLE.'.title') ?></th>
- <th class="column-5"><?= $paginator->order(t('Priority'), \Kanboard\Model\TaskModel::TABLE.'.priority') ?></th>
+ <th class="column-8"><?= $paginator->order(t('Priority'), \Kanboard\Model\TaskModel::TABLE.'.priority') ?></th>
<th class="column-20"><?= t('Time tracking') ?></th>
<th class="column-10"><?= $paginator->order(t('Due date'), \Kanboard\Model\TaskModel::TABLE.'.date_due') ?></th>
<th class="column-10"><?= $paginator->order(t('Column'), 'column_title') ?></th>
diff --git a/app/Template/event/comment_create.php b/app/Template/event/comment_create.php
index 45132e6d..780bba93 100644
--- a/app/Template/event/comment_create.php
+++ b/app/Template/event/comment_create.php
@@ -3,7 +3,7 @@
$this->text->e($author),
$this->url->link(t('#%d', $task['id']), 'TaskViewController', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id']))
) ?>
- <span class="activity-date"><?= $this->dt->datetime($date_creation) ?></span>
+ <small class="activity-date"><?= $this->dt->datetime($date_creation) ?></small>
</p>
<div class="activity-description">
<p class="activity-task-title"><?= $this->text->e($task['title']) ?></p>
diff --git a/app/Template/event/comment_delete.php b/app/Template/event/comment_delete.php
index ead7d56a..e3a2f9fa 100644
--- a/app/Template/event/comment_delete.php
+++ b/app/Template/event/comment_delete.php
@@ -3,7 +3,7 @@
$this->text->e($author),
$this->url->link(t('#%d', $task['id']), 'TaskViewController', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id']))
) ?>
- <span class="activity-date"><?= $this->dt->datetime($date_creation) ?></span>
+ <small class="activity-date"><?= $this->dt->datetime($date_creation) ?></small>
</p>
<div class="activity-description">
<p class="activity-task-title"><?= $this->text->e($task['title']) ?></p>
diff --git a/app/Template/event/comment_update.php b/app/Template/event/comment_update.php
index 5be598ac..9e25ec2d 100644
--- a/app/Template/event/comment_update.php
+++ b/app/Template/event/comment_update.php
@@ -3,7 +3,7 @@
$this->text->e($author),
$this->url->link(t('#%d', $task['id']), 'TaskViewController', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id']))
) ?>
- <span class="activity-date"><?= $this->dt->datetime($date_creation) ?></span>
+ <small class="activity-date"><?= $this->dt->datetime($date_creation) ?></small>
</p>
<div class="activity-description">
<p class="activity-task-title"><?= $this->text->e($task['title']) ?></p>
diff --git a/app/Template/event/subtask_create.php b/app/Template/event/subtask_create.php
index 1bf36c05..9a115c73 100644
--- a/app/Template/event/subtask_create.php
+++ b/app/Template/event/subtask_create.php
@@ -3,7 +3,7 @@
$this->text->e($author),
$this->url->link(t('#%d', $task['id']), 'TaskViewController', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id']))
) ?>
- <span class="activity-date"><?= $this->dt->datetime($date_creation) ?></span>
+ <small class="activity-date"><?= $this->dt->datetime($date_creation) ?></small>
</p>
<div class="activity-description">
<p class="activity-task-title"><?= $this->text->e($task['title']) ?></p>
diff --git a/app/Template/event/subtask_delete.php b/app/Template/event/subtask_delete.php
index 8ac11853..7f0d6d58 100644
--- a/app/Template/event/subtask_delete.php
+++ b/app/Template/event/subtask_delete.php
@@ -3,7 +3,7 @@
$this->text->e($author),
$this->url->link(t('#%d', $task['id']), 'TaskViewController', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id']))
) ?>
- <span class="activity-date"><?= $this->dt->datetime($date_creation) ?></span>
+ <small class="activity-date"><?= $this->dt->datetime($date_creation) ?></small>
</p>
<div class="activity-description">
<p class="activity-task-title"><?= $this->text->e($task['title']) ?></p>
diff --git a/app/Template/event/subtask_update.php b/app/Template/event/subtask_update.php
index 201402f6..e566022e 100644
--- a/app/Template/event/subtask_update.php
+++ b/app/Template/event/subtask_update.php
@@ -3,7 +3,7 @@
$this->text->e($author),
$this->url->link(t('#%d', $task['id']), 'TaskViewController', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id']))
) ?>
- <span class="activity-date"><?= $this->dt->datetime($date_creation) ?></span>
+ <small class="activity-date"><?= $this->dt->datetime($date_creation) ?></small>
</p>
<div class="activity-description">
<p class="activity-task-title"><?= $this->text->e($task['title']) ?></p>
diff --git a/app/Template/event/task_assignee_change.php b/app/Template/event/task_assignee_change.php
index 7539cd0b..405f8ac1 100644
--- a/app/Template/event/task_assignee_change.php
+++ b/app/Template/event/task_assignee_change.php
@@ -10,7 +10,7 @@
<?php else: ?>
<?= e('%s removed the assignee of the task %s', $this->text->e($author), $this->url->link(t('#%d', $task['id']), 'TaskViewController', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id']))) ?>
<?php endif ?>
- <span class="activity-date"><?= $this->dt->datetime($date_creation) ?></span>
+ <small class="activity-date"><?= $this->dt->datetime($date_creation) ?></small>
</p>
<div class="activity-description">
<p class="activity-task-title"><?= $this->text->e($task['title']) ?></p>
diff --git a/app/Template/event/task_close.php b/app/Template/event/task_close.php
index 90ff9207..1ac81ea9 100644
--- a/app/Template/event/task_close.php
+++ b/app/Template/event/task_close.php
@@ -3,7 +3,7 @@
$this->text->e($author),
$this->url->link(t('#%d', $task['id']), 'TaskViewController', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id']))
) ?>
- <span class="activity-date"><?= $this->dt->datetime($date_creation) ?></span>
+ <small class="activity-date"><?= $this->dt->datetime($date_creation) ?></small>
</p>
<div class="activity-description">
<p class="activity-task-title"><?= $this->text->e($task['title']) ?></p>
diff --git a/app/Template/event/task_create.php b/app/Template/event/task_create.php
index 017a5ada..9d0ff358 100644
--- a/app/Template/event/task_create.php
+++ b/app/Template/event/task_create.php
@@ -3,7 +3,7 @@
$this->text->e($author),
$this->url->link(t('#%d', $task['id']), 'TaskViewController', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id']))
) ?>
- <span class="activity-date"><?= $this->dt->datetime($date_creation) ?></span>
+ <small class="activity-date"><?= $this->dt->datetime($date_creation) ?></small>
</p>
<div class="activity-description">
<p class="activity-task-title"><?= $this->text->e($task['title']) ?></p>
diff --git a/app/Template/event/task_file_create.php b/app/Template/event/task_file_create.php
index d329529a..7e58fdc1 100644
--- a/app/Template/event/task_file_create.php
+++ b/app/Template/event/task_file_create.php
@@ -3,7 +3,7 @@
$this->text->e($author),
$this->url->link(t('#%d', $task['id']), 'TaskViewController', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id']))
) ?>
- <span class="activity-date"><?= $this->dt->datetime($date_creation) ?></span>
+ <small class="activity-date"><?= $this->dt->datetime($date_creation) ?></small>
</p>
<div class="activity-description">
<p class="activity-task-title"><?= $this->text->e($file['name']) ?></p>
diff --git a/app/Template/event/task_internal_link_create_update.php b/app/Template/event/task_internal_link_create_update.php
index de257977..4bc6ae9a 100644
--- a/app/Template/event/task_internal_link_create_update.php
+++ b/app/Template/event/task_internal_link_create_update.php
@@ -3,7 +3,7 @@
$this->text->e($author),
$this->url->link(t('#%d', $task['id']), 'TaskViewController', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id']))
) ?>
- <span class="activity-date"><?= $this->dt->datetime($date_creation) ?></span>
+ <small class="activity-date"><?= $this->dt->datetime($date_creation) ?></small>
</p>
<div class="activity-description">
<p class="activity-task-title">
diff --git a/app/Template/event/task_internal_link_delete.php b/app/Template/event/task_internal_link_delete.php
index e537bf81..3465fa57 100644
--- a/app/Template/event/task_internal_link_delete.php
+++ b/app/Template/event/task_internal_link_delete.php
@@ -3,7 +3,7 @@
$this->text->e($author),
$this->url->link(t('#%d', $task['id']), 'TaskViewController', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id']))
) ?>
- <span class="activity-date"><?= $this->dt->datetime($date_creation) ?></span>
+ <small class="activity-date"><?= $this->dt->datetime($date_creation) ?></small>
</p>
<div class="activity-description">
<p class="activity-task-title">
diff --git a/app/Template/event/task_move_column.php b/app/Template/event/task_move_column.php
index f3155e47..e7e5ec28 100644
--- a/app/Template/event/task_move_column.php
+++ b/app/Template/event/task_move_column.php
@@ -4,7 +4,7 @@
$this->url->link(t('#%d', $task['id']), 'TaskViewController', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])),
$this->text->e($task['column_title'])
) ?>
- <span class="activity-date"><?= $this->dt->datetime($date_creation) ?></span>
+ <small class="activity-date"><?= $this->dt->datetime($date_creation) ?></small>
</p>
<div class="activity-description">
<p class="activity-task-title"><?= $this->text->e($task['title']) ?></p>
diff --git a/app/Template/event/task_move_position.php b/app/Template/event/task_move_position.php
index ecdd02b6..48fbbb1e 100644
--- a/app/Template/event/task_move_position.php
+++ b/app/Template/event/task_move_position.php
@@ -5,7 +5,7 @@
$task['position'],
$this->text->e($task['column_title'])
) ?>
- <span class="activity-date"><?= $this->dt->datetime($date_creation) ?></span>
+ <small class="activity-date"><?= $this->dt->datetime($date_creation) ?></small>
</p>
<div class="activity-description">
<p class="activity-task-title"><?= $this->text->e($task['title']) ?></p>
diff --git a/app/Template/event/task_move_swimlane.php b/app/Template/event/task_move_swimlane.php
index fe9bfb55..a467875b 100644
--- a/app/Template/event/task_move_swimlane.php
+++ b/app/Template/event/task_move_swimlane.php
@@ -11,7 +11,7 @@
$this->text->e($task['swimlane_name'])
) ?>
<?php endif ?>
- <span class="activity-date"><?= $this->dt->datetime($date_creation) ?></span>
+ <small class="activity-date"><?= $this->dt->datetime($date_creation) ?></small>
</p>
<div class="activity-description">
<p class="activity-task-title"><?= $this->text->e($task['title']) ?></p>
diff --git a/app/Template/event/task_open.php b/app/Template/event/task_open.php
index 548aa98f..6d5252a1 100644
--- a/app/Template/event/task_open.php
+++ b/app/Template/event/task_open.php
@@ -3,7 +3,7 @@
$this->text->e($author),
$this->url->link(t('#%d', $task['id']), 'TaskViewController', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id']))
) ?>
- <span class="activity-date"><?= $this->dt->datetime($date_creation) ?></span>
+ <small class="activity-date"><?= $this->dt->datetime($date_creation) ?></small>
</p>
<div class="activity-description">
<p class="activity-task-title"><?= $this->text->e($task['title']) ?></p>
diff --git a/app/Template/event/task_update.php b/app/Template/event/task_update.php
index 7c7507c0..2608f623 100644
--- a/app/Template/event/task_update.php
+++ b/app/Template/event/task_update.php
@@ -3,7 +3,7 @@
$this->text->e($author),
$this->url->link(t('#%d', $task['id']), 'TaskViewController', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id']))
) ?>
- <span class="activity-date"><?= $this->dt->datetime($date_creation) ?></span>
+ <small class="activity-date"><?= $this->dt->datetime($date_creation) ?></small>
</p>
<div class="activity-description">
<p class="activity-task-title"><?= $this->text->e($task['title']) ?></p>
diff --git a/app/Template/group/index.php b/app/Template/group/index.php
index 1062e18c..fe8a07e7 100644
--- a/app/Template/group/index.php
+++ b/app/Template/group/index.php
@@ -8,7 +8,7 @@
<?php if ($paginator->isEmpty()): ?>
<p class="alert"><?= t('There is no group.') ?></p>
<?php else: ?>
- <table class="table-small table-fixed">
+ <table class="table-small table-fixed table-scrolling">
<tr>
<th class="column-5"><?= $paginator->order(t('Id'), 'id') ?></th>
<th class="column-20"><?= $paginator->order(t('External Id'), 'external_id') ?></th>
diff --git a/app/Template/group/users.php b/app/Template/group/users.php
index a4895ab7..73597b39 100644
--- a/app/Template/group/users.php
+++ b/app/Template/group/users.php
@@ -8,7 +8,7 @@
<?php if ($paginator->isEmpty()): ?>
<p class="alert"><?= t('There is no user in this group.') ?></p>
<?php else: ?>
- <table>
+ <table class="table-striped table-scrolling">
<tr>
<th><?= $paginator->order(t('Id'), 'id') ?></th>
<th><?= $paginator->order(t('Username'), 'username') ?></th>
diff --git a/app/Template/header.php b/app/Template/header.php
index a2b3fcb3..2fe68ebe 100644
--- a/app/Template/header.php
+++ b/app/Template/header.php
@@ -1,119 +1,26 @@
-<header>
- <nav>
- <h1>
- <span class="logo">
- <?= $this->url->link('K<span>B</span>', 'DashboardController', 'show', array(), false, '', t('Dashboard')) ?>
- </span>
- <span class="title">
- <?php if (! empty($project) && ! empty($task)): ?>
- <?= $this->url->link($this->text->e($project['name']), 'BoardViewController', 'show', array('project_id' => $project['id'])) ?>
- <?php else: ?>
- <?= $this->text->e($title) ?>
- <?php endif ?>
- </span>
- <?php if (! empty($description)): ?>
- <span class="tooltip" title="<?= $this->text->markdownAttribute($description) ?>">
- <i class="fa fa-info-circle"></i>
- </span>
- <?php endif ?>
- </h1>
- <ul>
- <?php if (isset($board_selector) && ! empty($board_selector)): ?>
- <li>
- <select id="board-selector"
- class="chosen-select select-auto-redirect"
- tabindex="-1"
- data-search-threshold="0"
- data-notfound="<?= t('No results match:') ?>"
- data-placeholder="<?= t('Display another project') ?>"
- data-redirect-regex="PROJECT_ID"
- data-redirect-url="<?= $this->url->href('BoardViewController', 'show', array('project_id' => 'PROJECT_ID')) ?>">
- <option value=""></option>
- <?php foreach ($board_selector as $board_id => $board_name): ?>
- <option value="<?= $board_id ?>"><?= $this->text->e($board_name) ?></option>
- <?php endforeach ?>
- </select>
- </li>
- <?php endif ?>
- <li class="user-links">
- <?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>
- <?php endif ?>
-
- <?php $has_project_creation_access = $this->user->hasAccess('ProjectCreationController', 'create'); ?>
- <?php $is_private_project_enabled = $this->app->config('disable_private_project', 0) == 0; ?>
-
- <?php if ($has_project_creation_access || (!$has_project_creation_access && $is_private_project_enabled)): ?>
- <div class="dropdown">
- <a href="#" class="dropdown-menu dropdown-menu-link-icon"><i class="fa fa-plus fa-fw"></i><i class="fa fa-caret-down"></i></a>
- <ul>
- <?php if ($has_project_creation_access): ?>
- <li><i class="fa fa-plus fa-fw"></i>
- <?= $this->url->link(t('New project'), 'ProjectCreationController', 'create', array(), false, 'popover') ?></li>
- <?php endif ?>
- <?php if ($is_private_project_enabled): ?>
- <li>
- <i class="fa fa-lock fa-fw"></i>
- <?= $this->url->link(t('New private project'), 'ProjectCreationController', 'createPrivate', array(), false, 'popover') ?>
- </li>
- <?php endif ?>
- <?= $this->hook->render('template:header:creation-dropdown') ?>
- </ul>
- </div>
- <?php endif ?>
+<?php $_title = $this->render('header/title', array(
+ 'project' => isset($project) ? $project : null,
+ 'task' => isset($task) ? $task : null,
+ 'description' => isset($description) ? $description : null,
+ 'title' => $title,
+)) ?>
- <div class="dropdown">
- <a href="#" class="dropdown-menu dropdown-menu-link-icon"><?= $this->avatar->currentUserSmall('avatar-inline') ?><i class="fa fa-caret-down"></i></a>
- <ul>
- <li class="no-hover"><strong><?= $this->text->e($this->user->getFullname()) ?></strong></li>
- <li>
- <i class="fa fa-tachometer fa-fw"></i>
- <?= $this->url->link(t('My dashboard'), 'DashboardController', 'show', array('user_id' => $this->user->getId())) ?>
- </li>
- <li>
- <i class="fa fa-home fa-fw"></i>
- <?= $this->url->link(t('My profile'), 'UserViewController', 'show', array('user_id' => $this->user->getId())) ?>
- </li>
- <li>
- <i class="fa fa-folder fa-fw"></i>
- <?= $this->url->link(t('Projects management'), 'ProjectListController', 'show') ?>
- </li>
- <?php if ($this->user->hasAccess('UserListController', 'show')): ?>
- <li>
- <i class="fa fa-user fa-fw"></i>
- <?= $this->url->link(t('Users management'), 'UserListController', 'show') ?>
- </li>
- <li>
- <i class="fa fa-group fa-fw"></i>
- <?= $this->url->link(t('Groups management'), 'GroupListController', 'index') ?>
- </li>
- <li>
- <i class="fa fa-cubes" aria-hidden="true"></i>
- <?= $this->url->link(t('Plugins'), 'PluginController', 'show') ?>
- </li>
- <li>
- <i class="fa fa-cog fa-fw"></i>
- <?= $this->url->link(t('Settings'), 'ConfigController', 'index') ?>
- </li>
- <?php endif ?>
+<?php $_top_right_corner = implode('&nbsp;', array(
+ $this->render('header/user_notifications'),
+ $this->render('header/creation_dropdown'),
+ $this->render('header/user_dropdown')
+ )) ?>
- <?= $this->hook->render('template:header:dropdown') ?>
-
- <li>
- <i class="fa fa-life-ring fa-fw"></i>
- <?= $this->url->link(t('Documentation'), 'DocumentationController', 'show') ?>
- </li>
- <?php if (! DISABLE_LOGOUT): ?>
- <li>
- <i class="fa fa-sign-out fa-fw"></i>
- <?= $this->url->link(t('Logout'), 'AuthController', 'logout') ?>
- </li>
- <?php endif ?>
- </ul>
- </div>
- </li>
- </ul>
- </nav>
+<header>
+ <div class="title-container">
+ <?= $_title ?>
+ </div>
+ <?php if (! empty($board_selector)): ?>
+ <div class="board-selector-container">
+ <?= $this->render('header/board_selector', array('board_selector' => $board_selector)) ?>
+ </div>
+ <?php endif ?>
+ <div class="menus-container pull-right">
+ <?= $_top_right_corner ?>
+ </div>
</header>
diff --git a/app/Template/header/board_selector.php b/app/Template/header/board_selector.php
new file mode 100644
index 00000000..b42d47f9
--- /dev/null
+++ b/app/Template/header/board_selector.php
@@ -0,0 +1,13 @@
+<select id="board-selector"
+ class="chosen-select select-auto-redirect"
+ tabindex="-1"
+ data-search-threshold="0"
+ data-notfound="<?= t('No results match:') ?>"
+ data-placeholder="<?= t('Display another project') ?>"
+ data-redirect-regex="PROJECT_ID"
+ data-redirect-url="<?= $this->url->href('BoardViewController', 'show', array('project_id' => 'PROJECT_ID')) ?>">
+ <option value=""></option>
+ <?php foreach ($board_selector as $board_id => $board_name): ?>
+ <option value="<?= $board_id ?>"><?= $this->text->e($board_name) ?></option>
+ <?php endforeach ?>
+</select>
diff --git a/app/Template/header/creation_dropdown.php b/app/Template/header/creation_dropdown.php
new file mode 100644
index 00000000..d3b9e7cb
--- /dev/null
+++ b/app/Template/header/creation_dropdown.php
@@ -0,0 +1,22 @@
+<?php $has_project_creation_access = $this->user->hasAccess('ProjectCreationController', 'create'); ?>
+<?php $is_private_project_enabled = $this->app->config('disable_private_project', 0) == 0; ?>
+
+<?php if ($has_project_creation_access || (!$has_project_creation_access && $is_private_project_enabled)): ?>
+ <div class="dropdown">
+ <a href="#" class="dropdown-menu dropdown-menu-link-icon"><i class="fa fa-plus fa-fw"></i><i class="fa fa-caret-down"></i></a>
+ <ul>
+ <?php if ($has_project_creation_access): ?>
+ <li><i class="fa fa-plus fa-fw"></i>
+ <?= $this->url->link(t('New project'), 'ProjectCreationController', 'create', array(), false, 'popover') ?>
+ </li>
+ <?php endif ?>
+ <?php if ($is_private_project_enabled): ?>
+ <li>
+ <i class="fa fa-lock fa-fw"></i>
+ <?= $this->url->link(t('New private project'), 'ProjectCreationController', 'createPrivate', array(), false, 'popover') ?>
+ </li>
+ <?php endif ?>
+ <?= $this->hook->render('template:header:creation-dropdown') ?>
+ </ul>
+ </div>
+<?php endif ?>
diff --git a/app/Template/header/title.php b/app/Template/header/title.php
new file mode 100644
index 00000000..61c6ee9a
--- /dev/null
+++ b/app/Template/header/title.php
@@ -0,0 +1,17 @@
+<h1>
+ <span class="logo">
+ <?= $this->url->link('K<span>B</span>', 'DashboardController', 'show', array(), false, '', t('Dashboard')) ?>
+ </span>
+ <span class="title">
+ <?php if (! empty($project) && ! empty($task)): ?>
+ <?= $this->url->link($this->text->e($project['name']), 'BoardViewController', 'show', array('project_id' => $project['id'])) ?>
+ <?php else: ?>
+ <?= $this->text->e($title) ?>
+ <?php endif ?>
+ </span>
+ <?php if (! empty($description)): ?>
+ <small class="tooltip" title="<?= $this->text->markdownAttribute($description) ?>">
+ <i class="fa fa-info-circle"></i>
+ </small>
+ <?php endif ?>
+</h1>
diff --git a/app/Template/header/user_dropdown.php b/app/Template/header/user_dropdown.php
new file mode 100644
index 00000000..49d08213
--- /dev/null
+++ b/app/Template/header/user_dropdown.php
@@ -0,0 +1,49 @@
+<div class="dropdown">
+ <a href="#" class="dropdown-menu dropdown-menu-link-icon"><?= $this->avatar->currentUserSmall('avatar-inline') ?><i class="fa fa-caret-down"></i></a>
+ <ul>
+ <li class="no-hover"><strong><?= $this->text->e($this->user->getFullname()) ?></strong></li>
+ <li>
+ <i class="fa fa-tachometer fa-fw"></i>
+ <?= $this->url->link(t('My dashboard'), 'DashboardController', 'show', array('user_id' => $this->user->getId())) ?>
+ </li>
+ <li>
+ <i class="fa fa-home fa-fw"></i>
+ <?= $this->url->link(t('My profile'), 'UserViewController', 'show', array('user_id' => $this->user->getId())) ?>
+ </li>
+ <li>
+ <i class="fa fa-folder fa-fw"></i>
+ <?= $this->url->link(t('Projects management'), 'ProjectListController', 'show') ?>
+ </li>
+ <?php if ($this->user->hasAccess('UserListController', 'show')): ?>
+ <li>
+ <i class="fa fa-user fa-fw"></i>
+ <?= $this->url->link(t('Users management'), 'UserListController', 'show') ?>
+ </li>
+ <li>
+ <i class="fa fa-group fa-fw"></i>
+ <?= $this->url->link(t('Groups management'), 'GroupListController', 'index') ?>
+ </li>
+ <li>
+ <i class="fa fa-cubes" aria-hidden="true"></i>
+ <?= $this->url->link(t('Plugins'), 'PluginController', 'show') ?>
+ </li>
+ <li>
+ <i class="fa fa-cog fa-fw"></i>
+ <?= $this->url->link(t('Settings'), 'ConfigController', 'index') ?>
+ </li>
+ <?php endif ?>
+
+ <?= $this->hook->render('template:header:dropdown') ?>
+
+ <li>
+ <i class="fa fa-life-ring fa-fw"></i>
+ <?= $this->url->link(t('Documentation'), 'DocumentationController', 'show') ?>
+ </li>
+ <?php if (! DISABLE_LOGOUT): ?>
+ <li>
+ <i class="fa fa-sign-out fa-fw"></i>
+ <?= $this->url->link(t('Logout'), 'AuthController', 'logout') ?>
+ </li>
+ <?php endif ?>
+ </ul>
+</div>
diff --git a/app/Template/header/user_notifications.php b/app/Template/header/user_notifications.php
new file mode 100644
index 00000000..83c545d2
--- /dev/null
+++ b/app/Template/header/user_notifications.php
@@ -0,0 +1,5 @@
+<?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>
+<?php endif ?>
diff --git a/app/Template/layout.php b/app/Template/layout.php
index 411237cb..8c85ffc6 100644
--- a/app/Template/layout.php
+++ b/app/Template/layout.php
@@ -15,7 +15,6 @@
<?= $this->asset->colorCss() ?>
<?= $this->asset->css('assets/css/vendor.min.css') ?>
<?= $this->asset->css('assets/css/app.min.css') ?>
- <?= $this->asset->css('assets/css/print.min.css', true, 'print') ?>
<?= $this->asset->customCss() ?>
<?php if (! isset($not_editable)): ?>
diff --git a/app/Template/link/index.php b/app/Template/link/index.php
index 7e32069a..70ead4a6 100644
--- a/app/Template/link/index.php
+++ b/app/Template/link/index.php
@@ -2,7 +2,7 @@
<h2><?= t('Link labels') ?></h2>
</div>
<?php if (! empty($links)): ?>
-<table>
+<table class="table-striped table-scrolling">
<tr>
<th class="column-70"><?= t('Link labels') ?></th>
<th><?= t('Actions') ?></th>
diff --git a/app/Template/project_header/header.php b/app/Template/project_header/header.php
index aaa8137b..6c91e38b 100644
--- a/app/Template/project_header/header.php
+++ b/app/Template/project_header/header.php
@@ -1,15 +1,21 @@
<div class="project-header">
<?= $this->hook->render('template:project:header:before', array('project' => $project)) ?>
- <?= $this->render('project_header/dropdown', array('project' => $project, 'board_view' => $board_view)) ?>
- <?= $this->render('project_header/views', array('project' => $project, 'filters' => $filters)) ?>
- <?= $this->render('project_header/search', array(
- 'project' => $project,
- 'filters' => $filters,
- 'custom_filters_list' => isset($custom_filters_list) ? $custom_filters_list : array(),
- 'users_list' => isset($users_list) ? $users_list : array(),
- 'categories_list' => isset($categories_list) ? $categories_list : array(),
- )) ?>
+ <div class="dropdown-component">
+ <?= $this->render('project_header/dropdown', array('project' => $project, 'board_view' => $board_view)) ?>
+ </div>
+ <div class="views-switcher-component">
+ <?= $this->render('project_header/views', array('project' => $project, 'filters' => $filters)) ?>
+ </div>
+ <div class="filter-box-component">
+ <?= $this->render('project_header/search', array(
+ 'project' => $project,
+ 'filters' => $filters,
+ 'custom_filters_list' => isset($custom_filters_list) ? $custom_filters_list : array(),
+ 'users_list' => isset($users_list) ? $users_list : array(),
+ 'categories_list' => isset($categories_list) ? $categories_list : array(),
+ )) ?>
+ </div>
<?= $this->hook->render('template:project:header:after', array('project' => $project)) ?>
-</div> \ No newline at end of file
+</div>
diff --git a/app/Template/project_header/search.php b/app/Template/project_header/search.php
index 8885d9c9..512e88d7 100644
--- a/app/Template/project_header/search.php
+++ b/app/Template/project_header/search.php
@@ -3,43 +3,54 @@
<?= $this->form->hidden('controller', $filters) ?>
<?= $this->form->hidden('action', $filters) ?>
<?= $this->form->hidden('project_id', $filters) ?>
- <?= $this->form->text('search', $filters, array(), array('placeholder="'.t('Filter').'"')) ?>
- <?= $this->render('app/filters_helper', array('reset' => 'status:open', 'project' => $project)) ?>
+ <div class="input-addon">
+ <?= $this->form->text('search', $filters, array(), array('placeholder="'.t('Filter').'"'), 'input-addon-field') ?>
+ <div class="input-addon-item">
+ <?= $this->render('app/filters_helper', array('reset' => 'status:open', 'project' => $project)) ?>
+ </div>
- <?php if (isset($custom_filters_list) && ! empty($custom_filters_list)): ?>
- <div class="dropdown">
- <a href="#" class="dropdown-menu dropdown-menu-link-icon" title="<?= t('Custom filters') ?>"><i class="fa fa-bookmark fa-fw"></i><i class="fa fa-caret-down"></i></a>
- <ul>
- <?php foreach ($custom_filters_list as $filter): ?>
- <li><a href="#" class="filter-helper" data-<?php if ($filter['append']): ?><?= 'append-' ?><?php endif ?>filter='<?= $this->text->e($filter['filter']) ?>'><?= $this->text->e($filter['name']) ?></a></li>
- <?php endforeach ?>
- </ul>
- </div>
- <?php endif ?>
+ <?php if (isset($custom_filters_list) && ! empty($custom_filters_list)): ?>
+ <div class="input-addon-item">
+ <div class="dropdown">
+ <a href="#" class="dropdown-menu dropdown-menu-link-icon" title="<?= t('Custom filters') ?>"><i class="fa fa-bookmark fa-fw"></i><i class="fa fa-caret-down"></i></a>
+ <ul>
+ <?php foreach ($custom_filters_list as $filter): ?>
+ <li><a href="#" class="filter-helper" data-<?php if ($filter['append']): ?><?= 'append-' ?><?php endif ?>filter='<?= $this->text->e($filter['filter']) ?>'><?= $this->text->e($filter['name']) ?></a></li>
+ <?php endforeach ?>
+ </ul>
+ </div>
+ </div>
+ <?php endif ?>
- <?php if (isset($users_list)): ?>
- <div class="dropdown">
- <a href="#" class="dropdown-menu dropdown-menu-link-icon" title="<?= t('User filters') ?>"><i class="fa fa-users fa-fw"></i> <i class="fa fa-caret-down"></i></a>
- <ul>
- <li><a href="#" class="filter-helper" data-unique-filter="assignee:nobody"><?= t('Not assigned') ?></a></li>
- <?php foreach ($users_list as $user): ?>
- <li><a href="#" class="filter-helper" data-unique-filter='assignee:"<?= $this->text->e($user) ?>"'><?= $this->text->e($user) ?></a></li>
- <?php endforeach ?>
- </ul>
- </div>
- <?php endif ?>
+ <?php if (isset($users_list)): ?>
+ <div class="input-addon-item">
+ <div class="dropdown">
+ <a href="#" class="dropdown-menu dropdown-menu-link-icon" title="<?= t('User filters') ?>"><i class="fa fa-users fa-fw"></i> <i class="fa fa-caret-down"></i></a>
+ <ul>
+ <li><a href="#" class="filter-helper" data-unique-filter="assignee:nobody"><?= t('Not assigned') ?></a></li>
+ <?php foreach ($users_list as $user): ?>
+ <li><a href="#" class="filter-helper" data-unique-filter='assignee:"<?= $this->text->e($user) ?>"'><?= $this->text->e($user) ?></a></li>
+ <?php endforeach ?>
+ </ul>
+ </div>
+ </div>
+ <?php endif ?>
- <?php if (isset($categories_list) && ! empty($categories_list)): ?>
- <div class="dropdown">
- <a href="#" class="dropdown-menu dropdown-menu-link-icon" title="<?= t('Category filters') ?>"><i class="fa fa-tags fa-fw"></i><i class="fa fa-caret-down"></i></a>
- <ul>
- <li><a href="#" class="filter-helper" data-unique-filter="category:none"><?= t('No category') ?></a></li>
- <?php foreach ($categories_list as $category): ?>
- <li><a href="#" class="filter-helper" data-unique-filter='category:"<?= $this->text->e($category) ?>"'><?= $this->text->e($category) ?></a></li>
- <?php endforeach ?>
- </ul>
+ <?php if (isset($categories_list) && ! empty($categories_list)): ?>
+ <div class="input-addon-item">
+ <div class="dropdown">
+ <a href="#" class="dropdown-menu dropdown-menu-link-icon" title="<?= t('Category filters') ?>"><i class="fa fa-tags fa-fw"></i><i class="fa fa-caret-down"></i></a>
+ <ul>
+ <li><a href="#" class="filter-helper" data-unique-filter="category:none"><?= t('No category') ?></a></li>
+ <?php foreach ($categories_list as $category): ?>
+ <li><a href="#" class="filter-helper" data-unique-filter='category:"<?= $this->text->e($category) ?>"'><?= $this->text->e($category) ?></a></li>
+ <?php endforeach ?>
+ </ul>
+ </div>
+ </div>
+ <?php endif ?>
</div>
- <?php endif ?>
+
</form>
</div>
diff --git a/app/Template/project_list/show.php b/app/Template/project_list/show.php
index 8b9f1396..4f7c2e83 100644
--- a/app/Template/project_list/show.php
+++ b/app/Template/project_list/show.php
@@ -1,24 +1,26 @@
<section id="main">
<div class="page-header">
<ul>
+ <?= $this->hook->render('template:project-list:menu:before', array('project' => $project)) ?>
<?php if ($this->user->hasAccess('ProjectUserOverviewController', 'managers')): ?>
<li><i class="fa fa-user fa-fw"></i><?= $this->url->link(t('Users overview'), 'ProjectUserOverviewController', 'managers') ?></li>
<?php endif ?>
<?php if ($this->user->hasAccess('ProjectGanttController', 'show')): ?>
<li><i class="fa fa-sliders fa-fw"></i><?= $this->url->link(t('Projects Gantt chart'), 'ProjectGanttController', 'show') ?></li>
<?php endif ?>
+ <?= $this->hook->render('template:project-list:menu:after', array('project' => $project)) ?>
</ul>
</div>
<?php if ($paginator->isEmpty()): ?>
<p class="alert"><?= t('No project') ?></p>
<?php else: ?>
- <table class="table-stripped table-small">
+ <table class="table-striped table-scrolling">
<tr>
- <th class="column-3"><?= $paginator->order(t('Id'), 'id') ?></th>
- <th class="column-5"><?= $paginator->order(t('Status'), 'is_active') ?></th>
+ <th class="column-5"><?= $paginator->order(t('Id'), 'id') ?></th>
+ <th class="column-8"><?= $paginator->order(t('Status'), 'is_active') ?></th>
<th class="column-15"><?= $paginator->order(t('Project'), 'name') ?></th>
- <th class="column-8"><?= $paginator->order(t('Start date'), 'start_date') ?></th>
- <th class="column-8"><?= $paginator->order(t('End date'), 'end_date') ?></th>
+ <th class="column-10"><?= $paginator->order(t('Start date'), 'start_date') ?></th>
+ <th class="column-10"><?= $paginator->order(t('End date'), 'end_date') ?></th>
<th class="column-15"><?= $paginator->order(t('Owner'), 'owner_id') ?></th>
<?php if ($this->user->hasAccess('ProjectUserOverviewController', 'managers')): ?>
<th class="column-10"><?= t('Users') ?></th>
@@ -73,7 +75,7 @@
<td class="dashboard-project-stats">
<?php foreach ($project['columns'] as $column): ?>
<strong title="<?= t('Task count') ?>"><?= $column['nb_tasks'] ?></strong>
- <span><?= $this->text->e($column['title']) ?></span>
+ <small><?= $this->text->e($column['title']) ?></small>
<?php endforeach ?>
</td>
</tr>
diff --git a/app/Template/project_overview/columns.php b/app/Template/project_overview/columns.php
index cc5782bd..daae9ca7 100644
--- a/app/Template/project_overview/columns.php
+++ b/app/Template/project_overview/columns.php
@@ -1,8 +1,8 @@
<div class="project-overview-columns">
<?php foreach ($project['columns'] as $column): ?>
<div class="project-overview-column">
- <strong title="<?= t('Task count') ?>"><?= $column['nb_tasks'] ?></strong><br>
- <span><?= $this->text->e($column['title']) ?></span>
+ <strong title="<?= t('Task count') ?>"><?= $column['nb_tasks'] ?></strong>
+ <small><?= $this->text->e($column['title']) ?></small>
</div>
<?php endforeach ?>
</div>
diff --git a/app/Template/project_overview/files.php b/app/Template/project_overview/files.php
index fa870938..826e6325 100644
--- a/app/Template/project_overview/files.php
+++ b/app/Template/project_overview/files.php
@@ -1,5 +1,5 @@
<?php if (! empty($files)): ?>
- <table class="table-stripped">
+ <table class="table-striped table-scrolling">
<tr>
<th><?= t('Filename') ?></th>
<th><?= t('Creator') ?></th>
diff --git a/app/Template/project_permission/index.php b/app/Template/project_permission/index.php
index d850ec50..c7b17782 100644
--- a/app/Template/project_permission/index.php
+++ b/app/Template/project_permission/index.php
@@ -9,7 +9,7 @@
<?php if (empty($users)): ?>
<div class="alert"><?= t('No user have been allowed specifically.') ?></div>
<?php else: ?>
- <table>
+ <table class="table-scrolling">
<tr>
<th class="column-50"><?= t('User') ?></th>
<th><?= t('Role') ?></th>
@@ -69,7 +69,7 @@
<?php if (empty($groups)): ?>
<div class="alert"><?= t('No group have been allowed specifically.') ?></div>
<?php else: ?>
- <table>
+ <table class="table-scrolling">
<tr>
<th class="column-50"><?= t('Group') ?></th>
<th><?= t('Role') ?></th>
diff --git a/app/Template/project_tag/index.php b/app/Template/project_tag/index.php
index 8e8dd96c..f77e21ee 100644
--- a/app/Template/project_tag/index.php
+++ b/app/Template/project_tag/index.php
@@ -11,7 +11,7 @@
<?php if (empty($tags)): ?>
<p class="alert"><?= t('There is no specific tag for this project at the moment.') ?></p>
<?php else: ?>
- <table class="table-striped">
+ <table class="table-striped table-scrolling">
<tr>
<th class="column-80"><?= t('Tag') ?></th>
<th><?= t('Action') ?></th>
diff --git a/app/Template/project_user_overview/roles.php b/app/Template/project_user_overview/roles.php
index 87c8df85..011714d4 100644
--- a/app/Template/project_user_overview/roles.php
+++ b/app/Template/project_user_overview/roles.php
@@ -1,7 +1,7 @@
<?php if ($paginator->isEmpty()): ?>
<p class="alert"><?= t('No project') ?></p>
<?php else: ?>
- <table class="table-fixed">
+ <table class="table-fixed table-scrolling">
<tr>
<th class="column-20"><?= $paginator->order(t('User'), 'users.username') ?></th>
<th class="column-25"><?= $paginator->order(t('Project'), 'projects.name') ?></th>
diff --git a/app/Template/project_user_overview/tasks.php b/app/Template/project_user_overview/tasks.php
index af0a3d97..8d682170 100644
--- a/app/Template/project_user_overview/tasks.php
+++ b/app/Template/project_user_overview/tasks.php
@@ -1,7 +1,7 @@
<?php if ($paginator->isEmpty()): ?>
<p class="alert"><?= t('No tasks found.') ?></p>
<?php elseif (! $paginator->isEmpty()): ?>
- <table class="table-small">
+ <table class="table-small table-striped table-scrolling">
<tr>
<th class="column-5"><?= $paginator->order(t('Id'), 'tasks.id') ?></th>
<th class="column-10"><?= $paginator->order(t('Project'), 'projects.name') ?></th>
diff --git a/app/Template/project_user_overview/tooltip_users.php b/app/Template/project_user_overview/tooltip_users.php
index 7117a87f..99b00030 100644
--- a/app/Template/project_user_overview/tooltip_users.php
+++ b/app/Template/project_user_overview/tooltip_users.php
@@ -1,7 +1,7 @@
<?php if (empty($users)): ?>
<p><?= t('There is no project member.') ?></p>
<?php else: ?>
- <table>
+ <table class="table-small">
<?php foreach ($roles as $role => $role_name): ?>
<?php if (isset($users[$role])): ?>
<tr><th><?= $role_name ?></th></tr>
diff --git a/app/Template/project_view/show.php b/app/Template/project_view/show.php
index 667a576c..afe60384 100644
--- a/app/Template/project_view/show.php
+++ b/app/Template/project_view/show.php
@@ -52,7 +52,7 @@
<div class="page-header">
<h2><?= t('Board') ?></h2>
</div>
-<table class="table-stripped">
+<table class="table-striped table-scrolling">
<tr>
<th class="column-40"><?= t('Column') ?></th>
<th class="column-20"><?= t('Task limit') ?></th>
diff --git a/app/Template/search/activity.php b/app/Template/search/activity.php
index 9abc7d7e..1dfd9234 100644
--- a/app/Template/search/activity.php
+++ b/app/Template/search/activity.php
@@ -12,8 +12,13 @@
<form method="get" action="<?= $this->url->dir() ?>" class="search">
<?= $this->form->hidden('controller', $values) ?>
<?= $this->form->hidden('action', $values) ?>
- <?= $this->form->text('search', $values, array(), array(empty($values['search']) ? 'autofocus' : '', 'placeholder="'.t('Search').'"'), 'form-input-large') ?>
- <?= $this->render('activity/filter_dropdown') ?>
+
+ <div class="input-addon">
+ <?= $this->form->text('search', $values, array(), array(empty($values['search']) ? 'autofocus' : '', 'placeholder="'.t('Search').'"'), 'input-addon-field') ?>
+ <div class="input-addon-item">
+ <?= $this->render('app/filters_helper') ?>
+ </div>
+ </div>
</form>
</div>
diff --git a/app/Template/search/index.php b/app/Template/search/index.php
index bc528af7..c59a5c99 100644
--- a/app/Template/search/index.php
+++ b/app/Template/search/index.php
@@ -12,8 +12,13 @@
<form method="get" action="<?= $this->url->dir() ?>" class="search">
<?= $this->form->hidden('controller', $values) ?>
<?= $this->form->hidden('action', $values) ?>
- <?= $this->form->text('search', $values, array(), array(empty($values['search']) ? 'autofocus' : '', 'placeholder="'.t('Search').'"'), 'form-input-large') ?>
- <?= $this->render('app/filters_helper') ?>
+
+ <div class="input-addon">
+ <?= $this->form->text('search', $values, array(), array(empty($values['search']) ? 'autofocus' : '', 'placeholder="'.t('Search').'"'), 'input-addon-field') ?>
+ <div class="input-addon-item">
+ <?= $this->render('app/filters_helper') ?>
+ </div>
+ </div>
</form>
</div>
diff --git a/app/Template/search/results.php b/app/Template/search/results.php
index 8376b9e8..8c439a8a 100644
--- a/app/Template/search/results.php
+++ b/app/Template/search/results.php
@@ -1,4 +1,4 @@
-<table class="table-fixed table-small">
+<table class="table-small table-scrolling">
<tr>
<th class="column-8"><?= $paginator->order(t('Project'), 'tasks.project_id') ?></th>
<th class="column-5"><?= $paginator->order(t('Id'), 'tasks.id') ?></th>
diff --git a/app/Template/subtask/table.php b/app/Template/subtask/table.php
index 4c6484ef..5c60df44 100644
--- a/app/Template/subtask/table.php
+++ b/app/Template/subtask/table.php
@@ -1,6 +1,6 @@
<?php if (! empty($subtasks)): ?>
<table
- class="subtasks-table table-stripped"
+ class="subtasks-table table-striped table-scrolling"
data-save-position-url="<?= $this->url->href('SubtaskController', 'movePosition', array('project_id' => $task['project_id'], 'task_id' => $task['id'])) ?>"
>
<thead>
diff --git a/app/Template/swimlane/table.php b/app/Template/swimlane/table.php
index be123b08..cefef9de 100644
--- a/app/Template/swimlane/table.php
+++ b/app/Template/swimlane/table.php
@@ -1,5 +1,5 @@
<table
- class="swimlanes-table table-stripped"
+ class="swimlanes-table table-striped table-scrolling"
data-save-position-url="<?= $this->url->href('SwimlaneController', 'move', array('project_id' => $project['id'])) ?>">
<thead>
<tr>
diff --git a/app/Template/tag/index.php b/app/Template/tag/index.php
index 2a495eb3..8e0c9a06 100644
--- a/app/Template/tag/index.php
+++ b/app/Template/tag/index.php
@@ -11,7 +11,7 @@
<?php if (empty($tags)): ?>
<p class="alert"><?= t('There is no global tag at the moment.') ?></p>
<?php else: ?>
- <table class="table-striped">
+ <table class="table-striped table-scrolling">
<tr>
<th class="column-80"><?= t('Tag') ?></th>
<th><?= t('Action') ?></th>
diff --git a/app/Template/task/analytics.php b/app/Template/task/analytics.php
index db2d0cef..071f24a7 100644
--- a/app/Template/task/analytics.php
+++ b/app/Template/task/analytics.php
@@ -1,6 +1,10 @@
-<div class="task-show-title color-<?= $task['color_id'] ?>">
- <h2><?= $this->text->e($task['title']) ?></h2>
-</div>
+<?= $this->render('task/details', array(
+ 'task' => $task,
+ 'tags' => $tags,
+ 'project' => $project,
+ 'editable' => false,
+)) ?>
+
<div class="page-header">
<h2><?= t('Analytics') ?></h2>
</div>
@@ -14,7 +18,7 @@
<h3 id="analytic-task-time-column"><?= t('Time spent into each column') ?></h3>
<div id="chart" data-metrics='<?= json_encode($time_spent_columns, JSON_HEX_APOS) ?>' data-label="<?= t('Time spent') ?>"></div>
-<table class="table-stripped">
+<table class="table-striped">
<tr>
<th><?= t('Column') ?></th>
<th><?= t('Time spent') ?></th>
diff --git a/app/Template/task/details.php b/app/Template/task/details.php
index 695957f9..a39c1bab 100644
--- a/app/Template/task/details.php
+++ b/app/Template/task/details.php
@@ -31,18 +31,21 @@
</li>
<?php endif ?>
<?php if ($project['is_public']): ?>
- <li class="smaller">
- <i class="fa fa-external-link fa-fw"></i>
- <?= $this->url->link(t('Public link'), 'TaskViewController', 'readonly', array('task_id' => $task['id'], 'token' => $project['token']), false, '', '', true) ?>
+ <li>
+ <small>
+ <i class="fa fa-external-link fa-fw"></i>
+ <?= $this->url->link(t('Public link'), 'TaskViewController', 'readonly', array('task_id' => $task['id'], 'token' => $project['token']), false, '', '', true) ?>
+ </small>
</li>
<?php endif ?>
<?php if ($project['is_public'] && !$editable): ?>
- <li class="smaller">
- <i class="fa fa-th fa-fw"></i>
- <?= $this->url->link(t('Back to the board'), 'BoardViewController', 'readonly', array('token' => $project['token'])) ?>
+ <li>
+ <small>
+ <i class="fa fa-th fa-fw"></i>
+ <?= $this->url->link(t('Back to the board'), 'BoardViewController', 'readonly', array('token' => $project['token'])) ?>
+ </small>
</li>
<?php endif ?>
- <li class="smaller">
<?= $this->hook->render('template:task:details:first-column', array('task' => $task)) ?>
</ul>
@@ -158,7 +161,7 @@
</div>
<?php if ($editable && empty($task['date_started'])): ?>
- <div class="task-summary-buttons">
+ <div class="buttons-header">
<?= $this->url->button('fa-play', t('Set start date'), 'TaskModificationController', 'start', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) ?>
</div>
<?php endif ?>
diff --git a/app/Template/task/show.php b/app/Template/task/show.php
index b18c2bca..a5c2d5a7 100644
--- a/app/Template/task/show.php
+++ b/app/Template/task/show.php
@@ -8,58 +8,58 @@
)) ?>
<?php if (!empty($task['description'])): ?>
-<?= $this->hook->render('template:task:show:before-description', array('task' => $task, 'project' => $project)) ?>
-<?= $this->render('task/description', array('task' => $task)) ?>
+ <?= $this->hook->render('template:task:show:before-description', array('task' => $task, 'project' => $project)) ?>
+ <?= $this->render('task/description', array('task' => $task)) ?>
<?php endif ?>
<?php if(!empty($subtasks)): ?>
-<?= $this->hook->render('template:task:show:before-subtasks', array('task' => $task, 'project' => $project)) ?>
-<?= $this->render('subtask/show', array(
- 'task' => $task,
- 'subtasks' => $subtasks,
- 'project' => $project,
- 'editable' => true,
-)) ?>
+ <?= $this->hook->render('template:task:show:before-subtasks', array('task' => $task, 'project' => $project)) ?>
+ <?= $this->render('subtask/show', array(
+ 'task' => $task,
+ 'subtasks' => $subtasks,
+ 'project' => $project,
+ 'editable' => true,
+ )) ?>
<?php endif ?>
<?php if (!empty($internal_links)): ?>
-<?= $this->hook->render('template:task:show:before-internal-links', array('task' => $task, 'project' => $project)) ?>
-<?= $this->render('task_internal_link/show', array(
- 'task' => $task,
- 'links' => $internal_links,
- 'project' => $project,
- 'link_label_list' => $link_label_list,
- 'editable' => true,
- 'is_public' => false,
-)) ?>
+ <?= $this->hook->render('template:task:show:before-internal-links', array('task' => $task, 'project' => $project)) ?>
+ <?= $this->render('task_internal_link/show', array(
+ 'task' => $task,
+ 'links' => $internal_links,
+ 'project' => $project,
+ 'link_label_list' => $link_label_list,
+ 'editable' => true,
+ 'is_public' => false,
+ )) ?>
<?php endif ?>
<?php if (!empty($external_links)): ?>
-<?= $this->hook->render('template:task:show:before-external-links', array('task' => $task, 'project' => $project)) ?>
-<?= $this->render('task_external_link/show', array(
- 'task' => $task,
- 'links' => $external_links,
- 'project' => $project,
-)) ?>
+ <?= $this->hook->render('template:task:show:before-external-links', array('task' => $task, 'project' => $project)) ?>
+ <?= $this->render('task_external_link/show', array(
+ 'task' => $task,
+ 'links' => $external_links,
+ 'project' => $project,
+ )) ?>
<?php endif ?>
<?php if (!empty($files) || !empty($images)): ?>
-<?= $this->hook->render('template:task:show:before-attachments', array('task' => $task, 'project' => $project)) ?>
-<?= $this->render('task_file/show', array(
- 'task' => $task,
- 'files' => $files,
- 'images' => $images
-)) ?>
+ <?= $this->hook->render('template:task:show:before-attachments', array('task' => $task, 'project' => $project)) ?>
+ <?= $this->render('task_file/show', array(
+ 'task' => $task,
+ 'files' => $files,
+ 'images' => $images
+ )) ?>
<?php endif ?>
<?php if (!empty($comments)): ?>
-<?= $this->hook->render('template:task:show:before-comments', array('task' => $task, 'project' => $project)) ?>
-<?= $this->render('comments/show', array(
- 'task' => $task,
- 'comments' => $comments,
- 'project' => $project,
- 'editable' => $this->user->hasProjectAccess('CommentController', 'edit', $project['id']),
-)) ?>
+ <?= $this->hook->render('template:task:show:before-comments', array('task' => $task, 'project' => $project)) ?>
+ <?= $this->render('comments/show', array(
+ 'task' => $task,
+ 'comments' => $comments,
+ 'project' => $project,
+ 'editable' => $this->user->hasProjectAccess('CommentController', 'edit', $project['id']),
+ )) ?>
<?php endif ?>
<?= $this->hook->render('template:task:show:bottom', array('task' => $task, 'project' => $project)) ?>
diff --git a/app/Template/task/time_tracking_details.php b/app/Template/task/time_tracking_details.php
index 1a179522..7cb419e0 100644
--- a/app/Template/task/time_tracking_details.php
+++ b/app/Template/task/time_tracking_details.php
@@ -1,6 +1,9 @@
-<div class="task-show-title color-<?= $task['color_id'] ?>">
- <h2><?= $this->text->e($task['title']) ?></h2>
-</div>
+<?= $this->render('task/details', array(
+ 'task' => $task,
+ 'tags' => $tags,
+ 'project' => $project,
+ 'editable' => false,
+)) ?>
<?= $this->render('task/time_tracking_summary', array('task' => $task)) ?>
@@ -8,7 +11,7 @@
<?php if ($subtask_paginator->isEmpty()): ?>
<p class="alert"><?= t('There is nothing to show.') ?></p>
<?php else: ?>
- <table class="table-fixed">
+ <table class="table-fixed table-scrolling">
<tr>
<th class="column-15"><?= $subtask_paginator->order(t('User'), 'username') ?></th>
<th><?= $subtask_paginator->order(t('Subtask'), 'subtask_title') ?></th>
diff --git a/app/Template/task/transitions.php b/app/Template/task/transitions.php
index 9e04c4e1..4a9f22ce 100644
--- a/app/Template/task/transitions.php
+++ b/app/Template/task/transitions.php
@@ -1,6 +1,9 @@
-<div class="task-show-title color-<?= $task['color_id'] ?>">
- <h2><?= $this->text->e($task['title']) ?></h2>
-</div>
+<?= $this->render('task/details', array(
+ 'task' => $task,
+ 'tags' => $tags,
+ 'project' => $project,
+ 'editable' => false,
+)) ?>
<div class="page-header">
<h2><?= t('Transitions') ?></h2>
@@ -9,7 +12,7 @@
<?php if (empty($transitions)): ?>
<p class="alert"><?= t('There is nothing to show.') ?></p>
<?php else: ?>
- <table class="table-stripped">
+ <table class="table-striped table-scrolling">
<tr>
<th><?= t('Date') ?></th>
<th><?= t('Source column') ?></th>
diff --git a/app/Template/task_bulk/show.php b/app/Template/task_bulk/show.php
index e9b138d5..11ddea31 100644
--- a/app/Template/task_bulk/show.php
+++ b/app/Template/task_bulk/show.php
@@ -1,5 +1,5 @@
<div class="page-header">
- <h2><?= t('Create tasks in bulk') ?></h2>
+ <h2><?= $this->text->e($project['name']) ?> &gt; <?= t('Create tasks in bulk') ?></h2>
</div>
<form class="popover-form" method="post" action="<?= $this->url->href('TaskBulkController', 'save', array('project_id' => $project['id'])) ?>" autocomplete="off">
diff --git a/app/Template/task_creation/show.php b/app/Template/task_creation/show.php
index 57e77f37..1a8a17d5 100644
--- a/app/Template/task_creation/show.php
+++ b/app/Template/task_creation/show.php
@@ -1,5 +1,5 @@
<div class="page-header">
- <h2><?= t('New task') ?></h2>
+ <h2><?= $this->text->e($project['name']) ?> &gt; <?= t('New task') ?></h2>
</div>
<form class="popover-form" method="post" action="<?= $this->url->href('TaskCreationController', 'save', array('project_id' => $values['project_id'])) ?>" autocomplete="off">
diff --git a/app/Template/task_external_link/table.php b/app/Template/task_external_link/table.php
index 56ef0363..cdfe0028 100644
--- a/app/Template/task_external_link/table.php
+++ b/app/Template/task_external_link/table.php
@@ -1,5 +1,5 @@
<?php if (! empty($links)): ?>
-<table class="table-stripped table-small">
+<table class="table-striped table-scrolling">
<tr>
<th class="column-10"><?= t('Type') ?></th>
<th><?= t('Title') ?></th>
diff --git a/app/Template/task_file/files.php b/app/Template/task_file/files.php
index 7ca59b1c..94c26f73 100644
--- a/app/Template/task_file/files.php
+++ b/app/Template/task_file/files.php
@@ -1,5 +1,5 @@
<?php if (! empty($files)): ?>
- <table class="table-stripped table-small">
+ <table class="table-striped table-scrolling">
<tr>
<th><?= t('Filename') ?></th>
<th><?= t('Creator') ?></th>
diff --git a/app/Template/task_gantt_creation/show.php b/app/Template/task_gantt_creation/show.php
index 7521d805..7906c39a 100644
--- a/app/Template/task_gantt_creation/show.php
+++ b/app/Template/task_gantt_creation/show.php
@@ -1,7 +1,7 @@
<div class="page-header">
- <h2><?= t('New task') ?></h2>
+ <h2><?= $this->text->e($project['name']) ?> &gt; <?= t('New task') ?></h2>
</div>
-<form method="post" action="<?= $this->url->href('TaskGanttCreationController', 'save', array('project_id' => $values['project_id'])) ?>" autocomplete="off">
+<form class="popover-form" method="post" action="<?= $this->url->href('TaskGanttCreationController', 'save', array('project_id' => $values['project_id'])) ?>" autocomplete="off">
<?= $this->form->csrf() ?>
<?= $this->form->hidden('project_id', $values) ?>
<?= $this->form->hidden('column_id', $values) ?>
diff --git a/app/Template/task_internal_link/table.php b/app/Template/task_internal_link/table.php
index 424d4791..6584a33a 100644
--- a/app/Template/task_internal_link/table.php
+++ b/app/Template/task_internal_link/table.php
@@ -1,5 +1,5 @@
<?php if (! empty($links)): ?>
-<table class="task-links-table table-stripped">
+<table class="task-links-table table-striped table-scrolling">
<?php foreach ($links as $label => $grouped_links): ?>
<?php $hide_td = false ?>
<?php foreach ($grouped_links as $link): ?>
diff --git a/app/Template/task_list/show.php b/app/Template/task_list/show.php
index bb95b6a3..0518e4c3 100644
--- a/app/Template/task_list/show.php
+++ b/app/Template/task_list/show.php
@@ -4,7 +4,7 @@
<?php if ($paginator->isEmpty()): ?>
<p class="alert"><?= t('No tasks found.') ?></p>
<?php elseif (! $paginator->isEmpty()): ?>
- <table class="table-fixed table-small">
+ <table class="table-striped table-scrolling table-small">
<tr>
<th class="column-5"><?= $paginator->order(t('Id'), 'tasks.id') ?></th>
<th class="column-10"><?= $paginator->order(t('Swimlane'), 'tasks.swimlane_id') ?></th>
diff --git a/app/Template/task_modification/show.php b/app/Template/task_modification/show.php
index cc38582c..734b247a 100644
--- a/app/Template/task_modification/show.php
+++ b/app/Template/task_modification/show.php
@@ -1,5 +1,5 @@
<div class="page-header">
- <h2><?= t('Edit a task') ?></h2>
+ <h2><?= $this->text->e($project['name']) ?> &gt; <?= $this->text->e($task['title']) ?></h2>
</div>
<form class="popover-form" method="post" action="<?= $this->url->href('TaskModificationController', 'update', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) ?>" autocomplete="off">
<?= $this->form->csrf() ?>
diff --git a/app/Template/user_list/show.php b/app/Template/user_list/show.php
index b2bd9377..5e285c89 100644
--- a/app/Template/user_list/show.php
+++ b/app/Template/user_list/show.php
@@ -12,7 +12,7 @@
<?php if ($paginator->isEmpty()): ?>
<p class="alert"><?= t('No user') ?></p>
<?php else: ?>
- <table class="table-stripped">
+ <table class="table-scrolling table-striped">
<tr>
<th class="column-5"><?= $paginator->order(t('Id'), 'id') ?></th>
<th class="column-18"><?= $paginator->order(t('Username'), 'username') ?></th>
diff --git a/app/Template/user_view/last.php b/app/Template/user_view/last.php
index 3de4d5e2..72f59bf6 100644
--- a/app/Template/user_view/last.php
+++ b/app/Template/user_view/last.php
@@ -5,7 +5,7 @@
<?php if (empty($last_logins)): ?>
<p class="alert"><?= t('Never connected.') ?></p>
<?php else: ?>
- <table class="table-small table-fixed">
+ <table class="table-small table-fixed table-scrolling table-striped">
<tr>
<th class="column-20"><?= t('Login date') ?></th>
<th class="column-15"><?= t('Authentication method') ?></th>
@@ -21,4 +21,4 @@
</tr>
<?php endforeach ?>
</table>
-<?php endif ?> \ No newline at end of file
+<?php endif ?>
diff --git a/app/Template/user_view/password_reset.php b/app/Template/user_view/password_reset.php
index 1371ce11..de7047e0 100644
--- a/app/Template/user_view/password_reset.php
+++ b/app/Template/user_view/password_reset.php
@@ -5,7 +5,7 @@
<?php if (empty($tokens)): ?>
<p class="alert"><?= t('The password has never been reinitialized.') ?></p>
<?php else: ?>
- <table class="table-small table-fixed">
+ <table class="table-small table-fixed table-scrolling table-striped">
<tr>
<th class="column-20"><?= t('Creation') ?></th>
<th class="column-20"><?= t('Expiration') ?></th>
@@ -23,4 +23,4 @@
</tr>
<?php endforeach ?>
</table>
-<?php endif ?> \ No newline at end of file
+<?php endif ?>
diff --git a/app/Template/user_view/sessions.php b/app/Template/user_view/sessions.php
index eda3ef7f..10497e4f 100644
--- a/app/Template/user_view/sessions.php
+++ b/app/Template/user_view/sessions.php
@@ -5,7 +5,7 @@
<?php if (empty($sessions)): ?>
<p class="alert"><?= t('No session.') ?></p>
<?php else: ?>
- <table class="table-small table-fixed">
+ <table class="table-small table-fixed table-scrolling table-striped">
<tr>
<th class="column-20"><?= t('Creation date') ?></th>
<th class="column-20"><?= t('Expiration date') ?></th>
diff --git a/app/Template/user_view/timesheet.php b/app/Template/user_view/timesheet.php
index 3df57492..aeffd2f4 100644
--- a/app/Template/user_view/timesheet.php
+++ b/app/Template/user_view/timesheet.php
@@ -6,7 +6,7 @@
<?php if ($subtask_paginator->isEmpty()): ?>
<p class="alert"><?= t('There is nothing to show.') ?></p>
<?php else: ?>
- <table class="table-fixed">
+ <table class="table-fixed table-scrolling table-striped">
<tr>
<th class="column-25"><?= $subtask_paginator->order(t('Task'), 'task_title') ?></th>
<th class="column-25"><?= $subtask_paginator->order(t('Subtask'), 'subtask_title') ?></th>
diff --git a/app/common.php b/app/common.php
index 15fd7a75..e5490c11 100644
--- a/app/common.php
+++ b/app/common.php
@@ -35,6 +35,7 @@ $container->register(new Kanboard\ServiceProvider\MailProvider());
$container->register(new Kanboard\ServiceProvider\HelperProvider());
$container->register(new Kanboard\ServiceProvider\SessionProvider());
$container->register(new Kanboard\ServiceProvider\LoggingProvider());
+$container->register(new Kanboard\ServiceProvider\CacheProvider());
$container->register(new Kanboard\ServiceProvider\DatabaseProvider());
$container->register(new Kanboard\ServiceProvider\AuthenticationProvider());
$container->register(new Kanboard\ServiceProvider\NotificationProvider());
diff --git a/app/constants.php b/app/constants.php
index 40b88fe9..3adb0835 100644
--- a/app/constants.php
+++ b/app/constants.php
@@ -12,6 +12,12 @@ defined('DATA_DIR') or define('DATA_DIR', ROOT_DIR.DIRECTORY_SEPARATOR.'data');
// Files directory (attachments)
defined('FILES_DIR') or define('FILES_DIR', DATA_DIR.DIRECTORY_SEPARATOR.'files');
+// Available cache drivers are "file" and "memory"
+defined('CACHE_DRIVER') or define('CACHE_DRIVER', 'memory');
+
+// Cache folder (file driver)
+defined('CACHE_DIR') or define('CACHE_DIR', DATA_DIR.DIRECTORY_SEPARATOR.'cache');
+
// Plugins settings
defined('PLUGINS_DIR') or define('PLUGINS_DIR', ROOT_DIR.DIRECTORY_SEPARATOR.'plugins');
defined('PLUGIN_API_URL') or define('PLUGIN_API_URL', 'https://kanboard.net/plugins.json');