From a675271ad71b7713d1b33bdba3c51b2b04813229 Mon Sep 17 00:00:00 2001 From: Frederic Guillot Date: Sun, 15 Nov 2015 12:50:33 -0500 Subject: Rewrite of session management --- app/Controller/Column.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'app/Controller/Column.php') diff --git a/app/Controller/Column.php b/app/Controller/Column.php index d28fb293..b484fe12 100644 --- a/app/Controller/Column.php +++ b/app/Controller/Column.php @@ -55,10 +55,10 @@ class Column extends Base if ($valid) { if ($this->board->addColumn($project['id'], $data['title'], $data['task_limit'], $data['description'])) { - $this->session->flash(t('Board updated successfully.')); + $this->flash->success(t('Board updated successfully.')); $this->response->redirect($this->helper->url->to('column', 'index', array('project_id' => $project['id']))); } else { - $this->session->flashError(t('Unable to update this board.')); + $this->flash->failure(t('Unable to update this board.')); } } @@ -98,10 +98,10 @@ class Column extends Base if ($valid) { if ($this->board->updateColumn($values['id'], $values['title'], $values['task_limit'], $values['description'])) { - $this->session->flash(t('Board updated successfully.')); + $this->flash->success(t('Board updated successfully.')); $this->response->redirect($this->helper->url->to('column', 'index', array('project_id' => $project['id']))); } else { - $this->session->flashError(t('Unable to update this board.')); + $this->flash->failure(t('Unable to update this board.')); } } @@ -155,9 +155,9 @@ class Column extends Base $column = $this->board->getColumn($this->request->getIntegerParam('column_id')); if (! empty($column) && $this->board->removeColumn($column['id'])) { - $this->session->flash(t('Column removed successfully.')); + $this->flash->success(t('Column removed successfully.')); } else { - $this->session->flashError(t('Unable to remove this column.')); + $this->flash->failure(t('Unable to remove this column.')); } $this->response->redirect($this->helper->url->to('column', 'index', array('project_id' => $project['id']))); -- cgit v1.2.3 From dc35a78374e9b091505cfc56eefcd0c631c56e3a Mon Sep 17 00:00:00 2001 From: Frederic Guillot Date: Wed, 13 Jan 2016 21:45:14 -0500 Subject: Move some validators to separate classes --- app/Api/Action.php | 2 +- app/Controller/Action.php | 2 +- app/Controller/Column.php | 4 +-- app/Core/Base.php | 2 ++ app/Model/Action.php | 26 ---------------- app/Model/ActionParameter.php | 3 -- app/Model/Board.php | 45 --------------------------- app/ServiceProvider/ClassProvider.php | 2 ++ app/Validator/ActionValidator.php | 38 +++++++++++++++++++++++ app/Validator/ColumnValidator.php | 58 +++++++++++++++++++++++++++++++++++ 10 files changed, 104 insertions(+), 78 deletions(-) create mode 100644 app/Validator/ActionValidator.php create mode 100644 app/Validator/ColumnValidator.php (limited to 'app/Controller/Column.php') diff --git a/app/Api/Action.php b/app/Api/Action.php index bdb5b26e..9e3b86f6 100644 --- a/app/Api/Action.php +++ b/app/Api/Action.php @@ -44,7 +44,7 @@ class Action extends \Kanboard\Core\Base 'params' => $params, ); - list($valid, ) = $this->action->validateCreation($values); + list($valid, ) = $this->actionValidator->validateCreation($values); if (! $valid) { return false; diff --git a/app/Controller/Action.php b/app/Controller/Action.php index 9b803893..645b53b7 100644 --- a/app/Controller/Action.php +++ b/app/Controller/Action.php @@ -116,7 +116,7 @@ class Action extends Base */ private function doCreation(array $project, array $values) { - list($valid, ) = $this->action->validateCreation($values); + list($valid, ) = $this->actionValidator->validateCreation($values); if ($valid) { if ($this->action->create($values) !== false) { diff --git a/app/Controller/Column.php b/app/Controller/Column.php index b484fe12..1ce575d7 100644 --- a/app/Controller/Column.php +++ b/app/Controller/Column.php @@ -51,7 +51,7 @@ class Column extends Base $values['title['.$column_id.']'] = $column_title; } - list($valid, $errors) = $this->board->validateCreation($data); + list($valid, $errors) = $this->columnValidator->validateCreation($data); if ($valid) { if ($this->board->addColumn($project['id'], $data['title'], $data['task_limit'], $data['description'])) { @@ -94,7 +94,7 @@ class Column extends Base $project = $this->getProject(); $values = $this->request->getValues(); - list($valid, $errors) = $this->board->validateModification($values); + list($valid, $errors) = $this->columnValidator->validateModification($values); if ($valid) { if ($this->board->updateColumn($values['id'], $values['title'], $values['task_limit'], $values['description'])) { diff --git a/app/Core/Base.php b/app/Core/Base.php index 723831e3..22f09403 100644 --- a/app/Core/Base.php +++ b/app/Core/Base.php @@ -113,6 +113,8 @@ use Pimple\Container; * @property \Kanboard\Model\UserUnreadNotification $userUnreadNotification * @property \Kanboard\Model\UserMetadata $userMetadata * @property \Kanboard\Model\Webhook $webhook + * @property \Kanboard\Validator\ActionValidator $actionValidator + * @property \Kanboard\Validator\ColumnValidator $columnValidator * @property \Kanboard\Validator\PasswordResetValidator $passwordResetValidator * @property \Kanboard\Validator\ProjectValidator $projectValidator * @property \Kanboard\Validator\SubtaskValidator $subtaskValidator diff --git a/app/Model/Action.php b/app/Model/Action.php index 5fcfbaa7..4da2fb8f 100644 --- a/app/Model/Action.php +++ b/app/Model/Action.php @@ -2,9 +2,6 @@ namespace Kanboard\Model; -use SimpleValidator\Validator; -use SimpleValidator\Validators; - /** * Action Model * @@ -188,27 +185,4 @@ class Action extends Base return true; } - - /** - * Validate action creation - * - * @access public - * @param array $values Required parameters to save an action - * @return array $valid, $errors [0] = Success or not, [1] = List of errors - */ - public function validateCreation(array $values) - { - $v = new Validator($values, array( - new Validators\Required('project_id', t('The project id is required')), - new Validators\Integer('project_id', t('This value must be an integer')), - new Validators\Required('event_name', t('This value is required')), - new Validators\Required('action_name', t('This value is required')), - new Validators\Required('params', t('This value is required')), - )); - - return array( - $v->execute(), - $v->getErrors() - ); - } } diff --git a/app/Model/ActionParameter.php b/app/Model/ActionParameter.php index 1e4d7544..62b03142 100644 --- a/app/Model/ActionParameter.php +++ b/app/Model/ActionParameter.php @@ -2,9 +2,6 @@ namespace Kanboard\Model; -use SimpleValidator\Validator; -use SimpleValidator\Validators; - /** * Action Parameter Model * diff --git a/app/Model/Board.php b/app/Model/Board.php index 79a1a92d..0f980f68 100644 --- a/app/Model/Board.php +++ b/app/Model/Board.php @@ -2,8 +2,6 @@ namespace Kanboard\Model; -use SimpleValidator\Validator; -use SimpleValidator\Validators; use PicoDb\Database; /** @@ -436,47 +434,4 @@ class Board extends Base { return $this->db->table(self::TABLE)->eq('id', $column_id)->remove(); } - - /** - * Validate column modification - * - * @access public - * @param array $values Required parameters to update a column - * @return array $valid, $errors [0] = Success or not, [1] = List of errors - */ - public function validateModification(array $values) - { - $v = new Validator($values, array( - new Validators\Integer('task_limit', t('This value must be an integer')), - new Validators\Required('title', t('The title is required')), - new Validators\MaxLength('title', t('The maximum length is %d characters', 50), 50), - )); - - return array( - $v->execute(), - $v->getErrors() - ); - } - - /** - * Validate column creation - * - * @access public - * @param array $values Required parameters to save an action - * @return array $valid, $errors [0] = Success or not, [1] = List of errors - */ - public function validateCreation(array $values) - { - $v = new Validator($values, array( - new Validators\Required('project_id', t('The project id is required')), - new Validators\Integer('project_id', t('This value must be an integer')), - new Validators\Required('title', t('The title is required')), - new Validators\MaxLength('title', t('The maximum length is %d characters', 50), 50), - )); - - return array( - $v->execute(), - $v->getErrors() - ); - } } diff --git a/app/ServiceProvider/ClassProvider.php b/app/ServiceProvider/ClassProvider.php index bb9e757e..61c97a07 100644 --- a/app/ServiceProvider/ClassProvider.php +++ b/app/ServiceProvider/ClassProvider.php @@ -85,6 +85,8 @@ class ClassProvider implements ServiceProviderInterface 'GroupAutoCompleteFormatter', ), 'Validator' => array( + 'ActionValidator', + 'ColumnValidator', 'PasswordResetValidator', 'ProjectValidator', 'SubtaskValidator', diff --git a/app/Validator/ActionValidator.php b/app/Validator/ActionValidator.php new file mode 100644 index 00000000..95ee7d21 --- /dev/null +++ b/app/Validator/ActionValidator.php @@ -0,0 +1,38 @@ +execute(), + $v->getErrors() + ); + } +} diff --git a/app/Validator/ColumnValidator.php b/app/Validator/ColumnValidator.php new file mode 100644 index 00000000..4c644e8a --- /dev/null +++ b/app/Validator/ColumnValidator.php @@ -0,0 +1,58 @@ +execute(), + $v->getErrors() + ); + } + + /** + * Validate column creation + * + * @access public + * @param array $values Required parameters to save an action + * @return array $valid, $errors [0] = Success or not, [1] = List of errors + */ + public function validateCreation(array $values) + { + $v = new Validator($values, array( + new Validators\Required('project_id', t('The project id is required')), + new Validators\Integer('project_id', t('This value must be an integer')), + new Validators\Required('title', t('The title is required')), + new Validators\MaxLength('title', t('The maximum length is %d characters', 50), 50), + )); + + return array( + $v->execute(), + $v->getErrors() + ); + } +} -- cgit v1.2.3 From 26492aba7ee2bfb8c525ea0aaa580aff47a414ba Mon Sep 17 00:00:00 2001 From: Frederic Guillot Date: Sun, 31 Jan 2016 21:44:49 -0500 Subject: Simplify layout and templates generation --- ChangeLog | 1 + app/Controller/Action.php | 8 +- app/Controller/Activity.php | 5 +- app/Controller/Analytic.php | 29 ++----- app/Controller/App.php | 30 ++------ app/Controller/Auth.php | 2 +- app/Controller/Base.php | 46 +----------- app/Controller/Board.php | 4 +- app/Controller/Calendar.php | 2 +- app/Controller/Category.php | 6 +- app/Controller/Column.php | 6 +- app/Controller/Comment.php | 6 +- app/Controller/Config.php | 36 +++------ app/Controller/Currency.php | 18 +---- app/Controller/Customfilter.php | 4 +- app/Controller/Doc.php | 4 +- app/Controller/Export.php | 2 +- app/Controller/File.php | 6 +- app/Controller/Gantt.php | 5 +- app/Controller/Group.php | 19 ++--- app/Controller/Link.php | 22 +----- app/Controller/Listing.php | 2 +- app/Controller/Oauth.php | 2 +- app/Controller/PasswordReset.php | 4 +- app/Controller/Project.php | 19 +++-- app/Controller/ProjectEdit.php | 2 +- app/Controller/ProjectPermission.php | 2 +- app/Controller/Projectuser.php | 21 +----- app/Controller/Search.php | 3 +- app/Controller/Subtask.php | 6 +- app/Controller/Swimlane.php | 6 +- app/Controller/Task.php | 12 +-- app/Controller/TaskExternalLink.php | 10 +-- app/Controller/TaskImport.php | 2 +- app/Controller/Taskduplication.php | 4 +- app/Controller/Tasklink.php | 8 +- app/Controller/Taskmodification.php | 6 +- app/Controller/Taskstatus.php | 2 +- app/Controller/Twofactor.php | 8 +- app/Controller/User.php | 56 ++++---------- app/Controller/UserImport.php | 2 +- app/Helper/Layout.php | 141 ++++++++++++++++++++++++++++++++++- app/Template/analytic/layout.php | 2 +- app/Template/app/layout.php | 2 +- app/Template/config/layout.php | 4 +- app/Template/config/sidebar.php | 3 - app/Template/project/layout.php | 2 +- app/Template/project_user/layout.php | 2 +- app/Template/task/details.php | 2 +- app/Template/task/layout.php | 4 +- app/Template/user/layout.php | 2 +- 51 files changed, 282 insertions(+), 320 deletions(-) (limited to 'app/Controller/Column.php') diff --git a/ChangeLog b/ChangeLog index 0345e020..3fa18d9b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -26,6 +26,7 @@ Improvements: * Have a new task assigned to the creator by default instead of "no assignee" * Show progress for task links in board tooltips * Simplify code to handle ajax popover and redirects +* Simplify layout and templates generation * Move task form elements to Task helper Version 1.0.24 diff --git a/app/Controller/Action.php b/app/Controller/Action.php index 645b53b7..482a210b 100644 --- a/app/Controller/Action.php +++ b/app/Controller/Action.php @@ -20,7 +20,7 @@ class Action extends Base $project = $this->getProject(); $actions = $this->action->getAllByProject($project['id']); - $this->response->html($this->projectLayout('action/index', array( + $this->response->html($this->helper->layout->project('action/index', array( 'values' => array('project_id' => $project['id']), 'project' => $project, 'actions' => $actions, @@ -51,7 +51,7 @@ class Action extends Base $this->response->redirect($this->helper->url->to('action', 'index', array('project_id' => $project['id']))); } - $this->response->html($this->projectLayout('action/event', array( + $this->response->html($this->helper->layout->project('action/event', array( 'values' => $values, 'project' => $project, 'events' => $this->actionManager->getCompatibleEvents($values['action_name']), @@ -83,7 +83,7 @@ class Action extends Base $projects_list = $this->projectUserRole->getActiveProjectsByUser($this->userSession->getId()); unset($projects_list[$project['id']]); - $this->response->html($this->projectLayout('action/params', array( + $this->response->html($this->helper->layout->project('action/params', array( 'values' => $values, 'action_params' => $action_params, 'columns_list' => $this->board->getColumnsList($project['id']), @@ -138,7 +138,7 @@ class Action extends Base { $project = $this->getProject(); - $this->response->html($this->projectLayout('action/remove', array( + $this->response->html($this->helper->layout->project('action/remove', array( 'action' => $this->action->getById($this->request->getIntegerParam('action_id')), 'available_events' => $this->eventManager->getAll(), 'available_actions' => $this->actionManager->getAvailableActions(), diff --git a/app/Controller/Activity.php b/app/Controller/Activity.php index 38658345..db520ebe 100644 --- a/app/Controller/Activity.php +++ b/app/Controller/Activity.php @@ -19,8 +19,7 @@ class Activity extends Base { $project = $this->getProject(); - $this->response->html($this->template->layout('activity/project', array( - 'board_selector' => $this->projectUserRole->getActiveProjectsByUser($this->userSession->getId()), + $this->response->html($this->helper->layout->app('activity/project', array( 'events' => $this->projectActivity->getProject($project['id']), 'project' => $project, 'title' => t('%s\'s activity', $project['name']) @@ -36,7 +35,7 @@ class Activity extends Base { $task = $this->getTask(); - $this->response->html($this->taskLayout('activity/task', array( + $this->response->html($this->helper->layout->task('activity/task', array( 'title' => $task['title'], 'task' => $task, 'events' => $this->projectActivity->getTask($task['id']), diff --git a/app/Controller/Analytic.php b/app/Controller/Analytic.php index d203fb8e..e7ab9ebc 100644 --- a/app/Controller/Analytic.php +++ b/app/Controller/Analytic.php @@ -1,6 +1,7 @@ projectUserRole->getActiveProjectsByUser($this->userSession->getId()); - $params['content_for_sublayout'] = $this->template->render($template, $params); - - return $this->template->layout('analytic/layout', $params); - } - /** * Show average Lead and Cycle time * @@ -37,7 +22,7 @@ class Analytic extends Base $project = $this->getProject(); list($from, $to) = $this->getDates(); - $this->response->html($this->layout('analytic/lead_cycle_time', array( + $this->response->html($this->helper->layout->analytic('analytic/lead_cycle_time', array( 'values' => array( 'from' => $from, 'to' => $to, @@ -69,7 +54,7 @@ class Analytic extends Base ->setQuery($query) ->calculate(); - $this->response->html($this->layout('analytic/compare_hours', array( + $this->response->html($this->helper->layout->analytic('analytic/compare_hours', array( 'project' => $project, 'paginator' => $paginator, 'metrics' => $this->estimatedTimeComparisonAnalytic->build($project['id']), @@ -86,7 +71,7 @@ class Analytic extends Base { $project = $this->getProject(); - $this->response->html($this->layout('analytic/avg_time_columns', array( + $this->response->html($this->helper->layout->analytic('analytic/avg_time_columns', array( 'project' => $project, 'metrics' => $this->averageTimeSpentColumnAnalytic->build($project['id']), 'title' => t('Average time spent into each column for "%s"', $project['name']), @@ -102,7 +87,7 @@ class Analytic extends Base { $project = $this->getProject(); - $this->response->html($this->layout('analytic/tasks', array( + $this->response->html($this->helper->layout->analytic('analytic/tasks', array( 'project' => $project, 'metrics' => $this->taskDistributionAnalytic->build($project['id']), 'title' => t('Task repartition for "%s"', $project['name']), @@ -118,7 +103,7 @@ class Analytic extends Base { $project = $this->getProject(); - $this->response->html($this->layout('analytic/users', array( + $this->response->html($this->helper->layout->analytic('analytic/users', array( 'project' => $project, 'metrics' => $this->userDistributionAnalytic->build($project['id']), 'title' => t('User repartition for "%s"', $project['name']), @@ -160,7 +145,7 @@ class Analytic extends Base $display_graph = $this->projectDailyColumnStats->countDays($project['id'], $from, $to) >= 2; - $this->response->html($this->layout($template, array( + $this->response->html($this->helper->layout->analytic($template, array( 'values' => array( 'from' => $from, 'to' => $to, diff --git a/app/Controller/App.php b/app/Controller/App.php index bdd7fbcf..1ce74506 100644 --- a/app/Controller/App.php +++ b/app/Controller/App.php @@ -12,22 +12,6 @@ use Kanboard\Model\Subtask as SubtaskModel; */ class App extends Base { - /** - * Common layout for dashboard views - * - * @access private - * @param string $template Template name - * @param array $params Template parameters - * @return string - */ - private function layout($template, array $params) - { - $params['board_selector'] = $this->projectUserRole->getActiveProjectsByUser($this->userSession->getId()); - $params['content_for_sublayout'] = $this->template->render($template, $params); - - return $this->template->layout('app/layout', $params); - } - /** * Get project pagination * @@ -101,7 +85,7 @@ class App extends Base { $user = $this->getUser(); - $this->response->html($this->layout('app/overview', array( + $this->response->html($this->helper->layout->dashboard('app/overview', array( 'title' => t('Dashboard'), 'project_paginator' => $this->getProjectPaginator($user['id'], 'index', 10), 'task_paginator' => $this->getTaskPaginator($user['id'], 'index', 10), @@ -119,7 +103,7 @@ class App extends Base { $user = $this->getUser(); - $this->response->html($this->layout('app/tasks', array( + $this->response->html($this->helper->layout->dashboard('app/tasks', array( 'title' => t('My tasks'), 'paginator' => $this->getTaskPaginator($user['id'], 'tasks', 50), 'user' => $user, @@ -135,7 +119,7 @@ class App extends Base { $user = $this->getUser(); - $this->response->html($this->layout('app/subtasks', array( + $this->response->html($this->helper->layout->dashboard('app/subtasks', array( 'title' => t('My subtasks'), 'paginator' => $this->getSubtaskPaginator($user['id'], 'subtasks', 50), 'user' => $user, @@ -151,7 +135,7 @@ class App extends Base { $user = $this->getUser(); - $this->response->html($this->layout('app/projects', array( + $this->response->html($this->helper->layout->dashboard('app/projects', array( 'title' => t('My projects'), 'paginator' => $this->getProjectPaginator($user['id'], 'projects', 25), 'user' => $user, @@ -167,7 +151,7 @@ class App extends Base { $user = $this->getUser(); - $this->response->html($this->layout('app/activity', array( + $this->response->html($this->helper->layout->dashboard('app/activity', array( 'title' => t('My activity stream'), 'events' => $this->projectActivity->getProjects($this->projectPermission->getActiveProjectIds($user['id']), 100), 'user' => $user, @@ -181,7 +165,7 @@ class App extends Base */ public function calendar() { - $this->response->html($this->layout('app/calendar', array( + $this->response->html($this->helper->layout->dashboard('app/calendar', array( 'title' => t('My calendar'), 'user' => $this->getUser(), ))); @@ -196,7 +180,7 @@ class App extends Base { $user = $this->getUser(); - $this->response->html($this->layout('app/notifications', array( + $this->response->html($this->helper->layout->dashboard('app/notifications', array( 'title' => t('My notifications'), 'notifications' => $this->userUnreadNotification->getAll($user['id']), 'user' => $user, diff --git a/app/Controller/Auth.php b/app/Controller/Auth.php index 5284e126..fef7f0e3 100644 --- a/app/Controller/Auth.php +++ b/app/Controller/Auth.php @@ -21,7 +21,7 @@ class Auth extends Base $this->response->redirect($this->helper->url->to('app', 'index')); } - $this->response->html($this->template->layout('auth/index', array( + $this->response->html($this->helper->layout->app('auth/index', array( 'captcha' => ! empty($values['username']) && $this->userLocking->hasCaptcha($values['username']), 'errors' => $errors, 'values' => $values, diff --git a/app/Controller/Base.php b/app/Controller/Base.php index 0939f44c..a80b3528 100644 --- a/app/Controller/Base.php +++ b/app/Controller/Base.php @@ -131,7 +131,7 @@ abstract class Base extends \Kanboard\Core\Base */ protected function notfound($no_layout = false) { - $this->response->html($this->template->layout('app/notfound', array( + $this->response->html($this->helper->layout->app('app/notfound', array( 'title' => t('Page not found'), 'no_layout' => $no_layout, ))); @@ -149,7 +149,7 @@ abstract class Base extends \Kanboard\Core\Base $this->response->text('Access Forbidden', 403); } - $this->response->html($this->template->layout('app/forbidden', array( + $this->response->html($this->helper->layout->app('app/forbidden', array( 'title' => t('Access Forbidden'), 'no_layout' => $no_layout, ))); @@ -179,48 +179,6 @@ abstract class Base extends \Kanboard\Core\Base } } - /** - * Common layout for task views - * - * @access protected - * @param string $template Template name - * @param array $params Template parameters - * @return string - */ - protected function taskLayout($template, array $params) - { - $content = $this->template->render($template, $params); - - if ($this->request->isAjax()) { - return $content; - } - - $params['title'] = $params['task']['project_name'].' > '.$params['task']['title']; - $params['task_content_for_layout'] = $content; - $params['board_selector'] = $this->projectUserRole->getActiveProjectsByUser($this->userSession->getId()); - - return $this->template->layout('task/layout', $params); - } - - /** - * Common layout for project views - * - * @access protected - * @param string $template Template name - * @param array $params Template parameters - * @return string - */ - protected function projectLayout($template, array $params, $sidebar_template = 'project/sidebar') - { - $content = $this->template->render($template, $params); - $params['project_content_for_layout'] = $content; - $params['title'] = $params['project']['name'] === $params['title'] ? $params['title'] : $params['project']['name'].' > '.$params['title']; - $params['board_selector'] = $this->projectUserRole->getActiveProjectsByUser($this->userSession->getId()); - $params['sidebar_template'] = $sidebar_template; - - return $this->template->layout('project/layout', $params); - } - /** * Common method to get a task for task views * diff --git a/app/Controller/Board.php b/app/Controller/Board.php index f64de69a..199f1703 100644 --- a/app/Controller/Board.php +++ b/app/Controller/Board.php @@ -27,7 +27,7 @@ class Board extends Base } // Display the board with a specific layout - $this->response->html($this->template->layout('board/view_public', array( + $this->response->html($this->helper->layout->app('board/view_public', array( 'project' => $project, 'swimlanes' => $this->board->getBoard($project['id']), 'title' => $project['name'], @@ -49,7 +49,7 @@ class Board extends Base { $params = $this->getProjectFilters('board', 'show'); - $this->response->html($this->template->layout('board/view_private', array( + $this->response->html($this->helper->layout->app('board/view_private', array( 'categories_list' => $this->category->getList($params['project']['id'], false), 'users_list' => $this->projectUserRole->getAssignableUsersList($params['project']['id'], false), 'custom_filters_list' => $this->customFilter->getAll($params['project']['id'], $this->userSession->getId()), diff --git a/app/Controller/Calendar.php b/app/Controller/Calendar.php index 67a402d3..a0a25e41 100644 --- a/app/Controller/Calendar.php +++ b/app/Controller/Calendar.php @@ -20,7 +20,7 @@ class Calendar extends Base */ public function show() { - $this->response->html($this->template->layout('calendar/show', array( + $this->response->html($this->helper->layout->app('calendar/show', array( 'check_interval' => $this->config->get('board_private_refresh_interval'), ) + $this->getProjectFilters('calendar', 'show'))); } diff --git a/app/Controller/Category.php b/app/Controller/Category.php index a0af4139..258a3b78 100644 --- a/app/Controller/Category.php +++ b/app/Controller/Category.php @@ -38,7 +38,7 @@ class Category extends Base { $project = $this->getProject(); - $this->response->html($this->projectLayout('category/index', array( + $this->response->html($this->helper->layout->project('category/index', array( 'categories' => $this->category->getList($project['id'], false), 'values' => $values + array('project_id' => $project['id']), 'errors' => $errors, @@ -81,7 +81,7 @@ class Category extends Base $project = $this->getProject(); $category = $this->getCategory($project['id']); - $this->response->html($this->projectLayout('category/edit', array( + $this->response->html($this->helper->layout->project('category/edit', array( 'values' => empty($values) ? $category : $values, 'errors' => $errors, 'project' => $project, @@ -123,7 +123,7 @@ class Category extends Base $project = $this->getProject(); $category = $this->getCategory($project['id']); - $this->response->html($this->projectLayout('category/remove', array( + $this->response->html($this->helper->layout->project('category/remove', array( 'project' => $project, 'category' => $category, 'title' => t('Remove a category') diff --git a/app/Controller/Column.php b/app/Controller/Column.php index 1ce575d7..3201c549 100644 --- a/app/Controller/Column.php +++ b/app/Controller/Column.php @@ -26,7 +26,7 @@ class Column extends Base $values['task_limit['.$column['id'].']'] = $column['task_limit'] ?: null; } - $this->response->html($this->projectLayout('column/index', array( + $this->response->html($this->helper->layout->project('column/index', array( 'errors' => $errors, 'values' => $values + array('project_id' => $project['id']), 'columns' => $columns, @@ -75,7 +75,7 @@ class Column extends Base $project = $this->getProject(); $column = $this->board->getColumn($this->request->getIntegerParam('column_id')); - $this->response->html($this->projectLayout('column/edit', array( + $this->response->html($this->helper->layout->project('column/edit', array( 'errors' => $errors, 'values' => $values ?: $column, 'project' => $project, @@ -136,7 +136,7 @@ class Column extends Base { $project = $this->getProject(); - $this->response->html($this->projectLayout('column/remove', array( + $this->response->html($this->helper->layout->project('column/remove', array( 'column' => $this->board->getColumn($this->request->getIntegerParam('column_id')), 'project' => $project, 'title' => t('Remove a column from a board') diff --git a/app/Controller/Comment.php b/app/Controller/Comment.php index 549c0c65..1e94779f 100644 --- a/app/Controller/Comment.php +++ b/app/Controller/Comment.php @@ -47,7 +47,7 @@ class Comment extends Base ); } - $this->response->html($this->taskLayout('comment/create', array( + $this->response->html($this->helper->layout->task('comment/create', array( 'values' => $values, 'errors' => $errors, 'task' => $task, @@ -90,7 +90,7 @@ class Comment extends Base $task = $this->getTask(); $comment = $this->getComment(); - $this->response->html($this->taskLayout('comment/edit', array( + $this->response->html($this->helper->layout->task('comment/edit', array( 'values' => empty($values) ? $comment : $values, 'errors' => $errors, 'comment' => $comment, @@ -135,7 +135,7 @@ class Comment extends Base $task = $this->getTask(); $comment = $this->getComment(); - $this->response->html($this->taskLayout('comment/remove', array( + $this->response->html($this->helper->layout->task('comment/remove', array( 'comment' => $comment, 'task' => $task, 'title' => t('Remove a comment') diff --git a/app/Controller/Config.php b/app/Controller/Config.php index 4aee8553..53f7cdb6 100644 --- a/app/Controller/Config.php +++ b/app/Controller/Config.php @@ -10,24 +10,6 @@ namespace Kanboard\Controller; */ class Config extends Base { - /** - * Common layout for config views - * - * @access private - * @param string $template Template name - * @param array $params Template parameters - * @return string - */ - private function layout($template, array $params) - { - $params['board_selector'] = $this->projectUserRole->getActiveProjectsByUser($this->userSession->getId()); - $params['values'] = $this->config->getAll(); - $params['errors'] = array(); - $params['config_content_for_layout'] = $this->template->render($template, $params); - - return $this->template->layout('config/layout', $params); - } - /** * Common method between pages * @@ -72,7 +54,7 @@ class Config extends Base */ public function index() { - $this->response->html($this->layout('config/about', array( + $this->response->html($this->helper->layout->config('config/about', array( 'db_size' => $this->config->getDatabaseSize(), 'title' => t('Settings').' > '.t('About'), ))); @@ -85,7 +67,7 @@ class Config extends Base */ public function plugins() { - $this->response->html($this->layout('config/plugins', array( + $this->response->html($this->helper->layout->config('config/plugins', array( 'plugins' => $this->pluginLoader->plugins, 'title' => t('Settings').' > '.t('Plugins'), ))); @@ -100,7 +82,7 @@ class Config extends Base { $this->common('application'); - $this->response->html($this->layout('config/application', array( + $this->response->html($this->helper->layout->config('config/application', array( 'languages' => $this->config->getLanguages(), 'timezones' => $this->config->getTimezones(), 'date_formats' => $this->dateParser->getAvailableFormats(), @@ -117,7 +99,7 @@ class Config extends Base { $this->common('project'); - $this->response->html($this->layout('config/project', array( + $this->response->html($this->helper->layout->config('config/project', array( 'colors' => $this->color->getList(), 'default_columns' => implode(', ', $this->board->getDefaultColumns()), 'title' => t('Settings').' > '.t('Project settings'), @@ -133,7 +115,7 @@ class Config extends Base { $this->common('board'); - $this->response->html($this->layout('config/board', array( + $this->response->html($this->helper->layout->config('config/board', array( 'title' => t('Settings').' > '.t('Board settings'), ))); } @@ -147,7 +129,7 @@ class Config extends Base { $this->common('calendar'); - $this->response->html($this->layout('config/calendar', array( + $this->response->html($this->helper->layout->config('config/calendar', array( 'title' => t('Settings').' > '.t('Calendar settings'), ))); } @@ -161,7 +143,7 @@ class Config extends Base { $this->common('integrations'); - $this->response->html($this->layout('config/integrations', array( + $this->response->html($this->helper->layout->config('config/integrations', array( 'title' => t('Settings').' > '.t('Integrations'), ))); } @@ -175,7 +157,7 @@ class Config extends Base { $this->common('webhook'); - $this->response->html($this->layout('config/webhook', array( + $this->response->html($this->helper->layout->config('config/webhook', array( 'title' => t('Settings').' > '.t('Webhook settings'), ))); } @@ -187,7 +169,7 @@ class Config extends Base */ public function api() { - $this->response->html($this->layout('config/api', array( + $this->response->html($this->helper->layout->config('config/api', array( 'title' => t('Settings').' > '.t('API'), ))); } diff --git a/app/Controller/Currency.php b/app/Controller/Currency.php index 42e404f8..ecaa9834 100644 --- a/app/Controller/Currency.php +++ b/app/Controller/Currency.php @@ -10,22 +10,6 @@ namespace Kanboard\Controller; */ class Currency extends Base { - /** - * Common layout for config views - * - * @access private - * @param string $template Template name - * @param array $params Template parameters - * @return string - */ - private function layout($template, array $params) - { - $params['board_selector'] = $this->projectUserRole->getActiveProjectsByUser($this->userSession->getId()); - $params['config_content_for_layout'] = $this->template->render($template, $params); - - return $this->template->layout('config/layout', $params); - } - /** * Display all currency rates and form * @@ -33,7 +17,7 @@ class Currency extends Base */ public function index(array $values = array(), array $errors = array()) { - $this->response->html($this->layout('currency/index', array( + $this->response->html($this->helper->layout->config('currency/index', array( 'config_values' => array('application_currency' => $this->config->get('application_currency')), 'values' => $values, 'errors' => $errors, diff --git a/app/Controller/Customfilter.php b/app/Controller/Customfilter.php index 1b43f1d0..da7eb77b 100644 --- a/app/Controller/Customfilter.php +++ b/app/Controller/Customfilter.php @@ -21,7 +21,7 @@ class Customfilter extends Base { $project = $this->getProject(); - $this->response->html($this->projectLayout('custom_filter/index', array( + $this->response->html($this->helper->layout->project('custom_filter/index', array( 'values' => $values + array('project_id' => $project['id']), 'errors' => $errors, 'project' => $project, @@ -90,7 +90,7 @@ class Customfilter extends Base $this->checkPermission($project, $filter); - $this->response->html($this->projectLayout('custom_filter/edit', array( + $this->response->html($this->helper->layout->project('custom_filter/edit', array( 'values' => empty($values) ? $filter : $values, 'errors' => $errors, 'project' => $project, diff --git a/app/Controller/Doc.php b/app/Controller/Doc.php index a233b120..6f309d48 100644 --- a/app/Controller/Doc.php +++ b/app/Controller/Doc.php @@ -52,8 +52,6 @@ class Doc extends Base } } - $this->response->html($this->template->layout('doc/show', $this->readFile($filename) + array( - 'board_selector' => $this->projectUserRole->getActiveProjectsByUser($this->userSession->getId()), - ))); + $this->response->html($this->helper->layout->app('doc/show', $this->readFile($filename))); } } diff --git a/app/Controller/Export.php b/app/Controller/Export.php index c39f58a1..977a4107 100644 --- a/app/Controller/Export.php +++ b/app/Controller/Export.php @@ -27,7 +27,7 @@ class Export extends Base $this->response->csv($data); } - $this->response->html($this->projectLayout('export/'.$action, array( + $this->response->html($this->helper->layout->project('export/'.$action, array( 'values' => array( 'controller' => 'export', 'action' => $action, diff --git a/app/Controller/File.php b/app/Controller/File.php index 18e787f1..b347f67f 100644 --- a/app/Controller/File.php +++ b/app/Controller/File.php @@ -26,7 +26,7 @@ class File extends Base return $this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])), true); } - $this->response->html($this->taskLayout('file/screenshot', array( + $this->response->html($this->helper->layout->task('file/screenshot', array( 'task' => $task, ))); } @@ -40,7 +40,7 @@ class File extends Base { $task = $this->getTask(); - $this->response->html($this->taskLayout('file/new', array( + $this->response->html($this->helper->layout->task('file/new', array( 'task' => $task, 'max_size' => ini_get('upload_max_filesize'), ))); @@ -178,7 +178,7 @@ class File extends Base $task = $this->getTask(); $file = $this->file->getById($this->request->getIntegerParam('file_id')); - $this->response->html($this->taskLayout('file/remove', array( + $this->response->html($this->helper->layout->task('file/remove', array( 'task' => $task, 'file' => $file, ))); diff --git a/app/Controller/Gantt.php b/app/Controller/Gantt.php index f312130c..b1dc2b7e 100644 --- a/app/Controller/Gantt.php +++ b/app/Controller/Gantt.php @@ -23,10 +23,9 @@ class Gantt extends Base $project_ids = $this->projectPermission->getActiveProjectIds($this->userSession->getId()); } - $this->response->html($this->template->layout('gantt/projects', array( + $this->response->html($this->helper->layout->app('gantt/projects', array( 'projects' => $this->projectGanttFormatter->filter($project_ids)->format(), 'title' => t('Gantt chart for all projects'), - 'board_selector' => $this->projectUserRole->getActiveProjectsByUser($this->userSession->getId()), ))); } @@ -65,7 +64,7 @@ class Gantt extends Base $filter->getQuery()->asc('column_position')->asc(TaskModel::TABLE.'.position'); } - $this->response->html($this->template->layout('gantt/project', $params + array( + $this->response->html($this->helper->layout->app('gantt/project', $params + array( 'users_list' => $this->projectUserRole->getAssignableUsersList($params['project']['id'], false), 'sorting' => $sorting, 'tasks' => $filter->format(), diff --git a/app/Controller/Group.php b/app/Controller/Group.php index e952c0e5..fa47f428 100644 --- a/app/Controller/Group.php +++ b/app/Controller/Group.php @@ -24,8 +24,7 @@ class Group extends Base ->setQuery($this->group->getQuery()) ->calculate(); - $this->response->html($this->template->layout('group/index', array( - 'board_selector' => $this->projectUserRole->getActiveProjectsByUser($this->userSession->getId()), + $this->response->html($this->helper->layout->app('group/index', array( 'title' => t('Groups').' ('.$paginator->getTotal().')', 'paginator' => $paginator, ))); @@ -48,8 +47,7 @@ class Group extends Base ->setQuery($this->groupMember->getQuery($group_id)) ->calculate(); - $this->response->html($this->template->layout('group/users', array( - 'board_selector' => $this->projectUserRole->getActiveProjectsByUser($this->userSession->getId()), + $this->response->html($this->helper->layout->app('group/users', array( 'title' => t('Members of %s', $group['name']).' ('.$paginator->getTotal().')', 'paginator' => $paginator, 'group' => $group, @@ -63,8 +61,7 @@ class Group extends Base */ public function create(array $values = array(), array $errors = array()) { - $this->response->html($this->template->layout('group/create', array( - 'board_selector' => $this->projectUserRole->getActiveProjectsByUser($this->userSession->getId()), + $this->response->html($this->helper->layout->app('group/create', array( 'errors' => $errors, 'values' => $values, 'title' => t('New group') @@ -104,8 +101,7 @@ class Group extends Base $values = $this->group->getById($this->request->getIntegerParam('group_id')); } - $this->response->html($this->template->layout('group/edit', array( - 'board_selector' => $this->projectUserRole->getActiveProjectsByUser($this->userSession->getId()), + $this->response->html($this->helper->layout->app('group/edit', array( 'errors' => $errors, 'values' => $values, 'title' => t('Edit group') @@ -148,8 +144,7 @@ class Group extends Base $values['group_id'] = $group_id; } - $this->response->html($this->template->layout('group/associate', array( - 'board_selector' => $this->projectUserRole->getActiveProjectsByUser($this->userSession->getId()), + $this->response->html($this->helper->layout->app('group/associate', array( 'users' => $this->user->prepareList($this->groupMember->getNotMembers($group_id)), 'group' => $group, 'errors' => $errors, @@ -191,7 +186,7 @@ class Group extends Base $group = $this->group->getById($group_id); $user = $this->user->getById($user_id); - $this->response->html($this->template->layout('group/dissociate', array( + $this->response->html($this->helper->layout->app('group/dissociate', array( 'group' => $group, 'user' => $user, 'title' => t('Remove user from group "%s"', $group['name']), @@ -228,7 +223,7 @@ class Group extends Base $group_id = $this->request->getIntegerParam('group_id'); $group = $this->group->getById($group_id); - $this->response->html($this->template->layout('group/remove', array( + $this->response->html($this->helper->layout->app('group/remove', array( 'group' => $group, 'title' => t('Remove group'), ))); diff --git a/app/Controller/Link.php b/app/Controller/Link.php index d52d1f91..ec7ab1af 100644 --- a/app/Controller/Link.php +++ b/app/Controller/Link.php @@ -11,22 +11,6 @@ namespace Kanboard\Controller; */ class Link extends Base { - /** - * Common layout for config views - * - * @access private - * @param string $template Template name - * @param array $params Template parameters - * @return string - */ - private function layout($template, array $params) - { - $params['board_selector'] = $this->projectUserRole->getActiveProjectsByUser($this->userSession->getId()); - $params['config_content_for_layout'] = $this->template->render($template, $params); - - return $this->template->layout('config/layout', $params); - } - /** * Get the current link * @@ -51,7 +35,7 @@ class Link extends Base */ public function index(array $values = array(), array $errors = array()) { - $this->response->html($this->layout('link/index', array( + $this->response->html($this->helper->layout->config('link/index', array( 'links' => $this->link->getMergedList(), 'values' => $values, 'errors' => $errors, @@ -91,7 +75,7 @@ class Link extends Base $link = $this->getLink(); $link['label'] = t($link['label']); - $this->response->html($this->layout('link/edit', array( + $this->response->html($this->helper->layout->config('link/edit', array( 'values' => $values ?: $link, 'errors' => $errors, 'labels' => $this->link->getList($link['id']), @@ -131,7 +115,7 @@ class Link extends Base { $link = $this->getLink(); - $this->response->html($this->layout('link/remove', array( + $this->response->html($this->helper->layout->config('link/remove', array( 'link' => $link, 'title' => t('Remove a link') ))); diff --git a/app/Controller/Listing.php b/app/Controller/Listing.php index b9c851f5..c7d3d9a8 100644 --- a/app/Controller/Listing.php +++ b/app/Controller/Listing.php @@ -30,7 +30,7 @@ class Listing extends Base ->setQuery($query) ->calculate(); - $this->response->html($this->template->layout('listing/show', $params + array( + $this->response->html($this->helper->layout->app('listing/show', $params + array( 'paginator' => $paginator, ))); } diff --git a/app/Controller/Oauth.php b/app/Controller/Oauth.php index bc670d1e..452faecd 100644 --- a/app/Controller/Oauth.php +++ b/app/Controller/Oauth.php @@ -95,7 +95,7 @@ class Oauth extends Base if ($this->authenticationManager->oauthAuthentication($provider)) { $this->response->redirect($this->helper->url->to('app', 'index')); } else { - $this->response->html($this->template->layout('auth/index', array( + $this->response->html($this->helper->layout->app('auth/index', array( 'errors' => array('login' => t('External authentication failed')), 'values' => array(), 'no_layout' => true, diff --git a/app/Controller/PasswordReset.php b/app/Controller/PasswordReset.php index 23567c9c..f6a0eb8e 100644 --- a/app/Controller/PasswordReset.php +++ b/app/Controller/PasswordReset.php @@ -17,7 +17,7 @@ class PasswordReset extends Base { $this->checkActivation(); - $this->response->html($this->template->layout('password_reset/create', array( + $this->response->html($this->helper->layout->app('password_reset/create', array( 'errors' => $errors, 'values' => $values, 'no_layout' => true, @@ -53,7 +53,7 @@ class PasswordReset extends Base $user_id = $this->passwordReset->getUserIdByToken($token); if ($user_id !== false) { - $this->response->html($this->template->layout('password_reset/change', array( + $this->response->html($this->helper->layout->app('password_reset/change', array( 'token' => $token, 'errors' => $errors, 'values' => $values, diff --git a/app/Controller/Project.php b/app/Controller/Project.php index 661fd68b..cdfbd94a 100644 --- a/app/Controller/Project.php +++ b/app/Controller/Project.php @@ -32,8 +32,7 @@ class Project extends Base ->setQuery($this->project->getQueryColumnStats($project_ids)) ->calculate(); - $this->response->html($this->template->layout('project/index', array( - 'board_selector' => $this->projectUserRole->getActiveProjectsByUser($this->userSession->getId()), + $this->response->html($this->helper->layout->app('project/index', array( 'paginator' => $paginator, 'nb_projects' => $nb_projects, 'title' => t('Projects').' ('.$nb_projects.')' @@ -49,7 +48,7 @@ class Project extends Base { $project = $this->getProject(); - $this->response->html($this->projectLayout('project/show', array( + $this->response->html($this->helper->layout->project('project/show', array( 'project' => $project, 'stats' => $this->project->getTaskStats($project['id']), 'title' => $project['name'], @@ -78,7 +77,7 @@ class Project extends Base $this->response->redirect($this->helper->url->to('project', 'share', array('project_id' => $project['id']))); } - $this->response->html($this->projectLayout('project/share', array( + $this->response->html($this->helper->layout->project('project/share', array( 'project' => $project, 'title' => t('Public access'), ))); @@ -99,7 +98,7 @@ class Project extends Base $this->response->redirect($this->helper->url->to('project', 'integrations', array('project_id' => $project['id']))); } - $this->response->html($this->projectLayout('project/integrations', array( + $this->response->html($this->helper->layout->project('project/integrations', array( 'project' => $project, 'title' => t('Integrations'), 'webhook_token' => $this->config->get('webhook_token'), @@ -124,7 +123,7 @@ class Project extends Base $this->response->redirect($this->helper->url->to('project', 'notifications', array('project_id' => $project['id']))); } - $this->response->html($this->projectLayout('project/notifications', array( + $this->response->html($this->helper->layout->project('project/notifications', array( 'notifications' => $this->projectNotification->readSettings($project['id']), 'types' => $this->projectNotificationType->getTypes(), 'project' => $project, @@ -153,7 +152,7 @@ class Project extends Base $this->response->redirect($this->helper->url->to('project', 'index')); } - $this->response->html($this->projectLayout('project/remove', array( + $this->response->html($this->helper->layout->project('project/remove', array( 'project' => $project, 'title' => t('Remove project') ))); @@ -182,7 +181,7 @@ class Project extends Base $this->response->redirect($this->helper->url->to('project', 'show', array('project_id' => $project_id))); } - $this->response->html($this->projectLayout('project/duplicate', array( + $this->response->html($this->helper->layout->project('project/duplicate', array( 'project' => $project, 'title' => t('Clone this project') ))); @@ -209,7 +208,7 @@ class Project extends Base $this->response->redirect($this->helper->url->to('project', 'show', array('project_id' => $project['id']))); } - $this->response->html($this->projectLayout('project/disable', array( + $this->response->html($this->helper->layout->project('project/disable', array( 'project' => $project, 'title' => t('Project activation') ))); @@ -236,7 +235,7 @@ class Project extends Base $this->response->redirect($this->helper->url->to('project', 'show', array('project_id' => $project['id']))); } - $this->response->html($this->projectLayout('project/enable', array( + $this->response->html($this->helper->layout->project('project/enable', array( 'project' => $project, 'title' => t('Project activation') ))); diff --git a/app/Controller/ProjectEdit.php b/app/Controller/ProjectEdit.php index 29793c47..f4a3a7cb 100644 --- a/app/Controller/ProjectEdit.php +++ b/app/Controller/ProjectEdit.php @@ -114,7 +114,7 @@ class ProjectEdit extends Base { $project = $this->getProject(); - $this->response->html($this->projectLayout($template, array( + $this->response->html($this->helper->layout->project($template, array( 'owners' => $this->projectUserRole->getAssignableUsersList($project['id'], true), 'values' => empty($values) ? $project : $values, 'errors' => $errors, diff --git a/app/Controller/ProjectPermission.php b/app/Controller/ProjectPermission.php index e0e58240..800da02f 100644 --- a/app/Controller/ProjectPermission.php +++ b/app/Controller/ProjectPermission.php @@ -43,7 +43,7 @@ class ProjectPermission extends Base $values['role'] = Role::PROJECT_MEMBER; } - $this->response->html($this->projectLayout('project_permission/index', array( + $this->response->html($this->helper->layout->project('project_permission/index', array( 'project' => $project, 'users' => $this->projectUserRole->getUsers($project['id']), 'groups' => $this->projectGroupRole->getGroups($project['id']), diff --git a/app/Controller/Projectuser.php b/app/Controller/Projectuser.php index 78b93ab6..9cd21021 100644 --- a/app/Controller/Projectuser.php +++ b/app/Controller/Projectuser.php @@ -14,23 +14,6 @@ use Kanboard\Core\Security\Role; */ class Projectuser extends Base { - /** - * Common layout for users overview views - * - * @access private - * @param string $template Template name - * @param array $params Template parameters - * @return string - */ - private function layout($template, array $params) - { - $params['board_selector'] = $this->projectUserRole->getActiveProjectsByUser($this->userSession->getId()); - $params['content_for_sublayout'] = $this->template->render($template, $params); - $params['filter'] = array('user_id' => $params['user_id']); - - return $this->template->layout('project_user/layout', $params); - } - private function common() { $user_id = $this->request->getIntegerParam('user_id', UserModel::EVERYBODY_ID); @@ -62,7 +45,7 @@ class Projectuser extends Base ->setQuery($query) ->calculate(); - $this->response->html($this->layout('project_user/roles', array( + $this->response->html($this->helper->layout->projectUser('project_user/roles', array( 'paginator' => $paginator, 'title' => $title, 'user_id' => $user_id, @@ -88,7 +71,7 @@ class Projectuser extends Base ->setQuery($query) ->calculate(); - $this->response->html($this->layout('project_user/tasks', array( + $this->response->html($this->helper->layout->projectUser('project_user/tasks', array( 'paginator' => $paginator, 'title' => $title, 'user_id' => $user_id, diff --git a/app/Controller/Search.php b/app/Controller/Search.php index 390210c0..9b9b9e65 100644 --- a/app/Controller/Search.php +++ b/app/Controller/Search.php @@ -36,8 +36,7 @@ class Search extends Base $nb_tasks = $paginator->getTotal(); } - $this->response->html($this->template->layout('search/index', array( - 'board_selector' => $projects, + $this->response->html($this->helper->layout->app('search/index', array( 'values' => array( 'search' => $search, 'controller' => 'search', diff --git a/app/Controller/Subtask.php b/app/Controller/Subtask.php index caaaa85e..526962a9 100644 --- a/app/Controller/Subtask.php +++ b/app/Controller/Subtask.php @@ -45,7 +45,7 @@ class Subtask extends Base ); } - $this->response->html($this->taskLayout('subtask/create', array( + $this->response->html($this->helper->layout->task('subtask/create', array( 'values' => $values, 'errors' => $errors, 'users_list' => $this->projectUserRole->getAssignableUsersList($task['project_id']), @@ -92,7 +92,7 @@ class Subtask extends Base $task = $this->getTask(); $subtask = $this->getSubTask(); - $this->response->html($this->taskLayout('subtask/edit', array( + $this->response->html($this->helper->layout->task('subtask/edit', array( 'values' => empty($values) ? $subtask : $values, 'errors' => $errors, 'users_list' => $this->projectUserRole->getAssignableUsersList($task['project_id']), @@ -138,7 +138,7 @@ class Subtask extends Base $task = $this->getTask(); $subtask = $this->getSubtask(); - $this->response->html($this->taskLayout('subtask/remove', array( + $this->response->html($this->helper->layout->task('subtask/remove', array( 'subtask' => $subtask, 'task' => $task, ))); diff --git a/app/Controller/Swimlane.php b/app/Controller/Swimlane.php index 66410888..4e8c2863 100644 --- a/app/Controller/Swimlane.php +++ b/app/Controller/Swimlane.php @@ -40,7 +40,7 @@ class Swimlane extends Base { $project = $this->getProject(); - $this->response->html($this->projectLayout('swimlane/index', array( + $this->response->html($this->helper->layout->project('swimlane/index', array( 'default_swimlane' => $this->swimlane->getDefault($project['id']), 'active_swimlanes' => $this->swimlane->getAllByStatus($project['id'], SwimlaneModel::ACTIVE), 'inactive_swimlanes' => $this->swimlane->getAllByStatus($project['id'], SwimlaneModel::INACTIVE), @@ -108,7 +108,7 @@ class Swimlane extends Base $project = $this->getProject(); $swimlane = $this->getSwimlane($project['id']); - $this->response->html($this->projectLayout('swimlane/edit', array( + $this->response->html($this->helper->layout->project('swimlane/edit', array( 'values' => empty($values) ? $swimlane : $values, 'errors' => $errors, 'project' => $project, @@ -150,7 +150,7 @@ class Swimlane extends Base $project = $this->getProject(); $swimlane = $this->getSwimlane($project['id']); - $this->response->html($this->projectLayout('swimlane/remove', array( + $this->response->html($this->helper->layout->project('swimlane/remove', array( 'project' => $project, 'swimlane' => $swimlane, 'title' => t('Remove a swimlane') diff --git a/app/Controller/Task.php b/app/Controller/Task.php index 1811dcb7..0d463725 100644 --- a/app/Controller/Task.php +++ b/app/Controller/Task.php @@ -30,7 +30,7 @@ class Task extends Base $this->notfound(true); } - $this->response->html($this->template->layout('task/public', array( + $this->response->html($this->helper->layout->app('task/public', array( 'project' => $project, 'comments' => $this->comment->getAll($task['id']), 'subtasks' => $this->subtask->getAll($task['id']), @@ -64,7 +64,7 @@ class Task extends Base $this->dateParser->format($values, array('date_started'), 'Y-m-d H:i'); - $this->response->html($this->taskLayout('task/show', array( + $this->response->html($this->helper->layout->task('task/show', array( 'project' => $this->project->getById($task['project_id']), 'files' => $this->file->getAllDocuments($task['id']), 'images' => $this->file->getAllImages($task['id']), @@ -95,7 +95,7 @@ class Task extends Base { $task = $this->getTask(); - $this->response->html($this->taskLayout('task/analytics', array( + $this->response->html($this->helper->layout->task('task/analytics', array( 'title' => $task['title'], 'task' => $task, 'lead_time' => $this->taskAnalytic->getLeadTime($task), @@ -121,7 +121,7 @@ class Task extends Base ->setQuery($this->subtaskTimeTracking->getTaskQuery($task['id'])) ->calculateOnlyIf($this->request->getStringParam('pagination') === 'subtasks'); - $this->response->html($this->taskLayout('task/time_tracking_details', array( + $this->response->html($this->helper->layout->task('task/time_tracking_details', array( 'task' => $task, 'subtask_paginator' => $subtask_paginator, ))); @@ -136,7 +136,7 @@ class Task extends Base { $task = $this->getTask(); - $this->response->html($this->taskLayout('task/transitions', array( + $this->response->html($this->helper->layout->task('task/transitions', array( 'task' => $task, 'transitions' => $this->transition->getAllByTask($task['id']), ))); @@ -167,7 +167,7 @@ class Task extends Base $this->response->redirect($this->helper->url->to('board', 'show', array('project_id' => $task['project_id']))); } - $this->response->html($this->taskLayout('task/remove', array( + $this->response->html($this->helper->layout->task('task/remove', array( 'task' => $task, ))); } diff --git a/app/Controller/TaskExternalLink.php b/app/Controller/TaskExternalLink.php index 9b9a7d3d..f26922dd 100644 --- a/app/Controller/TaskExternalLink.php +++ b/app/Controller/TaskExternalLink.php @@ -21,7 +21,7 @@ class TaskExternalLink extends Base { $task = $this->getTask(); - $this->response->html($this->taskLayout('task_external_link/show', array( + $this->response->html($this->helper->layout->task('task_external_link/show', array( 'links' => $this->taskExternalLink->getAll($task['id']), 'task' => $task, 'title' => t('List of external links'), @@ -37,7 +37,7 @@ class TaskExternalLink extends Base { $task = $this->getTask(); - $this->response->html($this->taskLayout('task_external_link/find', array( + $this->response->html($this->helper->layout->task('task_external_link/find', array( 'values' => $values, 'errors' => $errors, 'task' => $task, @@ -60,7 +60,7 @@ class TaskExternalLink extends Base $provider = $this->externalLinkManager->setUserInput($values)->find(); $link = $provider->getLink(); - $this->response->html($this->taskLayout('task_external_link/create', array( + $this->response->html($this->helper->layout->task('task_external_link/create', array( 'values' => array( 'title' => $link->getTitle(), 'url' => $link->getUrl(), @@ -116,7 +116,7 @@ class TaskExternalLink extends Base $provider = $this->externalLinkManager->getProvider($values['link_type']); - $this->response->html($this->taskLayout('task_external_link/edit', array( + $this->response->html($this->helper->layout->task('task_external_link/edit', array( 'values' => $values, 'errors' => $errors, 'task' => $task, @@ -158,7 +158,7 @@ class TaskExternalLink extends Base return $this->notfound(); } - $this->response->html($this->taskLayout('task_external_link/remove', array( + $this->response->html($this->helper->layout->task('task_external_link/remove', array( 'link' => $link, 'task' => $task, ))); diff --git a/app/Controller/TaskImport.php b/app/Controller/TaskImport.php index f09c14ce..460c608c 100644 --- a/app/Controller/TaskImport.php +++ b/app/Controller/TaskImport.php @@ -20,7 +20,7 @@ class TaskImport extends Base { $project = $this->getProject(); - $this->response->html($this->projectLayout('task_import/step1', array( + $this->response->html($this->helper->layout->project('task_import/step1', array( 'project' => $project, 'values' => $values, 'errors' => $errors, diff --git a/app/Controller/Taskduplication.php b/app/Controller/Taskduplication.php index 2362ae42..f940eee3 100644 --- a/app/Controller/Taskduplication.php +++ b/app/Controller/Taskduplication.php @@ -32,7 +32,7 @@ class Taskduplication extends Base } } - $this->response->html($this->taskLayout('task_duplication/duplicate', array( + $this->response->html($this->helper->layout->task('task_duplication/duplicate', array( 'task' => $task, ))); } @@ -128,7 +128,7 @@ class Taskduplication extends Base $users_list = array(); } - $this->response->html($this->taskLayout($template, array( + $this->response->html($this->helper->layout->task($template, array( 'values' => $values, 'task' => $task, 'projects_list' => $projects_list, diff --git a/app/Controller/Tasklink.php b/app/Controller/Tasklink.php index 73c641fb..fdb4fada 100644 --- a/app/Controller/Tasklink.php +++ b/app/Controller/Tasklink.php @@ -38,7 +38,7 @@ class Tasklink extends Base $task = $this->getTask(); $project = $this->project->getById($task['project_id']); - $this->response->html($this->taskLayout('tasklink/show', array( + $this->response->html($this->helper->layout->task('tasklink/show', array( 'links' => $this->taskLink->getAllGroupedByLabel($task['id']), 'task' => $task, 'project' => $project, @@ -56,7 +56,7 @@ class Tasklink extends Base { $task = $this->getTask(); - $this->response->html($this->taskLayout('tasklink/create', array( + $this->response->html($this->helper->layout->task('tasklink/create', array( 'values' => $values, 'errors' => $errors, 'task' => $task, @@ -106,7 +106,7 @@ class Tasklink extends Base $values['title'] = '#'.$opposite_task['id'].' - '.$opposite_task['title']; } - $this->response->html($this->taskLayout('tasklink/edit', array( + $this->response->html($this->helper->layout->task('tasklink/edit', array( 'values' => $values, 'errors' => $errors, 'task_link' => $task_link, @@ -150,7 +150,7 @@ class Tasklink extends Base $task = $this->getTask(); $link = $this->getTaskLink(); - $this->response->html($this->taskLayout('tasklink/remove', array( + $this->response->html($this->helper->layout->task('tasklink/remove', array( 'link' => $link, 'task' => $task, ))); diff --git a/app/Controller/Taskmodification.php b/app/Controller/Taskmodification.php index 940b8a22..dc368390 100644 --- a/app/Controller/Taskmodification.php +++ b/app/Controller/Taskmodification.php @@ -56,7 +56,7 @@ class Taskmodification extends Base $values = array('id' => $task['id'], 'description' => $task['description']); } - $this->response->html($this->taskLayout('task_modification/edit_description', array( + $this->response->html($this->helper->layout->task('task_modification/edit_description', array( 'values' => $values, 'errors' => $errors, 'task' => $task, @@ -104,7 +104,7 @@ class Taskmodification extends Base $this->dateParser->format($values, array('date_due')); - $this->response->html($this->taskLayout('task_modification/edit_task', array( + $this->response->html($this->helper->layout->task('task_modification/edit_task', array( 'project' => $project, 'values' => $values, 'errors' => $errors, @@ -176,6 +176,6 @@ class Taskmodification extends Base 'recurrence_basedate_list' => $this->task->getRecurrenceBasedateList(), ); - $this->response->html($this->taskLayout('task_modification/edit_recurrence', $params)); + $this->response->html($this->helper->layout->task('task_modification/edit_recurrence', $params)); } } diff --git a/app/Controller/Taskstatus.php b/app/Controller/Taskstatus.php index e28d5911..c07f2cc5 100644 --- a/app/Controller/Taskstatus.php +++ b/app/Controller/Taskstatus.php @@ -55,7 +55,7 @@ class Taskstatus extends Base return $this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])), true); } - $this->response->html($this->taskLayout($template, array( + $this->response->html($this->helper->layout->task($template, array( 'task' => $task, ))); } diff --git a/app/Controller/Twofactor.php b/app/Controller/Twofactor.php index 8dbfcf66..10292261 100644 --- a/app/Controller/Twofactor.php +++ b/app/Controller/Twofactor.php @@ -33,7 +33,7 @@ class Twofactor extends User $this->checkCurrentUser($user); unset($this->sessionStorage->twoFactorSecret); - $this->response->html($this->layout('twofactor/index', array( + $this->response->html($this->helper->layout->user('twofactor/index', array( 'user' => $user, 'provider' => $this->authenticationManager->getPostAuthenticationProvider()->getName(), ))); @@ -60,7 +60,7 @@ class Twofactor extends User $provider->setSecret($this->sessionStorage->twoFactorSecret); } - $this->response->html($this->layout('twofactor/show', array( + $this->response->html($this->helper->layout->user('twofactor/show', array( 'user' => $user, 'secret' => $this->sessionStorage->twoFactorSecret, 'qrcode_url' => $provider->getQrCodeUrl($label), @@ -165,7 +165,7 @@ class Twofactor extends User $this->sessionStorage->twoFactorBeforeCodeCalled = true; } - $this->response->html($this->template->layout('twofactor/check', array( + $this->response->html($this->helper->layout->app('twofactor/check', array( 'title' => t('Check two factor authentication code'), ))); } @@ -191,7 +191,7 @@ class Twofactor extends User $this->response->redirect($this->helper->url->to('user', 'show', array('user_id' => $user['id']))); } - $this->response->html($this->layout('twofactor/disable', array( + $this->response->html($this->helper->layout->user('twofactor/disable', array( 'user' => $user, ))); } diff --git a/app/Controller/User.php b/app/Controller/User.php index 97e01553..881266d4 100644 --- a/app/Controller/User.php +++ b/app/Controller/User.php @@ -14,27 +14,6 @@ use Kanboard\Core\Security\Role; */ class User extends Base { - /** - * Common layout for user views - * - * @access protected - * @param string $template Template name - * @param array $params Template parameters - * @return string - */ - protected function layout($template, array $params) - { - $content = $this->template->render($template, $params); - $params['user_content_for_layout'] = $content; - $params['board_selector'] = $this->projectUserRole->getActiveProjectsByUser($this->userSession->getId()); - - if (isset($params['user'])) { - $params['title'] = ($params['user']['name'] ?: $params['user']['username']).' (#'.$params['user']['id'].')'; - } - - return $this->template->layout('user/layout', $params); - } - /** * List all users * @@ -50,8 +29,7 @@ class User extends Base ->calculate(); $this->response->html( - $this->template->layout('user/index', array( - 'board_selector' => $this->projectUserRole->getActiveProjectsByUser($this->userSession->getId()), + $this->helper->layout->app('user/index', array( 'title' => t('Users').' ('.$paginator->getTotal().')', 'paginator' => $paginator, ))); @@ -71,8 +49,7 @@ class User extends Base } $this->response->html( - $this->template->layout('user/profile', array( - 'board_selector' => $this->projectUserRole->getActiveProjectsByUser($this->userSession->getId()), + $this->helper->layout->app('user/profile', array( 'title' => $user['name'] ?: $user['username'], 'user' => $user, ) @@ -88,11 +65,10 @@ class User extends Base { $is_remote = $this->request->getIntegerParam('remote') == 1 || (isset($values['is_ldap_user']) && $values['is_ldap_user'] == 1); - $this->response->html($this->template->layout($is_remote ? 'user/create_remote' : 'user/create_local', array( + $this->response->html($this->helper->layout->app($is_remote ? 'user/create_remote' : 'user/create_local', array( 'timezones' => $this->config->getTimezones(true), 'languages' => $this->config->getLanguages(true), 'roles' => $this->role->getApplicationRoles(), - 'board_selector' => $this->projectUserRole->getActiveProjectsByUser($this->userSession->getId()), 'projects' => $this->project->getList(), 'errors' => $errors, 'values' => $values + array('role' => Role::APP_USER), @@ -142,7 +118,7 @@ class User extends Base public function show() { $user = $this->getUser(); - $this->response->html($this->layout('user/show', array( + $this->response->html($this->helper->layout->user('user/show', array( 'user' => $user, 'timezones' => $this->config->getTimezones(true), 'languages' => $this->config->getLanguages(true), @@ -166,7 +142,7 @@ class User extends Base ->setQuery($this->subtaskTimeTracking->getUserQuery($user['id'])) ->calculateOnlyIf($this->request->getStringParam('pagination') === 'subtasks'); - $this->response->html($this->layout('user/timesheet', array( + $this->response->html($this->helper->layout->user('user/timesheet', array( 'subtask_paginator' => $subtask_paginator, 'user' => $user, ))); @@ -180,7 +156,7 @@ class User extends Base public function passwordReset() { $user = $this->getUser(); - $this->response->html($this->layout('user/password_reset', array( + $this->response->html($this->helper->layout->user('user/password_reset', array( 'tokens' => $this->passwordReset->getAll($user['id']), 'user' => $user, ))); @@ -194,7 +170,7 @@ class User extends Base public function last() { $user = $this->getUser(); - $this->response->html($this->layout('user/last', array( + $this->response->html($this->helper->layout->user('user/last', array( 'last_logins' => $this->lastLogin->getAll($user['id']), 'user' => $user, ))); @@ -208,7 +184,7 @@ class User extends Base public function sessions() { $user = $this->getUser(); - $this->response->html($this->layout('user/sessions', array( + $this->response->html($this->helper->layout->user('user/sessions', array( 'sessions' => $this->rememberMeSession->getAll($user['id']), 'user' => $user, ))); @@ -243,7 +219,7 @@ class User extends Base $this->response->redirect($this->helper->url->to('user', 'notifications', array('user_id' => $user['id']))); } - $this->response->html($this->layout('user/notifications', array( + $this->response->html($this->helper->layout->user('user/notifications', array( 'projects' => $this->projectUserRole->getProjectsByUser($user['id'], array(ProjectModel::ACTIVE)), 'notifications' => $this->userNotification->readSettings($user['id']), 'types' => $this->userNotificationType->getTypes(), @@ -268,7 +244,7 @@ class User extends Base $this->response->redirect($this->helper->url->to('user', 'integrations', array('user_id' => $user['id']))); } - $this->response->html($this->layout('user/integrations', array( + $this->response->html($this->helper->layout->user('user/integrations', array( 'user' => $user, 'values' => $this->userMetadata->getall($user['id']), ))); @@ -282,7 +258,7 @@ class User extends Base public function external() { $user = $this->getUser(); - $this->response->html($this->layout('user/external', array( + $this->response->html($this->helper->layout->user('user/external', array( 'last_logins' => $this->lastLogin->getAll($user['id']), 'user' => $user, ))); @@ -310,7 +286,7 @@ class User extends Base $this->response->redirect($this->helper->url->to('user', 'share', array('user_id' => $user['id']))); } - $this->response->html($this->layout('user/share', array( + $this->response->html($this->helper->layout->user('user/share', array( 'user' => $user, 'title' => t('Public access'), ))); @@ -342,7 +318,7 @@ class User extends Base } } - $this->response->html($this->layout('user/password', array( + $this->response->html($this->helper->layout->user('user/password', array( 'values' => $values, 'errors' => $errors, 'user' => $user, @@ -384,7 +360,7 @@ class User extends Base } } - $this->response->html($this->layout('user/edit', array( + $this->response->html($this->helper->layout->user('user/edit', array( 'values' => $values, 'errors' => $errors, 'user' => $user, @@ -422,7 +398,7 @@ class User extends Base } } - $this->response->html($this->layout('user/authentication', array( + $this->response->html($this->helper->layout->user('user/authentication', array( 'values' => $values, 'errors' => $errors, 'user' => $user, @@ -450,7 +426,7 @@ class User extends Base $this->response->redirect($this->helper->url->to('user', 'index')); } - $this->response->html($this->layout('user/remove', array( + $this->response->html($this->helper->layout->user('user/remove', array( 'user' => $user, ))); } diff --git a/app/Controller/UserImport.php b/app/Controller/UserImport.php index cbc5aa14..debd69e5 100644 --- a/app/Controller/UserImport.php +++ b/app/Controller/UserImport.php @@ -18,7 +18,7 @@ class UserImport extends Base */ public function step1(array $values = array(), array $errors = array()) { - $this->response->html($this->template->layout('user_import/step1', array( + $this->response->html($this->helper->layout->app('user_import/step1', array( 'values' => $values, 'errors' => $errors, 'max_size' => ini_get('upload_max_filesize'), diff --git a/app/Helper/Layout.php b/app/Helper/Layout.php index 685c7b84..8c00a311 100644 --- a/app/Helper/Layout.php +++ b/app/Helper/Layout.php @@ -26,7 +26,146 @@ class Layout extends Base return $this->template->render($template, $params); } - $params['board_selector'] = $this->projectUserRole->getActiveProjectsByUser($this->userSession->getId()); + if (! isset($params['no_layout']) && ! isset($params['board_selector'])) { + $params['board_selector'] = $this->projectUserRole->getActiveProjectsByUser($this->userSession->getId()); + } + return $this->template->layout($template, $params); } + + /** + * Common layout for user views + * + * @access public + * @param string $template Template name + * @param array $params Template parameters + * @return string + */ + public function user($template, array $params) + { + if (isset($params['user'])) { + $params['title'] = '#'.$params['user']['id'].' '.($params['user']['name'] ?: $params['user']['username']); + } + + return $this->subLayout('user/layout', 'user/sidebar', $template, $params); + } + + /** + * Common layout for task views + * + * @access public + * @param string $template Template name + * @param array $params Template parameters + * @return string + */ + public function task($template, array $params) + { + $params['title'] = '#'.$params['task']['id'].' '.$params['task']['title']; + return $this->subLayout('task/layout', 'task/sidebar', $template, $params); + } + + /** + * Common layout for project views + * + * @access public + * @param string $template + * @param array $params + * @param string $sidebar + * @return string + */ + public function project($template, array $params, $sidebar = 'project/sidebar') + { + if (empty($params['title'])) { + $params['title'] = $params['project']['name']; + } elseif ($params['project']['name'] !== $params['title']) { + $params['title'] = $params['project']['name'].' > '.$params['title']; + } + + return $this->subLayout('project/layout', $sidebar, $template, $params); + } + + /** + * Common layout for project user views + * + * @access public + * @param string $template + * @param array $params + * @return string + */ + public function projectUser($template, array $params) + { + $params['filter'] = array('user_id' => $params['user_id']); + return $this->subLayout('project_user/layout', 'project_user/sidebar', $template, $params); + } + + /** + * Common layout for config views + * + * @access public + * @param string $template + * @param array $params + * @return string + */ + public function config($template, array $params) + { + if (! isset($params['values'])) { + $params['values'] = $this->config->getAll(); + } + + if (! isset($params['errors'])) { + $params['errors'] = array(); + } + + return $this->subLayout('config/layout', 'config/sidebar', $template, $params); + } + + /** + * Common layout for dashboard views + * + * @access public + * @param string $template + * @param array $params + * @return string + */ + public function dashboard($template, array $params) + { + return $this->subLayout('app/layout', 'app/sidebar', $template, $params); + } + + /** + * Common layout for analytic views + * + * @access public + * @param string $template + * @param array $params + * @return string + */ + public function analytic($template, array $params) + { + return $this->subLayout('analytic/layout', 'analytic/sidebar', $template, $params); + } + + /** + * Common method to generate a sublayout + * + * @access public + * @param string $sublayout + * @param string $sidebar + * @param string $template + * @param array $params + * @return string + */ + public function subLayout($sublayout, $sidebar, $template, array $params = array()) + { + $content = $this->template->render($template, $params); + + if ($this->request->isAjax()) { + return $content; + } + + $params['content_for_sublayout'] = $content; + $params['sidebar_template'] = $sidebar; + + return $this->app($sublayout, $params); + } } diff --git a/app/Template/analytic/layout.php b/app/Template/analytic/layout.php index ff532fc0..4f22db10 100644 --- a/app/Template/analytic/layout.php +++ b/app/Template/analytic/layout.php @@ -33,7 +33,7 @@ \ No newline at end of file diff --git a/app/Template/project_user/layout.php b/app/Template/project_user/layout.php index a87efbff..3ced5590 100644 --- a/app/Template/project_user/layout.php +++ b/app/Template/project_user/layout.php @@ -15,7 +15,7 @@ \ No newline at end of file diff --git a/app/Template/user/layout.php b/app/Template/user/layout.php index 1e456348..3a0a5ba6 100644 --- a/app/Template/user/layout.php +++ b/app/Template/user/layout.php @@ -13,7 +13,7 @@ render('user/sidebar', array('user' => $user)) ?> \ No newline at end of file -- cgit v1.2.3 From 2d27c36a71f08bea60a992b051bfb8a2d8bd06b6 Mon Sep 17 00:00:00 2001 From: Frederic Guillot Date: Sat, 20 Feb 2016 10:46:10 -0500 Subject: Use inline popup to create new columns --- ChangeLog | 1 + app/Controller/Column.php | 50 +++++++++++++++++++++++---------------- app/Template/column/create.php | 41 ++++++++++++++++++++++++++++++++ app/Template/column/index.php | 44 +++++----------------------------- app/Validator/ColumnValidator.php | 35 ++++++++++++++++++++------- 5 files changed, 103 insertions(+), 68 deletions(-) create mode 100644 app/Template/column/create.php (limited to 'app/Controller/Column.php') diff --git a/ChangeLog b/ChangeLog index fa2c2597..31b089b0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -11,6 +11,7 @@ New features: Improvements: +* Use inline popup to create new columns * Improve filter box design * Improve image thumbnails and files table * Add confirmation inline popup to remove custom filter diff --git a/app/Controller/Column.php b/app/Controller/Column.php index 3201c549..77204164 100644 --- a/app/Controller/Column.php +++ b/app/Controller/Column.php @@ -15,20 +15,12 @@ class Column extends Base * * @access public */ - public function index(array $values = array(), array $errors = array()) + public function index() { $project = $this->getProject(); $columns = $this->board->getColumns($project['id']); - foreach ($columns as $column) { - $values['title['.$column['id'].']'] = $column['title']; - $values['description['.$column['id'].']'] = $column['description']; - $values['task_limit['.$column['id'].']'] = $column['task_limit'] ?: null; - } - $this->response->html($this->helper->layout->project('column/index', array( - 'errors' => $errors, - 'values' => $values + array('project_id' => $project['id']), 'columns' => $columns, 'project' => $project, 'title' => t('Edit board') @@ -36,33 +28,49 @@ class Column extends Base } /** - * Validate and add a new column + * Show form to create a new column * * @access public */ - public function create() + public function create(array $values = array(), array $errors = array()) { $project = $this->getProject(); $columns = $this->board->getColumnsList($project['id']); - $data = $this->request->getValues(); - $values = array(); - foreach ($columns as $column_id => $column_title) { - $values['title['.$column_id.']'] = $column_title; + if (empty($values)) { + $values = array('project_id' => $project['id']); } - list($valid, $errors) = $this->columnValidator->validateCreation($data); + $this->response->html($this->template->render('column/create', array( + 'values' => $values, + 'errors' => $errors, + 'project' => $project, + 'title' => t('Add a new column') + ))); + } + + /** + * Validate and add a new column + * + * @access public + */ + public function save() + { + $project = $this->getProject(); + $values = $this->request->getValues(); + + list($valid, $errors) = $this->columnValidator->validateCreation($values); if ($valid) { - if ($this->board->addColumn($project['id'], $data['title'], $data['task_limit'], $data['description'])) { - $this->flash->success(t('Board updated successfully.')); - $this->response->redirect($this->helper->url->to('column', 'index', array('project_id' => $project['id']))); + if ($this->board->addColumn($project['id'], $values['title'], $values['task_limit'], $values['description'])) { + $this->flash->success(t('Column created successfully.')); + return $this->response->redirect($this->helper->url->to('column', 'index', array('project_id' => $project['id'])), true); } else { - $this->flash->failure(t('Unable to update this board.')); + $errors['title'] = array(t('Another column with the same title exists in the project')); } } - $this->index($values, $errors); + $this->create($values, $errors); } /** diff --git a/app/Template/column/create.php b/app/Template/column/create.php new file mode 100644 index 00000000..58b130f5 --- /dev/null +++ b/app/Template/column/create.php @@ -0,0 +1,41 @@ + +
+ + form->csrf() ?> + + form->hidden('project_id', $values) ?> + + form->label(t('Title'), 'title') ?> + form->text('title', $values, $errors, array('autofocus', 'required', 'maxlength="50"')) ?> + + form->label(t('Task limit'), 'task_limit') ?> + form->number('task_limit', $values, $errors) ?> + + form->label(t('Description'), 'description') ?> + +
+
+ form->textarea('description', $values, $errors) ?> +
+
+
+
+
    +
  • + +
  • +
  • + +
  • +
+
+
url->doc(t('Write your text in Markdown'), 'syntax-guide') ?>
+ +
+ + + url->link(t('cancel'), 'column', 'index', array('project_id' => $project['id']), false, 'close-popover') ?> +
+
\ No newline at end of file diff --git a/app/Template/column/index.php b/app/Template/column/index.php index 85d46f26..8d95dd48 100644 --- a/app/Template/column/index.php +++ b/app/Template/column/index.php @@ -1,5 +1,11 @@ @@ -52,41 +58,3 @@ - -

-
- - form->csrf() ?> - - form->hidden('project_id', $values) ?> - - form->label(t('Title'), 'title') ?> - form->text('title', $values, $errors, array('required', 'maxlength="50"')) ?> - - form->label(t('Task limit'), 'task_limit') ?> - form->number('task_limit', $values, $errors) ?> - - form->label(t('Description'), 'description') ?> - -
-
- form->textarea('description', $values, $errors) ?> -
-
-
-
-
    -
  • - -
  • -
  • - -
  • -
-
-
url->doc(t('Write your text in Markdown'), 'syntax-guide') ?>
- -
- -
-
\ No newline at end of file diff --git a/app/Validator/ColumnValidator.php b/app/Validator/ColumnValidator.php index 4c644e8a..f0f1659b 100644 --- a/app/Validator/ColumnValidator.php +++ b/app/Validator/ColumnValidator.php @@ -22,11 +22,12 @@ class ColumnValidator extends Base */ public function validateModification(array $values) { - $v = new Validator($values, array( - new Validators\Integer('task_limit', t('This value must be an integer')), - new Validators\Required('title', t('The title is required')), - new Validators\MaxLength('title', t('The maximum length is %d characters', 50), 50), - )); + $rules = array( + new Validators\Required('id', t('This value is required')), + new Validators\Integer('id', t('This value must be an integer')), + ); + + $v = new Validator($values, array_merge($rules, $this->commonValidationRules())); return array( $v->execute(), @@ -43,16 +44,32 @@ class ColumnValidator extends Base */ public function validateCreation(array $values) { - $v = new Validator($values, array( + $rules = array( new Validators\Required('project_id', t('The project id is required')), new Validators\Integer('project_id', t('This value must be an integer')), - new Validators\Required('title', t('The title is required')), - new Validators\MaxLength('title', t('The maximum length is %d characters', 50), 50), - )); + ); + + $v = new Validator($values, array_merge($rules, $this->commonValidationRules())); return array( $v->execute(), $v->getErrors() ); } + + /** + * Common validation rules + * + * @access private + * @return array + */ + private function commonValidationRules() + { + return array( + new Validators\Integer('task_limit', t('This value must be an integer')), + new Validators\GreaterThan('task_limit', t('This value must be greater than %d', -1), -1), + new Validators\Required('title', t('The title is required')), + new Validators\MaxLength('title', t('The maximum length is %d characters', 50), 50), + ); + } } -- cgit v1.2.3 From c8c1242c26a11dc2abc7126829d76430612e7107 Mon Sep 17 00:00:00 2001 From: Frederic Guillot Date: Sat, 20 Feb 2016 11:24:43 -0500 Subject: Add drag and drop to change column positions --- ChangeLog | 2 +- Makefile | 2 +- app/Controller/Column.php | 13 ++++--- app/Controller/Subtask.php | 2 +- app/Model/Column.php | 64 +++++++++++++++++++++++++++++++++ app/Model/Subtask.php | 21 ----------- app/ServiceProvider/ClassProvider.php | 1 + app/Template/column/index.php | 48 ++++++++++++------------- app/Template/subtask/table.php | 6 ---- assets/js/app.js | 2 +- assets/js/src/App.js | 2 ++ assets/js/src/Column.js | 59 ++++++++++++++++++++++++++++++ tests/units/Model/ColumnTest.php | 68 +++++++++++++++++++++++++++++++++++ 13 files changed, 226 insertions(+), 64 deletions(-) create mode 100644 app/Model/Column.php create mode 100644 assets/js/src/Column.js create mode 100644 tests/units/Model/ColumnTest.php (limited to 'app/Controller/Column.php') diff --git a/ChangeLog b/ChangeLog index 31b089b0..ae7919bf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,7 +3,7 @@ Version 1.0.26 (unreleased) New features: -* Add subtasks drag and drop +* Add drag and drop to change subtasks and columns positions * Add file drag and drop and asynchronous upload * Enable/Disable users * Add setting option to disable private projects diff --git a/Makefile b/Makefile index 3e05f29c..a62c105a 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ CSS_APP = $(addprefix assets/css/src/, $(addsuffix .css, base links title table CSS_PRINT = $(addprefix assets/css/src/, $(addsuffix .css, print links table board task comment subtask markdown)) CSS_VENDOR = $(addprefix assets/css/vendor/, $(addsuffix .css, jquery-ui.min jquery-ui-timepicker-addon.min chosen.min fullcalendar.min font-awesome.min c3.min)) -JS_APP = $(addprefix assets/js/src/, $(addsuffix .js, Popover Dropdown Tooltip Markdown Search App Screenshot FileUpload Calendar Board Swimlane Gantt Task Project Subtask TaskRepartitionChart UserRepartitionChart CumulativeFlowDiagram BurndownChart AvgTimeColumnChart TaskTimeColumnChart LeadCycleTimeChart CompareHoursColumnChart Router)) +JS_APP = $(addprefix assets/js/src/, $(addsuffix .js, Popover Dropdown Tooltip Markdown Search App Screenshot FileUpload Calendar Board Column Swimlane Gantt Task Project Subtask TaskRepartitionChart UserRepartitionChart CumulativeFlowDiagram BurndownChart AvgTimeColumnChart TaskTimeColumnChart LeadCycleTimeChart CompareHoursColumnChart Router)) JS_VENDOR = $(addprefix assets/js/vendor/, $(addsuffix .js, jquery-1.11.3.min jquery-ui.min jquery-ui-timepicker-addon.min jquery.ui.touch-punch.min chosen.jquery.min moment.min fullcalendar.min mousetrap.min mousetrap-global-bind.min jquery.textcomplete)) JS_LANG = $(addprefix assets/js/vendor/lang/, $(addsuffix .js, cs da de es el fi fr hu id it ja nl nb pl pt pt-br ru sv sr th tr zh-cn)) diff --git a/app/Controller/Column.php b/app/Controller/Column.php index 77204164..2e028e0e 100644 --- a/app/Controller/Column.php +++ b/app/Controller/Column.php @@ -117,22 +117,21 @@ class Column extends Base } /** - * Move a column up or down + * Move column position * * @access public */ public function move() { - $this->checkCSRFParam(); $project = $this->getProject(); - $column_id = $this->request->getIntegerParam('column_id'); - $direction = $this->request->getStringParam('direction'); + $values = $this->request->getJson(); - if ($direction === 'up' || $direction === 'down') { - $this->board->{'move'.$direction}($project['id'], $column_id); + if (! empty($values)) { + $result = $this->column->changePosition($project['id'], $values['column_id'], $values['position']); + return $this->response->json(array('result' => $result)); } - $this->response->redirect($this->helper->url->to('column', 'index', array('project_id' => $project['id']))); + $this->forbidden(); } /** diff --git a/app/Controller/Subtask.php b/app/Controller/Subtask.php index a0a3eb66..8ca0ce92 100644 --- a/app/Controller/Subtask.php +++ b/app/Controller/Subtask.php @@ -174,7 +174,7 @@ class Subtask extends Base if (! empty($values) && $this->helper->user->hasProjectAccess('Subtask', 'movePosition', $project_id)) { $result = $this->subtask->changePosition($task_id, $values['subtask_id'], $values['position']); - $this->response->json(array('result' => $result)); + return $this->response->json(array('result' => $result)); } $this->forbidden(); diff --git a/app/Model/Column.php b/app/Model/Column.php new file mode 100644 index 00000000..286b6140 --- /dev/null +++ b/app/Model/Column.php @@ -0,0 +1,64 @@ +db->table(self::TABLE)->eq('project_id', $project_id)->asc('position')->findAll(); + } + + /** + * Change column position + * + * @access public + * @param integer $project_id + * @param integer $column_id + * @param integer $position + * @return boolean + */ + public function changePosition($project_id, $column_id, $position) + { + if ($position < 1 || $position > $this->db->table(self::TABLE)->eq('project_id', $project_id)->count()) { + return false; + } + + $column_ids = $this->db->table(self::TABLE)->eq('project_id', $project_id)->neq('id', $column_id)->asc('position')->findAllByColumn('id'); + $offset = 1; + $results = array(); + + foreach ($column_ids as $current_column_id) { + if ($offset == $position) { + $offset++; + } + + $results[] = $this->db->table(self::TABLE)->eq('id', $current_column_id)->update(array('position' => $offset)); + $offset++; + } + + $results[] = $this->db->table(self::TABLE)->eq('id', $column_id)->update(array('position' => $position)); + + return !in_array(false, $results, true); + } +} diff --git a/app/Model/Subtask.php b/app/Model/Subtask.php index 3707af13..b5898fcf 100644 --- a/app/Model/Subtask.php +++ b/app/Model/Subtask.php @@ -262,27 +262,6 @@ class Subtask extends Base return $this->db->table(self::TABLE)->eq('task_id', $task_id)->update(array('status' => self::STATUS_DONE)); } - /** - * Get subtasks with consecutive positions - * - * If you remove a subtask, the positions are not anymore consecutives - * - * @access public - * @param integer $task_id - * @return array - */ - public function getNormalizedPositions($task_id) - { - $subtasks = $this->db->hashtable(self::TABLE)->eq('task_id', $task_id)->asc('position')->getAll('id', 'position'); - $position = 1; - - foreach ($subtasks as $subtask_id => $subtask_position) { - $subtasks[$subtask_id] = $position++; - } - - return $subtasks; - } - /** * Save subtask position * diff --git a/app/ServiceProvider/ClassProvider.php b/app/ServiceProvider/ClassProvider.php index a4fa1ff2..0f2fbab5 100644 --- a/app/ServiceProvider/ClassProvider.php +++ b/app/ServiceProvider/ClassProvider.php @@ -27,6 +27,7 @@ class ClassProvider implements ServiceProviderInterface 'Board', 'Category', 'Color', + 'Column', 'Comment', 'Config', 'Currency', diff --git a/app/Template/column/index.php b/app/Template/column/index.php index 8d95dd48..c6a6e85b 100644 --- a/app/Template/column/index.php +++ b/app/Template/column/index.php @@ -8,28 +8,34 @@ - - - - - -

- + +

+ +
+ + + - - + + - +
e($column['title']) ?> - - '> - - - +
+ + e($column['title']) ?> + + '> + + + + + e($column['task_limit']) ?> e($column['task_limit']) ?>
- diff --git a/app/Template/subtask/table.php b/app/Template/subtask/table.php index 53902057..5db23245 100644 --- a/app/Template/subtask/table.php +++ b/app/Template/subtask/table.php @@ -1,8 +1,4 @@ - - - - render('subtask/menu', array( 'task' => $task, 'subtask' => $subtask, - 'first_position' => $first_position, - 'last_position' => $last_position, )) ?> diff --git a/assets/js/app.js b/assets/js/app.js index f7e5277e..d831659c 100644 --- a/assets/js/app.js +++ b/assets/js/app.js @@ -1278,4 +1278,4 @@ if (typeof jQuery === 'undefined') { return jQuery; })); -!function(a){"function"==typeof define&&define.amd?define(["jquery","moment"],a):a(jQuery,moment)}(function(a,b){function c(a){return a>1&&5>a&&1!==~~(a/10)}function d(a,b,d,e){var f=a+" ";switch(d){case"s":return b||e?"pár sekund":"pár sekundami";case"m":return b?"minuta":e?"minutu":"minutou";case"mm":return b||e?f+(c(a)?"minuty":"minut"):f+"minutami";case"h":return b?"hodina":e?"hodinu":"hodinou";case"hh":return b||e?f+(c(a)?"hodiny":"hodin"):f+"hodinami";case"d":return b||e?"den":"dnem";case"dd":return b||e?f+(c(a)?"dny":"dní"):f+"dny";case"M":return b||e?"měsíc":"měsícem";case"MM":return b||e?f+(c(a)?"měsíce":"měsíců"):f+"měsíci";case"y":return b||e?"rok":"rokem";case"yy":return b||e?f+(c(a)?"roky":"let"):f+"lety"}}var e="leden_únor_březen_duben_květen_červen_červenec_srpen_září_říjen_listopad_prosinec".split("_"),f="led_úno_bře_dub_kvě_čvn_čvc_srp_zář_říj_lis_pro".split("_");(b.defineLocale||b.lang).call(b,"cs",{months:e,monthsShort:f,monthsParse:function(a,b){var c,d=[];for(c=0;12>c;c++)d[c]=new RegExp("^"+a[c]+"$|^"+b[c]+"$","i");return d}(e,f),weekdays:"neděle_pondělí_úterý_středa_čtvrtek_pátek_sobota".split("_"),weekdaysShort:"ne_po_út_st_čt_pá_so".split("_"),weekdaysMin:"ne_po_út_st_čt_pá_so".split("_"),longDateFormat:{LT:"H:mm",LTS:"LT:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY LT",LLLL:"dddd D. MMMM YYYY LT"},calendar:{sameDay:"[dnes v] LT",nextDay:"[zítra v] LT",nextWeek:function(){switch(this.day()){case 0:return"[v neděli v] LT";case 1:case 2:return"[v] dddd [v] LT";case 3:return"[ve středu v] LT";case 4:return"[ve čtvrtek v] LT";case 5:return"[v pátek v] LT";case 6:return"[v sobotu v] LT"}},lastDay:"[včera v] LT",lastWeek:function(){switch(this.day()){case 0:return"[minulou neděli v] LT";case 1:case 2:return"[minulé] dddd [v] LT";case 3:return"[minulou středu v] LT";case 4:case 5:return"[minulý] dddd [v] LT";case 6:return"[minulou sobotu v] LT"}},sameElse:"L"},relativeTime:{future:"za %s",past:"před %s",s:d,m:d,mm:d,h:d,hh:d,d:d,dd:d,M:d,MM:d,y:d,yy:d},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}}),a.fullCalendar.datepickerLang("cs","cs",{closeText:"Zavřít",prevText:"<Dříve",nextText:"Později>",currentText:"Nyní",monthNames:["leden","únor","březen","duben","květen","červen","červenec","srpen","září","říjen","listopad","prosinec"],monthNamesShort:["led","úno","bře","dub","kvě","čer","čvc","srp","zář","říj","lis","pro"],dayNames:["neděle","pondělí","úterý","středa","čtvrtek","pátek","sobota"],dayNamesShort:["ne","po","út","st","čt","pá","so"],dayNamesMin:["ne","po","út","st","čt","pá","so"],weekHeader:"Týd",dateFormat:"dd.mm.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("cs",{buttonText:{month:"Měsíc",week:"Týden",day:"Den",list:"Agenda"},allDayText:"Celý den",eventLimitText:function(a){return"+další: "+a}})});!function(a){"function"==typeof define&&define.amd?define(["jquery","moment"],a):a(jQuery,moment)}(function(a,b){(b.defineLocale||b.lang).call(b,"da",{months:"januar_februar_marts_april_maj_juni_juli_august_september_oktober_november_december".split("_"),monthsShort:"jan_feb_mar_apr_maj_jun_jul_aug_sep_okt_nov_dec".split("_"),weekdays:"søndag_mandag_tirsdag_onsdag_torsdag_fredag_lørdag".split("_"),weekdaysShort:"søn_man_tir_ons_tor_fre_lør".split("_"),weekdaysMin:"sø_ma_ti_on_to_fr_lø".split("_"),longDateFormat:{LT:"HH:mm",LTS:"LT:ss",L:"DD/MM/YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY LT",LLLL:"dddd [d.] D. MMMM YYYY LT"},calendar:{sameDay:"[I dag kl.] LT",nextDay:"[I morgen kl.] LT",nextWeek:"dddd [kl.] LT",lastDay:"[I går kl.] LT",lastWeek:"[sidste] dddd [kl] LT",sameElse:"L"},relativeTime:{future:"om %s",past:"%s siden",s:"få sekunder",m:"et minut",mm:"%d minutter",h:"en time",hh:"%d timer",d:"en dag",dd:"%d dage",M:"en måned",MM:"%d måneder",y:"et år",yy:"%d år"},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}}),a.fullCalendar.datepickerLang("da","da",{closeText:"Luk",prevText:"<Forrige",nextText:"Næste>",currentText:"Idag",monthNames:["Januar","Februar","Marts","April","Maj","Juni","Juli","August","September","Oktober","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","Maj","Jun","Jul","Aug","Sep","Okt","Nov","Dec"],dayNames:["Søndag","Mandag","Tirsdag","Onsdag","Torsdag","Fredag","Lørdag"],dayNamesShort:["Søn","Man","Tir","Ons","Tor","Fre","Lør"],dayNamesMin:["Sø","Ma","Ti","On","To","Fr","Lø"],weekHeader:"Uge",dateFormat:"dd-mm-yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("da",{buttonText:{month:"Måned",week:"Uge",day:"Dag",list:"Agenda"},allDayText:"Hele dagen",eventLimitText:"flere"})});!function(a){"function"==typeof define&&define.amd?define(["jquery","moment"],a):a(jQuery,moment)}(function(a,b){function c(a,b,c,d){var e={m:["eine Minute","einer Minute"],h:["eine Stunde","einer Stunde"],d:["ein Tag","einem Tag"],dd:[a+" Tage",a+" Tagen"],M:["ein Monat","einem Monat"],MM:[a+" Monate",a+" Monaten"],y:["ein Jahr","einem Jahr"],yy:[a+" Jahre",a+" Jahren"]};return b?e[c][0]:e[c][1]}(b.defineLocale||b.lang).call(b,"de",{months:"Januar_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember".split("_"),monthsShort:"Jan._Febr._Mrz._Apr._Mai_Jun._Jul._Aug._Sept._Okt._Nov._Dez.".split("_"),weekdays:"Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag".split("_"),weekdaysShort:"So._Mo._Di._Mi._Do._Fr._Sa.".split("_"),weekdaysMin:"So_Mo_Di_Mi_Do_Fr_Sa".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY LT",LLLL:"dddd, D. MMMM YYYY LT"},calendar:{sameDay:"[Heute um] LT [Uhr]",sameElse:"L",nextDay:"[Morgen um] LT [Uhr]",nextWeek:"dddd [um] LT [Uhr]",lastDay:"[Gestern um] LT [Uhr]",lastWeek:"[letzten] dddd [um] LT [Uhr]"},relativeTime:{future:"in %s",past:"vor %s",s:"ein paar Sekunden",m:c,mm:"%d Minuten",h:c,hh:"%d Stunden",d:c,dd:c,M:c,MM:c,y:c,yy:c},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}}),a.fullCalendar.datepickerLang("de","de",{closeText:"Schließen",prevText:"<Zurück",nextText:"Vor>",currentText:"Heute",monthNames:["Januar","Februar","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember"],monthNamesShort:["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],dayNames:["Sonntag","Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag"],dayNamesShort:["So","Mo","Di","Mi","Do","Fr","Sa"],dayNamesMin:["So","Mo","Di","Mi","Do","Fr","Sa"],weekHeader:"KW",dateFormat:"dd.mm.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("de",{buttonText:{month:"Monat",week:"Woche",day:"Tag",list:"Terminübersicht"},allDayText:"Ganztägig",eventLimitText:function(a){return"+ weitere "+a}})});!function(a){"function"==typeof define&&define.amd?define(["jquery","moment"],a):a(jQuery,moment)}(function(a,b){var c="ene._feb._mar._abr._may._jun._jul._ago._sep._oct._nov._dic.".split("_"),d="ene_feb_mar_abr_may_jun_jul_ago_sep_oct_nov_dic".split("_");(b.defineLocale||b.lang).call(b,"es",{months:"enero_febrero_marzo_abril_mayo_junio_julio_agosto_septiembre_octubre_noviembre_diciembre".split("_"),monthsShort:function(a,b){return/-MMM-/.test(b)?d[a.month()]:c[a.month()]},weekdays:"domingo_lunes_martes_miércoles_jueves_viernes_sábado".split("_"),weekdaysShort:"dom._lun._mar._mié._jue._vie._sáb.".split("_"),weekdaysMin:"Do_Lu_Ma_Mi_Ju_Vi_Sá".split("_"),longDateFormat:{LT:"H:mm",LTS:"LT:ss",L:"DD/MM/YYYY",LL:"D [de] MMMM [de] YYYY",LLL:"D [de] MMMM [de] YYYY LT",LLLL:"dddd, D [de] MMMM [de] YYYY LT"},calendar:{sameDay:function(){return"[hoy a la"+(1!==this.hours()?"s":"")+"] LT"},nextDay:function(){return"[mañana a la"+(1!==this.hours()?"s":"")+"] LT"},nextWeek:function(){return"dddd [a la"+(1!==this.hours()?"s":"")+"] LT"},lastDay:function(){return"[ayer a la"+(1!==this.hours()?"s":"")+"] LT"},lastWeek:function(){return"[el] dddd [pasado a la"+(1!==this.hours()?"s":"")+"] LT"},sameElse:"L"},relativeTime:{future:"en %s",past:"hace %s",s:"unos segundos",m:"un minuto",mm:"%d minutos",h:"una hora",hh:"%d horas",d:"un día",dd:"%d días",M:"un mes",MM:"%d meses",y:"un año",yy:"%d años"},ordinalParse:/\d{1,2}º/,ordinal:"%dº",week:{dow:1,doy:4}}),a.fullCalendar.datepickerLang("es","es",{closeText:"Cerrar",prevText:"<Ant",nextText:"Sig>",currentText:"Hoy",monthNames:["enero","febrero","marzo","abril","mayo","junio","julio","agosto","septiembre","octubre","noviembre","diciembre"],monthNamesShort:["ene","feb","mar","abr","may","jun","jul","ago","sep","oct","nov","dic"],dayNames:["domingo","lunes","martes","miércoles","jueves","viernes","sábado"],dayNamesShort:["dom","lun","mar","mié","jue","vie","sáb"],dayNamesMin:["D","L","M","X","J","V","S"],weekHeader:"Sm",dateFormat:"dd/mm/yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("es",{buttonText:{month:"Mes",week:"Semana",day:"Día",list:"Agenda"},allDayHtml:"Todo
el día",eventLimitText:"más"})});!function(a){"function"==typeof define&&define.amd?define(["jquery","moment"],a):a(jQuery,moment)}(function(a,b){(b.defineLocale||b.lang).call(b,"el",{monthsNominativeEl:"Ιανουάριος_Φεβρουάριος_Μάρτιος_Απρίλιος_Μάιος_Ιούνιος_Ιούλιος_Αύγουστος_Σεπτέμβριος_Οκτώβριος_Νοέμβριος_Δεκέμβριος".split("_"),monthsGenitiveEl:"Ιανουαρίου_Φεβρουαρίου_Μαρτίου_Απριλίου_Μαΐου_Ιουνίου_Ιουλίου_Αυγούστου_Σεπτεμβρίου_Οκτωβρίου_Νοεμβρίου_Δεκεμβρίου".split("_"),months:function(a,b){return/D/.test(b.substring(0,b.indexOf("MMMM")))?this._monthsGenitiveEl[a.month()]:this._monthsNominativeEl[a.month()]},monthsShort:"Ιαν_Φεβ_Μαρ_Απρ_Μαϊ_Ιουν_Ιουλ_Αυγ_Σεπ_Οκτ_Νοε_Δεκ".split("_"),weekdays:"Κυριακή_Δευτέρα_Τρίτη_Τετάρτη_Πέμπτη_Παρασκευή_Σάββατο".split("_"),weekdaysShort:"Κυρ_Δευ_Τρι_Τετ_Πεμ_Παρ_Σαβ".split("_"),weekdaysMin:"Κυ_Δε_Τρ_Τε_Πε_Πα_Σα".split("_"),meridiem:function(a,b,c){return a>11?c?"μμ":"ΜΜ":c?"πμ":"ΠΜ"},isPM:function(a){return"μ"===(a+"").toLowerCase()[0]},meridiemParse:/[ΠΜ]\.?Μ?\.?/i,longDateFormat:{LT:"h:mm A",LTS:"h:mm:ss A",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd, D MMMM YYYY LT"},calendarEl:{sameDay:"[Σήμερα {}] LT",nextDay:"[Αύριο {}] LT",nextWeek:"dddd [{}] LT",lastDay:"[Χθες {}] LT",lastWeek:function(){switch(this.day()){case 6:return"[το προηγούμενο] dddd [{}] LT";default:return"[την προηγούμενη] dddd [{}] LT"}},sameElse:"L"},calendar:function(a,b){var c=this._calendarEl[a],d=b&&b.hours();return"function"==typeof c&&(c=c.apply(b)),c.replace("{}",d%12===1?"στη":"στις")},relativeTime:{future:"σε %s",past:"%s πριν",s:"λίγα δευτερόλεπτα",m:"ένα λεπτό",mm:"%d λεπτά",h:"μία ώρα",hh:"%d ώρες",d:"μία μέρα",dd:"%d μέρες",M:"ένας μήνας",MM:"%d μήνες",y:"ένας χρόνος",yy:"%d χρόνια"},ordinalParse:/\d{1,2}η/,ordinal:"%dη",week:{dow:1,doy:4}}),a.fullCalendar.datepickerLang("el","el",{closeText:"Κλείσιμο",prevText:"Προηγούμενος",nextText:"Επόμενος",currentText:"Σήμερα",monthNames:["Ιανουάριος","Φεβρουάριος","Μάρτιος","Απρίλιος","Μάιος","Ιούνιος","Ιούλιος","Αύγουστος","Σεπτέμβριος","Οκτώβριος","Νοέμβριος","Δεκέμβριος"],monthNamesShort:["Ιαν","Φεβ","Μαρ","Απρ","Μαι","Ιουν","Ιουλ","Αυγ","Σεπ","Οκτ","Νοε","Δεκ"],dayNames:["Κυριακή","Δευτέρα","Τρίτη","Τετάρτη","Πέμπτη","Παρασκευή","Σάββατο"],dayNamesShort:["Κυρ","Δευ","Τρι","Τετ","Πεμ","Παρ","Σαβ"],dayNamesMin:["Κυ","Δε","Τρ","Τε","Πε","Πα","Σα"],weekHeader:"Εβδ",dateFormat:"dd/mm/yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("el",{buttonText:{month:"Μήνας",week:"Εβδομάδα",day:"Ημέρα",list:"Ατζέντα"},allDayText:"Ολοήμερο",eventLimitText:"περισσότερα"})});!function(a){"function"==typeof define&&define.amd?define(["jquery","moment"],a):a(jQuery,moment)}(function(a,b){function c(a,b,c,e){var f="";switch(c){case"s":return e?"muutaman sekunnin":"muutama sekunti";case"m":return e?"minuutin":"minuutti";case"mm":f=e?"minuutin":"minuuttia";break;case"h":return e?"tunnin":"tunti";case"hh":f=e?"tunnin":"tuntia";break;case"d":return e?"päivän":"päivä";case"dd":f=e?"päivän":"päivää";break;case"M":return e?"kuukauden":"kuukausi";case"MM":f=e?"kuukauden":"kuukautta";break;case"y":return e?"vuoden":"vuosi";case"yy":f=e?"vuoden":"vuotta"}return f=d(a,e)+" "+f}function d(a,b){return 10>a?b?f[a]:e[a]:a}var e="nolla yksi kaksi kolme neljä viisi kuusi seitsemän kahdeksan yhdeksän".split(" "),f=["nolla","yhden","kahden","kolmen","neljän","viiden","kuuden",e[7],e[8],e[9]];(b.defineLocale||b.lang).call(b,"fi",{months:"tammikuu_helmikuu_maaliskuu_huhtikuu_toukokuu_kesäkuu_heinäkuu_elokuu_syyskuu_lokakuu_marraskuu_joulukuu".split("_"),monthsShort:"tammi_helmi_maalis_huhti_touko_kesä_heinä_elo_syys_loka_marras_joulu".split("_"),weekdays:"sunnuntai_maanantai_tiistai_keskiviikko_torstai_perjantai_lauantai".split("_"),weekdaysShort:"su_ma_ti_ke_to_pe_la".split("_"),weekdaysMin:"su_ma_ti_ke_to_pe_la".split("_"),longDateFormat:{LT:"HH.mm",LTS:"HH.mm.ss",L:"DD.MM.YYYY",LL:"Do MMMM[ta] YYYY",LLL:"Do MMMM[ta] YYYY, [klo] LT",LLLL:"dddd, Do MMMM[ta] YYYY, [klo] LT",l:"D.M.YYYY",ll:"Do MMM YYYY",lll:"Do MMM YYYY, [klo] LT",llll:"ddd, Do MMM YYYY, [klo] LT"},calendar:{sameDay:"[tänään] [klo] LT",nextDay:"[huomenna] [klo] LT",nextWeek:"dddd [klo] LT",lastDay:"[eilen] [klo] LT",lastWeek:"[viime] dddd[na] [klo] LT",sameElse:"L"},relativeTime:{future:"%s päästä",past:"%s sitten",s:c,m:c,mm:c,h:c,hh:c,d:c,dd:c,M:c,MM:c,y:c,yy:c},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}}),a.fullCalendar.datepickerLang("fi","fi",{closeText:"Sulje",prevText:"«Edellinen",nextText:"Seuraava»",currentText:"Tänään",monthNames:["Tammikuu","Helmikuu","Maaliskuu","Huhtikuu","Toukokuu","Kesäkuu","Heinäkuu","Elokuu","Syyskuu","Lokakuu","Marraskuu","Joulukuu"],monthNamesShort:["Tammi","Helmi","Maalis","Huhti","Touko","Kesä","Heinä","Elo","Syys","Loka","Marras","Joulu"],dayNamesShort:["Su","Ma","Ti","Ke","To","Pe","La"],dayNames:["Sunnuntai","Maanantai","Tiistai","Keskiviikko","Torstai","Perjantai","Lauantai"],dayNamesMin:["Su","Ma","Ti","Ke","To","Pe","La"],weekHeader:"Vk",dateFormat:"d.m.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("fi",{buttonText:{month:"Kuukausi",week:"Viikko",day:"Päivä",list:"Tapahtumat"},allDayText:"Koko päivä",eventLimitText:"lisää"})});!function(a){"function"==typeof define&&define.amd?define(["jquery","moment"],a):a(jQuery,moment)}(function(a,b){(b.defineLocale||b.lang).call(b,"fr",{months:"janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre".split("_"),monthsShort:"janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.".split("_"),weekdays:"dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi".split("_"),weekdaysShort:"dim._lun._mar._mer._jeu._ven._sam.".split("_"),weekdaysMin:"Di_Lu_Ma_Me_Je_Ve_Sa".split("_"),longDateFormat:{LT:"HH:mm",LTS:"LT:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:"[Aujourd'hui à] LT",nextDay:"[Demain à] LT",nextWeek:"dddd [à] LT",lastDay:"[Hier à] LT",lastWeek:"dddd [dernier à] LT",sameElse:"L"},relativeTime:{future:"dans %s",past:"il y a %s",s:"quelques secondes",m:"une minute",mm:"%d minutes",h:"une heure",hh:"%d heures",d:"un jour",dd:"%d jours",M:"un mois",MM:"%d mois",y:"un an",yy:"%d ans"},ordinalParse:/\d{1,2}(er|)/,ordinal:function(a){return a+(1===a?"er":"")},week:{dow:1,doy:4}}),a.fullCalendar.datepickerLang("fr","fr",{closeText:"Fermer",prevText:"Précédent",nextText:"Suivant",currentText:"Aujourd'hui",monthNames:["janvier","février","mars","avril","mai","juin","juillet","août","septembre","octobre","novembre","décembre"],monthNamesShort:["janv.","févr.","mars","avr.","mai","juin","juil.","août","sept.","oct.","nov.","déc."],dayNames:["dimanche","lundi","mardi","mercredi","jeudi","vendredi","samedi"],dayNamesShort:["dim.","lun.","mar.","mer.","jeu.","ven.","sam."],dayNamesMin:["D","L","M","M","J","V","S"],weekHeader:"Sem.",dateFormat:"dd/mm/yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("fr",{buttonText:{month:"Mois",week:"Semaine",day:"Jour",list:"Mon planning"},allDayHtml:"Toute la
journée",eventLimitText:"en plus"})});!function(a){"function"==typeof define&&define.amd?define(["jquery","moment"],a):a(jQuery,moment)}(function(a,b){function c(a,b,c,d){var e=a;switch(c){case"s":return d||b?"néhány másodperc":"néhány másodperce";case"m":return"egy"+(d||b?" perc":" perce");case"mm":return e+(d||b?" perc":" perce");case"h":return"egy"+(d||b?" óra":" órája");case"hh":return e+(d||b?" óra":" órája");case"d":return"egy"+(d||b?" nap":" napja");case"dd":return e+(d||b?" nap":" napja");case"M":return"egy"+(d||b?" hónap":" hónapja");case"MM":return e+(d||b?" hónap":" hónapja");case"y":return"egy"+(d||b?" év":" éve");case"yy":return e+(d||b?" év":" éve")}return""}function d(a){return(a?"":"[múlt] ")+"["+e[this.day()]+"] LT[-kor]"}var e="vasárnap hétfőn kedden szerdán csütörtökön pénteken szombaton".split(" ");(b.defineLocale||b.lang).call(b,"hu",{months:"január_február_március_április_május_június_július_augusztus_szeptember_október_november_december".split("_"),monthsShort:"jan_feb_márc_ápr_máj_jún_júl_aug_szept_okt_nov_dec".split("_"),weekdays:"vasárnap_hétfő_kedd_szerda_csütörtök_péntek_szombat".split("_"),weekdaysShort:"vas_hét_kedd_sze_csüt_pén_szo".split("_"),weekdaysMin:"v_h_k_sze_cs_p_szo".split("_"),longDateFormat:{LT:"H:mm",LTS:"LT:ss",L:"YYYY.MM.DD.",LL:"YYYY. MMMM D.",LLL:"YYYY. MMMM D., LT",LLLL:"YYYY. MMMM D., dddd LT"},meridiemParse:/de|du/i,isPM:function(a){return"u"===a.charAt(1).toLowerCase()},meridiem:function(a,b,c){return 12>a?c===!0?"de":"DE":c===!0?"du":"DU"},calendar:{sameDay:"[ma] LT[-kor]",nextDay:"[holnap] LT[-kor]",nextWeek:function(){return d.call(this,!0)},lastDay:"[tegnap] LT[-kor]",lastWeek:function(){return d.call(this,!1)},sameElse:"L"},relativeTime:{future:"%s múlva",past:"%s",s:c,m:c,mm:c,h:c,hh:c,d:c,dd:c,M:c,MM:c,y:c,yy:c},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:7}}),a.fullCalendar.datepickerLang("hu","hu",{closeText:"bezár",prevText:"vissza",nextText:"előre",currentText:"ma",monthNames:["Január","Február","Március","Április","Május","Június","Július","Augusztus","Szeptember","Október","November","December"],monthNamesShort:["Jan","Feb","Már","Ápr","Máj","Jún","Júl","Aug","Szep","Okt","Nov","Dec"],dayNames:["Vasárnap","Hétfő","Kedd","Szerda","Csütörtök","Péntek","Szombat"],dayNamesShort:["Vas","Hét","Ked","Sze","Csü","Pén","Szo"],dayNamesMin:["V","H","K","Sze","Cs","P","Szo"],weekHeader:"Hét",dateFormat:"yy.mm.dd.",firstDay:1,isRTL:!1,showMonthAfterYear:!0,yearSuffix:""}),a.fullCalendar.lang("hu",{buttonText:{month:"Hónap",week:"Hét",day:"Nap",list:"Napló"},allDayText:"Egész nap",eventLimitText:"további"})});!function(a){"function"==typeof define&&define.amd?define(["jquery","moment"],a):a(jQuery,moment)}(function(a,b){(b.defineLocale||b.lang).call(b,"id",{months:"Januari_Februari_Maret_April_Mei_Juni_Juli_Agustus_September_Oktober_November_Desember".split("_"),monthsShort:"Jan_Feb_Mar_Apr_Mei_Jun_Jul_Ags_Sep_Okt_Nov_Des".split("_"),weekdays:"Minggu_Senin_Selasa_Rabu_Kamis_Jumat_Sabtu".split("_"),weekdaysShort:"Min_Sen_Sel_Rab_Kam_Jum_Sab".split("_"),weekdaysMin:"Mg_Sn_Sl_Rb_Km_Jm_Sb".split("_"),longDateFormat:{LT:"HH.mm",LTS:"LT.ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY [pukul] LT",LLLL:"dddd, D MMMM YYYY [pukul] LT"},meridiemParse:/pagi|siang|sore|malam/,meridiemHour:function(a,b){return 12===a&&(a=0),"pagi"===b?a:"siang"===b?a>=11?a:a+12:"sore"===b||"malam"===b?a+12:void 0},meridiem:function(a,b,c){return 11>a?"pagi":15>a?"siang":19>a?"sore":"malam"},calendar:{sameDay:"[Hari ini pukul] LT",nextDay:"[Besok pukul] LT",nextWeek:"dddd [pukul] LT",lastDay:"[Kemarin pukul] LT",lastWeek:"dddd [lalu pukul] LT",sameElse:"L"},relativeTime:{future:"dalam %s",past:"%s yang lalu",s:"beberapa detik",m:"semenit",mm:"%d menit",h:"sejam",hh:"%d jam",d:"sehari",dd:"%d hari",M:"sebulan",MM:"%d bulan",y:"setahun",yy:"%d tahun"},week:{dow:1,doy:7}}),a.fullCalendar.datepickerLang("id","id",{closeText:"Tutup",prevText:"<mundur",nextText:"maju>",currentText:"hari ini",monthNames:["Januari","Februari","Maret","April","Mei","Juni","Juli","Agustus","September","Oktober","Nopember","Desember"],monthNamesShort:["Jan","Feb","Mar","Apr","Mei","Jun","Jul","Agus","Sep","Okt","Nop","Des"],dayNames:["Minggu","Senin","Selasa","Rabu","Kamis","Jumat","Sabtu"],dayNamesShort:["Min","Sen","Sel","Rab","kam","Jum","Sab"],dayNamesMin:["Mg","Sn","Sl","Rb","Km","jm","Sb"],weekHeader:"Mg",dateFormat:"dd/mm/yy",firstDay:0,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("id",{buttonText:{month:"Bulan",week:"Minggu",day:"Hari",list:"Agenda"},allDayHtml:"Sehari
penuh",eventLimitText:"lebih"})});!function(a){"function"==typeof define&&define.amd?define(["jquery","moment"],a):a(jQuery,moment)}(function(a,b){(b.defineLocale||b.lang).call(b,"it",{months:"gennaio_febbraio_marzo_aprile_maggio_giugno_luglio_agosto_settembre_ottobre_novembre_dicembre".split("_"),monthsShort:"gen_feb_mar_apr_mag_giu_lug_ago_set_ott_nov_dic".split("_"),weekdays:"Domenica_Lunedì_Martedì_Mercoledì_Giovedì_Venerdì_Sabato".split("_"),weekdaysShort:"Dom_Lun_Mar_Mer_Gio_Ven_Sab".split("_"),weekdaysMin:"D_L_Ma_Me_G_V_S".split("_"),longDateFormat:{LT:"HH:mm",LTS:"LT:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd, D MMMM YYYY LT"},calendar:{sameDay:"[Oggi alle] LT",nextDay:"[Domani alle] LT",nextWeek:"dddd [alle] LT",lastDay:"[Ieri alle] LT",lastWeek:function(){switch(this.day()){case 0:return"[la scorsa] dddd [alle] LT";default:return"[lo scorso] dddd [alle] LT"}},sameElse:"L"},relativeTime:{future:function(a){return(/^[0-9].+$/.test(a)?"tra":"in")+" "+a},past:"%s fa",s:"alcuni secondi",m:"un minuto",mm:"%d minuti",h:"un'ora",hh:"%d ore",d:"un giorno",dd:"%d giorni",M:"un mese",MM:"%d mesi",y:"un anno",yy:"%d anni"},ordinalParse:/\d{1,2}º/,ordinal:"%dº",week:{dow:1,doy:4}}),a.fullCalendar.datepickerLang("it","it",{closeText:"Chiudi",prevText:"<Prec",nextText:"Succ>",currentText:"Oggi",monthNames:["Gennaio","Febbraio","Marzo","Aprile","Maggio","Giugno","Luglio","Agosto","Settembre","Ottobre","Novembre","Dicembre"],monthNamesShort:["Gen","Feb","Mar","Apr","Mag","Giu","Lug","Ago","Set","Ott","Nov","Dic"],dayNames:["Domenica","Lunedì","Martedì","Mercoledì","Giovedì","Venerdì","Sabato"],dayNamesShort:["Dom","Lun","Mar","Mer","Gio","Ven","Sab"],dayNamesMin:["Do","Lu","Ma","Me","Gi","Ve","Sa"],weekHeader:"Sm",dateFormat:"dd/mm/yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("it",{buttonText:{month:"Mese",week:"Settimana",day:"Giorno",list:"Agenda"},allDayHtml:"Tutto il
giorno",eventLimitText:function(a){return"+altri "+a}})});!function(a){"function"==typeof define&&define.amd?define(["jquery","moment"],a):a(jQuery,moment)}(function(a,b){(b.defineLocale||b.lang).call(b,"ja",{months:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),monthsShort:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),weekdays:"日曜日_月曜日_火曜日_水曜日_木曜日_金曜日_土曜日".split("_"),weekdaysShort:"日_月_火_水_木_金_土".split("_"),weekdaysMin:"日_月_火_水_木_金_土".split("_"),longDateFormat:{LT:"Ah時m分",LTS:"LTs秒",L:"YYYY/MM/DD",LL:"YYYY年M月D日",LLL:"YYYY年M月D日LT",LLLL:"YYYY年M月D日LT dddd"},meridiemParse:/午前|午後/i,isPM:function(a){return"午後"===a},meridiem:function(a,b,c){return 12>a?"午前":"午後"},calendar:{sameDay:"[今日] LT",nextDay:"[明日] LT",nextWeek:"[来週]dddd LT",lastDay:"[昨日] LT",lastWeek:"[前週]dddd LT",sameElse:"L"},relativeTime:{future:"%s後",past:"%s前",s:"数秒",m:"1分",mm:"%d分",h:"1時間",hh:"%d時間",d:"1日",dd:"%d日",M:"1ヶ月",MM:"%dヶ月",y:"1年",yy:"%d年"}}),a.fullCalendar.datepickerLang("ja","ja",{closeText:"閉じる",prevText:"<前",nextText:"次>",currentText:"今日",monthNames:["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],monthNamesShort:["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],dayNames:["日曜日","月曜日","火曜日","水曜日","木曜日","金曜日","土曜日"],dayNamesShort:["日","月","火","水","木","金","土"],dayNamesMin:["日","月","火","水","木","金","土"],weekHeader:"週",dateFormat:"yy/mm/dd",firstDay:0,isRTL:!1,showMonthAfterYear:!0,yearSuffix:"年"}),a.fullCalendar.lang("ja",{buttonText:{month:"月",week:"週",day:"日",list:"予定リスト"},allDayText:"終日",eventLimitText:function(a){return"他 "+a+" 件"}})});!function(a){"function"==typeof define&&define.amd?define(["jquery","moment"],a):a(jQuery,moment)}(function(a,b){var c="jan._feb._mrt._apr._mei_jun._jul._aug._sep._okt._nov._dec.".split("_"),d="jan_feb_mrt_apr_mei_jun_jul_aug_sep_okt_nov_dec".split("_");(b.defineLocale||b.lang).call(b,"nl",{months:"januari_februari_maart_april_mei_juni_juli_augustus_september_oktober_november_december".split("_"),monthsShort:function(a,b){return/-MMM-/.test(b)?d[a.month()]:c[a.month()]},weekdays:"zondag_maandag_dinsdag_woensdag_donderdag_vrijdag_zaterdag".split("_"),weekdaysShort:"zo._ma._di._wo._do._vr._za.".split("_"),weekdaysMin:"Zo_Ma_Di_Wo_Do_Vr_Za".split("_"),longDateFormat:{LT:"HH:mm",LTS:"LT:ss",L:"DD-MM-YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:"[vandaag om] LT",nextDay:"[morgen om] LT",nextWeek:"dddd [om] LT",lastDay:"[gisteren om] LT",lastWeek:"[afgelopen] dddd [om] LT",sameElse:"L"},relativeTime:{future:"over %s",past:"%s geleden",s:"een paar seconden",m:"één minuut",mm:"%d minuten",h:"één uur",hh:"%d uur",d:"één dag",dd:"%d dagen",M:"één maand",MM:"%d maanden",y:"één jaar",yy:"%d jaar"},ordinalParse:/\d{1,2}(ste|de)/,ordinal:function(a){return a+(1===a||8===a||a>=20?"ste":"de")},week:{dow:1,doy:4}}),a.fullCalendar.datepickerLang("nl","nl",{closeText:"Sluiten",prevText:"←",nextText:"→",currentText:"Vandaag",monthNames:["januari","februari","maart","april","mei","juni","juli","augustus","september","oktober","november","december"],monthNamesShort:["jan","feb","mrt","apr","mei","jun","jul","aug","sep","okt","nov","dec"],dayNames:["zondag","maandag","dinsdag","woensdag","donderdag","vrijdag","zaterdag"],dayNamesShort:["zon","maa","din","woe","don","vri","zat"],dayNamesMin:["zo","ma","di","wo","do","vr","za"],weekHeader:"Wk",dateFormat:"dd-mm-yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("nl",{buttonText:{month:"Maand",week:"Week",day:"Dag",list:"Agenda"},allDayText:"Hele dag",eventLimitText:"extra"})});!function(a){"function"==typeof define&&define.amd?define(["jquery","moment"],a):a(jQuery,moment)}(function(a,b){(b.defineLocale||b.lang).call(b,"nb",{months:"januar_februar_mars_april_mai_juni_juli_august_september_oktober_november_desember".split("_"),monthsShort:"jan_feb_mar_apr_mai_jun_jul_aug_sep_okt_nov_des".split("_"),weekdays:"søndag_mandag_tirsdag_onsdag_torsdag_fredag_lørdag".split("_"),weekdaysShort:"søn_man_tirs_ons_tors_fre_lør".split("_"),weekdaysMin:"sø_ma_ti_on_to_fr_lø".split("_"),longDateFormat:{LT:"H.mm",LTS:"LT.ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY [kl.] LT",LLLL:"dddd D. MMMM YYYY [kl.] LT"},calendar:{sameDay:"[i dag kl.] LT",nextDay:"[i morgen kl.] LT",nextWeek:"dddd [kl.] LT",lastDay:"[i går kl.] LT",lastWeek:"[forrige] dddd [kl.] LT",sameElse:"L"},relativeTime:{future:"om %s",past:"for %s siden",s:"noen sekunder",m:"ett minutt",mm:"%d minutter",h:"en time",hh:"%d timer",d:"en dag",dd:"%d dager",M:"en måned",MM:"%d måneder",y:"ett år",yy:"%d år"},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}}),a.fullCalendar.datepickerLang("nb","nb",{closeText:"Lukk",prevText:"«Forrige",nextText:"Neste»",currentText:"I dag",monthNames:["januar","februar","mars","april","mai","juni","juli","august","september","oktober","november","desember"],monthNamesShort:["jan","feb","mar","apr","mai","jun","jul","aug","sep","okt","nov","des"],dayNamesShort:["søn","man","tir","ons","tor","fre","lør"],dayNames:["søndag","mandag","tirsdag","onsdag","torsdag","fredag","lørdag"],dayNamesMin:["sø","ma","ti","on","to","fr","lø"],weekHeader:"Uke",dateFormat:"dd.mm.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("nb",{buttonText:{month:"Måned",week:"Uke",day:"Dag",list:"Agenda"},allDayText:"Hele dagen",eventLimitText:"til"})});!function(a){"function"==typeof define&&define.amd?define(["jquery","moment"],a):a(jQuery,moment)}(function(a,b){function c(a){return 5>a%10&&a%10>1&&~~(a/10)%10!==1}function d(a,b,d){var e=a+" ";switch(d){case"m":return b?"minuta":"minutę";case"mm":return e+(c(a)?"minuty":"minut");case"h":return b?"godzina":"godzinę";case"hh":return e+(c(a)?"godziny":"godzin");case"MM":return e+(c(a)?"miesiące":"miesięcy");case"yy":return e+(c(a)?"lata":"lat")}}var e="styczeń_luty_marzec_kwiecień_maj_czerwiec_lipiec_sierpień_wrzesień_październik_listopad_grudzień".split("_"),f="stycznia_lutego_marca_kwietnia_maja_czerwca_lipca_sierpnia_września_października_listopada_grudnia".split("_");(b.defineLocale||b.lang).call(b,"pl",{months:function(a,b){return/D MMMM/.test(b)?f[a.month()]:e[a.month()]},monthsShort:"sty_lut_mar_kwi_maj_cze_lip_sie_wrz_paź_lis_gru".split("_"),weekdays:"niedziela_poniedziałek_wtorek_środa_czwartek_piątek_sobota".split("_"),weekdaysShort:"nie_pon_wt_śr_czw_pt_sb".split("_"),weekdaysMin:"N_Pn_Wt_Śr_Cz_Pt_So".split("_"),longDateFormat:{LT:"HH:mm",LTS:"LT:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd, D MMMM YYYY LT"},calendar:{sameDay:"[Dziś o] LT",nextDay:"[Jutro o] LT",nextWeek:"[W] dddd [o] LT",lastDay:"[Wczoraj o] LT",lastWeek:function(){switch(this.day()){case 0:return"[W zeszłą niedzielę o] LT";case 3:return"[W zeszłą środę o] LT";case 6:return"[W zeszłą sobotę o] LT";default:return"[W zeszły] dddd [o] LT"}},sameElse:"L"},relativeTime:{future:"za %s",past:"%s temu",s:"kilka sekund",m:d,mm:d,h:d,hh:d,d:"1 dzień",dd:"%d dni",M:"miesiąc",MM:d,y:"rok",yy:d},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}}),a.fullCalendar.datepickerLang("pl","pl",{closeText:"Zamknij",prevText:"<Poprzedni",nextText:"Następny>",currentText:"Dziś",monthNames:["Styczeń","Luty","Marzec","Kwiecień","Maj","Czerwiec","Lipiec","Sierpień","Wrzesień","Październik","Listopad","Grudzień"],monthNamesShort:["Sty","Lu","Mar","Kw","Maj","Cze","Lip","Sie","Wrz","Pa","Lis","Gru"],dayNames:["Niedziela","Poniedziałek","Wtorek","Środa","Czwartek","Piątek","Sobota"],dayNamesShort:["Nie","Pn","Wt","Śr","Czw","Pt","So"],dayNamesMin:["N","Pn","Wt","Śr","Cz","Pt","So"],weekHeader:"Tydz",dateFormat:"dd.mm.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("pl",{buttonText:{month:"Miesiąc",week:"Tydzień",day:"Dzień",list:"Plan dnia"},allDayText:"Cały dzień",eventLimitText:"więcej"})});!function(a){"function"==typeof define&&define.amd?define(["jquery","moment"],a):a(jQuery,moment)}(function(a,b){(b.defineLocale||b.lang).call(b,"pt",{months:"janeiro_fevereiro_março_abril_maio_junho_julho_agosto_setembro_outubro_novembro_dezembro".split("_"),monthsShort:"jan_fev_mar_abr_mai_jun_jul_ago_set_out_nov_dez".split("_"),weekdays:"domingo_segunda-feira_terça-feira_quarta-feira_quinta-feira_sexta-feira_sábado".split("_"),weekdaysShort:"dom_seg_ter_qua_qui_sex_sáb".split("_"),weekdaysMin:"dom_2ª_3ª_4ª_5ª_6ª_sáb".split("_"),longDateFormat:{LT:"HH:mm",LTS:"LT:ss",L:"DD/MM/YYYY",LL:"D [de] MMMM [de] YYYY",LLL:"D [de] MMMM [de] YYYY LT",LLLL:"dddd, D [de] MMMM [de] YYYY LT"},calendar:{sameDay:"[Hoje às] LT",nextDay:"[Amanhã às] LT",nextWeek:"dddd [às] LT",lastDay:"[Ontem às] LT",lastWeek:function(){return 0===this.day()||6===this.day()?"[Último] dddd [às] LT":"[Última] dddd [às] LT"},sameElse:"L"},relativeTime:{future:"em %s",past:"há %s",s:"segundos",m:"um minuto",mm:"%d minutos",h:"uma hora",hh:"%d horas",d:"um dia",dd:"%d dias",M:"um mês",MM:"%d meses",y:"um ano",yy:"%d anos"},ordinalParse:/\d{1,2}º/,ordinal:"%dº",week:{dow:1,doy:4}}),a.fullCalendar.datepickerLang("pt","pt",{closeText:"Fechar",prevText:"Anterior",nextText:"Seguinte",currentText:"Hoje",monthNames:["Janeiro","Fevereiro","Março","Abril","Maio","Junho","Julho","Agosto","Setembro","Outubro","Novembro","Dezembro"],monthNamesShort:["Jan","Fev","Mar","Abr","Mai","Jun","Jul","Ago","Set","Out","Nov","Dez"],dayNames:["Domingo","Segunda-feira","Terça-feira","Quarta-feira","Quinta-feira","Sexta-feira","Sábado"],dayNamesShort:["Dom","Seg","Ter","Qua","Qui","Sex","Sáb"],dayNamesMin:["Dom","Seg","Ter","Qua","Qui","Sex","Sáb"],weekHeader:"Sem",dateFormat:"dd/mm/yy",firstDay:0,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("pt",{buttonText:{month:"Mês",week:"Semana",day:"Dia",list:"Agenda"},allDayText:"Todo o dia",eventLimitText:"mais"})});!function(a){"function"==typeof define&&define.amd?define(["jquery","moment"],a):a(jQuery,moment)}(function(a,b){(b.defineLocale||b.lang).call(b,"pt-br",{months:"janeiro_fevereiro_março_abril_maio_junho_julho_agosto_setembro_outubro_novembro_dezembro".split("_"),monthsShort:"jan_fev_mar_abr_mai_jun_jul_ago_set_out_nov_dez".split("_"),weekdays:"domingo_segunda-feira_terça-feira_quarta-feira_quinta-feira_sexta-feira_sábado".split("_"),weekdaysShort:"dom_seg_ter_qua_qui_sex_sáb".split("_"),weekdaysMin:"dom_2ª_3ª_4ª_5ª_6ª_sáb".split("_"),longDateFormat:{LT:"HH:mm",LTS:"LT:ss",L:"DD/MM/YYYY",LL:"D [de] MMMM [de] YYYY",LLL:"D [de] MMMM [de] YYYY [às] LT",LLLL:"dddd, D [de] MMMM [de] YYYY [às] LT"},calendar:{sameDay:"[Hoje às] LT",nextDay:"[Amanhã às] LT",nextWeek:"dddd [às] LT",lastDay:"[Ontem às] LT",lastWeek:function(){return 0===this.day()||6===this.day()?"[Último] dddd [às] LT":"[Última] dddd [às] LT"},sameElse:"L"},relativeTime:{future:"em %s",past:"%s atrás",s:"segundos",m:"um minuto",mm:"%d minutos",h:"uma hora",hh:"%d horas",d:"um dia",dd:"%d dias",M:"um mês",MM:"%d meses",y:"um ano",yy:"%d anos"},ordinalParse:/\d{1,2}º/,ordinal:"%dº"}),a.fullCalendar.datepickerLang("pt-br","pt-BR",{closeText:"Fechar",prevText:"<Anterior",nextText:"Próximo>",currentText:"Hoje",monthNames:["Janeiro","Fevereiro","Março","Abril","Maio","Junho","Julho","Agosto","Setembro","Outubro","Novembro","Dezembro"],monthNamesShort:["Jan","Fev","Mar","Abr","Mai","Jun","Jul","Ago","Set","Out","Nov","Dez"],dayNames:["Domingo","Segunda-feira","Terça-feira","Quarta-feira","Quinta-feira","Sexta-feira","Sábado"],dayNamesShort:["Dom","Seg","Ter","Qua","Qui","Sex","Sáb"],dayNamesMin:["Dom","Seg","Ter","Qua","Qui","Sex","Sáb"],weekHeader:"Sm",dateFormat:"dd/mm/yy",firstDay:0,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("pt-br",{buttonText:{month:"Mês",week:"Semana",day:"Dia",list:"Compromissos"},allDayText:"dia inteiro",eventLimitText:function(a){return"mais +"+a}})});!function(a){"function"==typeof define&&define.amd?define(["jquery","moment"],a):a(jQuery,moment)}(function(a,b){function c(a,b){var c=a.split("_");return b%10===1&&b%100!==11?c[0]:b%10>=2&&4>=b%10&&(10>b%100||b%100>=20)?c[1]:c[2]}function d(a,b,d){var e={mm:b?"минута_минуты_минут":"минуту_минуты_минут",hh:"час_часа_часов",dd:"день_дня_дней",MM:"месяц_месяца_месяцев",yy:"год_года_лет"};return"m"===d?b?"минута":"минуту":a+" "+c(e[d],+a)}function e(a,b){var c={nominative:"январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь".split("_"),accusative:"января_февраля_марта_апреля_мая_июня_июля_августа_сентября_октября_ноября_декабря".split("_")},d=/D[oD]?(\[[^\[\]]*\]|\s+)+MMMM?/.test(b)?"accusative":"nominative";return c[d][a.month()]}function f(a,b){var c={nominative:"янв_фев_март_апр_май_июнь_июль_авг_сен_окт_ноя_дек".split("_"),accusative:"янв_фев_мар_апр_мая_июня_июля_авг_сен_окт_ноя_дек".split("_")},d=/D[oD]?(\[[^\[\]]*\]|\s+)+MMMM?/.test(b)?"accusative":"nominative";return c[d][a.month()]}function g(a,b){var c={nominative:"воскресенье_понедельник_вторник_среда_четверг_пятница_суббота".split("_"),accusative:"воскресенье_понедельник_вторник_среду_четверг_пятницу_субботу".split("_")},d=/\[ ?[Вв] ?(?:прошлую|следующую|эту)? ?\] ?dddd/.test(b)?"accusative":"nominative";return c[d][a.day()]}(b.defineLocale||b.lang).call(b,"ru",{months:e,monthsShort:f,weekdays:g,weekdaysShort:"вс_пн_вт_ср_чт_пт_сб".split("_"),weekdaysMin:"вс_пн_вт_ср_чт_пт_сб".split("_"),monthsParse:[/^янв/i,/^фев/i,/^мар/i,/^апр/i,/^ма[й|я]/i,/^июн/i,/^июл/i,/^авг/i,/^сен/i,/^окт/i,/^ноя/i,/^дек/i],longDateFormat:{LT:"HH:mm",LTS:"LT:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY г.",LLL:"D MMMM YYYY г., LT",LLLL:"dddd, D MMMM YYYY г., LT"},calendar:{sameDay:"[Сегодня в] LT",nextDay:"[Завтра в] LT",lastDay:"[Вчера в] LT",nextWeek:function(){return 2===this.day()?"[Во] dddd [в] LT":"[В] dddd [в] LT"},lastWeek:function(a){if(a.week()===this.week())return 2===this.day()?"[Во] dddd [в] LT":"[В] dddd [в] LT";switch(this.day()){case 0:return"[В прошлое] dddd [в] LT";case 1:case 2:case 4:return"[В прошлый] dddd [в] LT";case 3:case 5:case 6:return"[В прошлую] dddd [в] LT"}},sameElse:"L"},relativeTime:{future:"через %s",past:"%s назад",s:"несколько секунд",m:d,mm:d,h:"час",hh:d,d:"день",dd:d,M:"месяц",MM:d,y:"год",yy:d},meridiemParse:/ночи|утра|дня|вечера/i,isPM:function(a){return/^(дня|вечера)$/.test(a)},meridiem:function(a,b,c){return 4>a?"ночи":12>a?"утра":17>a?"дня":"вечера"},ordinalParse:/\d{1,2}-(й|го|я)/,ordinal:function(a,b){switch(b){case"M":case"d":case"DDD":return a+"-й";case"D":return a+"-го";case"w":case"W":return a+"-я";default:return a}},week:{dow:1,doy:7}}),a.fullCalendar.datepickerLang("ru","ru",{closeText:"Закрыть",prevText:"<Пред",nextText:"След>",currentText:"Сегодня",monthNames:["Январь","Февраль","Март","Апрель","Май","Июнь","Июль","Август","Сентябрь","Октябрь","Ноябрь","Декабрь"],monthNamesShort:["Янв","Фев","Мар","Апр","Май","Июн","Июл","Авг","Сен","Окт","Ноя","Дек"],dayNames:["воскресенье","понедельник","вторник","среда","четверг","пятница","суббота"],dayNamesShort:["вск","пнд","втр","срд","чтв","птн","сбт"],dayNamesMin:["Вс","Пн","Вт","Ср","Чт","Пт","Сб"],weekHeader:"Нед",dateFormat:"dd.mm.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("ru",{buttonText:{month:"Месяц",week:"Неделя",day:"День",list:"Повестка дня"},allDayText:"Весь день",eventLimitText:function(a){return"+ ещё "+a}})});!function(a){"function"==typeof define&&define.amd?define(["jquery","moment"],a):a(jQuery,moment)}(function(a,b){(b.defineLocale||b.lang).call(b,"sv",{months:"januari_februari_mars_april_maj_juni_juli_augusti_september_oktober_november_december".split("_"),monthsShort:"jan_feb_mar_apr_maj_jun_jul_aug_sep_okt_nov_dec".split("_"),weekdays:"söndag_måndag_tisdag_onsdag_torsdag_fredag_lördag".split("_"),weekdaysShort:"sön_mån_tis_ons_tor_fre_lör".split("_"),weekdaysMin:"sö_må_ti_on_to_fr_lö".split("_"),longDateFormat:{LT:"HH:mm",LTS:"LT:ss",L:"YYYY-MM-DD",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:"[Idag] LT",nextDay:"[Imorgon] LT",lastDay:"[Igår] LT",nextWeek:"dddd LT",lastWeek:"[Förra] dddd[en] LT",sameElse:"L"},relativeTime:{future:"om %s",past:"för %s sedan",s:"några sekunder",m:"en minut",mm:"%d minuter",h:"en timme",hh:"%d timmar",d:"en dag",dd:"%d dagar",M:"en månad",MM:"%d månader",y:"ett år",yy:"%d år"},ordinalParse:/\d{1,2}(e|a)/,ordinal:function(a){var b=a%10,c=1===~~(a%100/10)?"e":1===b?"a":2===b?"a":"e";return a+c},week:{dow:1,doy:4}}),a.fullCalendar.datepickerLang("sv","sv",{closeText:"Stäng",prevText:"«Förra",nextText:"Nästa»",currentText:"Idag",monthNames:["Januari","Februari","Mars","April","Maj","Juni","Juli","Augusti","September","Oktober","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","Maj","Jun","Jul","Aug","Sep","Okt","Nov","Dec"],dayNamesShort:["Sön","Mån","Tis","Ons","Tor","Fre","Lör"],dayNames:["Söndag","Måndag","Tisdag","Onsdag","Torsdag","Fredag","Lördag"],dayNamesMin:["Sö","Må","Ti","On","To","Fr","Lö"],weekHeader:"Ve",dateFormat:"yy-mm-dd",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("sv",{buttonText:{month:"Månad",week:"Vecka",day:"Dag",list:"Program"},allDayText:"Heldag",eventLimitText:"till"})});!function(a){"function"==typeof define&&define.amd?define(["jquery","moment"],a):a(jQuery,moment)}(function(a,b){var c={words:{m:["jedan minut","jedne minute"],mm:["minut","minute","minuta"],h:["jedan sat","jednog sata"],hh:["sat","sata","sati"],dd:["dan","dana","dana"],MM:["mesec","meseca","meseci"],yy:["godina","godine","godina"]},correctGrammaticalCase:function(a,b){return 1===a?b[0]:a>=2&&4>=a?b[1]:b[2]},translate:function(a,b,d){var e=c.words[d];return 1===d.length?b?e[0]:e[1]:a+" "+c.correctGrammaticalCase(a,e)}};(b.defineLocale||b.lang).call(b,"sr",{months:["januar","februar","mart","april","maj","jun","jul","avgust","septembar","oktobar","novembar","decembar"],monthsShort:["jan.","feb.","mar.","apr.","maj","jun","jul","avg.","sep.","okt.","nov.","dec."],weekdays:["nedelja","ponedeljak","utorak","sreda","četvrtak","petak","subota"],weekdaysShort:["ned.","pon.","uto.","sre.","čet.","pet.","sub."],weekdaysMin:["ne","po","ut","sr","če","pe","su"],longDateFormat:{LT:"H:mm",LTS:"LT:ss",L:"DD. MM. YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY LT",LLLL:"dddd, D. MMMM YYYY LT"},calendar:{sameDay:"[danas u] LT",nextDay:"[sutra u] LT",nextWeek:function(){switch(this.day()){case 0:return"[u] [nedelju] [u] LT";case 3:return"[u] [sredu] [u] LT";case 6:return"[u] [subotu] [u] LT";case 1:case 2:case 4:case 5:return"[u] dddd [u] LT"}},lastDay:"[juče u] LT",lastWeek:function(){var a=["[prošle] [nedelje] [u] LT","[prošlog] [ponedeljka] [u] LT","[prošlog] [utorka] [u] LT","[prošle] [srede] [u] LT","[prošlog] [četvrtka] [u] LT","[prošlog] [petka] [u] LT","[prošle] [subote] [u] LT"];return a[this.day()]},sameElse:"L"},relativeTime:{future:"za %s",past:"pre %s",s:"nekoliko sekundi",m:c.translate,mm:c.translate,h:c.translate,hh:c.translate,d:"dan",dd:c.translate,M:"mesec",MM:c.translate,y:"godinu",yy:c.translate},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:7}}),a.fullCalendar.datepickerLang("sr","sr",{closeText:"Затвори",prevText:"<",nextText:">",currentText:"Данас",monthNames:["Јануар","Фебруар","Март","Април","Мај","Јун","Јул","Август","Септембар","Октобар","Новембар","Децембар"],monthNamesShort:["Јан","Феб","Мар","Апр","Мај","Јун","Јул","Авг","Сеп","Окт","Нов","Дец"],dayNames:["Недеља","Понедељак","Уторак","Среда","Четвртак","Петак","Субота"],dayNamesShort:["Нед","Пон","Уто","Сре","Чет","Пет","Суб"],dayNamesMin:["Не","По","Ут","Ср","Че","Пе","Су"],weekHeader:"Сед",dateFormat:"dd.mm.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("sr",{buttonText:{month:"Месец",week:"Недеља",day:"Дан",list:"Планер"},allDayText:"Цео дан",eventLimitText:function(a){return"+ још "+a}})});!function(a){"function"==typeof define&&define.amd?define(["jquery","moment"],a):a(jQuery,moment)}(function(a,b){(b.defineLocale||b.lang).call(b,"th",{months:"มกราคม_กุมภาพันธ์_มีนาคม_เมษายน_พฤษภาคม_มิถุนายน_กรกฎาคม_สิงหาคม_กันยายน_ตุลาคม_พฤศจิกายน_ธันวาคม".split("_"),monthsShort:"มกรา_กุมภา_มีนา_เมษา_พฤษภา_มิถุนา_กรกฎา_สิงหา_กันยา_ตุลา_พฤศจิกา_ธันวา".split("_"),weekdays:"อาทิตย์_จันทร์_อังคาร_พุธ_พฤหัสบดี_ศุกร์_เสาร์".split("_"),weekdaysShort:"อาทิตย์_จันทร์_อังคาร_พุธ_พฤหัส_ศุกร์_เสาร์".split("_"),weekdaysMin:"อา._จ._อ._พ._พฤ._ศ._ส.".split("_"),longDateFormat:{LT:"H นาฬิกา m นาที",LTS:"LT s วินาที",L:"YYYY/MM/DD",LL:"D MMMM YYYY",LLL:"D MMMM YYYY เวลา LT",LLLL:"วันddddที่ D MMMM YYYY เวลา LT"},meridiemParse:/ก่อนเที่ยง|หลังเที่ยง/,isPM:function(a){return"หลังเที่ยง"===a},meridiem:function(a,b,c){return 12>a?"ก่อนเที่ยง":"หลังเที่ยง"},calendar:{sameDay:"[วันนี้ เวลา] LT",nextDay:"[พรุ่งนี้ เวลา] LT",nextWeek:"dddd[หน้า เวลา] LT",lastDay:"[เมื่อวานนี้ เวลา] LT",lastWeek:"[วัน]dddd[ที่แล้ว เวลา] LT",sameElse:"L"},relativeTime:{future:"อีก %s",past:"%sที่แล้ว",s:"ไม่กี่วินาที",m:"1 นาที",mm:"%d นาที",h:"1 ชั่วโมง",hh:"%d ชั่วโมง",d:"1 วัน",dd:"%d วัน",M:"1 เดือน",MM:"%d เดือน",y:"1 ปี",yy:"%d ปี"}}),a.fullCalendar.datepickerLang("th","th",{closeText:"ปิด",prevText:"« ย้อน",nextText:"ถัดไป »",currentText:"วันนี้",monthNames:["มกราคม","กุมภาพันธ์","มีนาคม","เมษายน","พฤษภาคม","มิถุนายน","กรกฎาคม","สิงหาคม","กันยายน","ตุลาคม","พฤศจิกายน","ธันวาคม"],monthNamesShort:["ม.ค.","ก.พ.","มี.ค.","เม.ย.","พ.ค.","มิ.ย.","ก.ค.","ส.ค.","ก.ย.","ต.ค.","พ.ย.","ธ.ค."],dayNames:["อาทิตย์","จันทร์","อังคาร","พุธ","พฤหัสบดี","ศุกร์","เสาร์"],dayNamesShort:["อา.","จ.","อ.","พ.","พฤ.","ศ.","ส."],dayNamesMin:["อา.","จ.","อ.","พ.","พฤ.","ศ.","ส."],weekHeader:"Wk",dateFormat:"dd/mm/yy",firstDay:0,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("th",{buttonText:{month:"เดือน",week:"สัปดาห์",day:"วัน",list:"แผนงาน"},allDayText:"ตลอดวัน",eventLimitText:"เพิ่มเติม"})});!function(a){"function"==typeof define&&define.amd?define(["jquery","moment"],a):a(jQuery,moment)}(function(a,b){var c={1:"'inci",5:"'inci",8:"'inci",70:"'inci",80:"'inci",2:"'nci",7:"'nci",20:"'nci",50:"'nci",3:"'üncü",4:"'üncü",100:"'üncü",6:"'ncı",9:"'uncu",10:"'uncu",30:"'uncu",60:"'ıncı",90:"'ıncı"};(b.defineLocale||b.lang).call(b,"tr",{months:"Ocak_Şubat_Mart_Nisan_Mayıs_Haziran_Temmuz_Ağustos_Eylül_Ekim_Kasım_Aralık".split("_"),monthsShort:"Oca_Şub_Mar_Nis_May_Haz_Tem_Ağu_Eyl_Eki_Kas_Ara".split("_"),weekdays:"Pazar_Pazartesi_Salı_Çarşamba_Perşembe_Cuma_Cumartesi".split("_"),weekdaysShort:"Paz_Pts_Sal_Çar_Per_Cum_Cts".split("_"),weekdaysMin:"Pz_Pt_Sa_Ça_Pe_Cu_Ct".split("_"),longDateFormat:{LT:"HH:mm",LTS:"LT:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd, D MMMM YYYY LT"},calendar:{sameDay:"[bugün saat] LT",nextDay:"[yarın saat] LT",nextWeek:"[haftaya] dddd [saat] LT",lastDay:"[dün] LT",lastWeek:"[geçen hafta] dddd [saat] LT",sameElse:"L"},relativeTime:{future:"%s sonra",past:"%s önce",s:"birkaç saniye",m:"bir dakika",mm:"%d dakika",h:"bir saat",hh:"%d saat",d:"bir gün",dd:"%d gün",M:"bir ay",MM:"%d ay",y:"bir yıl",yy:"%d yıl"},ordinalParse:/\d{1,2}'(inci|nci|üncü|ncı|uncu|ıncı)/,ordinal:function(a){if(0===a)return a+"'ıncı";var b=a%10,d=a%100-b,e=a>=100?100:null;return a+(c[b]||c[d]||c[e])},week:{dow:1,doy:7}}),a.fullCalendar.datepickerLang("tr","tr",{closeText:"kapat",prevText:"<geri",nextText:"ileri>",currentText:"bugün",monthNames:["Ocak","Şubat","Mart","Nisan","Mayıs","Haziran","Temmuz","Ağustos","Eylül","Ekim","Kasım","Aralık"],monthNamesShort:["Oca","Şub","Mar","Nis","May","Haz","Tem","Ağu","Eyl","Eki","Kas","Ara"],dayNames:["Pazar","Pazartesi","Salı","Çarşamba","Perşembe","Cuma","Cumartesi"],dayNamesShort:["Pz","Pt","Sa","Ça","Pe","Cu","Ct"],dayNamesMin:["Pz","Pt","Sa","Ça","Pe","Cu","Ct"],weekHeader:"Hf",dateFormat:"dd.mm.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("tr",{buttonText:{next:"ileri",month:"Ay",week:"Hafta",day:"Gün",list:"Ajanda"},allDayText:"Tüm gün",eventLimitText:"daha fazla"})});!function(a){"function"==typeof define&&define.amd?define(["jquery","moment"],a):a(jQuery,moment)}(function(a,b){(b.defineLocale||b.lang).call(b,"zh-cn",{months:"一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月".split("_"),monthsShort:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),weekdays:"星期日_星期一_星期二_星期三_星期四_星期五_星期六".split("_"),weekdaysShort:"周日_周一_周二_周三_周四_周五_周六".split("_"),weekdaysMin:"日_一_二_三_四_五_六".split("_"),longDateFormat:{LT:"Ah点mm",LTS:"Ah点m分s秒",L:"YYYY-MM-DD",LL:"YYYY年MMMD日",LLL:"YYYY年MMMD日LT",LLLL:"YYYY年MMMD日ddddLT",l:"YYYY-MM-DD",ll:"YYYY年MMMD日",lll:"YYYY年MMMD日LT",llll:"YYYY年MMMD日ddddLT"},meridiemParse:/凌晨|早上|上午|中午|下午|晚上/,meridiemHour:function(a,b){return 12===a&&(a=0),"凌晨"===b||"早上"===b||"上午"===b?a:"下午"===b||"晚上"===b?a+12:a>=11?a:a+12},meridiem:function(a,b,c){var d=100*a+b;return 600>d?"凌晨":900>d?"早上":1130>d?"上午":1230>d?"中午":1800>d?"下午":"晚上"},calendar:{sameDay:function(){return 0===this.minutes()?"[今天]Ah[点整]":"[今天]LT"},nextDay:function(){return 0===this.minutes()?"[明天]Ah[点整]":"[明天]LT"},lastDay:function(){return 0===this.minutes()?"[昨天]Ah[点整]":"[昨天]LT"},nextWeek:function(){var a,c;return a=b().startOf("week"),c=this.unix()-a.unix()>=604800?"[下]":"[本]",0===this.minutes()?c+"dddAh点整":c+"dddAh点mm"},lastWeek:function(){var a,c;return a=b().startOf("week"),c=this.unix()0};t.prototype.open=function(z){var y=this;y.app.dropdown.close();$.get(z,function(A){$("body").prepend('
'+A+"
");y.app.refresh();y.router.dispatch(this.app);y.afterOpen()})};t.prototype.close=function(y){if(this.isOpen()){if(y){y.preventDefault()}$("#popover-container").remove()}};t.prototype.onClick=function(A){A.preventDefault();A.stopPropagation();var z=A.currentTarget||A.target;var y=z.getAttribute("href");if(!y){y=z.getAttribute("data-href")}if(y){this.open(y)}};t.prototype.listen=function(){$(document).on("click",".popover",this.onClick.bind(this));$(document).on("click",".close-popover",this.close.bind(this));$(document).on("click","#popover-container",this.close.bind(this));$(document).on("click","#popover-content",function(y){y.stopPropagation()})};t.prototype.afterOpen=function(){var z=this;var y=$("#popover-content .popover-form");if(y){y.on("submit",function(A){A.preventDefault();$.ajax({type:"POST",url:y.attr("action"),data:y.serialize(),success:function(C,D,B){z.afterSubmit(C,B,z)}})})}$(document).on("click",".popover-link",function(A){A.preventDefault();$.ajax({type:"GET",url:$(this).attr("href"),success:function(C,D,B){z.afterSubmit(C,B,z)}})})};t.prototype.afterSubmit=function(A,z,y){var B=z.getResponseHeader("X-Ajax-Redirect");if(B){window.location=B==="self"?window.location.href.split("#")[0]:B}else{$("#popover-content").html(A);$("#popover-content input[autofocus]").focus();y.afterOpen()}};function r(){}r.prototype.listen=function(){var y=this;$(document).on("click",function(){y.close()});$(document).on("click",".dropdown-menu",function(C){C.preventDefault();C.stopImmediatePropagation();y.close();var A=$(this).next("ul");var D=$(this).offset();$("body").append(jQuery("
",{id:"dropdown"}));A.clone().appendTo("#dropdown");var E=$("#dropdown ul");E.addClass("dropdown-submenu-open");var B=E.outerHeight();var z=E.outerWidth();if(D.top+B-$(window).scrollTop()<$(window).height()||$(window).scrollTop()+D.top$(window).width()){E.css("left",D.left-z+$(this).outerWidth())}else{E.css("left",D.left)}});$(document).on("click",".dropdown-submenu-open li",function(z){if($(z.target).is("li")){$(this).find("a:visible")[0].click()}});$("textarea[data-mention-search-url]").textcomplete([{match:/(^|\s)@(\w*)$/,search:function(A,B){var z=$("textarea[data-mention-search-url]").data("mention-search-url");$.getJSON(z,{q:A}).done(function(C){B(C)}).fail(function(){B([])})},replace:function(z){return"$1@"+z+" "},cache:true}],{className:"textarea-dropdown"})};r.prototype.close=function(){$("#dropdown").remove()};function q(y){this.app=y}q.prototype.listen=function(){var y=this;$(".tooltip").tooltip({track:false,show:false,hide:false,position:{my:"left-20 top",at:"center bottom+9",using:function(z,A){$(this).css(z);var B=A.target.left+A.target.width/2-A.element.left-20;$("
").addClass("tooltip-arrow").addClass(A.vertical).addClass(B<1?"align-left":"align-right").appendTo(this)}},content:function(){var B=this;var z=$(this).attr("data-href");if(!z){return'
'+$(this).attr("title")+"
"}$.get(z,function A(E){var D=$(".ui-tooltip:visible");$(".ui-tooltip-content:visible").html(E);D.css({top:"",left:""});D.children(".tooltip-arrow").remove();var C=$(B).tooltip("option","position");C.of=$(B);D.position(C)});return''}}).on("mouseenter",function(){var z=this;$(this).tooltip("open");$(".ui-tooltip").on("mouseleave",function(){$(z).tooltip("close")})}).on("mouseleave focusout",function(z){z.stopImmediatePropagation();var A=this;setTimeout(function(){if(!$(".ui-tooltip:hover").length){$(A).tooltip("close")}},100)})};function l(){}l.prototype.showPreview=function(C){C.preventDefault();var z=$(".write-area");var B=$(".preview-area");var y=$("textarea");$("#markdown-write").parent().removeClass("form-tab-selected");$("#markdown-preview").parent().addClass("form-tab-selected");var A=$.ajax({url:$("body").data("markdown-preview-url"),contentType:"application/json",type:"POST",processData:false,dataType:"html",data:JSON.stringify({text:y.val()})});A.done(function(D){B.find(".markdown").html(D);B.css("height",y.css("height"));B.css("width",y.css("width"));z.hide();B.show()})};l.prototype.showWriter=function(y){y.preventDefault();$("#markdown-write").parent().addClass("form-tab-selected");$("#markdown-preview").parent().removeClass("form-tab-selected");$(".write-area").show();$(".preview-area").hide()};l.prototype.listen=function(){$(document).on("click","#markdown-preview",this.showPreview.bind(this));$(document).on("click","#markdown-write",this.showWriter.bind(this))};function f(y){this.app=y;this.keyboardShortcuts()}f.prototype.focus=function(){$(document).on("focus","#form-search",function(){if($("#form-search")[0].setSelectionRange){$("#form-search")[0].setSelectionRange($("#form-search").val().length,$("#form-search").val().length)}})};f.prototype.listen=function(){var y=this;$(document).on("click",".filter-helper",function(B){B.preventDefault();var A=$(this).data("filter");var z=$(this).data("append-filter");if(z){A=$("#form-search").val()+" "+z}$("#form-search").val(A);if($("#board").length){y.app.board.reloadFilters(A)}else{$("form.search").submit()}})};f.prototype.keyboardShortcuts=function(){var y=this;Mousetrap.bind("v o",function(A){var z=$(".view-overview");if(z.length){window.location=z.attr("href")}});Mousetrap.bind("v b",function(A){var z=$(".view-board");if(z.length){window.location=z.attr("href")}});Mousetrap.bind("v c",function(A){var z=$(".view-calendar");if(z.length){window.location=z.attr("href")}});Mousetrap.bind("v l",function(A){var z=$(".view-listing");if(z.length){window.location=z.attr("href")}});Mousetrap.bind("v g",function(A){var z=$(".view-gantt");if(z.length){window.location=z.attr("href")}});Mousetrap.bind("f",function(A){A.preventDefault();var z=document.getElementById("form-search");if(z){z.focus()}});Mousetrap.bind("r",function(A){A.preventDefault();var z=$(".filter-reset").data("filter");$("#form-search").val(z);if($("#board").length){y.app.board.reloadFilters(z)}else{$("form.search").submit()}})};function m(){this.board=new k(this);this.markdown=new l();this.search=new f(this);this.swimlane=new g();this.dropdown=new r();this.tooltip=new q(this);this.popover=new t(this);this.task=new a();this.project=new n();this.subtask=new e(this);this.file=new v(this);this.keyboardShortcuts();this.chosen();this.poll();$(".alert-fade-out").delay(4000).fadeOut(800,function(){$(this).remove()});var y=false;$("select.task-reload-project-destination").change(function(){if(!y){$(".loading-icon").show();y=true;window.location=$(this).data("redirect").replace(/PROJECT_ID/g,$(this).val())}})}m.prototype.listen=function(){this.project.listen();this.popover.listen();this.markdown.listen();this.tooltip.listen();this.dropdown.listen();this.search.listen();this.task.listen();this.swimlane.listen();this.subtask.listen();this.file.listen();this.search.focus();this.autoComplete();this.datePicker();this.focus()};m.prototype.refresh=function(){$(document).off();this.listen()};m.prototype.focus=function(){$("[autofocus]").each(function(y,z){$(this).focus()});$(document).on("focus",".auto-select",function(){$(this).select()});$(document).on("mouseup",".auto-select",function(y){y.preventDefault()})};m.prototype.poll=function(){window.setInterval(this.checkSession,60000)};m.prototype.keyboardShortcuts=function(){var y=this;Mousetrap.bindGlobal("mod+enter",function(){$("form").submit()});Mousetrap.bind("b",function(z){z.preventDefault();$("#board-selector").trigger("chosen:open")});Mousetrap.bindGlobal("esc",function(){y.popover.close();y.dropdown.close()})};m.prototype.checkSession=function(){if(!$(".form-login").length){$.ajax({cache:false,url:$("body").data("status-url"),statusCode:{401:function(){window.location=$("body").data("login-url")}}})}};m.prototype.datePicker=function(){$.datepicker.setDefaults($.datepicker.regional[$("body").data("js-lang")]);$(".form-date").datepicker({showOtherMonths:true,selectOtherMonths:true,dateFormat:"yy-mm-dd",constrainInput:false});$(".form-datetime").datetimepicker({controlType:"select",oneLine:true,dateFormat:"yy-mm-dd",constrainInput:false})};m.prototype.autoComplete=function(){$(".autocomplete").each(function(){var z=$(this);var A=z.data("dst-field");var y=z.data("dst-extra-field");if($("#form-"+A).val()==""){z.parent().find("input[type=submit]").attr("disabled","disabled")}z.autocomplete({source:z.data("search-url"),minLength:1,select:function(B,C){$("input[name="+A+"]").val(C.item.id);if(y){$("input[name="+y+"]").val(C.item[y])}z.parent().find("input[type=submit]").removeAttr("disabled")}})})};m.prototype.chosen=function(){$(".chosen-select").each(function(){var y=$(this).data("search-threshold");if(y===undefined){y=10}$(this).chosen({width:"180px",no_results_text:$(this).data("notfound"),disable_search_threshold:y})});$(".select-auto-redirect").change(function(){var y=new RegExp($(this).data("redirect-regex"),"g");window.location=$(this).data("redirect-url").replace(y,$(this).val())})};m.prototype.showLoadingIcon=function(){$("body").append(' ')};m.prototype.hideLoadingIcon=function(){$("#app-loading-icon").remove()};m.prototype.isVisible=function(){var y="";if(typeof document.hidden!=="undefined"){y="visibilityState"}else{if(typeof document.mozHidden!=="undefined"){y="mozVisibilityState"}else{if(typeof document.msHidden!=="undefined"){y="msVisibilityState"}else{if(typeof document.webkitHidden!=="undefined"){y="webkitVisibilityState"}}}}if(y!=""){return document[y]=="visible"}return true};m.prototype.formatDuration=function(y){if(y>=86400){return Math.round(y/86400)+"d"}else{if(y>=3600){return Math.round(y/3600)+"h"}else{if(y>=60){return Math.round(y/60)+"m"}}}return y+"s"};function d(){this.pasteCatcher=null}d.prototype.execute=function(){this.initialize()};d.prototype.initialize=function(){this.destroy();if(!window.Clipboard){this.pasteCatcher=document.createElement("div");this.pasteCatcher.id="screenshot-pastezone";this.pasteCatcher.contentEditable="true";this.pasteCatcher.style.opacity=0;this.pasteCatcher.style.position="fixed";this.pasteCatcher.style.top=0;this.pasteCatcher.style.right=0;this.pasteCatcher.style.width=0;document.body.insertBefore(this.pasteCatcher,document.body.firstChild);this.pasteCatcher.focus();document.addEventListener("click",this.setFocus.bind(this));document.getElementById("screenshot-zone").addEventListener("click",this.setFocus.bind(this))}window.addEventListener("paste",this.pasteHandler.bind(this))};d.prototype.destroy=function(){if(this.pasteCatcher!=null){document.body.removeChild(this.pasteCatcher)}else{if(document.getElementById("screenshot-pastezone")){document.body.removeChild(document.getElementById("screenshot-pastezone"))}}document.removeEventListener("click",this.setFocus.bind(this));this.pasteCatcher=null};d.prototype.setFocus=function(){if(this.pasteCatcher!==null){this.pasteCatcher.focus()}};d.prototype.pasteHandler=function(D){if(D.clipboardData&&D.clipboardData.items){var B=D.clipboardData.items;if(B){for(var C=0;C0){$("#file-upload-button").prop("disabled",false);$("#file-dropzone-inner").hide();var C=jQuery("
- + e($column['title']) ?> '> diff --git a/app/Template/project_overview/files.php b/app/Template/project_overview/files.php index 03835f6b..7eb8c762 100644 --- a/app/Template/project_overview/files.php +++ b/app/Template/project_overview/files.php @@ -67,7 +67,7 @@ file->getPreviewType($file['name']) !== null): ?>
  • - url->link(t('View'), 'FileViewer', 'show', array('project_id' => $project['id'], 'file_id' => $file['id']), false, 'popover') ?> + url->link(t('View file'), 'FileViewer', 'show', array('project_id' => $project['id'], 'file_id' => $file['id']), false, 'popover') ?>
  • diff --git a/app/Template/subtask/table.php b/app/Template/subtask/table.php index 5db23245..13d2c7cc 100644 --- a/app/Template/subtask/table.php +++ b/app/Template/subtask/table.php @@ -18,7 +18,7 @@
  • - + subtask->toggleStatus($subtask, $task['project_id'], true) ?> subtask->getTitle($subtask) ?> diff --git a/app/Template/task_file/show.php b/app/Template/task_file/show.php index 8aa76520..c3f2bb98 100644 --- a/app/Template/task_file/show.php +++ b/app/Template/task_file/show.php @@ -57,7 +57,7 @@ file->getPreviewType($file['name']) !== null): ?>
  • - url->link(t('View'), 'FileViewer', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'], 'file_id' => $file['id']), false, 'popover') ?> + url->link(t('View file'), 'FileViewer', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'], 'file_id' => $file['id']), false, 'popover') ?>
  • -- cgit v1.2.3 From fc468088c3b39bc4e9d185683442db1d36b61e23 Mon Sep 17 00:00:00 2001 From: Frederic Guillot Date: Sat, 20 Feb 2016 15:08:18 -0500 Subject: Split Board model into multiple classes --- ChangeLog | 1 + app/Action/CommentCreationMoveTaskColumn.php | 2 +- app/Action/TaskDuplicateAnotherProject.php | 2 +- app/Analytic/AverageTimeSpentColumnAnalytic.php | 2 +- app/Analytic/TaskDistributionAnalytic.php | 2 +- app/Api/Board.php | 35 ---- app/Api/Column.php | 42 ++++ app/Controller/Action.php | 4 +- app/Controller/BoardPopover.php | 4 +- app/Controller/Column.php | 16 +- app/Controller/Gantt.php | 2 +- app/Controller/Task.php | 4 +- app/Controller/Taskcreation.php | 2 +- app/Controller/Taskduplication.php | 2 +- app/Formatter/TaskFilterGanttFormatter.php | 2 +- app/Helper/Task.php | 2 +- app/Model/ActionParameter.php | 4 +- app/Model/Board.php | 268 +----------------------- app/Model/Column.php | 145 +++++++++++++ app/Model/Project.php | 4 +- app/Model/ProjectDailyColumnStats.php | 2 +- app/Model/TaskAnalytic.php | 2 +- app/Model/TaskCreation.php | 2 +- app/Model/TaskDuplication.php | 8 +- app/Model/TaskFilter.php | 2 +- app/Model/TaskFinder.php | 10 +- app/Model/TaskImport.php | 2 +- app/Model/TaskLink.php | 6 +- app/Model/Transition.php | 8 +- app/Subscriber/RecurringTaskSubscriber.php | 4 +- jsonrpc.php | 2 + tests/integration/ApiTest.php | 70 ------- tests/integration/BoardTest.php | 21 ++ tests/integration/ColumnTest.php | 65 ++++++ tests/units/Model/ActionTest.php | 6 +- tests/units/Model/BoardTest.php | 227 +------------------- tests/units/Model/ColumnTest.php | 168 +++++++++++++++ tests/units/Model/ProjectTest.php | 2 - tests/units/Model/TaskPositionTest.php | 14 +- 39 files changed, 511 insertions(+), 655 deletions(-) create mode 100644 app/Api/Column.php create mode 100644 tests/integration/BoardTest.php create mode 100644 tests/integration/ColumnTest.php (limited to 'app/Controller/Column.php') diff --git a/ChangeLog b/ChangeLog index ae7919bf..190a57ad 100644 --- a/ChangeLog +++ b/ChangeLog @@ -16,6 +16,7 @@ Improvements: * Improve image thumbnails and files table * Add confirmation inline popup to remove custom filter * Increase client_max_body_size value for Nginx +* Split Board model into multiple classes Bug fixes: diff --git a/app/Action/CommentCreationMoveTaskColumn.php b/app/Action/CommentCreationMoveTaskColumn.php index 4473cf91..11224d67 100644 --- a/app/Action/CommentCreationMoveTaskColumn.php +++ b/app/Action/CommentCreationMoveTaskColumn.php @@ -71,7 +71,7 @@ class CommentCreationMoveTaskColumn extends Base return false; } - $column = $this->board->getColumn($data['column_id']); + $column = $this->column->getById($data['column_id']); return (bool) $this->comment->create(array( 'comment' => t('Moved to column %s', $column['title']), diff --git a/app/Action/TaskDuplicateAnotherProject.php b/app/Action/TaskDuplicateAnotherProject.php index 5bcdce08..5f05136e 100644 --- a/app/Action/TaskDuplicateAnotherProject.php +++ b/app/Action/TaskDuplicateAnotherProject.php @@ -74,7 +74,7 @@ class TaskDuplicateAnotherProject extends Base */ public function doAction(array $data) { - $destination_column_id = $this->board->getFirstColumn($this->getParam('project_id')); + $destination_column_id = $this->column->getFirstColumnId($this->getParam('project_id')); return (bool) $this->taskDuplication->duplicateToProject($data['task_id'], $this->getParam('project_id'), null, $destination_column_id); } diff --git a/app/Analytic/AverageTimeSpentColumnAnalytic.php b/app/Analytic/AverageTimeSpentColumnAnalytic.php index c3cff548..bef55419 100644 --- a/app/Analytic/AverageTimeSpentColumnAnalytic.php +++ b/app/Analytic/AverageTimeSpentColumnAnalytic.php @@ -40,7 +40,7 @@ class AverageTimeSpentColumnAnalytic extends Base private function initialize($project_id) { $stats = array(); - $columns = $this->board->getColumnsList($project_id); + $columns = $this->column->getList($project_id); foreach ($columns as $column_id => $column_title) { $stats[$column_id] = array( diff --git a/app/Analytic/TaskDistributionAnalytic.php b/app/Analytic/TaskDistributionAnalytic.php index 614c5f72..838652e3 100644 --- a/app/Analytic/TaskDistributionAnalytic.php +++ b/app/Analytic/TaskDistributionAnalytic.php @@ -23,7 +23,7 @@ class TaskDistributionAnalytic extends Base { $metrics = array(); $total = 0; - $columns = $this->board->getColumns($project_id); + $columns = $this->column->getAll($project_id); foreach ($columns as $column) { $nb_tasks = $this->taskFinder->countByColumnId($project_id, $column['id']); diff --git a/app/Api/Board.php b/app/Api/Board.php index d615b1dc..185ac51a 100644 --- a/app/Api/Board.php +++ b/app/Api/Board.php @@ -15,39 +15,4 @@ class Board extends Base $this->checkProjectPermission($project_id); return $this->board->getBoard($project_id); } - - public function getColumns($project_id) - { - return $this->board->getColumns($project_id); - } - - public function getColumn($column_id) - { - return $this->board->getColumn($column_id); - } - - public function moveColumnUp($project_id, $column_id) - { - return $this->board->moveUp($project_id, $column_id); - } - - public function moveColumnDown($project_id, $column_id) - { - return $this->board->moveDown($project_id, $column_id); - } - - public function updateColumn($column_id, $title, $task_limit = 0, $description = '') - { - return $this->board->updateColumn($column_id, $title, $task_limit, $description); - } - - public function addColumn($project_id, $title, $task_limit = 0, $description = '') - { - return $this->board->addColumn($project_id, $title, $task_limit, $description); - } - - public function removeColumn($column_id) - { - return $this->board->removeColumn($column_id); - } } diff --git a/app/Api/Column.php b/app/Api/Column.php new file mode 100644 index 00000000..ddc3a5d0 --- /dev/null +++ b/app/Api/Column.php @@ -0,0 +1,42 @@ +column->getAll($project_id); + } + + public function getColumn($column_id) + { + return $this->column->getById($column_id); + } + + public function updateColumn($column_id, $title, $task_limit = 0, $description = '') + { + return $this->column->update($column_id, $title, $task_limit, $description); + } + + public function addColumn($project_id, $title, $task_limit = 0, $description = '') + { + return $this->column->create($project_id, $title, $task_limit, $description); + } + + public function removeColumn($column_id) + { + return $this->column->remove($column_id); + } + + public function changeColumnPosition($project_id, $column_id, $position) + { + return $this->column->changePosition($project_id, $column_id, $position); + } +} diff --git a/app/Controller/Action.php b/app/Controller/Action.php index 482a210b..6c324324 100644 --- a/app/Controller/Action.php +++ b/app/Controller/Action.php @@ -27,7 +27,7 @@ class Action extends Base 'available_actions' => $this->actionManager->getAvailableActions(), 'available_events' => $this->eventManager->getAll(), 'available_params' => $this->actionManager->getAvailableParameters($actions), - 'columns_list' => $this->board->getColumnsList($project['id']), + 'columns_list' => $this->column->getList($project['id']), 'users_list' => $this->projectUserRole->getAssignableUsersList($project['id']), 'projects_list' => $this->projectUserRole->getProjectsByUser($this->userSession->getId()), 'colors_list' => $this->color->getList(), @@ -86,7 +86,7 @@ class Action extends Base $this->response->html($this->helper->layout->project('action/params', array( 'values' => $values, 'action_params' => $action_params, - 'columns_list' => $this->board->getColumnsList($project['id']), + 'columns_list' => $this->column->getList($project['id']), 'users_list' => $this->projectUserRole->getAssignableUsersList($project['id']), 'projects_list' => $projects_list, 'colors_list' => $this->color->getList(), diff --git a/app/Controller/BoardPopover.php b/app/Controller/BoardPopover.php index 965669ff..63dab302 100644 --- a/app/Controller/BoardPopover.php +++ b/app/Controller/BoardPopover.php @@ -112,7 +112,7 @@ class BoardPopover extends Base $this->response->html($this->template->render('board/popover_close_all_tasks_column', array( 'project' => $project, 'nb_tasks' => $this->taskFinder->countByColumnAndSwimlaneId($project['id'], $column_id, $swimlane_id), - 'column' => $this->board->getColumnTitleById($column_id), + 'column' => $this->column->getColumnTitleById($column_id), 'swimlane' => $this->swimlane->getNameById($swimlane_id) ?: t($project['default_swimlane']), 'values' => array('column_id' => $column_id, 'swimlane_id' => $swimlane_id), ))); @@ -129,7 +129,7 @@ class BoardPopover extends Base $values = $this->request->getValues(); $this->taskStatus->closeTasksBySwimlaneAndColumn($values['swimlane_id'], $values['column_id']); - $this->flash->success(t('All tasks of the column "%s" and the swimlane "%s" have been closed successfully.', $this->board->getColumnTitleById($values['column_id']), $this->swimlane->getNameById($values['swimlane_id']) ?: t($project['default_swimlane']))); + $this->flash->success(t('All tasks of the column "%s" and the swimlane "%s" have been closed successfully.', $this->column->getColumnTitleById($values['column_id']), $this->swimlane->getNameById($values['swimlane_id']) ?: t($project['default_swimlane']))); $this->response->redirect($this->helper->url->to('board', 'show', array('project_id' => $project['id']))); } } diff --git a/app/Controller/Column.php b/app/Controller/Column.php index 329413ef..e02c7dcb 100644 --- a/app/Controller/Column.php +++ b/app/Controller/Column.php @@ -18,7 +18,7 @@ class Column extends Base public function index() { $project = $this->getProject(); - $columns = $this->board->getColumns($project['id']); + $columns = $this->column->getAll($project['id']); $this->response->html($this->helper->layout->project('column/index', array( 'columns' => $columns, @@ -35,7 +35,7 @@ class Column extends Base public function create(array $values = array(), array $errors = array()) { $project = $this->getProject(); - $columns = $this->board->getColumnsList($project['id']); + $columns = $this->column->getList($project['id']); if (empty($values)) { $values = array('project_id' => $project['id']); @@ -62,7 +62,7 @@ class Column extends Base list($valid, $errors) = $this->columnValidator->validateCreation($values); if ($valid) { - if ($this->board->addColumn($project['id'], $values['title'], $values['task_limit'], $values['description'])) { + if ($this->column->create($project['id'], $values['title'], $values['task_limit'], $values['description'])) { $this->flash->success(t('Column created successfully.')); return $this->response->redirect($this->helper->url->to('column', 'index', array('project_id' => $project['id'])), true); } else { @@ -81,7 +81,7 @@ class Column extends Base public function edit(array $values = array(), array $errors = array()) { $project = $this->getProject(); - $column = $this->board->getColumn($this->request->getIntegerParam('column_id')); + $column = $this->column->getById($this->request->getIntegerParam('column_id')); $this->response->html($this->helper->layout->project('column/edit', array( 'errors' => $errors, @@ -105,7 +105,7 @@ class Column extends Base list($valid, $errors) = $this->columnValidator->validateModification($values); if ($valid) { - if ($this->board->updateColumn($values['id'], $values['title'], $values['task_limit'], $values['description'])) { + if ($this->column->update($values['id'], $values['title'], $values['task_limit'], $values['description'])) { $this->flash->success(t('Board updated successfully.')); $this->response->redirect($this->helper->url->to('column', 'index', array('project_id' => $project['id']))); } else { @@ -144,7 +144,7 @@ class Column extends Base $project = $this->getProject(); $this->response->html($this->helper->layout->project('column/remove', array( - 'column' => $this->board->getColumn($this->request->getIntegerParam('column_id')), + 'column' => $this->column->getById($this->request->getIntegerParam('column_id')), 'project' => $project, 'title' => t('Remove a column from a board') ))); @@ -159,9 +159,9 @@ class Column extends Base { $project = $this->getProject(); $this->checkCSRFParam(); - $column = $this->board->getColumn($this->request->getIntegerParam('column_id')); + $column_id = $this->request->getIntegerParam('column_id'); - if (! empty($column) && $this->board->removeColumn($column['id'])) { + if ($this->column->remove($column_id)) { $this->flash->success(t('Column removed successfully.')); } else { $this->flash->failure(t('Unable to remove this column.')); diff --git a/app/Controller/Gantt.php b/app/Controller/Gantt.php index 5dbd1243..9ffa277f 100644 --- a/app/Controller/Gantt.php +++ b/app/Controller/Gantt.php @@ -103,7 +103,7 @@ class Gantt extends Base $values = $values + array( 'project_id' => $project['id'], - 'column_id' => $this->board->getFirstColumn($project['id']), + 'column_id' => $this->column->getFirstColumnId($project['id']), 'position' => 1 ); diff --git a/app/Controller/Task.php b/app/Controller/Task.php index 98b7a041..539d377b 100644 --- a/app/Controller/Task.php +++ b/app/Controller/Task.php @@ -36,7 +36,7 @@ class Task extends Base 'subtasks' => $this->subtask->getAll($task['id']), 'links' => $this->taskLink->getAllGroupedByLabel($task['id']), 'task' => $task, - 'columns_list' => $this->board->getColumnsList($task['project_id']), + 'columns_list' => $this->column->getList($task['project_id']), 'colors_list' => $this->color->getList(), 'title' => $task['title'], 'no_layout' => true, @@ -74,7 +74,7 @@ class Task extends Base 'task' => $task, 'values' => $values, 'link_label_list' => $this->link->getList(0, false), - 'columns_list' => $this->board->getColumnsList($task['project_id']), + 'columns_list' => $this->column->getList($task['project_id']), 'colors_list' => $this->color->getList(), 'users_list' => $this->projectUserRole->getAssignableUsersList($task['project_id'], true, false, false), 'title' => $task['project_name'].' > '.$task['title'], diff --git a/app/Controller/Taskcreation.php b/app/Controller/Taskcreation.php index f1ac7272..1d8a0e29 100644 --- a/app/Controller/Taskcreation.php +++ b/app/Controller/Taskcreation.php @@ -36,7 +36,7 @@ class Taskcreation extends Base 'project' => $project, 'errors' => $errors, 'values' => $values + array('project_id' => $project['id']), - 'columns_list' => $this->board->getColumnsList($project['id']), + 'columns_list' => $this->column->getList($project['id']), 'users_list' => $this->projectUserRole->getAssignableUsersList($project['id'], true, false, true), 'colors_list' => $this->color->getList(), 'categories_list' => $this->category->getList($project['id']), diff --git a/app/Controller/Taskduplication.php b/app/Controller/Taskduplication.php index 7e7fccd6..7641a48d 100644 --- a/app/Controller/Taskduplication.php +++ b/app/Controller/Taskduplication.php @@ -115,7 +115,7 @@ class Taskduplication extends Base $dst_project_id = $this->request->getIntegerParam('dst_project_id', key($projects_list)); $swimlanes_list = $this->swimlane->getList($dst_project_id, false, true); - $columns_list = $this->board->getColumnsList($dst_project_id); + $columns_list = $this->column->getList($dst_project_id); $categories_list = $this->category->getList($dst_project_id); $users_list = $this->projectUserRole->getAssignableUsersList($dst_project_id); diff --git a/app/Formatter/TaskFilterGanttFormatter.php b/app/Formatter/TaskFilterGanttFormatter.php index 08059d4c..a4eef1ee 100644 --- a/app/Formatter/TaskFilterGanttFormatter.php +++ b/app/Formatter/TaskFilterGanttFormatter.php @@ -47,7 +47,7 @@ class TaskFilterGanttFormatter extends TaskFilter implements FormatterInterface private function formatTask(array $task) { if (! isset($this->columns[$task['project_id']])) { - $this->columns[$task['project_id']] = $this->board->getColumnsList($task['project_id']); + $this->columns[$task['project_id']] = $this->column->getList($task['project_id']); } $start = $task['date_started'] ?: time(); diff --git a/app/Helper/Task.php b/app/Helper/Task.php index e85d6e30..6058c099 100644 --- a/app/Helper/Task.php +++ b/app/Helper/Task.php @@ -178,7 +178,7 @@ class Task extends Base public function getProgress($task) { if (! isset($this->columns[$task['project_id']])) { - $this->columns[$task['project_id']] = $this->board->getColumnsList($task['project_id']); + $this->columns[$task['project_id']] = $this->column->getList($task['project_id']); } return $this->task->getProgress($task, $this->columns[$task['project_id']]); diff --git a/app/Model/ActionParameter.php b/app/Model/ActionParameter.php index 62b03142..53edcbc8 100644 --- a/app/Model/ActionParameter.php +++ b/app/Model/ActionParameter.php @@ -150,8 +150,8 @@ class ActionParameter extends Base case 'dest_column_id': case 'dst_column_id': case 'column_id': - $column = $this->board->getColumn($value); - return empty($column) ? false : $this->board->getColumnIdByTitle($project_id, $column['title']) ?: false; + $column = $this->column->getById($value); + return empty($column) ? false : $this->column->getColumnIdByTitle($project_id, $column['title']) ?: false; case 'user_id': case 'owner_id': return $this->projectPermission->isAssignable($project_id, $value) ? $value : false; diff --git a/app/Model/Board.php b/app/Model/Board.php index 0f980f68..f677266f 100644 --- a/app/Model/Board.php +++ b/app/Model/Board.php @@ -12,13 +12,6 @@ use PicoDb\Database; */ class Board extends Base { - /** - * SQL table name - * - * @var string - */ - const TABLE = 'columns'; - /** * Get Kanboard default columns * @@ -73,7 +66,7 @@ class Board extends Base 'description' => $column['description'], ); - if (! $this->db->table(self::TABLE)->save($values)) { + if (! $this->db->table(Column::TABLE)->save($values)) { return false; } } @@ -91,7 +84,7 @@ class Board extends Base */ public function duplicate($project_from, $project_to) { - $columns = $this->db->table(Board::TABLE) + $columns = $this->db->table(Column::TABLE) ->columns('title', 'task_limit', 'description') ->eq('project_id', $project_from) ->asc('position') @@ -100,134 +93,6 @@ class Board extends Base return $this->board->create($project_to, $columns); } - /** - * Add a new column to the board - * - * @access public - * @param integer $project_id Project id - * @param string $title Column title - * @param integer $task_limit Task limit - * @param string $description Column description - * @return boolean|integer - */ - public function addColumn($project_id, $title, $task_limit = 0, $description = '') - { - $values = array( - 'project_id' => $project_id, - 'title' => $title, - 'task_limit' => intval($task_limit), - 'position' => $this->getLastColumnPosition($project_id) + 1, - 'description' => $description, - ); - - return $this->persist(self::TABLE, $values); - } - - /** - * Update a column - * - * @access public - * @param integer $column_id Column id - * @param string $title Column title - * @param integer $task_limit Task limit - * @param string $description Optional description - * @return boolean - */ - public function updateColumn($column_id, $title, $task_limit = 0, $description = '') - { - return $this->db->table(self::TABLE)->eq('id', $column_id)->update(array( - 'title' => $title, - 'task_limit' => intval($task_limit), - 'description' => $description, - )); - } - - /** - * Get columns with consecutive positions - * - * If you remove a column, the positions are not anymore consecutives - * - * @access public - * @param integer $project_id - * @return array - */ - public function getNormalizedColumnPositions($project_id) - { - $columns = $this->db->hashtable(self::TABLE)->eq('project_id', $project_id)->asc('position')->getAll('id', 'position'); - $position = 1; - - foreach ($columns as $column_id => $column_position) { - $columns[$column_id] = $position++; - } - - return $columns; - } - - /** - * Save the new positions for a set of columns - * - * @access public - * @param array $columns Hashmap of column_id/column_position - * @return boolean - */ - public function saveColumnPositions(array $columns) - { - return $this->db->transaction(function (Database $db) use ($columns) { - - foreach ($columns as $column_id => $position) { - if (! $db->table(Board::TABLE)->eq('id', $column_id)->update(array('position' => $position))) { - return false; - } - } - }); - } - - /** - * Move a column down, increment the column position value - * - * @access public - * @param integer $project_id Project id - * @param integer $column_id Column id - * @return boolean - */ - public function moveDown($project_id, $column_id) - { - $columns = $this->getNormalizedColumnPositions($project_id); - $positions = array_flip($columns); - - if (isset($columns[$column_id]) && $columns[$column_id] < count($columns)) { - $position = ++$columns[$column_id]; - $columns[$positions[$position]]--; - - return $this->saveColumnPositions($columns); - } - - return false; - } - - /** - * Move a column up, decrement the column position value - * - * @access public - * @param integer $project_id Project id - * @param integer $column_id Column id - * @return boolean - */ - public function moveUp($project_id, $column_id) - { - $columns = $this->getNormalizedColumnPositions($project_id); - $positions = array_flip($columns); - - if (isset($columns[$column_id]) && $columns[$column_id] > 1) { - $position = --$columns[$column_id]; - $columns[$positions[$position]]++; - - return $this->saveColumnPositions($columns); - } - - return false; - } - /** * Get all tasks sorted by columns and swimlanes * @@ -239,7 +104,7 @@ class Board extends Base public function getBoard($project_id, $callback = null) { $swimlanes = $this->swimlane->getSwimlanes($project_id); - $columns = $this->getColumns($project_id); + $columns = $this->column->getAll($project_id); $nb_columns = count($columns); for ($i = 0, $ilen = count($swimlanes); $i < $ilen; $i++) { @@ -307,131 +172,4 @@ class Board extends Base return $prepend ? array(-1 => t('All columns')) + $listing : $listing; } - - /** - * Get the first column id for a given project - * - * @access public - * @param integer $project_id Project id - * @return integer - */ - public function getFirstColumn($project_id) - { - return $this->db->table(self::TABLE)->eq('project_id', $project_id)->asc('position')->findOneColumn('id'); - } - - /** - * Get the last column id for a given project - * - * @access public - * @param integer $project_id Project id - * @return integer - */ - public function getLastColumn($project_id) - { - return $this->db->table(self::TABLE)->eq('project_id', $project_id)->desc('position')->findOneColumn('id'); - } - - /** - * Get the list of columns sorted by position [ column_id => title ] - * - * @access public - * @param integer $project_id Project id - * @param boolean $prepend Prepend a default value - * @return array - */ - public function getColumnsList($project_id, $prepend = false) - { - $listing = $this->db->hashtable(self::TABLE)->eq('project_id', $project_id)->asc('position')->getAll('id', 'title'); - return $prepend ? array(-1 => t('All columns')) + $listing : $listing; - } - - /** - * Get all columns sorted by position for a given project - * - * @access public - * @param integer $project_id Project id - * @return array - */ - public function getColumns($project_id) - { - return $this->db->table(self::TABLE)->eq('project_id', $project_id)->asc('position')->findAll(); - } - - /** - * Get the number of columns for a given project - * - * @access public - * @param integer $project_id Project id - * @return integer - */ - public function countColumns($project_id) - { - return $this->db->table(self::TABLE)->eq('project_id', $project_id)->count(); - } - - /** - * Get a column by the id - * - * @access public - * @param integer $column_id Column id - * @return array - */ - public function getColumn($column_id) - { - return $this->db->table(self::TABLE)->eq('id', $column_id)->findOne(); - } - - /** - * Get a column id by the name - * - * @access public - * @param integer $project_id - * @param string $title - * @return integer - */ - public function getColumnIdByTitle($project_id, $title) - { - return (int) $this->db->table(self::TABLE)->eq('project_id', $project_id)->eq('title', $title)->findOneColumn('id'); - } - - /** - * Get a column title by the id - * - * @access public - * @param integer $column_id - * @return integer - */ - public function getColumnTitleById($column_id) - { - return $this->db->table(self::TABLE)->eq('id', $column_id)->findOneColumn('title'); - } - - /** - * Get the position of the last column for a given project - * - * @access public - * @param integer $project_id Project id - * @return integer - */ - public function getLastColumnPosition($project_id) - { - return (int) $this->db - ->table(self::TABLE) - ->eq('project_id', $project_id) - ->desc('position') - ->findOneColumn('position'); - } - - /** - * Remove a column and all tasks associated to this column - * - * @access public - * @param integer $column_id Column id - * @return boolean - */ - public function removeColumn($column_id) - { - return $this->db->table(self::TABLE)->eq('id', $column_id)->remove(); - } } diff --git a/app/Model/Column.php b/app/Model/Column.php index 286b6140..ccdcb049 100644 --- a/app/Model/Column.php +++ b/app/Model/Column.php @@ -17,6 +17,83 @@ class Column extends Base */ const TABLE = 'columns'; + /** + * Get a column by the id + * + * @access public + * @param integer $column_id Column id + * @return array + */ + public function getById($column_id) + { + return $this->db->table(self::TABLE)->eq('id', $column_id)->findOne(); + } + + /** + * Get the first column id for a given project + * + * @access public + * @param integer $project_id Project id + * @return integer + */ + public function getFirstColumnId($project_id) + { + return $this->db->table(self::TABLE)->eq('project_id', $project_id)->asc('position')->findOneColumn('id'); + } + + /** + * Get the last column id for a given project + * + * @access public + * @param integer $project_id Project id + * @return integer + */ + public function getLastColumnId($project_id) + { + return $this->db->table(self::TABLE)->eq('project_id', $project_id)->desc('position')->findOneColumn('id'); + } + + /** + * Get the position of the last column for a given project + * + * @access public + * @param integer $project_id Project id + * @return integer + */ + public function getLastColumnPosition($project_id) + { + return (int) $this->db + ->table(self::TABLE) + ->eq('project_id', $project_id) + ->desc('position') + ->findOneColumn('position'); + } + + /** + * Get a column id by the name + * + * @access public + * @param integer $project_id + * @param string $title + * @return integer + */ + public function getColumnIdByTitle($project_id, $title) + { + return (int) $this->db->table(self::TABLE)->eq('project_id', $project_id)->eq('title', $title)->findOneColumn('id'); + } + + /** + * Get a column title by the id + * + * @access public + * @param integer $column_id + * @return integer + */ + public function getColumnTitleById($column_id) + { + return $this->db->table(self::TABLE)->eq('id', $column_id)->findOneColumn('title'); + } + /** * Get all columns sorted by position for a given project * @@ -29,6 +106,74 @@ class Column extends Base return $this->db->table(self::TABLE)->eq('project_id', $project_id)->asc('position')->findAll(); } + /** + * Get the list of columns sorted by position [ column_id => title ] + * + * @access public + * @param integer $project_id Project id + * @param boolean $prepend Prepend a default value + * @return array + */ + public function getList($project_id, $prepend = false) + { + $listing = $this->db->hashtable(self::TABLE)->eq('project_id', $project_id)->asc('position')->getAll('id', 'title'); + return $prepend ? array(-1 => t('All columns')) + $listing : $listing; + } + + /** + * Add a new column to the board + * + * @access public + * @param integer $project_id Project id + * @param string $title Column title + * @param integer $task_limit Task limit + * @param string $description Column description + * @return boolean|integer + */ + public function create($project_id, $title, $task_limit = 0, $description = '') + { + $values = array( + 'project_id' => $project_id, + 'title' => $title, + 'task_limit' => intval($task_limit), + 'position' => $this->getLastColumnPosition($project_id) + 1, + 'description' => $description, + ); + + return $this->persist(self::TABLE, $values); + } + + /** + * Update a column + * + * @access public + * @param integer $column_id Column id + * @param string $title Column title + * @param integer $task_limit Task limit + * @param string $description Optional description + * @return boolean + */ + public function update($column_id, $title, $task_limit = 0, $description = '') + { + return $this->db->table(self::TABLE)->eq('id', $column_id)->update(array( + 'title' => $title, + 'task_limit' => intval($task_limit), + 'description' => $description, + )); + } + + /** + * Remove a column and all tasks associated to this column + * + * @access public + * @param integer $column_id Column id + * @return boolean + */ + public function remove($column_id) + { + return $this->db->table(self::TABLE)->eq('id', $column_id)->remove(); + } + /** * Change column position * diff --git a/app/Model/Project.php b/app/Model/Project.php index d0a8bfc8..a79e46a1 100644 --- a/app/Model/Project.php +++ b/app/Model/Project.php @@ -241,7 +241,7 @@ class Project extends Base { $stats = array(); $stats['nb_active_tasks'] = 0; - $columns = $this->board->getColumns($project_id); + $columns = $this->column->getAll($project_id); $column_stats = $this->board->getColumnStats($project_id); foreach ($columns as &$column) { @@ -265,7 +265,7 @@ class Project extends Base */ public function getColumnStats(array &$project) { - $project['columns'] = $this->board->getColumns($project['id']); + $project['columns'] = $this->column->getAll($project['id']); $stats = $this->board->getColumnStats($project['id']); foreach ($project['columns'] as &$column) { diff --git a/app/Model/ProjectDailyColumnStats.php b/app/Model/ProjectDailyColumnStats.php index cf79be84..2bcc4d55 100644 --- a/app/Model/ProjectDailyColumnStats.php +++ b/app/Model/ProjectDailyColumnStats.php @@ -84,7 +84,7 @@ class ProjectDailyColumnStats extends Base */ public function getAggregatedMetrics($project_id, $from, $to, $field = 'total') { - $columns = $this->board->getColumnsList($project_id); + $columns = $this->column->getList($project_id); $metrics = $this->getMetrics($project_id, $from, $to); return $this->buildAggregate($metrics, $columns, $field); } diff --git a/app/Model/TaskAnalytic.php b/app/Model/TaskAnalytic.php index bdfec3cb..cff56744 100644 --- a/app/Model/TaskAnalytic.php +++ b/app/Model/TaskAnalytic.php @@ -48,7 +48,7 @@ class TaskAnalytic extends Base public function getTimeSpentByColumn(array $task) { $result = array(); - $columns = $this->board->getColumnsList($task['project_id']); + $columns = $this->column->getList($task['project_id']); $sums = $this->transition->getTimeSpentByTask($task['id']); foreach ($columns as $column_id => $column_title) { diff --git a/app/Model/TaskCreation.php b/app/Model/TaskCreation.php index f7d981fa..576eb18c 100644 --- a/app/Model/TaskCreation.php +++ b/app/Model/TaskCreation.php @@ -56,7 +56,7 @@ class TaskCreation extends Base $this->resetFields($values, array('date_started', 'creator_id', 'owner_id', 'swimlane_id', 'date_due', 'score', 'category_id', 'time_estimated')); if (empty($values['column_id'])) { - $values['column_id'] = $this->board->getFirstColumn($values['project_id']); + $values['column_id'] = $this->column->getFirstColumnId($values['project_id']); } if (empty($values['color_id'])) { diff --git a/app/Model/TaskDuplication.php b/app/Model/TaskDuplication.php index e81fb232..b081aac1 100644 --- a/app/Model/TaskDuplication.php +++ b/app/Model/TaskDuplication.php @@ -64,7 +64,7 @@ class TaskDuplication extends Base if ($values['recurrence_status'] == Task::RECURRING_STATUS_PENDING) { $values['recurrence_parent'] = $task_id; - $values['column_id'] = $this->board->getFirstColumn($values['project_id']); + $values['column_id'] = $this->column->getFirstColumnId($values['project_id']); $this->calculateRecurringTaskDueDate($values); $recurring_task_id = $this->save($task_id, $values); @@ -181,12 +181,12 @@ class TaskDuplication extends Base // Check if the column exists for the destination project if ($values['column_id'] > 0) { - $values['column_id'] = $this->board->getColumnIdByTitle( + $values['column_id'] = $this->column->getColumnIdByTitle( $values['project_id'], - $this->board->getColumnTitleById($values['column_id']) + $this->column->getColumnTitleById($values['column_id']) ); - $values['column_id'] = $values['column_id'] ?: $this->board->getFirstColumn($values['project_id']); + $values['column_id'] = $values['column_id'] ?: $this->column->getFirstColumnId($values['project_id']); } return $values; diff --git a/app/Model/TaskFilter.php b/app/Model/TaskFilter.php index 7ceb4a97..1883298d 100644 --- a/app/Model/TaskFilter.php +++ b/app/Model/TaskFilter.php @@ -469,7 +469,7 @@ class TaskFilter extends Base $this->query->beginOr(); foreach ($values as $project) { - $this->query->ilike(Board::TABLE.'.title', $project); + $this->query->ilike(Column::TABLE.'.title', $project); } $this->query->closeOr(); diff --git a/app/Model/TaskFinder.php b/app/Model/TaskFinder.php index 95ddc12f..0492a9bf 100644 --- a/app/Model/TaskFinder.php +++ b/app/Model/TaskFinder.php @@ -38,14 +38,14 @@ class TaskFinder extends Base Task::TABLE.'.time_spent', Task::TABLE.'.time_estimated', Project::TABLE.'.name AS project_name', - Board::TABLE.'.title AS column_name', + Column::TABLE.'.title AS column_name', User::TABLE.'.username AS assignee_username', User::TABLE.'.name AS assignee_name' ) ->eq(Task::TABLE.'.is_active', $is_active) ->in(Project::TABLE.'.id', $project_ids) ->join(Project::TABLE, 'id', 'project_id') - ->join(Board::TABLE, 'id', 'column_id', Task::TABLE) + ->join(Column::TABLE, 'id', 'column_id', Task::TABLE) ->join(User::TABLE, 'id', 'owner_id', Task::TABLE); } @@ -129,15 +129,15 @@ class TaskFinder extends Base User::TABLE.'.name AS assignee_name', Category::TABLE.'.name AS category_name', Category::TABLE.'.description AS category_description', - Board::TABLE.'.title AS column_name', - Board::TABLE.'.position AS column_position', + Column::TABLE.'.title AS column_name', + Column::TABLE.'.position AS column_position', Swimlane::TABLE.'.name AS swimlane_name', Project::TABLE.'.default_swimlane', Project::TABLE.'.name AS project_name' ) ->join(User::TABLE, 'id', 'owner_id', Task::TABLE) ->join(Category::TABLE, 'id', 'category_id', Task::TABLE) - ->join(Board::TABLE, 'id', 'column_id', Task::TABLE) + ->join(Column::TABLE, 'id', 'column_id', Task::TABLE) ->join(Swimlane::TABLE, 'id', 'swimlane_id', Task::TABLE) ->join(Project::TABLE, 'id', 'project_id', Task::TABLE); } diff --git a/app/Model/TaskImport.php b/app/Model/TaskImport.php index e8dd1946..ccab0152 100644 --- a/app/Model/TaskImport.php +++ b/app/Model/TaskImport.php @@ -111,7 +111,7 @@ class TaskImport extends Base } if (! empty($row['column'])) { - $values['column_id'] = $this->board->getColumnIdByTitle($this->projectId, $row['column']); + $values['column_id'] = $this->column->getColumnIdByTitle($this->projectId, $row['column']); } if (! empty($row['category'])) { diff --git a/app/Model/TaskLink.php b/app/Model/TaskLink.php index 034fcf45..a57bf3b0 100644 --- a/app/Model/TaskLink.php +++ b/app/Model/TaskLink.php @@ -81,17 +81,17 @@ class TaskLink extends Base Task::TABLE.'.owner_id AS task_assignee_id', User::TABLE.'.username AS task_assignee_username', User::TABLE.'.name AS task_assignee_name', - Board::TABLE.'.title AS column_title', + Column::TABLE.'.title AS column_title', Project::TABLE.'.name AS project_name' ) ->eq(self::TABLE.'.task_id', $task_id) ->join(Link::TABLE, 'id', 'link_id') ->join(Task::TABLE, 'id', 'opposite_task_id') - ->join(Board::TABLE, 'id', 'column_id', Task::TABLE) + ->join(Column::TABLE, 'id', 'column_id', Task::TABLE) ->join(User::TABLE, 'id', 'owner_id', Task::TABLE) ->join(Project::TABLE, 'id', 'project_id', Task::TABLE) ->asc(Link::TABLE.'.id') - ->desc(Board::TABLE.'.position') + ->desc(Column::TABLE.'.position') ->desc(Task::TABLE.'.is_active') ->asc(Task::TABLE.'.position') ->asc(Task::TABLE.'.id') diff --git a/app/Model/Transition.php b/app/Model/Transition.php index b1f8f678..aa76d58f 100644 --- a/app/Model/Transition.php +++ b/app/Model/Transition.php @@ -76,8 +76,8 @@ class Transition extends Base ->eq('task_id', $task_id) ->desc('date') ->join(User::TABLE, 'id', 'user_id') - ->join(Board::TABLE.' as src', 'id', 'src_column_id', self::TABLE, 'src') - ->join(Board::TABLE.' as dst', 'id', 'dst_column_id', self::TABLE, 'dst') + ->join(Column::TABLE.' as src', 'id', 'src_column_id', self::TABLE, 'src') + ->join(Column::TABLE.' as dst', 'id', 'dst_column_id', self::TABLE, 'dst') ->findAll(); } @@ -118,8 +118,8 @@ class Transition extends Base ->desc('date') ->join(Task::TABLE, 'id', 'task_id') ->join(User::TABLE, 'id', 'user_id') - ->join(Board::TABLE.' as src', 'id', 'src_column_id', self::TABLE, 'src') - ->join(Board::TABLE.' as dst', 'id', 'dst_column_id', self::TABLE, 'dst') + ->join(Column::TABLE.' as src', 'id', 'src_column_id', self::TABLE, 'src') + ->join(Column::TABLE.' as dst', 'id', 'dst_column_id', self::TABLE, 'dst') ->findAll(); } diff --git a/app/Subscriber/RecurringTaskSubscriber.php b/app/Subscriber/RecurringTaskSubscriber.php index 6d5aee89..09a5665a 100644 --- a/app/Subscriber/RecurringTaskSubscriber.php +++ b/app/Subscriber/RecurringTaskSubscriber.php @@ -21,9 +21,9 @@ class RecurringTaskSubscriber extends BaseSubscriber implements EventSubscriberI $this->logger->debug('Subscriber executed: '.__METHOD__); if ($event['recurrence_status'] == Task::RECURRING_STATUS_PENDING) { - if ($event['recurrence_trigger'] == Task::RECURRING_TRIGGER_FIRST_COLUMN && $this->board->getFirstColumn($event['project_id']) == $event['src_column_id']) { + if ($event['recurrence_trigger'] == Task::RECURRING_TRIGGER_FIRST_COLUMN && $this->column->getFirstColumnId($event['project_id']) == $event['src_column_id']) { $this->taskDuplication->duplicateRecurringTask($event['task_id']); - } elseif ($event['recurrence_trigger'] == Task::RECURRING_TRIGGER_LAST_COLUMN && $this->board->getLastColumn($event['project_id']) == $event['dst_column_id']) { + } elseif ($event['recurrence_trigger'] == Task::RECURRING_TRIGGER_LAST_COLUMN && $this->column->getLastColumnId($event['project_id']) == $event['dst_column_id']) { $this->taskDuplication->duplicateRecurringTask($event['task_id']); } } diff --git a/jsonrpc.php b/jsonrpc.php index 1d59d4ea..d2163347 100644 --- a/jsonrpc.php +++ b/jsonrpc.php @@ -8,6 +8,7 @@ use Kanboard\Api\Me; use Kanboard\Api\Action; use Kanboard\Api\App; use Kanboard\Api\Board; +use Kanboard\Api\Column; use Kanboard\Api\Category; use Kanboard\Api\Comment; use Kanboard\Api\File; @@ -30,6 +31,7 @@ $server->attach(new Me($container)); $server->attach(new Action($container)); $server->attach(new App($container)); $server->attach(new Board($container)); +$server->attach(new Column($container)); $server->attach(new Category($container)); $server->attach(new Comment($container)); $server->attach(new File($container)); diff --git a/tests/integration/ApiTest.php b/tests/integration/ApiTest.php index 8b970a6c..679238a2 100644 --- a/tests/integration/ApiTest.php +++ b/tests/integration/ApiTest.php @@ -170,76 +170,6 @@ class Api extends PHPUnit_Framework_TestCase $this->assertCount(0, $activities); } - public function testGetBoard() - { - $board = $this->client->getBoard(1); - $this->assertTrue(is_array($board)); - $this->assertEquals(1, count($board)); - $this->assertEquals('Default swimlane', $board[0]['name']); - $this->assertEquals(4, count($board[0]['columns'])); - } - - public function testGetColumns() - { - $columns = $this->client->getColumns(1); - $this->assertTrue(is_array($columns)); - $this->assertEquals(4, count($columns)); - $this->assertEquals('Done', $columns[3]['title']); - } - - public function testMoveColumnUp() - { - $this->assertTrue($this->client->moveColumnUp(1, 4)); - - $columns = $this->client->getColumns(1); - $this->assertTrue(is_array($columns)); - $this->assertEquals('Done', $columns[2]['title']); - $this->assertEquals('Work in progress', $columns[3]['title']); - } - - public function testMoveColumnDown() - { - $this->assertTrue($this->client->moveColumnDown(1, 4)); - - $columns = $this->client->getColumns(1); - $this->assertTrue(is_array($columns)); - $this->assertEquals('Work in progress', $columns[2]['title']); - $this->assertEquals('Done', $columns[3]['title']); - } - - public function testUpdateColumn() - { - $this->assertTrue($this->client->updateColumn(4, 'Boo', 2)); - - $columns = $this->client->getColumns(1); - $this->assertTrue(is_array($columns)); - $this->assertEquals('Boo', $columns[3]['title']); - $this->assertEquals(2, $columns[3]['task_limit']); - } - - public function testAddColumn() - { - $column_id = $this->client->addColumn(1, 'New column'); - - $this->assertNotFalse($column_id); - $this->assertInternalType('int', $column_id); - $this->assertTrue($column_id > 0); - - $columns = $this->client->getColumns(1); - $this->assertTrue(is_array($columns)); - $this->assertEquals(5, count($columns)); - $this->assertEquals('New column', $columns[4]['title']); - } - - public function testRemoveColumn() - { - $this->assertTrue($this->client->removeColumn(5)); - - $columns = $this->client->getColumns(1); - $this->assertTrue(is_array($columns)); - $this->assertEquals(4, count($columns)); - } - public function testGetDefaultSwimlane() { $swimlane = $this->client->getDefaultSwimlane(1); diff --git a/tests/integration/BoardTest.php b/tests/integration/BoardTest.php new file mode 100644 index 00000000..bf8d50b9 --- /dev/null +++ b/tests/integration/BoardTest.php @@ -0,0 +1,21 @@ +assertEquals(1, $this->app->createProject('A project')); + } + + public function testGetBoard() + { + $board = $this->app->getBoard(1); + $this->assertCount(1, $board); + $this->assertEquals('Default swimlane', $board[0]['name']); + + $this->assertCount(4, $board[0]['columns']); + $this->assertEquals('Ready', $board[0]['columns'][1]['title']); + } +} diff --git a/tests/integration/ColumnTest.php b/tests/integration/ColumnTest.php new file mode 100644 index 00000000..6d02afc0 --- /dev/null +++ b/tests/integration/ColumnTest.php @@ -0,0 +1,65 @@ +assertEquals(1, $this->app->createProject('A project')); + } + + public function testGetColumns() + { + $columns = $this->app->getColumns($this->getProjectId()); + $this->assertCount(4, $columns); + $this->assertEquals('Done', $columns[3]['title']); + } + + public function testUpdateColumn() + { + $this->assertTrue($this->app->updateColumn(4, 'Boo', 2)); + + $columns = $this->app->getColumns($this->getProjectId()); + $this->assertEquals('Boo', $columns[3]['title']); + $this->assertEquals(2, $columns[3]['task_limit']); + } + + public function testAddColumn() + { + $column_id = $this->app->addColumn($this->getProjectId(), 'New column'); + + $this->assertNotFalse($column_id); + $this->assertInternalType('int', $column_id); + $this->assertTrue($column_id > 0); + + $columns = $this->app->getColumns($this->getProjectId()); + $this->assertCount(5, $columns); + $this->assertEquals('New column', $columns[4]['title']); + } + + public function testRemoveColumn() + { + $this->assertTrue($this->app->removeColumn(5)); + + $columns = $this->app->getColumns($this->getProjectId()); + $this->assertCount(4, $columns); + } + + public function testChangeColumnPosition() + { + $this->assertTrue($this->app->changeColumnPosition($this->getProjectId(), 1, 3)); + + $columns = $this->app->getColumns($this->getProjectId()); + $this->assertCount(4, $columns); + + $this->assertEquals('Ready', $columns[0]['title']); + $this->assertEquals(1, $columns[0]['position']); + $this->assertEquals('Work in progress', $columns[1]['title']); + $this->assertEquals(2, $columns[1]['position']); + $this->assertEquals('Backlog', $columns[2]['title']); + $this->assertEquals(3, $columns[2]['position']); + $this->assertEquals('Boo', $columns[3]['title']); + $this->assertEquals(4, $columns[3]['position']); + } +} diff --git a/tests/units/Model/ActionTest.php b/tests/units/Model/ActionTest.php index 8d574115..ed687846 100644 --- a/tests/units/Model/ActionTest.php +++ b/tests/units/Model/ActionTest.php @@ -6,7 +6,7 @@ use Kanboard\Model\Action; use Kanboard\Model\Project; use Kanboard\Model\Task; use Kanboard\Model\User; -use Kanboard\Model\Board; +use Kanboard\Model\Column; use Kanboard\Model\Category; use Kanboard\Model\ProjectUserRole; use Kanboard\Core\Security\Role; @@ -260,12 +260,12 @@ class ActionTest extends Base { $projectModel = new Project($this->container); $actionModel = new Action($this->container); - $boardModel = new Board($this->container); + $columnModel = new Column($this->container); $this->assertEquals(1, $projectModel->create(array('name' => 'test1'))); $this->assertEquals(2, $projectModel->create(array('name' => 'test2'))); - $this->assertTrue($boardModel->updateColumn(2, 'My unique column')); + $this->assertTrue($columnModel->update(2, 'My unique column')); $this->assertEquals(1, $actionModel->create(array( 'project_id' => 1, diff --git a/tests/units/Model/BoardTest.php b/tests/units/Model/BoardTest.php index bb6c4b76..bb0778ce 100644 --- a/tests/units/Model/BoardTest.php +++ b/tests/units/Model/BoardTest.php @@ -4,6 +4,7 @@ require_once __DIR__.'/../Base.php'; use Kanboard\Model\Project; use Kanboard\Model\Board; +use Kanboard\Model\Column; use Kanboard\Model\Config; use Kanboard\Model\TaskCreation; use Kanboard\Model\TaskFinder; @@ -15,12 +16,13 @@ class BoardTest extends Base { $p = new Project($this->container); $b = new Board($this->container); + $columnModel = new Column($this->container); $c = new Config($this->container); // Default columns $this->assertEquals(1, $p->create(array('name' => 'UnitTest1'))); - $columns = $b->getColumnsList(1); + $columns = $columnModel->getList(1); $this->assertTrue(is_array($columns)); $this->assertEquals(4, count($columns)); @@ -37,7 +39,7 @@ class BoardTest extends Base $this->assertEquals($input, $c->get('board_columns')); $this->assertEquals(2, $p->create(array('name' => 'UnitTest2'))); - $columns = $b->getColumnsList(2); + $columns = $columnModel->getList(2); $this->assertTrue(is_array($columns)); $this->assertEquals(2, count($columns)); @@ -161,225 +163,4 @@ class BoardTest extends Base $this->assertEquals(1, $board[1]['columns'][3]['tasks'][0]['position']); $this->assertEquals(1, $board[1]['columns'][3]['tasks'][0]['swimlane_id']); } - - public function testGetColumn() - { - $p = new Project($this->container); - $b = new Board($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'UnitTest1'))); - - $column = $b->getColumn(3); - $this->assertNotEmpty($column); - $this->assertEquals('Work in progress', $column['title']); - - $column = $b->getColumn(33); - $this->assertEmpty($column); - } - - public function testRemoveColumn() - { - $p = new Project($this->container); - $b = new Board($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'UnitTest1'))); - $this->assertTrue($b->removeColumn(3)); - $this->assertFalse($b->removeColumn(322)); - - $columns = $b->getColumns(1); - $this->assertTrue(is_array($columns)); - $this->assertEquals(3, count($columns)); - } - - public function testUpdateColumn() - { - $p = new Project($this->container); - $b = new Board($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'UnitTest1'))); - - $this->assertTrue($b->updateColumn(3, 'blah', 5)); - $this->assertTrue($b->updateColumn(2, 'boo')); - - $column = $b->getColumn(3); - $this->assertNotEmpty($column); - $this->assertEquals('blah', $column['title']); - $this->assertEquals(5, $column['task_limit']); - - $column = $b->getColumn(2); - $this->assertNotEmpty($column); - $this->assertEquals('boo', $column['title']); - $this->assertEquals(0, $column['task_limit']); - } - - public function testAddColumn() - { - $p = new Project($this->container); - $b = new Board($this->container); - - $this->assertEquals(1, $p->create(array('name' => 'UnitTest1'))); - $this->assertNotFalse($b->addColumn(1, 'another column')); - $this->assertNotFalse($b->addColumn(1, 'one more', 3, 'one more description')); - - $columns = $b->getColumns(1); - $this->assertTrue(is_array($columns)); - $this->assertEquals(6, count($columns)); - - $this->assertEquals('another column', $columns[4]['title']); - $this->assertEquals(0, $columns[4]['task_limit']); - $this->assertEquals(5, $columns[4]['position']); - - $this->assertEquals('one more', $columns[5]['title']); - $this->assertEquals(3, $columns[5]['task_limit']); - $this->assertEquals(6, $columns[5]['position']); - $this->assertEquals('one more description', $columns[5]['description']); - } - - public function testMoveColumns() - { - $p = new Project($this->container); - $b = new Board($this->container); - - // We create 2 projects - $this->assertEquals(1, $p->create(array('name' => 'UnitTest1'))); - $this->assertEquals(2, $p->create(array('name' => 'UnitTest2'))); - - // We get the columns of the project 2 - $columns = $b->getColumns(2); - $columns_id = array_keys($b->getColumnsList(2)); - $this->assertNotEmpty($columns); - - // Initial order: 5, 6, 7, 8 - - // Move the column 1 down - $this->assertEquals(1, $columns[0]['position']); - $this->assertEquals($columns_id[0], $columns[0]['id']); - - $this->assertEquals(2, $columns[1]['position']); - $this->assertEquals($columns_id[1], $columns[1]['id']); - - $this->assertTrue($b->moveDown(2, $columns[0]['id'])); - $columns = $b->getColumns(2); // Sorted by position - - // New order: 6, 5, 7, 8 - - $this->assertEquals(1, $columns[0]['position']); - $this->assertEquals($columns_id[1], $columns[0]['id']); - - $this->assertEquals(2, $columns[1]['position']); - $this->assertEquals($columns_id[0], $columns[1]['id']); - - // Move the column 3 up - $this->assertTrue($b->moveUp(2, $columns[2]['id'])); - $columns = $b->getColumns(2); - - // New order: 6, 7, 5, 8 - - $this->assertEquals(1, $columns[0]['position']); - $this->assertEquals($columns_id[1], $columns[0]['id']); - - $this->assertEquals(2, $columns[1]['position']); - $this->assertEquals($columns_id[2], $columns[1]['id']); - - $this->assertEquals(3, $columns[2]['position']); - $this->assertEquals($columns_id[0], $columns[2]['id']); - - // Move column 1 up (must do nothing because it's the first column) - $this->assertFalse($b->moveUp(2, $columns[0]['id'])); - $columns = $b->getColumns(2); - - // Order: 6, 7, 5, 8 - - $this->assertEquals(1, $columns[0]['position']); - $this->assertEquals($columns_id[1], $columns[0]['id']); - - // Move column 4 down (must do nothing because it's the last column) - $this->assertFalse($b->moveDown(2, $columns[3]['id'])); - $columns = $b->getColumns(2); - - // Order: 6, 7, 5, 8 - - $this->assertEquals(4, $columns[3]['position']); - $this->assertEquals($columns_id[3], $columns[3]['id']); - } - - public function testMoveUpAndRemoveColumn() - { - $p = new Project($this->container); - $b = new Board($this->container); - - // We create a project - $this->assertEquals(1, $p->create(array('name' => 'UnitTest1'))); - - // We remove the second column - $this->assertTrue($b->removeColumn(2)); - - $columns = $b->getColumns(1); - $this->assertNotEmpty($columns); - $this->assertCount(3, $columns); - - $this->assertEquals(1, $columns[0]['position']); - $this->assertEquals(3, $columns[1]['position']); - $this->assertEquals(4, $columns[2]['position']); - - $this->assertEquals(1, $columns[0]['id']); - $this->assertEquals(3, $columns[1]['id']); - $this->assertEquals(4, $columns[2]['id']); - - // We move up the second column - $this->assertTrue($b->moveUp(1, $columns[1]['id'])); - - // Check the new positions - $columns = $b->getColumns(1); - $this->assertNotEmpty($columns); - $this->assertCount(3, $columns); - - $this->assertEquals(1, $columns[0]['position']); - $this->assertEquals(2, $columns[1]['position']); - $this->assertEquals(3, $columns[2]['position']); - - $this->assertEquals(3, $columns[0]['id']); - $this->assertEquals(1, $columns[1]['id']); - $this->assertEquals(4, $columns[2]['id']); - } - - public function testMoveDownAndRemoveColumn() - { - $p = new Project($this->container); - $b = new Board($this->container); - - // We create a project - $this->assertEquals(1, $p->create(array('name' => 'UnitTest1'))); - - // We remove the second column - $this->assertTrue($b->removeColumn(2)); - - $columns = $b->getColumns(1); - $this->assertNotEmpty($columns); - $this->assertCount(3, $columns); - - $this->assertEquals(1, $columns[0]['position']); - $this->assertEquals(3, $columns[1]['position']); - $this->assertEquals(4, $columns[2]['position']); - - $this->assertEquals(1, $columns[0]['id']); - $this->assertEquals(3, $columns[1]['id']); - $this->assertEquals(4, $columns[2]['id']); - - // We move up the second column - $this->assertTrue($b->moveDown(1, $columns[0]['id'])); - - // Check the new positions - $columns = $b->getColumns(1); - $this->assertNotEmpty($columns); - $this->assertCount(3, $columns); - - $this->assertEquals(1, $columns[0]['position']); - $this->assertEquals(2, $columns[1]['position']); - $this->assertEquals(3, $columns[2]['position']); - - $this->assertEquals(3, $columns[0]['id']); - $this->assertEquals(1, $columns[1]['id']); - $this->assertEquals(4, $columns[2]['id']); - } } diff --git a/tests/units/Model/ColumnTest.php b/tests/units/Model/ColumnTest.php index a03c3717..e40f89c6 100644 --- a/tests/units/Model/ColumnTest.php +++ b/tests/units/Model/ColumnTest.php @@ -7,6 +7,174 @@ use Kanboard\Model\Column; class ColumnTest extends Base { + public function testGetColumn() + { + $projectModel = new Project($this->container); + $columnModel = new Column($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'UnitTest'))); + + $column = $columnModel->getById(3); + $this->assertNotEmpty($column); + $this->assertEquals('Work in progress', $column['title']); + + $column = $columnModel->getById(33); + $this->assertEmpty($column); + } + + public function testGetFirstColumnId() + { + $projectModel = new Project($this->container); + $columnModel = new Column($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'UnitTest'))); + $this->assertEquals(1, $columnModel->getFirstColumnId(1)); + } + + public function testGetLastColumnId() + { + $projectModel = new Project($this->container); + $columnModel = new Column($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'UnitTest'))); + $this->assertEquals(4, $columnModel->getLastColumnId(1)); + } + + public function testGetLastColumnPosition() + { + $projectModel = new Project($this->container); + $columnModel = new Column($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'UnitTest'))); + $this->assertEquals(4, $columnModel->getLastColumnPosition(1)); + } + + public function testGetColumnIdByTitle() + { + $projectModel = new Project($this->container); + $columnModel = new Column($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'UnitTest'))); + $this->assertEquals(2, $columnModel->getColumnIdByTitle(1, 'Ready')); + } + + public function testGetTitleByColumnId() + { + $projectModel = new Project($this->container); + $columnModel = new Column($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'UnitTest'))); + $this->assertEquals('Work in progress', $columnModel->getColumnTitleById(3)); + } + + public function testGetAll() + { + $projectModel = new Project($this->container); + $columnModel = new Column($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'UnitTest'))); + + $columns = $columnModel->getAll(1); + $this->assertCount(4, $columns); + + $this->assertEquals(1, $columns[0]['id']); + $this->assertEquals(1, $columns[0]['position']); + $this->assertEquals('Backlog', $columns[0]['title']); + + $this->assertEquals(2, $columns[1]['id']); + $this->assertEquals(2, $columns[1]['position']); + $this->assertEquals('Ready', $columns[1]['title']); + + $this->assertEquals(3, $columns[2]['id']); + $this->assertEquals(3, $columns[2]['position']); + $this->assertEquals('Work in progress', $columns[2]['title']); + + $this->assertEquals(4, $columns[3]['id']); + $this->assertEquals(4, $columns[3]['position']); + $this->assertEquals('Done', $columns[3]['title']); + } + + public function testGetList() + { + $projectModel = new Project($this->container); + $columnModel = new Column($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'UnitTest'))); + + $columns = $columnModel->getList(1); + $this->assertCount(4, $columns); + $this->assertEquals('Backlog', $columns[1]); + $this->assertEquals('Ready', $columns[2]); + $this->assertEquals('Work in progress', $columns[3]); + $this->assertEquals('Done', $columns[4]); + + $columns = $columnModel->getList(1, true); + $this->assertCount(5, $columns); + $this->assertEquals('All columns', $columns[-1]); + $this->assertEquals('Backlog', $columns[1]); + $this->assertEquals('Ready', $columns[2]); + $this->assertEquals('Work in progress', $columns[3]); + $this->assertEquals('Done', $columns[4]); + } + + public function testAddColumn() + { + $projectModel = new Project($this->container); + $columnModel = new Column($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'UnitTest'))); + $this->assertNotFalse($columnModel->create(1, 'another column')); + $this->assertNotFalse($columnModel->create(1, 'one more', 3, 'one more description')); + + $columns = $columnModel->getAll(1); + $this->assertTrue(is_array($columns)); + $this->assertEquals(6, count($columns)); + + $this->assertEquals('another column', $columns[4]['title']); + $this->assertEquals(0, $columns[4]['task_limit']); + $this->assertEquals(5, $columns[4]['position']); + + $this->assertEquals('one more', $columns[5]['title']); + $this->assertEquals(3, $columns[5]['task_limit']); + $this->assertEquals(6, $columns[5]['position']); + $this->assertEquals('one more description', $columns[5]['description']); + } + + public function testUpdateColumn() + { + $projectModel = new Project($this->container); + $columnModel = new Column($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'UnitTest'))); + + $this->assertTrue($columnModel->update(3, 'blah', 5)); + $this->assertTrue($columnModel->update(2, 'boo')); + + $column = $columnModel->getById(3); + $this->assertNotEmpty($column); + $this->assertEquals('blah', $column['title']); + $this->assertEquals(5, $column['task_limit']); + + $column = $columnModel->getById(2); + $this->assertNotEmpty($column); + $this->assertEquals('boo', $column['title']); + $this->assertEquals(0, $column['task_limit']); + } + + public function testRemoveColumn() + { + $projectModel = new Project($this->container); + $columnModel = new Column($this->container); + + $this->assertEquals(1, $projectModel->create(array('name' => 'UnitTest'))); + $this->assertTrue($columnModel->remove(3)); + $this->assertFalse($columnModel->remove(322)); + + $columns = $columnModel->getAll(1); + $this->assertTrue(is_array($columns)); + $this->assertEquals(3, count($columns)); + } + public function testChangePosition() { $projectModel = new Project($this->container); diff --git a/tests/units/Model/ProjectTest.php b/tests/units/Model/ProjectTest.php index cadb42a6..5478fa40 100644 --- a/tests/units/Model/ProjectTest.php +++ b/tests/units/Model/ProjectTest.php @@ -8,8 +8,6 @@ use Kanboard\Model\Project; use Kanboard\Model\User; use Kanboard\Model\Task; use Kanboard\Model\TaskCreation; -use Kanboard\Model\Acl; -use Kanboard\Model\Board; use Kanboard\Model\Config; use Kanboard\Model\Category; diff --git a/tests/units/Model/TaskPositionTest.php b/tests/units/Model/TaskPositionTest.php index 5f045768..28145a66 100644 --- a/tests/units/Model/TaskPositionTest.php +++ b/tests/units/Model/TaskPositionTest.php @@ -3,7 +3,7 @@ require_once __DIR__.'/../Base.php'; use Kanboard\Model\Task; -use Kanboard\Model\Board; +use Kanboard\Model\Column; use Kanboard\Model\TaskStatus; use Kanboard\Model\TaskPosition; use Kanboard\Model\TaskCreation; @@ -21,23 +21,23 @@ class TaskPositionTest extends Base $tc = new TaskCreation($this->container); $tf = new TaskFinder($this->container); $p = new Project($this->container); - $b = new Board($this->container); + $columnModel = new Column($this->container); $this->assertEquals(1, $p->create(array('name' => 'Project #1'))); $this->assertEquals(1, $tc->create(array('title' => 'Task #1', 'project_id' => 1, 'column_id' => 1))); - $this->assertEquals(0, $t->getProgress($tf->getById(1), $b->getColumnsList(1))); + $this->assertEquals(0, $t->getProgress($tf->getById(1), $columnModel->getList(1))); $this->assertTrue($tp->movePosition(1, 1, 2, 1)); - $this->assertEquals(25, $t->getProgress($tf->getById(1), $b->getColumnsList(1))); + $this->assertEquals(25, $t->getProgress($tf->getById(1), $columnModel->getList(1))); $this->assertTrue($tp->movePosition(1, 1, 3, 1)); - $this->assertEquals(50, $t->getProgress($tf->getById(1), $b->getColumnsList(1))); + $this->assertEquals(50, $t->getProgress($tf->getById(1), $columnModel->getList(1))); $this->assertTrue($tp->movePosition(1, 1, 4, 1)); - $this->assertEquals(75, $t->getProgress($tf->getById(1), $b->getColumnsList(1))); + $this->assertEquals(75, $t->getProgress($tf->getById(1), $columnModel->getList(1))); $this->assertTrue($ts->close(1)); - $this->assertEquals(100, $t->getProgress($tf->getById(1), $b->getColumnsList(1))); + $this->assertEquals(100, $t->getProgress($tf->getById(1), $columnModel->getList(1))); } public function testMoveTaskToWrongPosition() -- cgit v1.2.3 From 5fe68d4d499a8496229763369b50d71c9fa16200 Mon Sep 17 00:00:00 2001 From: Frederic Guillot Date: Sat, 20 Feb 2016 18:11:08 -0500 Subject: Add drag and drop to change swimlane positions --- ChangeLog | 6 +- app/Api/Swimlane.php | 11 +- app/Controller/Column.php | 3 +- app/Controller/Swimlane.php | 97 +++++++++--- app/Locale/bs_BA/translations.php | 6 +- app/Locale/cs_CZ/translations.php | 6 +- app/Locale/da_DK/translations.php | 6 +- app/Locale/de_DE/translations.php | 6 +- app/Locale/el_GR/translations.php | 6 +- app/Locale/es_ES/translations.php | 6 +- app/Locale/fi_FI/translations.php | 6 +- app/Locale/fr_FR/translations.php | 6 +- app/Locale/hu_HU/translations.php | 6 +- app/Locale/id_ID/translations.php | 6 +- app/Locale/it_IT/translations.php | 6 +- app/Locale/ja_JP/translations.php | 6 +- app/Locale/my_MY/translations.php | 6 +- app/Locale/nb_NO/translations.php | 6 +- app/Locale/nl_NL/translations.php | 6 +- app/Locale/pl_PL/translations.php | 6 +- app/Locale/pt_BR/translations.php | 6 +- app/Locale/pt_PT/translations.php | 6 +- app/Locale/ru_RU/translations.php | 6 +- app/Locale/sr_Latn_RS/translations.php | 6 +- app/Locale/sv_SE/translations.php | 6 +- app/Locale/th_TH/translations.php | 6 +- app/Locale/tr_TR/translations.php | 6 +- app/Locale/zh_CN/translations.php | 6 +- app/Model/Swimlane.php | 106 +++++++------ app/Template/swimlane/create.php | 37 +++++ app/Template/swimlane/edit_default.php | 18 +++ app/Template/swimlane/index.php | 87 +++-------- app/Template/swimlane/table.php | 113 +++++++++----- assets/js/app.js | 2 +- assets/js/src/App.js | 2 +- assets/js/src/Swimlane.js | 56 ++++++- doc/api-column-procedures.markdown | 2 +- doc/api-swimlane-procedures.markdown | 43 +----- tests/integration/ApiTest.php | 128 ---------------- tests/integration/SwimlaneTest.php | 103 +++++++++++++ tests/units/Model/SwimlaneTest.php | 273 +++++++++++++-------------------- 41 files changed, 587 insertions(+), 644 deletions(-) create mode 100644 app/Template/swimlane/create.php create mode 100644 app/Template/swimlane/edit_default.php create mode 100644 tests/integration/SwimlaneTest.php (limited to 'app/Controller/Column.php') diff --git a/ChangeLog b/ChangeLog index 11dbbfb4..619e9438 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,11 +3,13 @@ Version 1.0.26 (unreleased) Breaking changes: -* API procedures: "moveColumnUp" and "moveColumnDown" are replace by "changeColumnPosition" +* API procedures: + - "moveColumnUp" and "moveColumnDown" are replace by "changeColumnPosition" + - "moveSwimlaneUp" and "moveSwimlaneDown" are replace by "changeSwimlanePosition" New features: -* Add drag and drop to change subtasks and columns positions +* Add drag and drop to change subtasks, swimlanes and columns positions * Add file drag and drop and asynchronous upload * Enable/Disable users * Add setting option to disable private projects diff --git a/app/Api/Swimlane.php b/app/Api/Swimlane.php index 84c699ab..03a2819f 100644 --- a/app/Api/Swimlane.php +++ b/app/Api/Swimlane.php @@ -48,9 +48,11 @@ class Swimlane extends \Kanboard\Core\Base public function updateSwimlane($swimlane_id, $name, $description = null) { $values = array('id' => $swimlane_id, 'name' => $name); + if (!is_null($description)) { $values['description'] = $description; } + return $this->swimlane->update($values); } @@ -69,13 +71,8 @@ class Swimlane extends \Kanboard\Core\Base return $this->swimlane->enable($project_id, $swimlane_id); } - public function moveSwimlaneUp($project_id, $swimlane_id) - { - return $this->swimlane->moveUp($project_id, $swimlane_id); - } - - public function moveSwimlaneDown($project_id, $swimlane_id) + public function changeSwimlanePosition($project_id, $swimlane_id, $position) { - return $this->swimlane->moveDown($project_id, $swimlane_id); + return $this->swimlane->changePosition($project_id, $swimlane_id, $position); } } diff --git a/app/Controller/Column.php b/app/Controller/Column.php index e02c7dcb..66073b56 100644 --- a/app/Controller/Column.php +++ b/app/Controller/Column.php @@ -35,7 +35,6 @@ class Column extends Base public function create(array $values = array(), array $errors = array()) { $project = $this->getProject(); - $columns = $this->column->getList($project['id']); if (empty($values)) { $values = array('project_id' => $project['id']); @@ -126,7 +125,7 @@ class Column extends Base $project = $this->getProject(); $values = $this->request->getJson(); - if (! empty($values)) { + if (! empty($values) && isset($values['column_id']) && isset($values['position'])) { $result = $this->column->changePosition($project['id'], $values['column_id'], $values['position']); return $this->response->json(array('result' => $result)); } diff --git a/app/Controller/Swimlane.php b/app/Controller/Swimlane.php index 4e8c2863..8270a16f 100644 --- a/app/Controller/Swimlane.php +++ b/app/Controller/Swimlane.php @@ -36,7 +36,7 @@ class Swimlane extends Base * * @access public */ - public function index(array $values = array(), array $errors = array()) + public function index() { $project = $this->getProject(); @@ -44,10 +44,24 @@ class Swimlane extends Base 'default_swimlane' => $this->swimlane->getDefault($project['id']), 'active_swimlanes' => $this->swimlane->getAllByStatus($project['id'], SwimlaneModel::ACTIVE), 'inactive_swimlanes' => $this->swimlane->getAllByStatus($project['id'], SwimlaneModel::INACTIVE), + 'project' => $project, + 'title' => t('Swimlanes') + ))); + } + + /** + * Create a new swimlane + * + * @access public + */ + public function create(array $values = array(), array $errors = array()) + { + $project = $this->getProject(); + + $this->response->html($this->template->render('swimlane/create', array( 'values' => $values + array('project_id' => $project['id']), 'errors' => $errors, 'project' => $project, - 'title' => t('Swimlanes') ))); } @@ -67,11 +81,28 @@ class Swimlane extends Base $this->flash->success(t('Your swimlane have been created successfully.')); $this->response->redirect($this->helper->url->to('swimlane', 'index', array('project_id' => $project['id']))); } else { - $this->flash->failure(t('Unable to create your swimlane.')); + $errors = array('name' => array(t('Another swimlane with the same name exists in the project'))); } } - $this->index($values, $errors); + $this->create($values, $errors); + } + + /** + * Edit default swimlane (display the form) + * + * @access public + */ + public function editDefault(array $values = array(), array $errors = array()) + { + $project = $this->getProject(); + $swimlane = $this->swimlane->getDefault($project['id']); + + $this->response->html($this->helper->layout->project('swimlane/edit_default', array( + 'values' => empty($values) ? $swimlane : $values, + 'errors' => $errors, + 'project' => $project, + ))); } /** @@ -79,23 +110,23 @@ class Swimlane extends Base * * @access public */ - public function change() + public function updateDefault() { $project = $this->getProject(); $values = $this->request->getValues() + array('show_default_swimlane' => 0); - list($valid, ) = $this->swimlaneValidator->validateDefaultModification($values); + list($valid, $errors) = $this->swimlaneValidator->validateDefaultModification($values); if ($valid) { if ($this->swimlane->updateDefault($values)) { $this->flash->success(t('The default swimlane have been updated successfully.')); - $this->response->redirect($this->helper->url->to('swimlane', 'index', array('project_id' => $project['id']))); + $this->response->redirect($this->helper->url->to('swimlane', 'index', array('project_id' => $project['id'])), true); } else { $this->flash->failure(t('Unable to update this swimlane.')); } } - $this->index(); + $this->editDefault($values, $errors); } /** @@ -112,7 +143,6 @@ class Swimlane extends Base 'values' => empty($values) ? $swimlane : $values, 'errors' => $errors, 'project' => $project, - 'title' => t('Swimlanes') ))); } @@ -133,7 +163,7 @@ class Swimlane extends Base $this->flash->success(t('Swimlane updated successfully.')); $this->response->redirect($this->helper->url->to('swimlane', 'index', array('project_id' => $project['id']))); } else { - $this->flash->failure(t('Unable to update this swimlane.')); + $errors = array('name' => array(t('Another swimlane with the same name exists in the project'))); } } @@ -153,7 +183,6 @@ class Swimlane extends Base $this->response->html($this->helper->layout->project('swimlane/remove', array( 'project' => $project, 'swimlane' => $swimlane, - 'title' => t('Remove a swimlane') ))); } @@ -197,6 +226,25 @@ class Swimlane extends Base $this->response->redirect($this->helper->url->to('swimlane', 'index', array('project_id' => $project['id']))); } + /** + * Disable default swimlane + * + * @access public + */ + public function disableDefault() + { + $this->checkCSRFParam(); + $project = $this->getProject(); + + if ($this->swimlane->disableDefault($project['id'])) { + $this->flash->success(t('Swimlane updated successfully.')); + } else { + $this->flash->failure(t('Unable to update this swimlane.')); + } + + $this->response->redirect($this->helper->url->to('swimlane', 'index', array('project_id' => $project['id']))); + } + /** * Enable a swimlane * @@ -218,32 +266,39 @@ class Swimlane extends Base } /** - * Move up a swimlane + * Enable default swimlane * * @access public */ - public function moveup() + public function enableDefault() { $this->checkCSRFParam(); $project = $this->getProject(); - $swimlane_id = $this->request->getIntegerParam('swimlane_id'); - $this->swimlane->moveUp($project['id'], $swimlane_id); + if ($this->swimlane->enableDefault($project['id'])) { + $this->flash->success(t('Swimlane updated successfully.')); + } else { + $this->flash->failure(t('Unable to update this swimlane.')); + } + $this->response->redirect($this->helper->url->to('swimlane', 'index', array('project_id' => $project['id']))); } /** - * Move down a swimlane + * Move swimlane position * * @access public */ - public function movedown() + public function move() { - $this->checkCSRFParam(); $project = $this->getProject(); - $swimlane_id = $this->request->getIntegerParam('swimlane_id'); + $values = $this->request->getJson(); - $this->swimlane->moveDown($project['id'], $swimlane_id); - $this->response->redirect($this->helper->url->to('swimlane', 'index', array('project_id' => $project['id']))); + if (! empty($values) && isset($values['swimlane_id']) && isset($values['position'])) { + $result = $this->swimlane->changePosition($project['id'], $values['swimlane_id'], $values['position']); + return $this->response->json(array('result' => $result)); + } + + $this->forbidden(); } } diff --git a/app/Locale/bs_BA/translations.php b/app/Locale/bs_BA/translations.php index 95cafaeb..5dbb4ffc 100644 --- a/app/Locale/bs_BA/translations.php +++ b/app/Locale/bs_BA/translations.php @@ -72,7 +72,6 @@ return array( 'Remove project' => 'Ukloni projekat', 'Edit the board for "%s"' => 'Uredi tablu za "%s"', 'All projects' => 'Svi projekti', - 'Change columns' => 'Zamijeni kolonu', 'Add a new column' => 'Dodaj novu kolonu', 'Title' => 'Naslov', 'Nobody assigned' => 'Niko nije dodijeljen', @@ -208,8 +207,6 @@ return array( 'Assign a color to a specific user' => 'Dodeli boju korisniku', 'Column title' => 'Naslov kolone', 'Position' => 'Pozicija', - 'Move Up' => 'Podigni', - 'Move Down' => 'Spusti', 'Duplicate to another project' => 'Dupliciraj u drugi projekat', 'Duplicate' => 'Dupliciraj', 'link' => 'link', @@ -501,7 +498,6 @@ return array( 'Do you really want to remove this swimlane: "%s"?' => 'Da li zaista želiš ukloniti ovu swimline traku: "%s"?', 'Inactive swimlanes' => 'Neaktivne swimline trake', 'Remove a swimlane' => 'Ukloni swimline traku', - 'Rename' => 'Preimenuj', 'Show default swimlane' => 'Prikaži podrazumijevanu swimline traku', 'Swimlane modification for the project "%s"' => 'Izmjene swimline trake za projekat "%s"', 'Swimlane not found.' => 'Swimline traka nije pronađena.', @@ -509,7 +505,6 @@ return array( 'Swimlanes' => 'Swimline trake', 'Swimlane updated successfully.' => 'Swimline traka uspjeno ažurirana.', 'The default swimlane have been updated successfully.' => 'Podrazumijevana swimline traka uspješno ažurirana.', - 'Unable to create your swimlane.' => 'Nemoguće kreirati swimline traku.', 'Unable to remove this swimlane.' => 'Nemoguće ukloniti swimline traku.', 'Unable to update this swimlane.' => 'Nemoguće ažurirati swimline traku.', 'Your swimlane have been created successfully.' => 'Swimline traka je uspješno kreirana.', @@ -1152,4 +1147,5 @@ return array( // 'Last activity' => '', // 'Change subtask position' => '', // 'This value must be greater than %d' => '', + // 'Another swimlane with the same name exists in the project' => '', ); diff --git a/app/Locale/cs_CZ/translations.php b/app/Locale/cs_CZ/translations.php index cd0ce06c..95a4ea13 100644 --- a/app/Locale/cs_CZ/translations.php +++ b/app/Locale/cs_CZ/translations.php @@ -72,7 +72,6 @@ return array( 'Remove project' => 'Vyjmout projekt', 'Edit the board for "%s"' => 'Editace nástěnky pro "%s" ', 'All projects' => 'Všechny projekty', - 'Change columns' => 'Změna sloupců', 'Add a new column' => 'Přidat nový sloupec', 'Title' => 'Název', 'Nobody assigned' => 'Nepřiřazena žádná osoba', @@ -208,8 +207,6 @@ return array( 'Assign a color to a specific user' => 'Přiřadit barvu konkrétnímu uživateli', 'Column title' => 'Název sloupce', 'Position' => 'Pozice', - 'Move Up' => 'Posunout nahoru', - 'Move Down' => 'Posunout dolu', 'Duplicate to another project' => 'Vytvořit kopii v jiném projektu', 'Duplicate' => 'Vytvořit kopii', 'link' => 'Link', @@ -501,7 +498,6 @@ return array( 'Do you really want to remove this swimlane: "%s"?' => 'Diese Swimlane wirklich ändern: "%s"?', 'Inactive swimlanes' => 'Inaktive Swimlane', 'Remove a swimlane' => 'Odstranit swimlane', - 'Rename' => 'Přejmenovat', 'Show default swimlane' => 'Standard Swimlane anzeigen', 'Swimlane modification for the project "%s"' => 'Swimlane Änderung für das Projekt "%s"', 'Swimlane not found.' => 'Swimlane nicht gefunden', @@ -509,7 +505,6 @@ return array( 'Swimlanes' => 'Swimlanes', 'Swimlane updated successfully.' => 'Swimlane erfolgreich geändert.', 'The default swimlane have been updated successfully.' => 'Die standard Swimlane wurden erfolgreich aktualisiert. Die standard Swimlane wurden erfolgreich aktualisiert.', - 'Unable to create your swimlane.' => 'Es ist nicht möglich die Swimlane zu erstellen.', 'Unable to remove this swimlane.' => 'Es ist nicht möglich die Swimlane zu entfernen.', 'Unable to update this swimlane.' => 'Es ist nicht möglich die Swimöane zu ändern.', 'Your swimlane have been created successfully.' => 'Die Swimlane wurde erfolgreich angelegt.', @@ -1152,4 +1147,5 @@ return array( // 'Last activity' => '', // 'Change subtask position' => '', // 'This value must be greater than %d' => '', + // 'Another swimlane with the same name exists in the project' => '', ); diff --git a/app/Locale/da_DK/translations.php b/app/Locale/da_DK/translations.php index 05c1d61f..d8dec37f 100644 --- a/app/Locale/da_DK/translations.php +++ b/app/Locale/da_DK/translations.php @@ -72,7 +72,6 @@ return array( 'Remove project' => 'Fjern projekt', 'Edit the board for "%s"' => 'Rediger boardet for "%s"', 'All projects' => 'Alle Projekter', - 'Change columns' => 'Ændre kolonner', 'Add a new column' => 'Tilføj en ny kolonne', 'Title' => 'Titel', 'Nobody assigned' => 'Ingen ansvarlig', @@ -208,8 +207,6 @@ return array( 'Assign a color to a specific user' => 'Tildel en farve til en bestemt bruger', 'Column title' => 'Kolonne titel', 'Position' => 'Position', - 'Move Up' => 'Ryk op', - 'Move Down' => 'Ryk ned', 'Duplicate to another project' => 'Kopier til et andet projekt', 'Duplicate' => 'Kopier', 'link' => 'link', @@ -501,7 +498,6 @@ return array( // 'Do you really want to remove this swimlane: "%s"?' => '', // 'Inactive swimlanes' => '', // 'Remove a swimlane' => '', - // 'Rename' => '', // 'Show default swimlane' => '', // 'Swimlane modification for the project "%s"' => '', // 'Swimlane not found.' => '', @@ -509,7 +505,6 @@ return array( // 'Swimlanes' => '', // 'Swimlane updated successfully.' => '', // 'The default swimlane have been updated successfully.' => '', - // 'Unable to create your swimlane.' => '', // 'Unable to remove this swimlane.' => '', // 'Unable to update this swimlane.' => '', // 'Your swimlane have been created successfully.' => '', @@ -1152,4 +1147,5 @@ return array( // 'Last activity' => '', // 'Change subtask position' => '', // 'This value must be greater than %d' => '', + // 'Another swimlane with the same name exists in the project' => '', ); diff --git a/app/Locale/de_DE/translations.php b/app/Locale/de_DE/translations.php index 4e1b8690..6c9f4a45 100644 --- a/app/Locale/de_DE/translations.php +++ b/app/Locale/de_DE/translations.php @@ -72,7 +72,6 @@ return array( 'Remove project' => 'Projekt löschen', 'Edit the board for "%s"' => 'Pinnwand für "%s" bearbeiten', 'All projects' => 'Alle Projekte', - 'Change columns' => 'Spalten ändern', 'Add a new column' => 'Neue Spalte hinzufügen', 'Title' => 'Titel', 'Nobody assigned' => 'Nicht zugeordnet', @@ -208,8 +207,6 @@ return array( 'Assign a color to a specific user' => 'Einem Benutzer eine Farbe zuordnen', 'Column title' => 'Spaltentitel', 'Position' => 'Position', - 'Move Up' => 'nach oben', - 'Move Down' => 'nach unten', 'Duplicate to another project' => 'In ein anderes Projekt duplizieren', 'Duplicate' => 'Duplizieren', 'link' => 'Link', @@ -501,7 +498,6 @@ return array( 'Do you really want to remove this swimlane: "%s"?' => 'Diese Swimlane wirklich ändern: "%s"?', 'Inactive swimlanes' => 'Inaktive Swimlane', 'Remove a swimlane' => 'Swimlane entfernen', - 'Rename' => 'umbenennen', 'Show default swimlane' => 'Standard-Swimlane anzeigen', 'Swimlane modification for the project "%s"' => 'Swimlane-Änderung für das Projekt "%s"', 'Swimlane not found.' => 'Swimlane nicht gefunden', @@ -509,7 +505,6 @@ return array( 'Swimlanes' => 'Swimlanes', 'Swimlane updated successfully.' => 'Swimlane erfolgreich geändert.', 'The default swimlane have been updated successfully.' => 'Die Standard-Swimlane wurden erfolgreich aktualisiert. Die Standard-Swimlane wurden erfolgreich aktualisiert.', - 'Unable to create your swimlane.' => 'Es ist nicht möglich, Swimlane zu erstellen.', 'Unable to remove this swimlane.' => 'Es ist nicht möglich, die Swimlane zu entfernen.', 'Unable to update this swimlane.' => 'Es ist nicht möglich, die Swimlane zu ändern.', 'Your swimlane have been created successfully.' => 'Die Swimlane wurde erfolgreich angelegt.', @@ -1152,4 +1147,5 @@ return array( // 'Last activity' => '', // 'Change subtask position' => '', // 'This value must be greater than %d' => '', + // 'Another swimlane with the same name exists in the project' => '', ); diff --git a/app/Locale/el_GR/translations.php b/app/Locale/el_GR/translations.php index 94373048..a06c8d06 100644 --- a/app/Locale/el_GR/translations.php +++ b/app/Locale/el_GR/translations.php @@ -72,7 +72,6 @@ return array( 'Remove project' => 'Αφαίρεση του έργου', 'Edit the board for "%s"' => 'Διόρθωση πίνακα από « %s »', 'All projects' => 'Όλα τα έργα', - 'Change columns' => 'Αλλαγή στηλών', 'Add a new column' => 'Πρόσθήκη στήλης', 'Title' => 'Τίτλος', 'Nobody assigned' => 'Δεν έχει ανατεθεί', @@ -208,8 +207,6 @@ return array( 'Assign a color to a specific user' => 'Ανάθεση χρώματος σε συγκεκριμένο χρήστη', 'Column title' => 'Τίτλος στήλης', 'Position' => 'Θέση', - 'Move Up' => 'Μετακίνηση πάνω', - 'Move Down' => 'Μετακίνηση κάτω', 'Duplicate to another project' => 'Αντιγραφή σε άλλο έργο', 'Duplicate' => 'Αντιγραφή', 'link' => 'σύνδεσμος', @@ -501,7 +498,6 @@ return array( 'Do you really want to remove this swimlane: "%s"?' => 'Σίγουρα θέλετε να αφαιρέσετε τη λωρίδα : « %s » ?', 'Inactive swimlanes' => 'Λωρίδες ανενεργές', 'Remove a swimlane' => 'Αφαιρέστε μια λωρίδα', - 'Rename' => 'Μετονομασία', 'Show default swimlane' => 'Εμφάνιση προεπιλεγμένων λωρίδων', 'Swimlane modification for the project "%s"' => 'Τροποποίηση λωρίδας για το έργο « %s »', 'Swimlane not found.' => 'Η λωρίδα δεν βρέθηκε.', @@ -509,7 +505,6 @@ return array( 'Swimlanes' => 'Swimlanes', 'Swimlane updated successfully.' => 'Η λωρίδα ενημερώθηκε με επιτυχία.', 'The default swimlane have been updated successfully.' => 'Η προεπιλεγμένη λωρίδα ενημερώθηκε με επιτυχία.', - 'Unable to create your swimlane.' => 'Αδύνατο να δημιουργηθεί η λωρίδα.', 'Unable to remove this swimlane.' => 'Αδύνατο να αφαιρεθεί η λωρίδα.', 'Unable to update this swimlane.' => 'Αδύνατο να ενημερωθεί η λωρίδα.', 'Your swimlane have been created successfully.' => 'Η λωρίδα δημιουργήθηκε με επιτυχία.', @@ -1152,4 +1147,5 @@ return array( // 'Last activity' => '', // 'Change subtask position' => '', // 'This value must be greater than %d' => '', + // 'Another swimlane with the same name exists in the project' => '', ); diff --git a/app/Locale/es_ES/translations.php b/app/Locale/es_ES/translations.php index 359dea61..7d1154c9 100644 --- a/app/Locale/es_ES/translations.php +++ b/app/Locale/es_ES/translations.php @@ -72,7 +72,6 @@ return array( 'Remove project' => 'Suprimir el proyecto', 'Edit the board for "%s"' => 'Modificar el tablero para « %s »', 'All projects' => 'Todos los proyectos', - 'Change columns' => 'Cambiar las columnas', 'Add a new column' => 'Añadir una nueva columna', 'Title' => 'Título', 'Nobody assigned' => 'Nadie asignado', @@ -208,8 +207,6 @@ return array( 'Assign a color to a specific user' => 'Asignar un color a un usuario específico', 'Column title' => 'Título de la columna', 'Position' => 'Posición', - 'Move Up' => 'Mover hacia arriba', - 'Move Down' => 'Mover hacia abajo', 'Duplicate to another project' => 'Duplicar a otro proyecto', 'Duplicate' => 'Duplicar', 'link' => 'vinculación', @@ -501,7 +498,6 @@ return array( 'Do you really want to remove this swimlane: "%s"?' => '¿Realmente quiere quitar esta calle: "%s"?', 'Inactive swimlanes' => 'Calles inactivas', 'Remove a swimlane' => 'Quitar un calle', - 'Rename' => 'Renombrar', 'Show default swimlane' => 'Mostrar calle por defecto', 'Swimlane modification for the project "%s"' => 'Modificación de la calle para el proyecto "%s"', 'Swimlane not found.' => 'Calle no encontrada', @@ -509,7 +505,6 @@ return array( 'Swimlanes' => 'Calles', 'Swimlane updated successfully.' => 'Calle actualizada correctamente', 'The default swimlane have been updated successfully.' => 'La calle por defecto ha sido actualizada correctamente', - 'Unable to create your swimlane.' => 'Imposible crear su calle', 'Unable to remove this swimlane.' => 'Imposible de quitar esta calle', 'Unable to update this swimlane.' => 'Imposible de actualizar esta calle', 'Your swimlane have been created successfully.' => 'Su calle ha sido creada correctamente', @@ -1152,4 +1147,5 @@ return array( // 'Last activity' => '', // 'Change subtask position' => '', // 'This value must be greater than %d' => '', + // 'Another swimlane with the same name exists in the project' => '', ); diff --git a/app/Locale/fi_FI/translations.php b/app/Locale/fi_FI/translations.php index f72e62c8..5395308d 100644 --- a/app/Locale/fi_FI/translations.php +++ b/app/Locale/fi_FI/translations.php @@ -72,7 +72,6 @@ return array( 'Remove project' => 'Poista projekti', 'Edit the board for "%s"' => 'Muokkaa taulua projektille "%s"', 'All projects' => 'Kaikki projektit', - 'Change columns' => 'Muokkaa sarakkeita', 'Add a new column' => 'Lisää uusi sarake', 'Title' => 'Nimi', 'Nobody assigned' => 'Ei suorittajaa', @@ -208,8 +207,6 @@ return array( 'Assign a color to a specific user' => 'Valitse väri käyttäjälle', 'Column title' => 'Sarakkeen nimi', 'Position' => 'Positio', - 'Move Up' => 'Siirrä ylös', - 'Move Down' => 'Siirrä alas', 'Duplicate to another project' => 'Kopioi toiseen projektiin', 'Duplicate' => 'Monista', 'link' => 'linkki', @@ -501,7 +498,6 @@ return array( 'Do you really want to remove this swimlane: "%s"?' => 'Haluatko varmasti poistaa tämän kaistan: "%s"?', 'Inactive swimlanes' => 'Passiiviset kaistat', 'Remove a swimlane' => 'Poista kaista', - 'Rename' => 'Uudelleennimeä', 'Show default swimlane' => 'Näytä oletuskaista', 'Swimlane modification for the project "%s"' => 'Kaistamuutos projektille "%s"', 'Swimlane not found.' => 'Kaistaa ei löydy', @@ -509,7 +505,6 @@ return array( 'Swimlanes' => 'Kaistat', 'Swimlane updated successfully.' => 'Kaista päivitetty onnistuneesti.', 'The default swimlane have been updated successfully.' => 'Oletuskaista päivitetty onnistuneesti.', - 'Unable to create your swimlane.' => 'Kaistan luonti epäonnistui.', 'Unable to remove this swimlane.' => 'Kaistan poisto epäonnistui.', 'Unable to update this swimlane.' => 'Kaistan päivittäminen epäonnistui.', 'Your swimlane have been created successfully.' => 'Kaista luotu onnistuneesti.', @@ -1152,4 +1147,5 @@ return array( // 'Last activity' => '', // 'Change subtask position' => '', // 'This value must be greater than %d' => '', + // 'Another swimlane with the same name exists in the project' => '', ); diff --git a/app/Locale/fr_FR/translations.php b/app/Locale/fr_FR/translations.php index b346b479..c2132bda 100644 --- a/app/Locale/fr_FR/translations.php +++ b/app/Locale/fr_FR/translations.php @@ -72,7 +72,6 @@ return array( 'Remove project' => 'Supprimer le projet', 'Edit the board for "%s"' => 'Modifier le tableau pour « %s »', 'All projects' => 'Tous les projets', - 'Change columns' => 'Changer les colonnes', 'Add a new column' => 'Ajouter une nouvelle colonne', 'Title' => 'Titre', 'Nobody assigned' => 'Personne assignée', @@ -208,8 +207,6 @@ return array( 'Assign a color to a specific user' => 'Assigner une couleur à un utilisateur', 'Column title' => 'Titre de la colonne', 'Position' => 'Position', - 'Move Up' => 'Déplacer vers le haut', - 'Move Down' => 'Déplacer vers le bas', 'Duplicate to another project' => 'Dupliquer dans un autre projet', 'Duplicate' => 'Dupliquer', 'link' => 'lien', @@ -503,7 +500,6 @@ return array( 'Do you really want to remove this swimlane: "%s"?' => 'Voulez-vous vraiment supprimer cette swimlane : « %s » ?', 'Inactive swimlanes' => 'Swimlanes inactives', 'Remove a swimlane' => 'Supprimer une swimlane', - 'Rename' => 'Renommer', 'Show default swimlane' => 'Afficher la swimlane par défaut', 'Swimlane modification for the project "%s"' => 'Modification d\'une swimlane pour le projet « %s »', 'Swimlane not found.' => 'Cette swimlane est introuvable.', @@ -511,7 +507,6 @@ return array( 'Swimlanes' => 'Swimlanes', 'Swimlane updated successfully.' => 'Swimlane mise à jour avec succès.', 'The default swimlane have been updated successfully.' => 'La swimlane par défaut a été mise à jour avec succès.', - 'Unable to create your swimlane.' => 'Impossible de créer votre swimlane.', 'Unable to remove this swimlane.' => 'Impossible de supprimer cette swimlane.', 'Unable to update this swimlane.' => 'Impossible de mettre à jour cette swimlane.', 'Your swimlane have been created successfully.' => 'Votre swimlane a été créée avec succès.', @@ -1155,4 +1150,5 @@ return array( 'Last activity' => 'Dernières activités', 'Change subtask position' => 'Changer la position de la sous-tâche', 'This value must be greater than %d' => 'Cette valeur doit être plus grande que %d', + 'Another swimlane with the same name exists in the project' => 'Une autre swimlane existe avec le même nom dans le projet', ); diff --git a/app/Locale/hu_HU/translations.php b/app/Locale/hu_HU/translations.php index fe016170..54a9fc6a 100644 --- a/app/Locale/hu_HU/translations.php +++ b/app/Locale/hu_HU/translations.php @@ -72,7 +72,6 @@ return array( 'Remove project' => 'Projekt törlése', 'Edit the board for "%s"' => 'Tábla szerkesztése: "%s"', 'All projects' => 'Minden projekt', - 'Change columns' => 'Oszlop módosítása', 'Add a new column' => 'Új oszlop', 'Title' => 'Cím', 'Nobody assigned' => 'Nincs felelős', @@ -208,8 +207,6 @@ return array( 'Assign a color to a specific user' => 'Szín hozzárendelése a felhasználóhoz', 'Column title' => 'Oszlopfejléc', 'Position' => 'Pozíció', - 'Move Up' => 'Fel', - 'Move Down' => 'Le', 'Duplicate to another project' => 'Másolás másik projektbe', 'Duplicate' => 'Másolás', 'link' => 'link', @@ -501,7 +498,6 @@ return array( 'Do you really want to remove this swimlane: "%s"?' => 'Valóban törli a folyamatot:%s ?', 'Inactive swimlanes' => 'Inaktív folyamatok', 'Remove a swimlane' => 'Folyamat törlés', - 'Rename' => 'Átnevezés', 'Show default swimlane' => 'Alapértelmezett folyamat megjelenítése', 'Swimlane modification for the project "%s"' => '%s projekt folyamatainak módosítása', 'Swimlane not found.' => 'Folyamat nem található', @@ -509,7 +505,6 @@ return array( 'Swimlanes' => 'Folyamatok', 'Swimlane updated successfully.' => 'Folyamat sikeresn frissítve', 'The default swimlane have been updated successfully.' => 'Az alapértelmezett folyamat sikeresen frissítve.', - 'Unable to create your swimlane.' => 'A folyamat létrehozása sikertelen.', 'Unable to remove this swimlane.' => 'A folyamat törlése sikertelen.', 'Unable to update this swimlane.' => 'A folyamat frissítése sikertelen.', 'Your swimlane have been created successfully.' => 'A folyamat sikeresen létrehozva.', @@ -1152,4 +1147,5 @@ return array( // 'Last activity' => '', // 'Change subtask position' => '', // 'This value must be greater than %d' => '', + // 'Another swimlane with the same name exists in the project' => '', ); diff --git a/app/Locale/id_ID/translations.php b/app/Locale/id_ID/translations.php index 64c7e78f..bd6b11e5 100644 --- a/app/Locale/id_ID/translations.php +++ b/app/Locale/id_ID/translations.php @@ -72,7 +72,6 @@ return array( 'Remove project' => 'Hapus proyek', 'Edit the board for "%s"' => 'Rubah papan untuk « %s »', 'All projects' => 'Semua proyek', - 'Change columns' => 'Rubah kolom', 'Add a new column' => 'Tambah kolom baru', 'Title' => 'Judul', 'Nobody assigned' => 'Tidak ada yang ditugaskan', @@ -208,8 +207,6 @@ return array( 'Assign a color to a specific user' => 'Menetapkan warna untuk pengguna tertentu', 'Column title' => 'Judul kolom', 'Position' => 'Posisi', - 'Move Up' => 'Pindah ke atas', - 'Move Down' => 'Pindah ke bawah', 'Duplicate to another project' => 'Duplikasi ke proyek lain', 'Duplicate' => 'Duplikasi', 'link' => 'tautan', @@ -501,7 +498,6 @@ return array( 'Do you really want to remove this swimlane: "%s"?' => 'Apakah anda yakin akan menghapus swimlane ini : « %s » ?', 'Inactive swimlanes' => 'Swimlanes tidak aktif', 'Remove a swimlane' => 'Supprimer une swimlane', - 'Rename' => 'Ganti nama', 'Show default swimlane' => 'Perlihatkan standar swimlane', 'Swimlane modification for the project "%s"' => 'Modifikasi swimlane untuk proyek « %s »', 'Swimlane not found.' => 'Swimlane tidak ditemukan.', @@ -509,7 +505,6 @@ return array( 'Swimlanes' => 'Swimlanes', 'Swimlane updated successfully.' => 'Swimlane berhasil diperbaharui.', 'The default swimlane have been updated successfully.' => 'Standar swimlane berhasil diperbaharui.', - 'Unable to create your swimlane.' => 'Tidak dapat membuat swimlane anda.', 'Unable to remove this swimlane.' => 'Tidak dapat menghapus swimlane ini.', 'Unable to update this swimlane.' => 'Tidak dapat memperbaharui swimlane ini.', 'Your swimlane have been created successfully.' => 'Swimlane anda berhasil dibuat.', @@ -1152,4 +1147,5 @@ return array( // 'Last activity' => '', // 'Change subtask position' => '', // 'This value must be greater than %d' => '', + // 'Another swimlane with the same name exists in the project' => '', ); diff --git a/app/Locale/it_IT/translations.php b/app/Locale/it_IT/translations.php index c4afa8c6..4e227888 100644 --- a/app/Locale/it_IT/translations.php +++ b/app/Locale/it_IT/translations.php @@ -72,7 +72,6 @@ return array( 'Remove project' => 'Cancella il progetto', 'Edit the board for "%s"' => 'Modifica la bacheca per "%s"', 'All projects' => 'Tutti i progetti', - 'Change columns' => 'Cambia le colonne', 'Add a new column' => 'Aggiungi una nuova colonna', 'Title' => 'Titolo', 'Nobody assigned' => 'Nessuno assegnato', @@ -208,8 +207,6 @@ return array( 'Assign a color to a specific user' => 'Assegna un colore ad un utente specifico', 'Column title' => 'Titolo della colonna', 'Position' => 'Posizione', - 'Move Up' => 'Sposta in alto', - 'Move Down' => 'Sposta in basso', 'Duplicate to another project' => 'Duplica in un altro progetto', 'Duplicate' => 'Duplica', 'link' => 'relazione', @@ -501,7 +498,6 @@ return array( 'Do you really want to remove this swimlane: "%s"?' => 'Vuoi davvero rimuovere la seguente corsia: "%s"?', 'Inactive swimlanes' => 'Corsie inattive', 'Remove a swimlane' => 'Rimuovi una corsia', - 'Rename' => 'Rinomina', 'Show default swimlane' => 'Mostra la corsia predefinita', 'Swimlane modification for the project "%s"' => 'Modifica corsia per il progetto "%s"', 'Swimlane not found.' => 'Corsia non trovata.', @@ -509,7 +505,6 @@ return array( 'Swimlanes' => 'Corsie', 'Swimlane updated successfully.' => 'Corsia aggiornata con successo.', 'The default swimlane have been updated successfully.' => 'La corsia predefinita è stata aggiornata con successo.', - 'Unable to create your swimlane.' => 'Impossibile creare la corsia.', 'Unable to remove this swimlane.' => 'Impossibile rimuovere questa corsia.', 'Unable to update this swimlane.' => 'Impossibile aggiornare questa corsia.', 'Your swimlane have been created successfully.' => 'La tua corsia è stata creata con successo', @@ -1152,4 +1147,5 @@ return array( // 'Last activity' => '', // 'Change subtask position' => '', // 'This value must be greater than %d' => '', + // 'Another swimlane with the same name exists in the project' => '', ); diff --git a/app/Locale/ja_JP/translations.php b/app/Locale/ja_JP/translations.php index 443e4f3e..46755e10 100644 --- a/app/Locale/ja_JP/translations.php +++ b/app/Locale/ja_JP/translations.php @@ -72,7 +72,6 @@ return array( 'Remove project' => 'プロジェクトの削除', 'Edit the board for "%s"' => 'ボード「%s」を変更する', 'All projects' => 'すべてのプロジェクト', - 'Change columns' => 'カラムの変更', 'Add a new column' => 'カラムの追加', 'Title' => 'タイトル', 'Nobody assigned' => '担当なし', @@ -208,8 +207,6 @@ return array( 'Assign a color to a specific user' => '色をユーザに割り当てる', 'Column title' => 'カラムのタイトル', 'Position' => '位置', - 'Move Up' => '上に動かす', - 'Move Down' => '下に動かす', 'Duplicate to another project' => '別のプロジェクトに複製する', 'Duplicate' => '複製する', 'link' => 'リンク', @@ -501,7 +498,6 @@ return array( 'Do you really want to remove this swimlane: "%s"?' => 'このスイムレーン「%s」を本当に削除しますか?', 'Inactive swimlanes' => 'インタラクティブなスイムレーン', 'Remove a swimlane' => 'スイムレーンの削除', - 'Rename' => '名前の変更', 'Show default swimlane' => 'デフォルトスイムレーンの表示', 'Swimlane modification for the project "%s"' => '「%s」に対するスイムレーン変更', 'Swimlane not found.' => 'スイムレーンが見つかりません。', @@ -509,7 +505,6 @@ return array( 'Swimlanes' => 'スイムレーン', 'Swimlane updated successfully.' => 'スイムレーンを更新しました。', 'The default swimlane have been updated successfully.' => 'デフォルトスイムレーンを更新しました。', - 'Unable to create your swimlane.' => 'スイムレーンを追加できませんでした。', 'Unable to remove this swimlane.' => 'スイムレーンを削除できませんでした。', 'Unable to update this swimlane.' => 'スイムレーンを更新できませんでした。', 'Your swimlane have been created successfully.' => 'スイムレーンが作成されました。', @@ -1152,4 +1147,5 @@ return array( // 'Last activity' => '', // 'Change subtask position' => '', // 'This value must be greater than %d' => '', + // 'Another swimlane with the same name exists in the project' => '', ); diff --git a/app/Locale/my_MY/translations.php b/app/Locale/my_MY/translations.php index 6ef22534..39f2b81f 100644 --- a/app/Locale/my_MY/translations.php +++ b/app/Locale/my_MY/translations.php @@ -72,7 +72,6 @@ return array( 'Remove project' => 'Hapus projek', 'Edit the board for "%s"' => 'Ubah papan untuk « %s »', 'All projects' => 'Semua projek', - 'Change columns' => 'Ubah kolom', 'Add a new column' => 'Tambah kolom baru', 'Title' => 'Judul', 'Nobody assigned' => 'Tidak ada yang ditugaskan', @@ -208,8 +207,6 @@ return array( 'Assign a color to a specific user' => 'Menetapkan warna untuk pengguna tertentu', 'Column title' => 'Judul kolom', 'Position' => 'Posisi', - 'Move Up' => 'Pindah ke atas', - 'Move Down' => 'Pindah ke bawah', 'Duplicate to another project' => 'Duplikasi ke projek lain', 'Duplicate' => 'Duplikasi', 'link' => 'Pautan', @@ -501,7 +498,6 @@ return array( 'Do you really want to remove this swimlane: "%s"?' => 'Anda yakin untuk menghapus swimlane ini : « %s » ?', 'Inactive swimlanes' => 'Swimlanes tidak aktif', 'Remove a swimlane' => 'Padam swimlane', - 'Rename' => 'Namakan semula', 'Show default swimlane' => 'Tampilkan piawai swimlane', 'Swimlane modification for the project "%s"' => 'Modifikasi swimlane untuk projek « %s »', 'Swimlane not found.' => 'Swimlane tidak ditemui.', @@ -509,7 +505,6 @@ return array( 'Swimlanes' => 'Swimlanes', 'Swimlane updated successfully.' => 'Swimlane telah dikemaskini.', 'The default swimlane have been updated successfully.' => 'Standar swimlane berhasil diperbaharui.', - 'Unable to create your swimlane.' => 'Tidak dapat membuat swimlane anda.', 'Unable to remove this swimlane.' => 'Tidak dapat menghapus swimlane ini.', 'Unable to update this swimlane.' => 'Tidak dapat memperbaharui swimlane ini.', 'Your swimlane have been created successfully.' => 'Swimlane anda berhasil dibuat.', @@ -1152,4 +1147,5 @@ return array( // 'Last activity' => '', // 'Change subtask position' => '', // 'This value must be greater than %d' => '', + // 'Another swimlane with the same name exists in the project' => '', ); diff --git a/app/Locale/nb_NO/translations.php b/app/Locale/nb_NO/translations.php index 49b55fe5..9fe533ee 100644 --- a/app/Locale/nb_NO/translations.php +++ b/app/Locale/nb_NO/translations.php @@ -72,7 +72,6 @@ return array( 'Remove project' => 'Fjern prosjekt', 'Edit the board for "%s"' => 'Endre prosjektsiden for "%s"', 'All projects' => 'Alle prosjekter', - 'Change columns' => 'Endre kolonner', 'Add a new column' => 'Legg til en ny kolonne', 'Title' => 'Tittel', 'Nobody assigned' => 'Ikke tildelt', @@ -208,8 +207,6 @@ return array( 'Assign a color to a specific user' => 'Tildel en farge til en bestemt bruker', 'Column title' => 'Kolonne tittel', 'Position' => 'Posisjon', - 'Move Up' => 'Flytt opp', - 'Move Down' => 'Flytt ned', 'Duplicate to another project' => 'Kopier til et annet prosjekt', 'Duplicate' => 'Kopier', 'link' => 'link', @@ -501,7 +498,6 @@ return array( // 'Do you really want to remove this swimlane: "%s"?' => '', // 'Inactive swimlanes' => '', 'Remove a swimlane' => 'Fjern en svømmebane', - 'Rename' => 'Endre navn', 'Show default swimlane' => 'Vis standard svømmebane', // 'Swimlane modification for the project "%s"' => '', 'Swimlane not found.' => 'Svømmebane ikke funnet', @@ -509,7 +505,6 @@ return array( 'Swimlanes' => 'Svømmebaner', 'Swimlane updated successfully.' => 'Svømmebane oppdatert', // 'The default swimlane have been updated successfully.' => '', - // 'Unable to create your swimlane.' => '', // 'Unable to remove this swimlane.' => '', // 'Unable to update this swimlane.' => '', // 'Your swimlane have been created successfully.' => '', @@ -1152,4 +1147,5 @@ return array( // 'Last activity' => '', // 'Change subtask position' => '', // 'This value must be greater than %d' => '', + // 'Another swimlane with the same name exists in the project' => '', ); diff --git a/app/Locale/nl_NL/translations.php b/app/Locale/nl_NL/translations.php index 610113c8..edf5f484 100644 --- a/app/Locale/nl_NL/translations.php +++ b/app/Locale/nl_NL/translations.php @@ -72,7 +72,6 @@ return array( 'Remove project' => 'Project verwijderen', 'Edit the board for "%s"' => 'Bord bewerken voor « %s »', 'All projects' => 'Alle projecten', - 'Change columns' => 'Kolommen veranderen', 'Add a new column' => 'Kolom toevoegen', 'Title' => 'Titel', 'Nobody assigned' => 'Niemand toegewezen', @@ -208,8 +207,6 @@ return array( 'Assign a color to a specific user' => 'Wijs een kleur toe aan een gebruiker', 'Column title' => 'Kolom titel', 'Position' => 'Positie', - 'Move Up' => 'Omhoog verplaatsen', - 'Move Down' => 'Omlaag verplaatsen', 'Duplicate to another project' => 'Dupliceren in een ander project', 'Duplicate' => 'Dupliceren', 'link' => 'koppelen', @@ -501,7 +498,6 @@ return array( 'Do you really want to remove this swimlane: "%s"?' => 'Weet u zeker dat u deze swimlane wil verwijderen : « %s » ?', 'Inactive swimlanes' => 'Inactieve swinlanes', 'Remove a swimlane' => 'Verwijder swinlane', - 'Rename' => 'Hernoemen', 'Show default swimlane' => 'Standaard swimlane tonen', 'Swimlane modification for the project "%s"' => 'Swinlane aanpassing voor project « %s »', 'Swimlane not found.' => 'Swimlane niet gevonden.', @@ -509,7 +505,6 @@ return array( 'Swimlanes' => 'Swimlanes', 'Swimlane updated successfully.' => 'Swimlane succesvol aangepast.', 'The default swimlane have been updated successfully.' => 'De standaard swimlane is succesvol aangepast.', - 'Unable to create your swimlane.' => 'Swimlane aanmaken niet gelukt.', 'Unable to remove this swimlane.' => 'Swimlane verwijderen niet gelukt.', 'Unable to update this swimlane.' => 'Swimlane aanpassen niet gelukt.', 'Your swimlane have been created successfully.' => 'Swimlane succesvol aangemaakt.', @@ -1152,4 +1147,5 @@ return array( // 'Last activity' => '', // 'Change subtask position' => '', // 'This value must be greater than %d' => '', + // 'Another swimlane with the same name exists in the project' => '', ); diff --git a/app/Locale/pl_PL/translations.php b/app/Locale/pl_PL/translations.php index 7c0ed9ca..4a6f5426 100644 --- a/app/Locale/pl_PL/translations.php +++ b/app/Locale/pl_PL/translations.php @@ -72,7 +72,6 @@ return array( 'Remove project' => 'Usuń projekt', 'Edit the board for "%s"' => 'Edytuj tablicę dla "%s"', 'All projects' => 'Wszystkie projekty', - 'Change columns' => 'Zmień kolumny', 'Add a new column' => 'Dodaj nową kolumnę', 'Title' => 'Tytuł', 'Nobody assigned' => 'Nikt nie przypisany', @@ -208,8 +207,6 @@ return array( 'Assign a color to a specific user' => 'Przypisz kolor do wybranego użytkownika', 'Column title' => 'Tytuł kolumny', 'Position' => 'Pozycja', - 'Move Up' => 'Przenieś wyżej', - 'Move Down' => 'Przenieś niżej', 'Duplicate to another project' => 'Skopiuj do innego projektu', 'Duplicate' => 'Utwórz kopię', 'link' => 'link', @@ -501,7 +498,6 @@ return array( 'Do you really want to remove this swimlane: "%s"?' => 'Czy na pewno chcesz usunąć proces: "%s"?', 'Inactive swimlanes' => 'Nieaktywne procesy', 'Remove a swimlane' => 'Usuń proces', - 'Rename' => 'Zmień nazwe', 'Show default swimlane' => 'Pokaż domyślny proces', 'Swimlane modification for the project "%s"' => 'Edycja procesów dla projektu "%s"', 'Swimlane not found.' => 'Nie znaleziono procesu.', @@ -509,7 +505,6 @@ return array( 'Swimlanes' => 'Procesy', 'Swimlane updated successfully.' => 'Proces zaktualizowany pomyślnie.', 'The default swimlane have been updated successfully.' => 'Domyślny proces zaktualizowany pomyślnie.', - 'Unable to create your swimlane.' => 'Nie można utworzyć procesu.', 'Unable to remove this swimlane.' => 'Nie można usunąć procesu.', 'Unable to update this swimlane.' => 'Nie można zaktualizować procesu.', 'Your swimlane have been created successfully.' => 'Proces tworzony pomyślnie.', @@ -1152,4 +1147,5 @@ return array( // 'Last activity' => '', // 'Change subtask position' => '', // 'This value must be greater than %d' => '', + // 'Another swimlane with the same name exists in the project' => '', ); diff --git a/app/Locale/pt_BR/translations.php b/app/Locale/pt_BR/translations.php index e0eb8ceb..8e9856b7 100644 --- a/app/Locale/pt_BR/translations.php +++ b/app/Locale/pt_BR/translations.php @@ -72,7 +72,6 @@ return array( 'Remove project' => 'Remover projeto', 'Edit the board for "%s"' => 'Editar o board para "%s"', 'All projects' => 'Todos os projetos', - 'Change columns' => 'Modificar colunas', 'Add a new column' => 'Adicionar uma nova coluna', 'Title' => 'Título', 'Nobody assigned' => 'Ninguém designado', @@ -208,8 +207,6 @@ return array( 'Assign a color to a specific user' => 'Designar uma cor para um usuário específico', 'Column title' => 'Título da coluna', 'Position' => 'Posição', - 'Move Up' => 'Mover para cima', - 'Move Down' => 'Mover para baixo', 'Duplicate to another project' => 'Duplicar para outro projeto', 'Duplicate' => 'Duplicar', 'link' => 'link', @@ -501,7 +498,6 @@ return array( 'Do you really want to remove this swimlane: "%s"?' => 'Você realmente deseja remover esta swimlane: "%s"?', 'Inactive swimlanes' => 'Desativar swimlanes', 'Remove a swimlane' => 'Remover uma swimlane', - 'Rename' => 'Renomear', 'Show default swimlane' => 'Exibir swimlane padrão', 'Swimlane modification for the project "%s"' => 'Modificação de swimlane para o projeto "%s"', 'Swimlane not found.' => 'Swimlane não encontrada.', @@ -509,7 +505,6 @@ return array( 'Swimlanes' => 'Swimlanes', 'Swimlane updated successfully.' => 'Swimlane atualizada com sucesso.', 'The default swimlane have been updated successfully.' => 'A swimlane padrão foi atualizada com sucesso.', - 'Unable to create your swimlane.' => 'Não foi possível criar a sua swimlane.', 'Unable to remove this swimlane.' => 'Não foi possível remover esta swimlane.', 'Unable to update this swimlane.' => 'Não foi possível atualizar esta swimlane.', 'Your swimlane have been created successfully.' => 'Sua swimlane foi criada com sucesso.', @@ -1152,4 +1147,5 @@ return array( // 'Last activity' => '', // 'Change subtask position' => '', // 'This value must be greater than %d' => '', + // 'Another swimlane with the same name exists in the project' => '', ); diff --git a/app/Locale/pt_PT/translations.php b/app/Locale/pt_PT/translations.php index 6dac8190..84918130 100644 --- a/app/Locale/pt_PT/translations.php +++ b/app/Locale/pt_PT/translations.php @@ -72,7 +72,6 @@ return array( 'Remove project' => 'Remover projecto', 'Edit the board for "%s"' => 'Editar o quadro para "%s"', 'All projects' => 'Todos os projectos', - 'Change columns' => 'Modificar colunas', 'Add a new column' => 'Adicionar uma nova coluna', 'Title' => 'Título', 'Nobody assigned' => 'Ninguém assignado', @@ -208,8 +207,6 @@ return array( 'Assign a color to a specific user' => 'Designar uma cor para um utilizador específico', 'Column title' => 'Título da coluna', 'Position' => 'Posição', - 'Move Up' => 'Mover para cima', - 'Move Down' => 'Mover para baixo', 'Duplicate to another project' => 'Duplicar para outro projecto', 'Duplicate' => 'Duplicar', 'link' => 'link', @@ -501,7 +498,6 @@ return array( 'Do you really want to remove this swimlane: "%s"?' => 'Tem a certeza que quer remover este swimlane: "%s"?', 'Inactive swimlanes' => 'Desactivar swimlanes', 'Remove a swimlane' => 'Remover um swimlane', - 'Rename' => 'Renomear', 'Show default swimlane' => 'Mostrar swimlane padrão', 'Swimlane modification for the project "%s"' => 'Modificação de swimlane para o projecto "%s"', 'Swimlane not found.' => 'Swimlane não encontrado.', @@ -509,7 +505,6 @@ return array( 'Swimlanes' => 'Swimlanes', 'Swimlane updated successfully.' => 'Swimlane atualizado com sucesso.', 'The default swimlane have been updated successfully.' => 'O swimlane padrão foi atualizado com sucesso.', - 'Unable to create your swimlane.' => 'Não foi possível criar o seu swimlane.', 'Unable to remove this swimlane.' => 'Não foi possível remover este swimlane.', 'Unable to update this swimlane.' => 'Não foi possível atualizar este swimlane.', 'Your swimlane have been created successfully.' => 'Seu swimlane foi criado com sucesso.', @@ -1152,4 +1147,5 @@ return array( // 'Last activity' => '', // 'Change subtask position' => '', // 'This value must be greater than %d' => '', + // 'Another swimlane with the same name exists in the project' => '', ); diff --git a/app/Locale/ru_RU/translations.php b/app/Locale/ru_RU/translations.php index 6b2d88cd..66428927 100644 --- a/app/Locale/ru_RU/translations.php +++ b/app/Locale/ru_RU/translations.php @@ -72,7 +72,6 @@ return array( 'Remove project' => 'Удалить проект', 'Edit the board for "%s"' => 'Изменить доску для "%s"', 'All projects' => 'Все проекты', - 'Change columns' => 'Изменить колонки', 'Add a new column' => 'Добавить новую колонку', 'Title' => 'Название', 'Nobody assigned' => 'Никто не назначен', @@ -208,8 +207,6 @@ return array( 'Assign a color to a specific user' => 'Назначить определенный цвет пользователю', 'Column title' => 'Название колонки', 'Position' => 'Расположение', - 'Move Up' => 'Сдвинуть вверх', - 'Move Down' => 'Сдвинуть вниз', 'Duplicate to another project' => 'Клонировать в другой проект', 'Duplicate' => 'Клонировать', 'link' => 'ссылка', @@ -501,7 +498,6 @@ return array( 'Do you really want to remove this swimlane: "%s"?' => 'Вы действительно хотите удалить дорожку "%s"?', 'Inactive swimlanes' => 'Неактивные дорожки', 'Remove a swimlane' => 'Удалить дорожку', - 'Rename' => 'Переименовать', 'Show default swimlane' => 'Показать стандартную дорожку', 'Swimlane modification for the project "%s"' => 'Редактирование дорожки для проекта "%s"', 'Swimlane not found.' => 'Дорожка не найдена.', @@ -509,7 +505,6 @@ return array( 'Swimlanes' => 'Дорожки', 'Swimlane updated successfully.' => 'Дорожка успешно обновлена.', 'The default swimlane have been updated successfully.' => 'Стандартная swimlane был успешно обновлен.', - 'Unable to create your swimlane.' => 'Невозможно создать дорожку.', 'Unable to remove this swimlane.' => 'Невозможно удалить дорожку.', 'Unable to update this swimlane.' => 'Невозможно обновить дорожку.', 'Your swimlane have been created successfully.' => 'Ваша дорожка была успешно создан.', @@ -1152,4 +1147,5 @@ return array( // 'Last activity' => '', // 'Change subtask position' => '', // 'This value must be greater than %d' => '', + // 'Another swimlane with the same name exists in the project' => '', ); diff --git a/app/Locale/sr_Latn_RS/translations.php b/app/Locale/sr_Latn_RS/translations.php index b49a8395..79769ae5 100644 --- a/app/Locale/sr_Latn_RS/translations.php +++ b/app/Locale/sr_Latn_RS/translations.php @@ -72,7 +72,6 @@ return array( 'Remove project' => 'Ukloni projekat', 'Edit the board for "%s"' => 'Izmeni tablu za "%s"', 'All projects' => 'Svi projekti', - 'Change columns' => 'Zameni kolonu', 'Add a new column' => 'Dodaj novu kolonu', 'Title' => 'Naslov', 'Nobody assigned' => 'Niko nije dodeljen', @@ -208,8 +207,6 @@ return array( 'Assign a color to a specific user' => 'Dodeli boju korisniku', 'Column title' => 'Naslov kolone', 'Position' => 'Pozicija', - 'Move Up' => 'Podigni', - 'Move Down' => 'Spusti', 'Duplicate to another project' => 'Kopiraj u drugi projekat', 'Duplicate' => 'Napravi kopiju', 'link' => 'link', @@ -501,7 +498,6 @@ return array( 'Do you really want to remove this swimlane: "%s"?' => 'Da li da uklonim razdelnik: "%s"?', 'Inactive swimlanes' => 'Neaktivni razdelniki', 'Remove a swimlane' => 'Ukloni razdelnik', - 'Rename' => 'Preimenuj', 'Show default swimlane' => 'Prikaži osnovni razdelnik', 'Swimlane modification for the project "%s"' => 'Izmena razdelnika za projekat "%s"', 'Swimlane not found.' => 'Razdelnik nije pronađen.', @@ -509,7 +505,6 @@ return array( 'Swimlanes' => 'Razdelnici', 'Swimlane updated successfully.' => 'Razdelnik zaktualizowany pomyślnie.', // 'The default swimlane have been updated successfully.' => '', - // 'Unable to create your swimlane.' => '', // 'Unable to remove this swimlane.' => '', // 'Unable to update this swimlane.' => '', 'Your swimlane have been created successfully.' => 'Razdelnik je uspešno kreiran.', @@ -1152,4 +1147,5 @@ return array( // 'Last activity' => '', // 'Change subtask position' => '', // 'This value must be greater than %d' => '', + // 'Another swimlane with the same name exists in the project' => '', ); diff --git a/app/Locale/sv_SE/translations.php b/app/Locale/sv_SE/translations.php index 10692462..bbd54907 100644 --- a/app/Locale/sv_SE/translations.php +++ b/app/Locale/sv_SE/translations.php @@ -72,7 +72,6 @@ return array( 'Remove project' => 'Ta bort projekt', 'Edit the board for "%s"' => 'Ändra tavlan för "%s"', 'All projects' => 'Alla projekt', - 'Change columns' => 'Ändra kolumner', 'Add a new column' => 'Lägg till ny kolumn', 'Title' => 'Titel', 'Nobody assigned' => 'Ingen tilldelad', @@ -208,8 +207,6 @@ return array( 'Assign a color to a specific user' => 'Tilldela en färg till en specifik användare', 'Column title' => 'Kolumnens titel', 'Position' => 'Position', - 'Move Up' => 'Flytta upp', - 'Move Down' => 'Flytta ned', 'Duplicate to another project' => 'Kopiera till ett annat projekt', 'Duplicate' => 'Kopiera uppgiften', 'link' => 'länk', @@ -501,7 +498,6 @@ return array( 'Do you really want to remove this swimlane: "%s"?' => 'Vill du verkligen ta bort denna swimlane: "%s"?', 'Inactive swimlanes' => 'Inaktiv swimlane', 'Remove a swimlane' => 'Ta bort en swimlane', - 'Rename' => 'Byt namn', 'Show default swimlane' => 'Visa standard swimlane', 'Swimlane modification for the project "%s"' => 'Ändra swimlane för projektet "%s"', 'Swimlane not found.' => 'Swimlane kunde inte hittas', @@ -509,7 +505,6 @@ return array( 'Swimlanes' => 'Swimlanes', 'Swimlane updated successfully.' => 'Swimlane uppdaterad', 'The default swimlane have been updated successfully.' => 'Standardswimlane har uppdaterats', - 'Unable to create your swimlane.' => 'Kunde inte skapa din swimlane', 'Unable to remove this swimlane.' => 'Kunde inte ta bort swimlane', 'Unable to update this swimlane.' => 'Kunde inte uppdatera swimlane', 'Your swimlane have been created successfully.' => 'Din swimlane har skapats', @@ -1152,4 +1147,5 @@ return array( // 'Last activity' => '', // 'Change subtask position' => '', // 'This value must be greater than %d' => '', + // 'Another swimlane with the same name exists in the project' => '', ); diff --git a/app/Locale/th_TH/translations.php b/app/Locale/th_TH/translations.php index 867e847e..437272c8 100644 --- a/app/Locale/th_TH/translations.php +++ b/app/Locale/th_TH/translations.php @@ -72,7 +72,6 @@ return array( 'Remove project' => 'ลบโปรเจค', 'Edit the board for "%s"' => 'แก้ไขบอร์ดสำหรับ « %s »', 'All projects' => 'โปรเจคทั้งหมด', - 'Change columns' => 'เปลี่ยนคอลัมน์', 'Add a new column' => 'เพิ่มคอลัมน์ใหม่', 'Title' => 'หัวเรื่อง', 'Nobody assigned' => 'ไม่กำหนดใคร', @@ -208,8 +207,6 @@ return array( 'Assign a color to a specific user' => 'กำหนดสีให้ผู้ใช้แบบเจาะจง', 'Column title' => 'หัวเรื่องคอลัมน์', 'Position' => 'ตำแหน่ง', - 'Move Up' => 'ย้ายขึ้น', - 'Move Down' => 'ย้ายลง', 'Duplicate to another project' => 'ทำซ้ำในโปรเจคอื่น', 'Duplicate' => 'ทำซ้ำ', 'link' => 'ลิงค์', @@ -501,7 +498,6 @@ return array( 'Do you really want to remove this swimlane: "%s"?' => 'คุณต้องการลบสวิมเลนนี้ : "%s"?', 'Inactive swimlanes' => 'สวิมเลนไม่ทำงาน', 'Remove a swimlane' => 'ลบสวิมเลน', - 'Rename' => 'เปลี่ยนชื่อ', 'Show default swimlane' => 'แสดงสวิมเลนเริ่มต้น', 'Swimlane modification for the project "%s"' => 'แก้ไขสวิมเลนสำหรับโปรเจค "%s"', 'Swimlane not found.' => 'หาสวิมเลนไม่พบ', @@ -509,7 +505,6 @@ return array( 'Swimlanes' => 'สวิมเลน', 'Swimlane updated successfully.' => 'ปรับปรุงสวิมเลนเรียบร้อยแล้ว', 'The default swimlane have been updated successfully.' => 'สวิมเลนเริ่มต้นปรับปรุงเรียบร้อยแล้ว', - 'Unable to create your swimlane.' => 'ไม่สามารถสร้างสวิมเลนของคุณได้', 'Unable to remove this swimlane.' => 'ไม่สามารถลบสวิมเลนนี้', 'Unable to update this swimlane.' => 'ไม่สามารถปรับปรุงสวิมเลนนี้', 'Your swimlane have been created successfully.' => 'สวิมเลนของคุณถูกสร้างเรียบร้อยแล้ว', @@ -1152,4 +1147,5 @@ return array( // 'Last activity' => '', // 'Change subtask position' => '', // 'This value must be greater than %d' => '', + // 'Another swimlane with the same name exists in the project' => '', ); diff --git a/app/Locale/tr_TR/translations.php b/app/Locale/tr_TR/translations.php index 8cd5f922..b070adeb 100644 --- a/app/Locale/tr_TR/translations.php +++ b/app/Locale/tr_TR/translations.php @@ -72,7 +72,6 @@ return array( 'Remove project' => 'Projeyi sil', 'Edit the board for "%s"' => 'Tabloyu "%s" için güncelle', 'All projects' => 'Tüm projeler', - 'Change columns' => 'Sütunları değiştir', 'Add a new column' => 'Yeni sütun ekle', 'Title' => 'Başlık', 'Nobody assigned' => 'Kullanıcı atanmamış', @@ -208,8 +207,6 @@ return array( 'Assign a color to a specific user' => 'Bir kullanıcıya renk tanımla', 'Column title' => 'Sütun başlığı', 'Position' => 'Pozisyon', - 'Move Up' => 'Yukarı taşı', - 'Move Down' => 'Aşağı taşı', 'Duplicate to another project' => 'Başka bir projeye kopyala', 'Duplicate' => 'Kopya oluştur', 'link' => 'bağlantı', @@ -501,7 +498,6 @@ return array( 'Do you really want to remove this swimlane: "%s"?' => 'Bu Kulvarı silmek istediğinize emin misiniz?: "%s"?', 'Inactive swimlanes' => 'Pasif Kulvarlar', 'Remove a swimlane' => 'Kulvarı sil', - 'Rename' => 'Yeniden adlandır', 'Show default swimlane' => 'Varsayılan Kulvarı göster', 'Swimlane modification for the project "%s"' => '"%s" Projesi için Kulvar değişikliği', 'Swimlane not found.' => 'Kulvar bulunamadı', @@ -509,7 +505,6 @@ return array( 'Swimlanes' => 'Kulvarlar', 'Swimlane updated successfully.' => 'Kulvar başarıyla güncellendi.', 'The default swimlane have been updated successfully.' => 'Varsayılan Kulvarlar başarıyla güncellendi.', - 'Unable to create your swimlane.' => 'Bu Kulvarı oluşturmak mümkün değil.', 'Unable to remove this swimlane.' => 'Bu Kulvarı silmek mümkün değil.', 'Unable to update this swimlane.' => 'Bu Kulvarı değiştirmek mümkün değil.', 'Your swimlane have been created successfully.' => 'Kulvar başarıyla oluşturuldu.', @@ -1152,4 +1147,5 @@ return array( // 'Last activity' => '', // 'Change subtask position' => '', // 'This value must be greater than %d' => '', + // 'Another swimlane with the same name exists in the project' => '', ); diff --git a/app/Locale/zh_CN/translations.php b/app/Locale/zh_CN/translations.php index 6facfef2..06f67c5f 100644 --- a/app/Locale/zh_CN/translations.php +++ b/app/Locale/zh_CN/translations.php @@ -72,7 +72,6 @@ return array( 'Remove project' => '移除项目', 'Edit the board for "%s"' => '为"%s"修改看板', 'All projects' => '所有项目', - 'Change columns' => '更改栏目', 'Add a new column' => '添加新栏目', 'Title' => '标题', 'Nobody assigned' => '无人被指派', @@ -208,8 +207,6 @@ return array( 'Assign a color to a specific user' => '为特定用户指派颜色', 'Column title' => '栏目名称', 'Position' => '位置', - 'Move Up' => '往上移', - 'Move Down' => '往下移', 'Duplicate to another project' => '复制到另一项目', 'Duplicate' => '复制', 'link' => '连接', @@ -501,7 +498,6 @@ return array( 'Do you really want to remove this swimlane: "%s"?' => '确定要删除里程碑:"%s"?', 'Inactive swimlanes' => '非活动里程碑', 'Remove a swimlane' => '删除里程碑', - 'Rename' => '重命名', 'Show default swimlane' => '显示默认里程碑', 'Swimlane modification for the project "%s"' => '项目"%s"的里程碑变更', 'Swimlane not found.' => '未找到里程碑。', @@ -509,7 +505,6 @@ return array( 'Swimlanes' => '里程碑', 'Swimlane updated successfully.' => '成功更新了里程碑。', 'The default swimlane have been updated successfully.' => '成功更新了默认里程碑。', - 'Unable to create your swimlane.' => '无法创建里程碑。', 'Unable to remove this swimlane.' => '无法删除此里程碑', 'Unable to update this swimlane.' => '无法更新此里程碑', 'Your swimlane have been created successfully.' => '已经成功创建里程碑。', @@ -1152,4 +1147,5 @@ return array( // 'Last activity' => '', // 'Change subtask position' => '', // 'This value must be greater than %d' => '', + // 'Another swimlane with the same name exists in the project' => '', ); diff --git a/app/Model/Swimlane.php b/app/Model/Swimlane.php index 6b0dcdc5..721f20d3 100644 --- a/app/Model/Swimlane.php +++ b/app/Model/Swimlane.php @@ -262,6 +262,40 @@ class Swimlane extends Base )); } + /** + * Enable the default swimlane + * + * @access public + * @param integer $project_id + * @return bool + */ + public function enableDefault($project_id) + { + return $this->db + ->table(Project::TABLE) + ->eq('id', $project_id) + ->update(array( + 'show_default_swimlane' => 1, + )); + } + + /** + * Disable the default swimlane + * + * @access public + * @param integer $project_id + * @return bool + */ + public function disableDefault($project_id) + { + return $this->db + ->table(Project::TABLE) + ->eq('id', $project_id) + ->update(array( + 'show_default_swimlane' => 0, + )); + } + /** * Get the last position of a swimlane * @@ -366,6 +400,7 @@ class Swimlane extends Base ->eq('project_id', $project_id) ->eq('is_active', 1) ->asc('position') + ->asc('id') ->findAllByColumn('id'); if (! $swimlanes) { @@ -382,69 +417,42 @@ class Swimlane extends Base } /** - * Move a swimlane down, increment the position value + * Change swimlane position * * @access public - * @param integer $project_id Project id - * @param integer $swimlane_id Swimlane id + * @param integer $project_id + * @param integer $swimlane_id + * @param integer $position * @return boolean */ - public function moveDown($project_id, $swimlane_id) + public function changePosition($project_id, $swimlane_id, $position) { - $swimlanes = $this->db->hashtable(self::TABLE) - ->eq('project_id', $project_id) - ->eq('is_active', self::ACTIVE) - ->asc('position') - ->getAll('id', 'position'); - - $positions = array_flip($swimlanes); - - if (isset($swimlanes[$swimlane_id]) && $swimlanes[$swimlane_id] < count($swimlanes)) { - $position = ++$swimlanes[$swimlane_id]; - $swimlanes[$positions[$position]]--; - - $this->db->startTransaction(); - $this->db->table(self::TABLE)->eq('id', $swimlane_id)->update(array('position' => $position)); - $this->db->table(self::TABLE)->eq('id', $positions[$position])->update(array('position' => $swimlanes[$positions[$position]])); - $this->db->closeTransaction(); - - return true; + if ($position < 1 || $position > $this->db->table(self::TABLE)->eq('project_id', $project_id)->count()) { + return false; } - return false; - } - - /** - * Move a swimlane up, decrement the position value - * - * @access public - * @param integer $project_id Project id - * @param integer $swimlane_id Swimlane id - * @return boolean - */ - public function moveUp($project_id, $swimlane_id) - { - $swimlanes = $this->db->hashtable(self::TABLE) + $swimlane_ids = $this->db->table(self::TABLE) + ->eq('is_active', 1) ->eq('project_id', $project_id) - ->eq('is_active', self::ACTIVE) + ->neq('id', $swimlane_id) ->asc('position') - ->getAll('id', 'position'); - - $positions = array_flip($swimlanes); + ->findAllByColumn('id'); - if (isset($swimlanes[$swimlane_id]) && $swimlanes[$swimlane_id] > 1) { - $position = --$swimlanes[$swimlane_id]; - $swimlanes[$positions[$position]]++; + $offset = 1; + $results = array(); - $this->db->startTransaction(); - $this->db->table(self::TABLE)->eq('id', $swimlane_id)->update(array('position' => $position)); - $this->db->table(self::TABLE)->eq('id', $positions[$position])->update(array('position' => $swimlanes[$positions[$position]])); - $this->db->closeTransaction(); + foreach ($swimlane_ids as $current_swimlane_id) { + if ($offset == $position) { + $offset++; + } - return true; + $results[] = $this->db->table(self::TABLE)->eq('id', $current_swimlane_id)->update(array('position' => $offset)); + $offset++; } - return false; + $results[] = $this->db->table(self::TABLE)->eq('id', $swimlane_id)->update(array('position' => $position)); + + return !in_array(false, $results, true); } /** diff --git a/app/Template/swimlane/create.php b/app/Template/swimlane/create.php new file mode 100644 index 00000000..bb389555 --- /dev/null +++ b/app/Template/swimlane/create.php @@ -0,0 +1,37 @@ + +
    + + form->csrf() ?> + form->hidden('project_id', $values) ?> + + form->label(t('Name'), 'name') ?> + form->text('name', $values, $errors, array('autofocus', 'required', 'maxlength="50"')) ?> + + form->label(t('Description'), 'description') ?> + +
    +
    + form->textarea('description', $values, $errors) ?> +
    +
    +
    +
    +
      +
    • + +
    • +
    • + +
    • +
    +
    +
    url->doc(t('Write your text in Markdown'), 'syntax-guide') ?>
    + +
    + + + url->link(t('cancel'), 'Swimlane', 'index', array('project_id' => $project['id']), false, 'close-popover') ?> +
    +
    diff --git a/app/Template/swimlane/edit_default.php b/app/Template/swimlane/edit_default.php new file mode 100644 index 00000000..df25ec12 --- /dev/null +++ b/app/Template/swimlane/edit_default.php @@ -0,0 +1,18 @@ + +
    + form->csrf() ?> + form->hidden('id', $values) ?> + + form->label(t('Name'), 'default_swimlane') ?> + form->text('default_swimlane', $values, $errors, array('required', 'maxlength="50"')) ?> + + form->checkbox('show_default_swimlane', t('Show default swimlane'), 1, $values['show_default_swimlane'] == 1) ?> + +
    + + + url->link(t('cancel'), 'Swimlane', 'index', array('project_id' => $project['id']), false, 'close-popover') ?> +
    +
    diff --git a/app/Template/swimlane/index.php b/app/Template/swimlane/index.php index 90100a98..fad35306 100644 --- a/app/Template/swimlane/index.php +++ b/app/Template/swimlane/index.php @@ -1,71 +1,28 @@ -
    - form->csrf() ?> - form->hidden('id', $default_swimlane) ?> - - form->label(t('Rename'), 'default_swimlane') ?> - form->text('default_swimlane', $default_swimlane, array(), array('required', 'maxlength="50"')) ?> - - - form->checkbox('show_default_swimlane', t('Show default swimlane'), 1, $default_swimlane['show_default_swimlane'] == 1) ?> - - form->hidden('show_default_swimlane', $default_swimlane) ?> - - -
    - -
    -
    - - - -render('swimlane/table', array('swimlanes' => $active_swimlanes, 'project' => $project)) ?> + +

    + render('swimlane/table', array( + 'swimlanes' => $active_swimlanes, + 'project' => $project, + 'default_swimlane' => $default_swimlane['show_default_swimlane'] == 1 ? $default_swimlane : array() + )) ?> - - -render('swimlane/table', array('swimlanes' => $inactive_swimlanes, 'project' => $project, 'hide_position' => true)) ?> + +

    + render('swimlane/table', array( + 'swimlanes' => $inactive_swimlanes, + 'project' => $project, + 'default_swimlane' => $default_swimlane['show_default_swimlane'] == 0 ? $default_swimlane : array(), + 'disable_handler' => true + )) ?> - - -
    - - form->csrf() ?> - form->hidden('project_id', $values) ?> - - form->label(t('Name'), 'name') ?> - form->text('name', $values, $errors, array('required', 'maxlength="50"')) ?> - - form->label(t('Description'), 'description') ?> - -
    -
    - form->textarea('description', $values, $errors) ?> -
    -
    -
    -
    -
      -
    • - -
    • -
    • - -
    • -
    -
    -
    url->doc(t('Write your text in Markdown'), 'syntax-guide') ?>
    - -
    - -
    -
    diff --git a/app/Template/swimlane/table.php b/app/Template/swimlane/table.php index 60eea47b..1e6a86bc 100644 --- a/app/Template/swimlane/table.php +++ b/app/Template/swimlane/table.php @@ -1,47 +1,76 @@ - - - - - - - - - - - - - - - + + + + +
    #e($swimlane['name']) ?> - + +
    diff --git a/assets/js/app.js b/assets/js/app.js index d831659c..d5e973b9 100644 --- a/assets/js/app.js +++ b/assets/js/app.js @@ -1278,4 +1278,4 @@ if (typeof jQuery === 'undefined') { return jQuery; })); -!function(a){"function"==typeof define&&define.amd?define(["jquery","moment"],a):a(jQuery,moment)}(function(a,b){function c(a){return a>1&&5>a&&1!==~~(a/10)}function d(a,b,d,e){var f=a+" ";switch(d){case"s":return b||e?"pár sekund":"pár sekundami";case"m":return b?"minuta":e?"minutu":"minutou";case"mm":return b||e?f+(c(a)?"minuty":"minut"):f+"minutami";case"h":return b?"hodina":e?"hodinu":"hodinou";case"hh":return b||e?f+(c(a)?"hodiny":"hodin"):f+"hodinami";case"d":return b||e?"den":"dnem";case"dd":return b||e?f+(c(a)?"dny":"dní"):f+"dny";case"M":return b||e?"měsíc":"měsícem";case"MM":return b||e?f+(c(a)?"měsíce":"měsíců"):f+"měsíci";case"y":return b||e?"rok":"rokem";case"yy":return b||e?f+(c(a)?"roky":"let"):f+"lety"}}var e="leden_únor_březen_duben_květen_červen_červenec_srpen_září_říjen_listopad_prosinec".split("_"),f="led_úno_bře_dub_kvě_čvn_čvc_srp_zář_říj_lis_pro".split("_");(b.defineLocale||b.lang).call(b,"cs",{months:e,monthsShort:f,monthsParse:function(a,b){var c,d=[];for(c=0;12>c;c++)d[c]=new RegExp("^"+a[c]+"$|^"+b[c]+"$","i");return d}(e,f),weekdays:"neděle_pondělí_úterý_středa_čtvrtek_pátek_sobota".split("_"),weekdaysShort:"ne_po_út_st_čt_pá_so".split("_"),weekdaysMin:"ne_po_út_st_čt_pá_so".split("_"),longDateFormat:{LT:"H:mm",LTS:"LT:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY LT",LLLL:"dddd D. MMMM YYYY LT"},calendar:{sameDay:"[dnes v] LT",nextDay:"[zítra v] LT",nextWeek:function(){switch(this.day()){case 0:return"[v neděli v] LT";case 1:case 2:return"[v] dddd [v] LT";case 3:return"[ve středu v] LT";case 4:return"[ve čtvrtek v] LT";case 5:return"[v pátek v] LT";case 6:return"[v sobotu v] LT"}},lastDay:"[včera v] LT",lastWeek:function(){switch(this.day()){case 0:return"[minulou neděli v] LT";case 1:case 2:return"[minulé] dddd [v] LT";case 3:return"[minulou středu v] LT";case 4:case 5:return"[minulý] dddd [v] LT";case 6:return"[minulou sobotu v] LT"}},sameElse:"L"},relativeTime:{future:"za %s",past:"před %s",s:d,m:d,mm:d,h:d,hh:d,d:d,dd:d,M:d,MM:d,y:d,yy:d},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}}),a.fullCalendar.datepickerLang("cs","cs",{closeText:"Zavřít",prevText:"<Dříve",nextText:"Později>",currentText:"Nyní",monthNames:["leden","únor","březen","duben","květen","červen","červenec","srpen","září","říjen","listopad","prosinec"],monthNamesShort:["led","úno","bře","dub","kvě","čer","čvc","srp","zář","říj","lis","pro"],dayNames:["neděle","pondělí","úterý","středa","čtvrtek","pátek","sobota"],dayNamesShort:["ne","po","út","st","čt","pá","so"],dayNamesMin:["ne","po","út","st","čt","pá","so"],weekHeader:"Týd",dateFormat:"dd.mm.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("cs",{buttonText:{month:"Měsíc",week:"Týden",day:"Den",list:"Agenda"},allDayText:"Celý den",eventLimitText:function(a){return"+další: "+a}})});!function(a){"function"==typeof define&&define.amd?define(["jquery","moment"],a):a(jQuery,moment)}(function(a,b){(b.defineLocale||b.lang).call(b,"da",{months:"januar_februar_marts_april_maj_juni_juli_august_september_oktober_november_december".split("_"),monthsShort:"jan_feb_mar_apr_maj_jun_jul_aug_sep_okt_nov_dec".split("_"),weekdays:"søndag_mandag_tirsdag_onsdag_torsdag_fredag_lørdag".split("_"),weekdaysShort:"søn_man_tir_ons_tor_fre_lør".split("_"),weekdaysMin:"sø_ma_ti_on_to_fr_lø".split("_"),longDateFormat:{LT:"HH:mm",LTS:"LT:ss",L:"DD/MM/YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY LT",LLLL:"dddd [d.] D. MMMM YYYY LT"},calendar:{sameDay:"[I dag kl.] LT",nextDay:"[I morgen kl.] LT",nextWeek:"dddd [kl.] LT",lastDay:"[I går kl.] LT",lastWeek:"[sidste] dddd [kl] LT",sameElse:"L"},relativeTime:{future:"om %s",past:"%s siden",s:"få sekunder",m:"et minut",mm:"%d minutter",h:"en time",hh:"%d timer",d:"en dag",dd:"%d dage",M:"en måned",MM:"%d måneder",y:"et år",yy:"%d år"},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}}),a.fullCalendar.datepickerLang("da","da",{closeText:"Luk",prevText:"<Forrige",nextText:"Næste>",currentText:"Idag",monthNames:["Januar","Februar","Marts","April","Maj","Juni","Juli","August","September","Oktober","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","Maj","Jun","Jul","Aug","Sep","Okt","Nov","Dec"],dayNames:["Søndag","Mandag","Tirsdag","Onsdag","Torsdag","Fredag","Lørdag"],dayNamesShort:["Søn","Man","Tir","Ons","Tor","Fre","Lør"],dayNamesMin:["Sø","Ma","Ti","On","To","Fr","Lø"],weekHeader:"Uge",dateFormat:"dd-mm-yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("da",{buttonText:{month:"Måned",week:"Uge",day:"Dag",list:"Agenda"},allDayText:"Hele dagen",eventLimitText:"flere"})});!function(a){"function"==typeof define&&define.amd?define(["jquery","moment"],a):a(jQuery,moment)}(function(a,b){function c(a,b,c,d){var e={m:["eine Minute","einer Minute"],h:["eine Stunde","einer Stunde"],d:["ein Tag","einem Tag"],dd:[a+" Tage",a+" Tagen"],M:["ein Monat","einem Monat"],MM:[a+" Monate",a+" Monaten"],y:["ein Jahr","einem Jahr"],yy:[a+" Jahre",a+" Jahren"]};return b?e[c][0]:e[c][1]}(b.defineLocale||b.lang).call(b,"de",{months:"Januar_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember".split("_"),monthsShort:"Jan._Febr._Mrz._Apr._Mai_Jun._Jul._Aug._Sept._Okt._Nov._Dez.".split("_"),weekdays:"Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag".split("_"),weekdaysShort:"So._Mo._Di._Mi._Do._Fr._Sa.".split("_"),weekdaysMin:"So_Mo_Di_Mi_Do_Fr_Sa".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY LT",LLLL:"dddd, D. MMMM YYYY LT"},calendar:{sameDay:"[Heute um] LT [Uhr]",sameElse:"L",nextDay:"[Morgen um] LT [Uhr]",nextWeek:"dddd [um] LT [Uhr]",lastDay:"[Gestern um] LT [Uhr]",lastWeek:"[letzten] dddd [um] LT [Uhr]"},relativeTime:{future:"in %s",past:"vor %s",s:"ein paar Sekunden",m:c,mm:"%d Minuten",h:c,hh:"%d Stunden",d:c,dd:c,M:c,MM:c,y:c,yy:c},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}}),a.fullCalendar.datepickerLang("de","de",{closeText:"Schließen",prevText:"<Zurück",nextText:"Vor>",currentText:"Heute",monthNames:["Januar","Februar","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember"],monthNamesShort:["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],dayNames:["Sonntag","Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag"],dayNamesShort:["So","Mo","Di","Mi","Do","Fr","Sa"],dayNamesMin:["So","Mo","Di","Mi","Do","Fr","Sa"],weekHeader:"KW",dateFormat:"dd.mm.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("de",{buttonText:{month:"Monat",week:"Woche",day:"Tag",list:"Terminübersicht"},allDayText:"Ganztägig",eventLimitText:function(a){return"+ weitere "+a}})});!function(a){"function"==typeof define&&define.amd?define(["jquery","moment"],a):a(jQuery,moment)}(function(a,b){var c="ene._feb._mar._abr._may._jun._jul._ago._sep._oct._nov._dic.".split("_"),d="ene_feb_mar_abr_may_jun_jul_ago_sep_oct_nov_dic".split("_");(b.defineLocale||b.lang).call(b,"es",{months:"enero_febrero_marzo_abril_mayo_junio_julio_agosto_septiembre_octubre_noviembre_diciembre".split("_"),monthsShort:function(a,b){return/-MMM-/.test(b)?d[a.month()]:c[a.month()]},weekdays:"domingo_lunes_martes_miércoles_jueves_viernes_sábado".split("_"),weekdaysShort:"dom._lun._mar._mié._jue._vie._sáb.".split("_"),weekdaysMin:"Do_Lu_Ma_Mi_Ju_Vi_Sá".split("_"),longDateFormat:{LT:"H:mm",LTS:"LT:ss",L:"DD/MM/YYYY",LL:"D [de] MMMM [de] YYYY",LLL:"D [de] MMMM [de] YYYY LT",LLLL:"dddd, D [de] MMMM [de] YYYY LT"},calendar:{sameDay:function(){return"[hoy a la"+(1!==this.hours()?"s":"")+"] LT"},nextDay:function(){return"[mañana a la"+(1!==this.hours()?"s":"")+"] LT"},nextWeek:function(){return"dddd [a la"+(1!==this.hours()?"s":"")+"] LT"},lastDay:function(){return"[ayer a la"+(1!==this.hours()?"s":"")+"] LT"},lastWeek:function(){return"[el] dddd [pasado a la"+(1!==this.hours()?"s":"")+"] LT"},sameElse:"L"},relativeTime:{future:"en %s",past:"hace %s",s:"unos segundos",m:"un minuto",mm:"%d minutos",h:"una hora",hh:"%d horas",d:"un día",dd:"%d días",M:"un mes",MM:"%d meses",y:"un año",yy:"%d años"},ordinalParse:/\d{1,2}º/,ordinal:"%dº",week:{dow:1,doy:4}}),a.fullCalendar.datepickerLang("es","es",{closeText:"Cerrar",prevText:"<Ant",nextText:"Sig>",currentText:"Hoy",monthNames:["enero","febrero","marzo","abril","mayo","junio","julio","agosto","septiembre","octubre","noviembre","diciembre"],monthNamesShort:["ene","feb","mar","abr","may","jun","jul","ago","sep","oct","nov","dic"],dayNames:["domingo","lunes","martes","miércoles","jueves","viernes","sábado"],dayNamesShort:["dom","lun","mar","mié","jue","vie","sáb"],dayNamesMin:["D","L","M","X","J","V","S"],weekHeader:"Sm",dateFormat:"dd/mm/yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("es",{buttonText:{month:"Mes",week:"Semana",day:"Día",list:"Agenda"},allDayHtml:"Todo
    el día",eventLimitText:"más"})});!function(a){"function"==typeof define&&define.amd?define(["jquery","moment"],a):a(jQuery,moment)}(function(a,b){(b.defineLocale||b.lang).call(b,"el",{monthsNominativeEl:"Ιανουάριος_Φεβρουάριος_Μάρτιος_Απρίλιος_Μάιος_Ιούνιος_Ιούλιος_Αύγουστος_Σεπτέμβριος_Οκτώβριος_Νοέμβριος_Δεκέμβριος".split("_"),monthsGenitiveEl:"Ιανουαρίου_Φεβρουαρίου_Μαρτίου_Απριλίου_Μαΐου_Ιουνίου_Ιουλίου_Αυγούστου_Σεπτεμβρίου_Οκτωβρίου_Νοεμβρίου_Δεκεμβρίου".split("_"),months:function(a,b){return/D/.test(b.substring(0,b.indexOf("MMMM")))?this._monthsGenitiveEl[a.month()]:this._monthsNominativeEl[a.month()]},monthsShort:"Ιαν_Φεβ_Μαρ_Απρ_Μαϊ_Ιουν_Ιουλ_Αυγ_Σεπ_Οκτ_Νοε_Δεκ".split("_"),weekdays:"Κυριακή_Δευτέρα_Τρίτη_Τετάρτη_Πέμπτη_Παρασκευή_Σάββατο".split("_"),weekdaysShort:"Κυρ_Δευ_Τρι_Τετ_Πεμ_Παρ_Σαβ".split("_"),weekdaysMin:"Κυ_Δε_Τρ_Τε_Πε_Πα_Σα".split("_"),meridiem:function(a,b,c){return a>11?c?"μμ":"ΜΜ":c?"πμ":"ΠΜ"},isPM:function(a){return"μ"===(a+"").toLowerCase()[0]},meridiemParse:/[ΠΜ]\.?Μ?\.?/i,longDateFormat:{LT:"h:mm A",LTS:"h:mm:ss A",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd, D MMMM YYYY LT"},calendarEl:{sameDay:"[Σήμερα {}] LT",nextDay:"[Αύριο {}] LT",nextWeek:"dddd [{}] LT",lastDay:"[Χθες {}] LT",lastWeek:function(){switch(this.day()){case 6:return"[το προηγούμενο] dddd [{}] LT";default:return"[την προηγούμενη] dddd [{}] LT"}},sameElse:"L"},calendar:function(a,b){var c=this._calendarEl[a],d=b&&b.hours();return"function"==typeof c&&(c=c.apply(b)),c.replace("{}",d%12===1?"στη":"στις")},relativeTime:{future:"σε %s",past:"%s πριν",s:"λίγα δευτερόλεπτα",m:"ένα λεπτό",mm:"%d λεπτά",h:"μία ώρα",hh:"%d ώρες",d:"μία μέρα",dd:"%d μέρες",M:"ένας μήνας",MM:"%d μήνες",y:"ένας χρόνος",yy:"%d χρόνια"},ordinalParse:/\d{1,2}η/,ordinal:"%dη",week:{dow:1,doy:4}}),a.fullCalendar.datepickerLang("el","el",{closeText:"Κλείσιμο",prevText:"Προηγούμενος",nextText:"Επόμενος",currentText:"Σήμερα",monthNames:["Ιανουάριος","Φεβρουάριος","Μάρτιος","Απρίλιος","Μάιος","Ιούνιος","Ιούλιος","Αύγουστος","Σεπτέμβριος","Οκτώβριος","Νοέμβριος","Δεκέμβριος"],monthNamesShort:["Ιαν","Φεβ","Μαρ","Απρ","Μαι","Ιουν","Ιουλ","Αυγ","Σεπ","Οκτ","Νοε","Δεκ"],dayNames:["Κυριακή","Δευτέρα","Τρίτη","Τετάρτη","Πέμπτη","Παρασκευή","Σάββατο"],dayNamesShort:["Κυρ","Δευ","Τρι","Τετ","Πεμ","Παρ","Σαβ"],dayNamesMin:["Κυ","Δε","Τρ","Τε","Πε","Πα","Σα"],weekHeader:"Εβδ",dateFormat:"dd/mm/yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("el",{buttonText:{month:"Μήνας",week:"Εβδομάδα",day:"Ημέρα",list:"Ατζέντα"},allDayText:"Ολοήμερο",eventLimitText:"περισσότερα"})});!function(a){"function"==typeof define&&define.amd?define(["jquery","moment"],a):a(jQuery,moment)}(function(a,b){function c(a,b,c,e){var f="";switch(c){case"s":return e?"muutaman sekunnin":"muutama sekunti";case"m":return e?"minuutin":"minuutti";case"mm":f=e?"minuutin":"minuuttia";break;case"h":return e?"tunnin":"tunti";case"hh":f=e?"tunnin":"tuntia";break;case"d":return e?"päivän":"päivä";case"dd":f=e?"päivän":"päivää";break;case"M":return e?"kuukauden":"kuukausi";case"MM":f=e?"kuukauden":"kuukautta";break;case"y":return e?"vuoden":"vuosi";case"yy":f=e?"vuoden":"vuotta"}return f=d(a,e)+" "+f}function d(a,b){return 10>a?b?f[a]:e[a]:a}var e="nolla yksi kaksi kolme neljä viisi kuusi seitsemän kahdeksan yhdeksän".split(" "),f=["nolla","yhden","kahden","kolmen","neljän","viiden","kuuden",e[7],e[8],e[9]];(b.defineLocale||b.lang).call(b,"fi",{months:"tammikuu_helmikuu_maaliskuu_huhtikuu_toukokuu_kesäkuu_heinäkuu_elokuu_syyskuu_lokakuu_marraskuu_joulukuu".split("_"),monthsShort:"tammi_helmi_maalis_huhti_touko_kesä_heinä_elo_syys_loka_marras_joulu".split("_"),weekdays:"sunnuntai_maanantai_tiistai_keskiviikko_torstai_perjantai_lauantai".split("_"),weekdaysShort:"su_ma_ti_ke_to_pe_la".split("_"),weekdaysMin:"su_ma_ti_ke_to_pe_la".split("_"),longDateFormat:{LT:"HH.mm",LTS:"HH.mm.ss",L:"DD.MM.YYYY",LL:"Do MMMM[ta] YYYY",LLL:"Do MMMM[ta] YYYY, [klo] LT",LLLL:"dddd, Do MMMM[ta] YYYY, [klo] LT",l:"D.M.YYYY",ll:"Do MMM YYYY",lll:"Do MMM YYYY, [klo] LT",llll:"ddd, Do MMM YYYY, [klo] LT"},calendar:{sameDay:"[tänään] [klo] LT",nextDay:"[huomenna] [klo] LT",nextWeek:"dddd [klo] LT",lastDay:"[eilen] [klo] LT",lastWeek:"[viime] dddd[na] [klo] LT",sameElse:"L"},relativeTime:{future:"%s päästä",past:"%s sitten",s:c,m:c,mm:c,h:c,hh:c,d:c,dd:c,M:c,MM:c,y:c,yy:c},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}}),a.fullCalendar.datepickerLang("fi","fi",{closeText:"Sulje",prevText:"«Edellinen",nextText:"Seuraava»",currentText:"Tänään",monthNames:["Tammikuu","Helmikuu","Maaliskuu","Huhtikuu","Toukokuu","Kesäkuu","Heinäkuu","Elokuu","Syyskuu","Lokakuu","Marraskuu","Joulukuu"],monthNamesShort:["Tammi","Helmi","Maalis","Huhti","Touko","Kesä","Heinä","Elo","Syys","Loka","Marras","Joulu"],dayNamesShort:["Su","Ma","Ti","Ke","To","Pe","La"],dayNames:["Sunnuntai","Maanantai","Tiistai","Keskiviikko","Torstai","Perjantai","Lauantai"],dayNamesMin:["Su","Ma","Ti","Ke","To","Pe","La"],weekHeader:"Vk",dateFormat:"d.m.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("fi",{buttonText:{month:"Kuukausi",week:"Viikko",day:"Päivä",list:"Tapahtumat"},allDayText:"Koko päivä",eventLimitText:"lisää"})});!function(a){"function"==typeof define&&define.amd?define(["jquery","moment"],a):a(jQuery,moment)}(function(a,b){(b.defineLocale||b.lang).call(b,"fr",{months:"janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre".split("_"),monthsShort:"janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.".split("_"),weekdays:"dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi".split("_"),weekdaysShort:"dim._lun._mar._mer._jeu._ven._sam.".split("_"),weekdaysMin:"Di_Lu_Ma_Me_Je_Ve_Sa".split("_"),longDateFormat:{LT:"HH:mm",LTS:"LT:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:"[Aujourd'hui à] LT",nextDay:"[Demain à] LT",nextWeek:"dddd [à] LT",lastDay:"[Hier à] LT",lastWeek:"dddd [dernier à] LT",sameElse:"L"},relativeTime:{future:"dans %s",past:"il y a %s",s:"quelques secondes",m:"une minute",mm:"%d minutes",h:"une heure",hh:"%d heures",d:"un jour",dd:"%d jours",M:"un mois",MM:"%d mois",y:"un an",yy:"%d ans"},ordinalParse:/\d{1,2}(er|)/,ordinal:function(a){return a+(1===a?"er":"")},week:{dow:1,doy:4}}),a.fullCalendar.datepickerLang("fr","fr",{closeText:"Fermer",prevText:"Précédent",nextText:"Suivant",currentText:"Aujourd'hui",monthNames:["janvier","février","mars","avril","mai","juin","juillet","août","septembre","octobre","novembre","décembre"],monthNamesShort:["janv.","févr.","mars","avr.","mai","juin","juil.","août","sept.","oct.","nov.","déc."],dayNames:["dimanche","lundi","mardi","mercredi","jeudi","vendredi","samedi"],dayNamesShort:["dim.","lun.","mar.","mer.","jeu.","ven.","sam."],dayNamesMin:["D","L","M","M","J","V","S"],weekHeader:"Sem.",dateFormat:"dd/mm/yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("fr",{buttonText:{month:"Mois",week:"Semaine",day:"Jour",list:"Mon planning"},allDayHtml:"Toute la
    journée",eventLimitText:"en plus"})});!function(a){"function"==typeof define&&define.amd?define(["jquery","moment"],a):a(jQuery,moment)}(function(a,b){function c(a,b,c,d){var e=a;switch(c){case"s":return d||b?"néhány másodperc":"néhány másodperce";case"m":return"egy"+(d||b?" perc":" perce");case"mm":return e+(d||b?" perc":" perce");case"h":return"egy"+(d||b?" óra":" órája");case"hh":return e+(d||b?" óra":" órája");case"d":return"egy"+(d||b?" nap":" napja");case"dd":return e+(d||b?" nap":" napja");case"M":return"egy"+(d||b?" hónap":" hónapja");case"MM":return e+(d||b?" hónap":" hónapja");case"y":return"egy"+(d||b?" év":" éve");case"yy":return e+(d||b?" év":" éve")}return""}function d(a){return(a?"":"[múlt] ")+"["+e[this.day()]+"] LT[-kor]"}var e="vasárnap hétfőn kedden szerdán csütörtökön pénteken szombaton".split(" ");(b.defineLocale||b.lang).call(b,"hu",{months:"január_február_március_április_május_június_július_augusztus_szeptember_október_november_december".split("_"),monthsShort:"jan_feb_márc_ápr_máj_jún_júl_aug_szept_okt_nov_dec".split("_"),weekdays:"vasárnap_hétfő_kedd_szerda_csütörtök_péntek_szombat".split("_"),weekdaysShort:"vas_hét_kedd_sze_csüt_pén_szo".split("_"),weekdaysMin:"v_h_k_sze_cs_p_szo".split("_"),longDateFormat:{LT:"H:mm",LTS:"LT:ss",L:"YYYY.MM.DD.",LL:"YYYY. MMMM D.",LLL:"YYYY. MMMM D., LT",LLLL:"YYYY. MMMM D., dddd LT"},meridiemParse:/de|du/i,isPM:function(a){return"u"===a.charAt(1).toLowerCase()},meridiem:function(a,b,c){return 12>a?c===!0?"de":"DE":c===!0?"du":"DU"},calendar:{sameDay:"[ma] LT[-kor]",nextDay:"[holnap] LT[-kor]",nextWeek:function(){return d.call(this,!0)},lastDay:"[tegnap] LT[-kor]",lastWeek:function(){return d.call(this,!1)},sameElse:"L"},relativeTime:{future:"%s múlva",past:"%s",s:c,m:c,mm:c,h:c,hh:c,d:c,dd:c,M:c,MM:c,y:c,yy:c},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:7}}),a.fullCalendar.datepickerLang("hu","hu",{closeText:"bezár",prevText:"vissza",nextText:"előre",currentText:"ma",monthNames:["Január","Február","Március","Április","Május","Június","Július","Augusztus","Szeptember","Október","November","December"],monthNamesShort:["Jan","Feb","Már","Ápr","Máj","Jún","Júl","Aug","Szep","Okt","Nov","Dec"],dayNames:["Vasárnap","Hétfő","Kedd","Szerda","Csütörtök","Péntek","Szombat"],dayNamesShort:["Vas","Hét","Ked","Sze","Csü","Pén","Szo"],dayNamesMin:["V","H","K","Sze","Cs","P","Szo"],weekHeader:"Hét",dateFormat:"yy.mm.dd.",firstDay:1,isRTL:!1,showMonthAfterYear:!0,yearSuffix:""}),a.fullCalendar.lang("hu",{buttonText:{month:"Hónap",week:"Hét",day:"Nap",list:"Napló"},allDayText:"Egész nap",eventLimitText:"további"})});!function(a){"function"==typeof define&&define.amd?define(["jquery","moment"],a):a(jQuery,moment)}(function(a,b){(b.defineLocale||b.lang).call(b,"id",{months:"Januari_Februari_Maret_April_Mei_Juni_Juli_Agustus_September_Oktober_November_Desember".split("_"),monthsShort:"Jan_Feb_Mar_Apr_Mei_Jun_Jul_Ags_Sep_Okt_Nov_Des".split("_"),weekdays:"Minggu_Senin_Selasa_Rabu_Kamis_Jumat_Sabtu".split("_"),weekdaysShort:"Min_Sen_Sel_Rab_Kam_Jum_Sab".split("_"),weekdaysMin:"Mg_Sn_Sl_Rb_Km_Jm_Sb".split("_"),longDateFormat:{LT:"HH.mm",LTS:"LT.ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY [pukul] LT",LLLL:"dddd, D MMMM YYYY [pukul] LT"},meridiemParse:/pagi|siang|sore|malam/,meridiemHour:function(a,b){return 12===a&&(a=0),"pagi"===b?a:"siang"===b?a>=11?a:a+12:"sore"===b||"malam"===b?a+12:void 0},meridiem:function(a,b,c){return 11>a?"pagi":15>a?"siang":19>a?"sore":"malam"},calendar:{sameDay:"[Hari ini pukul] LT",nextDay:"[Besok pukul] LT",nextWeek:"dddd [pukul] LT",lastDay:"[Kemarin pukul] LT",lastWeek:"dddd [lalu pukul] LT",sameElse:"L"},relativeTime:{future:"dalam %s",past:"%s yang lalu",s:"beberapa detik",m:"semenit",mm:"%d menit",h:"sejam",hh:"%d jam",d:"sehari",dd:"%d hari",M:"sebulan",MM:"%d bulan",y:"setahun",yy:"%d tahun"},week:{dow:1,doy:7}}),a.fullCalendar.datepickerLang("id","id",{closeText:"Tutup",prevText:"<mundur",nextText:"maju>",currentText:"hari ini",monthNames:["Januari","Februari","Maret","April","Mei","Juni","Juli","Agustus","September","Oktober","Nopember","Desember"],monthNamesShort:["Jan","Feb","Mar","Apr","Mei","Jun","Jul","Agus","Sep","Okt","Nop","Des"],dayNames:["Minggu","Senin","Selasa","Rabu","Kamis","Jumat","Sabtu"],dayNamesShort:["Min","Sen","Sel","Rab","kam","Jum","Sab"],dayNamesMin:["Mg","Sn","Sl","Rb","Km","jm","Sb"],weekHeader:"Mg",dateFormat:"dd/mm/yy",firstDay:0,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("id",{buttonText:{month:"Bulan",week:"Minggu",day:"Hari",list:"Agenda"},allDayHtml:"Sehari
    penuh",eventLimitText:"lebih"})});!function(a){"function"==typeof define&&define.amd?define(["jquery","moment"],a):a(jQuery,moment)}(function(a,b){(b.defineLocale||b.lang).call(b,"it",{months:"gennaio_febbraio_marzo_aprile_maggio_giugno_luglio_agosto_settembre_ottobre_novembre_dicembre".split("_"),monthsShort:"gen_feb_mar_apr_mag_giu_lug_ago_set_ott_nov_dic".split("_"),weekdays:"Domenica_Lunedì_Martedì_Mercoledì_Giovedì_Venerdì_Sabato".split("_"),weekdaysShort:"Dom_Lun_Mar_Mer_Gio_Ven_Sab".split("_"),weekdaysMin:"D_L_Ma_Me_G_V_S".split("_"),longDateFormat:{LT:"HH:mm",LTS:"LT:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd, D MMMM YYYY LT"},calendar:{sameDay:"[Oggi alle] LT",nextDay:"[Domani alle] LT",nextWeek:"dddd [alle] LT",lastDay:"[Ieri alle] LT",lastWeek:function(){switch(this.day()){case 0:return"[la scorsa] dddd [alle] LT";default:return"[lo scorso] dddd [alle] LT"}},sameElse:"L"},relativeTime:{future:function(a){return(/^[0-9].+$/.test(a)?"tra":"in")+" "+a},past:"%s fa",s:"alcuni secondi",m:"un minuto",mm:"%d minuti",h:"un'ora",hh:"%d ore",d:"un giorno",dd:"%d giorni",M:"un mese",MM:"%d mesi",y:"un anno",yy:"%d anni"},ordinalParse:/\d{1,2}º/,ordinal:"%dº",week:{dow:1,doy:4}}),a.fullCalendar.datepickerLang("it","it",{closeText:"Chiudi",prevText:"<Prec",nextText:"Succ>",currentText:"Oggi",monthNames:["Gennaio","Febbraio","Marzo","Aprile","Maggio","Giugno","Luglio","Agosto","Settembre","Ottobre","Novembre","Dicembre"],monthNamesShort:["Gen","Feb","Mar","Apr","Mag","Giu","Lug","Ago","Set","Ott","Nov","Dic"],dayNames:["Domenica","Lunedì","Martedì","Mercoledì","Giovedì","Venerdì","Sabato"],dayNamesShort:["Dom","Lun","Mar","Mer","Gio","Ven","Sab"],dayNamesMin:["Do","Lu","Ma","Me","Gi","Ve","Sa"],weekHeader:"Sm",dateFormat:"dd/mm/yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("it",{buttonText:{month:"Mese",week:"Settimana",day:"Giorno",list:"Agenda"},allDayHtml:"Tutto il
    giorno",eventLimitText:function(a){return"+altri "+a}})});!function(a){"function"==typeof define&&define.amd?define(["jquery","moment"],a):a(jQuery,moment)}(function(a,b){(b.defineLocale||b.lang).call(b,"ja",{months:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),monthsShort:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),weekdays:"日曜日_月曜日_火曜日_水曜日_木曜日_金曜日_土曜日".split("_"),weekdaysShort:"日_月_火_水_木_金_土".split("_"),weekdaysMin:"日_月_火_水_木_金_土".split("_"),longDateFormat:{LT:"Ah時m分",LTS:"LTs秒",L:"YYYY/MM/DD",LL:"YYYY年M月D日",LLL:"YYYY年M月D日LT",LLLL:"YYYY年M月D日LT dddd"},meridiemParse:/午前|午後/i,isPM:function(a){return"午後"===a},meridiem:function(a,b,c){return 12>a?"午前":"午後"},calendar:{sameDay:"[今日] LT",nextDay:"[明日] LT",nextWeek:"[来週]dddd LT",lastDay:"[昨日] LT",lastWeek:"[前週]dddd LT",sameElse:"L"},relativeTime:{future:"%s後",past:"%s前",s:"数秒",m:"1分",mm:"%d分",h:"1時間",hh:"%d時間",d:"1日",dd:"%d日",M:"1ヶ月",MM:"%dヶ月",y:"1年",yy:"%d年"}}),a.fullCalendar.datepickerLang("ja","ja",{closeText:"閉じる",prevText:"<前",nextText:"次>",currentText:"今日",monthNames:["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],monthNamesShort:["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],dayNames:["日曜日","月曜日","火曜日","水曜日","木曜日","金曜日","土曜日"],dayNamesShort:["日","月","火","水","木","金","土"],dayNamesMin:["日","月","火","水","木","金","土"],weekHeader:"週",dateFormat:"yy/mm/dd",firstDay:0,isRTL:!1,showMonthAfterYear:!0,yearSuffix:"年"}),a.fullCalendar.lang("ja",{buttonText:{month:"月",week:"週",day:"日",list:"予定リスト"},allDayText:"終日",eventLimitText:function(a){return"他 "+a+" 件"}})});!function(a){"function"==typeof define&&define.amd?define(["jquery","moment"],a):a(jQuery,moment)}(function(a,b){var c="jan._feb._mrt._apr._mei_jun._jul._aug._sep._okt._nov._dec.".split("_"),d="jan_feb_mrt_apr_mei_jun_jul_aug_sep_okt_nov_dec".split("_");(b.defineLocale||b.lang).call(b,"nl",{months:"januari_februari_maart_april_mei_juni_juli_augustus_september_oktober_november_december".split("_"),monthsShort:function(a,b){return/-MMM-/.test(b)?d[a.month()]:c[a.month()]},weekdays:"zondag_maandag_dinsdag_woensdag_donderdag_vrijdag_zaterdag".split("_"),weekdaysShort:"zo._ma._di._wo._do._vr._za.".split("_"),weekdaysMin:"Zo_Ma_Di_Wo_Do_Vr_Za".split("_"),longDateFormat:{LT:"HH:mm",LTS:"LT:ss",L:"DD-MM-YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:"[vandaag om] LT",nextDay:"[morgen om] LT",nextWeek:"dddd [om] LT",lastDay:"[gisteren om] LT",lastWeek:"[afgelopen] dddd [om] LT",sameElse:"L"},relativeTime:{future:"over %s",past:"%s geleden",s:"een paar seconden",m:"één minuut",mm:"%d minuten",h:"één uur",hh:"%d uur",d:"één dag",dd:"%d dagen",M:"één maand",MM:"%d maanden",y:"één jaar",yy:"%d jaar"},ordinalParse:/\d{1,2}(ste|de)/,ordinal:function(a){return a+(1===a||8===a||a>=20?"ste":"de")},week:{dow:1,doy:4}}),a.fullCalendar.datepickerLang("nl","nl",{closeText:"Sluiten",prevText:"←",nextText:"→",currentText:"Vandaag",monthNames:["januari","februari","maart","april","mei","juni","juli","augustus","september","oktober","november","december"],monthNamesShort:["jan","feb","mrt","apr","mei","jun","jul","aug","sep","okt","nov","dec"],dayNames:["zondag","maandag","dinsdag","woensdag","donderdag","vrijdag","zaterdag"],dayNamesShort:["zon","maa","din","woe","don","vri","zat"],dayNamesMin:["zo","ma","di","wo","do","vr","za"],weekHeader:"Wk",dateFormat:"dd-mm-yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("nl",{buttonText:{month:"Maand",week:"Week",day:"Dag",list:"Agenda"},allDayText:"Hele dag",eventLimitText:"extra"})});!function(a){"function"==typeof define&&define.amd?define(["jquery","moment"],a):a(jQuery,moment)}(function(a,b){(b.defineLocale||b.lang).call(b,"nb",{months:"januar_februar_mars_april_mai_juni_juli_august_september_oktober_november_desember".split("_"),monthsShort:"jan_feb_mar_apr_mai_jun_jul_aug_sep_okt_nov_des".split("_"),weekdays:"søndag_mandag_tirsdag_onsdag_torsdag_fredag_lørdag".split("_"),weekdaysShort:"søn_man_tirs_ons_tors_fre_lør".split("_"),weekdaysMin:"sø_ma_ti_on_to_fr_lø".split("_"),longDateFormat:{LT:"H.mm",LTS:"LT.ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY [kl.] LT",LLLL:"dddd D. MMMM YYYY [kl.] LT"},calendar:{sameDay:"[i dag kl.] LT",nextDay:"[i morgen kl.] LT",nextWeek:"dddd [kl.] LT",lastDay:"[i går kl.] LT",lastWeek:"[forrige] dddd [kl.] LT",sameElse:"L"},relativeTime:{future:"om %s",past:"for %s siden",s:"noen sekunder",m:"ett minutt",mm:"%d minutter",h:"en time",hh:"%d timer",d:"en dag",dd:"%d dager",M:"en måned",MM:"%d måneder",y:"ett år",yy:"%d år"},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}}),a.fullCalendar.datepickerLang("nb","nb",{closeText:"Lukk",prevText:"«Forrige",nextText:"Neste»",currentText:"I dag",monthNames:["januar","februar","mars","april","mai","juni","juli","august","september","oktober","november","desember"],monthNamesShort:["jan","feb","mar","apr","mai","jun","jul","aug","sep","okt","nov","des"],dayNamesShort:["søn","man","tir","ons","tor","fre","lør"],dayNames:["søndag","mandag","tirsdag","onsdag","torsdag","fredag","lørdag"],dayNamesMin:["sø","ma","ti","on","to","fr","lø"],weekHeader:"Uke",dateFormat:"dd.mm.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("nb",{buttonText:{month:"Måned",week:"Uke",day:"Dag",list:"Agenda"},allDayText:"Hele dagen",eventLimitText:"til"})});!function(a){"function"==typeof define&&define.amd?define(["jquery","moment"],a):a(jQuery,moment)}(function(a,b){function c(a){return 5>a%10&&a%10>1&&~~(a/10)%10!==1}function d(a,b,d){var e=a+" ";switch(d){case"m":return b?"minuta":"minutę";case"mm":return e+(c(a)?"minuty":"minut");case"h":return b?"godzina":"godzinę";case"hh":return e+(c(a)?"godziny":"godzin");case"MM":return e+(c(a)?"miesiące":"miesięcy");case"yy":return e+(c(a)?"lata":"lat")}}var e="styczeń_luty_marzec_kwiecień_maj_czerwiec_lipiec_sierpień_wrzesień_październik_listopad_grudzień".split("_"),f="stycznia_lutego_marca_kwietnia_maja_czerwca_lipca_sierpnia_września_października_listopada_grudnia".split("_");(b.defineLocale||b.lang).call(b,"pl",{months:function(a,b){return/D MMMM/.test(b)?f[a.month()]:e[a.month()]},monthsShort:"sty_lut_mar_kwi_maj_cze_lip_sie_wrz_paź_lis_gru".split("_"),weekdays:"niedziela_poniedziałek_wtorek_środa_czwartek_piątek_sobota".split("_"),weekdaysShort:"nie_pon_wt_śr_czw_pt_sb".split("_"),weekdaysMin:"N_Pn_Wt_Śr_Cz_Pt_So".split("_"),longDateFormat:{LT:"HH:mm",LTS:"LT:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd, D MMMM YYYY LT"},calendar:{sameDay:"[Dziś o] LT",nextDay:"[Jutro o] LT",nextWeek:"[W] dddd [o] LT",lastDay:"[Wczoraj o] LT",lastWeek:function(){switch(this.day()){case 0:return"[W zeszłą niedzielę o] LT";case 3:return"[W zeszłą środę o] LT";case 6:return"[W zeszłą sobotę o] LT";default:return"[W zeszły] dddd [o] LT"}},sameElse:"L"},relativeTime:{future:"za %s",past:"%s temu",s:"kilka sekund",m:d,mm:d,h:d,hh:d,d:"1 dzień",dd:"%d dni",M:"miesiąc",MM:d,y:"rok",yy:d},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}}),a.fullCalendar.datepickerLang("pl","pl",{closeText:"Zamknij",prevText:"<Poprzedni",nextText:"Następny>",currentText:"Dziś",monthNames:["Styczeń","Luty","Marzec","Kwiecień","Maj","Czerwiec","Lipiec","Sierpień","Wrzesień","Październik","Listopad","Grudzień"],monthNamesShort:["Sty","Lu","Mar","Kw","Maj","Cze","Lip","Sie","Wrz","Pa","Lis","Gru"],dayNames:["Niedziela","Poniedziałek","Wtorek","Środa","Czwartek","Piątek","Sobota"],dayNamesShort:["Nie","Pn","Wt","Śr","Czw","Pt","So"],dayNamesMin:["N","Pn","Wt","Śr","Cz","Pt","So"],weekHeader:"Tydz",dateFormat:"dd.mm.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("pl",{buttonText:{month:"Miesiąc",week:"Tydzień",day:"Dzień",list:"Plan dnia"},allDayText:"Cały dzień",eventLimitText:"więcej"})});!function(a){"function"==typeof define&&define.amd?define(["jquery","moment"],a):a(jQuery,moment)}(function(a,b){(b.defineLocale||b.lang).call(b,"pt",{months:"janeiro_fevereiro_março_abril_maio_junho_julho_agosto_setembro_outubro_novembro_dezembro".split("_"),monthsShort:"jan_fev_mar_abr_mai_jun_jul_ago_set_out_nov_dez".split("_"),weekdays:"domingo_segunda-feira_terça-feira_quarta-feira_quinta-feira_sexta-feira_sábado".split("_"),weekdaysShort:"dom_seg_ter_qua_qui_sex_sáb".split("_"),weekdaysMin:"dom_2ª_3ª_4ª_5ª_6ª_sáb".split("_"),longDateFormat:{LT:"HH:mm",LTS:"LT:ss",L:"DD/MM/YYYY",LL:"D [de] MMMM [de] YYYY",LLL:"D [de] MMMM [de] YYYY LT",LLLL:"dddd, D [de] MMMM [de] YYYY LT"},calendar:{sameDay:"[Hoje às] LT",nextDay:"[Amanhã às] LT",nextWeek:"dddd [às] LT",lastDay:"[Ontem às] LT",lastWeek:function(){return 0===this.day()||6===this.day()?"[Último] dddd [às] LT":"[Última] dddd [às] LT"},sameElse:"L"},relativeTime:{future:"em %s",past:"há %s",s:"segundos",m:"um minuto",mm:"%d minutos",h:"uma hora",hh:"%d horas",d:"um dia",dd:"%d dias",M:"um mês",MM:"%d meses",y:"um ano",yy:"%d anos"},ordinalParse:/\d{1,2}º/,ordinal:"%dº",week:{dow:1,doy:4}}),a.fullCalendar.datepickerLang("pt","pt",{closeText:"Fechar",prevText:"Anterior",nextText:"Seguinte",currentText:"Hoje",monthNames:["Janeiro","Fevereiro","Março","Abril","Maio","Junho","Julho","Agosto","Setembro","Outubro","Novembro","Dezembro"],monthNamesShort:["Jan","Fev","Mar","Abr","Mai","Jun","Jul","Ago","Set","Out","Nov","Dez"],dayNames:["Domingo","Segunda-feira","Terça-feira","Quarta-feira","Quinta-feira","Sexta-feira","Sábado"],dayNamesShort:["Dom","Seg","Ter","Qua","Qui","Sex","Sáb"],dayNamesMin:["Dom","Seg","Ter","Qua","Qui","Sex","Sáb"],weekHeader:"Sem",dateFormat:"dd/mm/yy",firstDay:0,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("pt",{buttonText:{month:"Mês",week:"Semana",day:"Dia",list:"Agenda"},allDayText:"Todo o dia",eventLimitText:"mais"})});!function(a){"function"==typeof define&&define.amd?define(["jquery","moment"],a):a(jQuery,moment)}(function(a,b){(b.defineLocale||b.lang).call(b,"pt-br",{months:"janeiro_fevereiro_março_abril_maio_junho_julho_agosto_setembro_outubro_novembro_dezembro".split("_"),monthsShort:"jan_fev_mar_abr_mai_jun_jul_ago_set_out_nov_dez".split("_"),weekdays:"domingo_segunda-feira_terça-feira_quarta-feira_quinta-feira_sexta-feira_sábado".split("_"),weekdaysShort:"dom_seg_ter_qua_qui_sex_sáb".split("_"),weekdaysMin:"dom_2ª_3ª_4ª_5ª_6ª_sáb".split("_"),longDateFormat:{LT:"HH:mm",LTS:"LT:ss",L:"DD/MM/YYYY",LL:"D [de] MMMM [de] YYYY",LLL:"D [de] MMMM [de] YYYY [às] LT",LLLL:"dddd, D [de] MMMM [de] YYYY [às] LT"},calendar:{sameDay:"[Hoje às] LT",nextDay:"[Amanhã às] LT",nextWeek:"dddd [às] LT",lastDay:"[Ontem às] LT",lastWeek:function(){return 0===this.day()||6===this.day()?"[Último] dddd [às] LT":"[Última] dddd [às] LT"},sameElse:"L"},relativeTime:{future:"em %s",past:"%s atrás",s:"segundos",m:"um minuto",mm:"%d minutos",h:"uma hora",hh:"%d horas",d:"um dia",dd:"%d dias",M:"um mês",MM:"%d meses",y:"um ano",yy:"%d anos"},ordinalParse:/\d{1,2}º/,ordinal:"%dº"}),a.fullCalendar.datepickerLang("pt-br","pt-BR",{closeText:"Fechar",prevText:"<Anterior",nextText:"Próximo>",currentText:"Hoje",monthNames:["Janeiro","Fevereiro","Março","Abril","Maio","Junho","Julho","Agosto","Setembro","Outubro","Novembro","Dezembro"],monthNamesShort:["Jan","Fev","Mar","Abr","Mai","Jun","Jul","Ago","Set","Out","Nov","Dez"],dayNames:["Domingo","Segunda-feira","Terça-feira","Quarta-feira","Quinta-feira","Sexta-feira","Sábado"],dayNamesShort:["Dom","Seg","Ter","Qua","Qui","Sex","Sáb"],dayNamesMin:["Dom","Seg","Ter","Qua","Qui","Sex","Sáb"],weekHeader:"Sm",dateFormat:"dd/mm/yy",firstDay:0,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("pt-br",{buttonText:{month:"Mês",week:"Semana",day:"Dia",list:"Compromissos"},allDayText:"dia inteiro",eventLimitText:function(a){return"mais +"+a}})});!function(a){"function"==typeof define&&define.amd?define(["jquery","moment"],a):a(jQuery,moment)}(function(a,b){function c(a,b){var c=a.split("_");return b%10===1&&b%100!==11?c[0]:b%10>=2&&4>=b%10&&(10>b%100||b%100>=20)?c[1]:c[2]}function d(a,b,d){var e={mm:b?"минута_минуты_минут":"минуту_минуты_минут",hh:"час_часа_часов",dd:"день_дня_дней",MM:"месяц_месяца_месяцев",yy:"год_года_лет"};return"m"===d?b?"минута":"минуту":a+" "+c(e[d],+a)}function e(a,b){var c={nominative:"январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь".split("_"),accusative:"января_февраля_марта_апреля_мая_июня_июля_августа_сентября_октября_ноября_декабря".split("_")},d=/D[oD]?(\[[^\[\]]*\]|\s+)+MMMM?/.test(b)?"accusative":"nominative";return c[d][a.month()]}function f(a,b){var c={nominative:"янв_фев_март_апр_май_июнь_июль_авг_сен_окт_ноя_дек".split("_"),accusative:"янв_фев_мар_апр_мая_июня_июля_авг_сен_окт_ноя_дек".split("_")},d=/D[oD]?(\[[^\[\]]*\]|\s+)+MMMM?/.test(b)?"accusative":"nominative";return c[d][a.month()]}function g(a,b){var c={nominative:"воскресенье_понедельник_вторник_среда_четверг_пятница_суббота".split("_"),accusative:"воскресенье_понедельник_вторник_среду_четверг_пятницу_субботу".split("_")},d=/\[ ?[Вв] ?(?:прошлую|следующую|эту)? ?\] ?dddd/.test(b)?"accusative":"nominative";return c[d][a.day()]}(b.defineLocale||b.lang).call(b,"ru",{months:e,monthsShort:f,weekdays:g,weekdaysShort:"вс_пн_вт_ср_чт_пт_сб".split("_"),weekdaysMin:"вс_пн_вт_ср_чт_пт_сб".split("_"),monthsParse:[/^янв/i,/^фев/i,/^мар/i,/^апр/i,/^ма[й|я]/i,/^июн/i,/^июл/i,/^авг/i,/^сен/i,/^окт/i,/^ноя/i,/^дек/i],longDateFormat:{LT:"HH:mm",LTS:"LT:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY г.",LLL:"D MMMM YYYY г., LT",LLLL:"dddd, D MMMM YYYY г., LT"},calendar:{sameDay:"[Сегодня в] LT",nextDay:"[Завтра в] LT",lastDay:"[Вчера в] LT",nextWeek:function(){return 2===this.day()?"[Во] dddd [в] LT":"[В] dddd [в] LT"},lastWeek:function(a){if(a.week()===this.week())return 2===this.day()?"[Во] dddd [в] LT":"[В] dddd [в] LT";switch(this.day()){case 0:return"[В прошлое] dddd [в] LT";case 1:case 2:case 4:return"[В прошлый] dddd [в] LT";case 3:case 5:case 6:return"[В прошлую] dddd [в] LT"}},sameElse:"L"},relativeTime:{future:"через %s",past:"%s назад",s:"несколько секунд",m:d,mm:d,h:"час",hh:d,d:"день",dd:d,M:"месяц",MM:d,y:"год",yy:d},meridiemParse:/ночи|утра|дня|вечера/i,isPM:function(a){return/^(дня|вечера)$/.test(a)},meridiem:function(a,b,c){return 4>a?"ночи":12>a?"утра":17>a?"дня":"вечера"},ordinalParse:/\d{1,2}-(й|го|я)/,ordinal:function(a,b){switch(b){case"M":case"d":case"DDD":return a+"-й";case"D":return a+"-го";case"w":case"W":return a+"-я";default:return a}},week:{dow:1,doy:7}}),a.fullCalendar.datepickerLang("ru","ru",{closeText:"Закрыть",prevText:"<Пред",nextText:"След>",currentText:"Сегодня",monthNames:["Январь","Февраль","Март","Апрель","Май","Июнь","Июль","Август","Сентябрь","Октябрь","Ноябрь","Декабрь"],monthNamesShort:["Янв","Фев","Мар","Апр","Май","Июн","Июл","Авг","Сен","Окт","Ноя","Дек"],dayNames:["воскресенье","понедельник","вторник","среда","четверг","пятница","суббота"],dayNamesShort:["вск","пнд","втр","срд","чтв","птн","сбт"],dayNamesMin:["Вс","Пн","Вт","Ср","Чт","Пт","Сб"],weekHeader:"Нед",dateFormat:"dd.mm.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("ru",{buttonText:{month:"Месяц",week:"Неделя",day:"День",list:"Повестка дня"},allDayText:"Весь день",eventLimitText:function(a){return"+ ещё "+a}})});!function(a){"function"==typeof define&&define.amd?define(["jquery","moment"],a):a(jQuery,moment)}(function(a,b){(b.defineLocale||b.lang).call(b,"sv",{months:"januari_februari_mars_april_maj_juni_juli_augusti_september_oktober_november_december".split("_"),monthsShort:"jan_feb_mar_apr_maj_jun_jul_aug_sep_okt_nov_dec".split("_"),weekdays:"söndag_måndag_tisdag_onsdag_torsdag_fredag_lördag".split("_"),weekdaysShort:"sön_mån_tis_ons_tor_fre_lör".split("_"),weekdaysMin:"sö_må_ti_on_to_fr_lö".split("_"),longDateFormat:{LT:"HH:mm",LTS:"LT:ss",L:"YYYY-MM-DD",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:"[Idag] LT",nextDay:"[Imorgon] LT",lastDay:"[Igår] LT",nextWeek:"dddd LT",lastWeek:"[Förra] dddd[en] LT",sameElse:"L"},relativeTime:{future:"om %s",past:"för %s sedan",s:"några sekunder",m:"en minut",mm:"%d minuter",h:"en timme",hh:"%d timmar",d:"en dag",dd:"%d dagar",M:"en månad",MM:"%d månader",y:"ett år",yy:"%d år"},ordinalParse:/\d{1,2}(e|a)/,ordinal:function(a){var b=a%10,c=1===~~(a%100/10)?"e":1===b?"a":2===b?"a":"e";return a+c},week:{dow:1,doy:4}}),a.fullCalendar.datepickerLang("sv","sv",{closeText:"Stäng",prevText:"«Förra",nextText:"Nästa»",currentText:"Idag",monthNames:["Januari","Februari","Mars","April","Maj","Juni","Juli","Augusti","September","Oktober","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","Maj","Jun","Jul","Aug","Sep","Okt","Nov","Dec"],dayNamesShort:["Sön","Mån","Tis","Ons","Tor","Fre","Lör"],dayNames:["Söndag","Måndag","Tisdag","Onsdag","Torsdag","Fredag","Lördag"],dayNamesMin:["Sö","Må","Ti","On","To","Fr","Lö"],weekHeader:"Ve",dateFormat:"yy-mm-dd",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("sv",{buttonText:{month:"Månad",week:"Vecka",day:"Dag",list:"Program"},allDayText:"Heldag",eventLimitText:"till"})});!function(a){"function"==typeof define&&define.amd?define(["jquery","moment"],a):a(jQuery,moment)}(function(a,b){var c={words:{m:["jedan minut","jedne minute"],mm:["minut","minute","minuta"],h:["jedan sat","jednog sata"],hh:["sat","sata","sati"],dd:["dan","dana","dana"],MM:["mesec","meseca","meseci"],yy:["godina","godine","godina"]},correctGrammaticalCase:function(a,b){return 1===a?b[0]:a>=2&&4>=a?b[1]:b[2]},translate:function(a,b,d){var e=c.words[d];return 1===d.length?b?e[0]:e[1]:a+" "+c.correctGrammaticalCase(a,e)}};(b.defineLocale||b.lang).call(b,"sr",{months:["januar","februar","mart","april","maj","jun","jul","avgust","septembar","oktobar","novembar","decembar"],monthsShort:["jan.","feb.","mar.","apr.","maj","jun","jul","avg.","sep.","okt.","nov.","dec."],weekdays:["nedelja","ponedeljak","utorak","sreda","četvrtak","petak","subota"],weekdaysShort:["ned.","pon.","uto.","sre.","čet.","pet.","sub."],weekdaysMin:["ne","po","ut","sr","če","pe","su"],longDateFormat:{LT:"H:mm",LTS:"LT:ss",L:"DD. MM. YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY LT",LLLL:"dddd, D. MMMM YYYY LT"},calendar:{sameDay:"[danas u] LT",nextDay:"[sutra u] LT",nextWeek:function(){switch(this.day()){case 0:return"[u] [nedelju] [u] LT";case 3:return"[u] [sredu] [u] LT";case 6:return"[u] [subotu] [u] LT";case 1:case 2:case 4:case 5:return"[u] dddd [u] LT"}},lastDay:"[juče u] LT",lastWeek:function(){var a=["[prošle] [nedelje] [u] LT","[prošlog] [ponedeljka] [u] LT","[prošlog] [utorka] [u] LT","[prošle] [srede] [u] LT","[prošlog] [četvrtka] [u] LT","[prošlog] [petka] [u] LT","[prošle] [subote] [u] LT"];return a[this.day()]},sameElse:"L"},relativeTime:{future:"za %s",past:"pre %s",s:"nekoliko sekundi",m:c.translate,mm:c.translate,h:c.translate,hh:c.translate,d:"dan",dd:c.translate,M:"mesec",MM:c.translate,y:"godinu",yy:c.translate},ordinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:7}}),a.fullCalendar.datepickerLang("sr","sr",{closeText:"Затвори",prevText:"<",nextText:">",currentText:"Данас",monthNames:["Јануар","Фебруар","Март","Април","Мај","Јун","Јул","Август","Септембар","Октобар","Новембар","Децембар"],monthNamesShort:["Јан","Феб","Мар","Апр","Мај","Јун","Јул","Авг","Сеп","Окт","Нов","Дец"],dayNames:["Недеља","Понедељак","Уторак","Среда","Четвртак","Петак","Субота"],dayNamesShort:["Нед","Пон","Уто","Сре","Чет","Пет","Суб"],dayNamesMin:["Не","По","Ут","Ср","Че","Пе","Су"],weekHeader:"Сед",dateFormat:"dd.mm.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("sr",{buttonText:{month:"Месец",week:"Недеља",day:"Дан",list:"Планер"},allDayText:"Цео дан",eventLimitText:function(a){return"+ још "+a}})});!function(a){"function"==typeof define&&define.amd?define(["jquery","moment"],a):a(jQuery,moment)}(function(a,b){(b.defineLocale||b.lang).call(b,"th",{months:"มกราคม_กุมภาพันธ์_มีนาคม_เมษายน_พฤษภาคม_มิถุนายน_กรกฎาคม_สิงหาคม_กันยายน_ตุลาคม_พฤศจิกายน_ธันวาคม".split("_"),monthsShort:"มกรา_กุมภา_มีนา_เมษา_พฤษภา_มิถุนา_กรกฎา_สิงหา_กันยา_ตุลา_พฤศจิกา_ธันวา".split("_"),weekdays:"อาทิตย์_จันทร์_อังคาร_พุธ_พฤหัสบดี_ศุกร์_เสาร์".split("_"),weekdaysShort:"อาทิตย์_จันทร์_อังคาร_พุธ_พฤหัส_ศุกร์_เสาร์".split("_"),weekdaysMin:"อา._จ._อ._พ._พฤ._ศ._ส.".split("_"),longDateFormat:{LT:"H นาฬิกา m นาที",LTS:"LT s วินาที",L:"YYYY/MM/DD",LL:"D MMMM YYYY",LLL:"D MMMM YYYY เวลา LT",LLLL:"วันddddที่ D MMMM YYYY เวลา LT"},meridiemParse:/ก่อนเที่ยง|หลังเที่ยง/,isPM:function(a){return"หลังเที่ยง"===a},meridiem:function(a,b,c){return 12>a?"ก่อนเที่ยง":"หลังเที่ยง"},calendar:{sameDay:"[วันนี้ เวลา] LT",nextDay:"[พรุ่งนี้ เวลา] LT",nextWeek:"dddd[หน้า เวลา] LT",lastDay:"[เมื่อวานนี้ เวลา] LT",lastWeek:"[วัน]dddd[ที่แล้ว เวลา] LT",sameElse:"L"},relativeTime:{future:"อีก %s",past:"%sที่แล้ว",s:"ไม่กี่วินาที",m:"1 นาที",mm:"%d นาที",h:"1 ชั่วโมง",hh:"%d ชั่วโมง",d:"1 วัน",dd:"%d วัน",M:"1 เดือน",MM:"%d เดือน",y:"1 ปี",yy:"%d ปี"}}),a.fullCalendar.datepickerLang("th","th",{closeText:"ปิด",prevText:"« ย้อน",nextText:"ถัดไป »",currentText:"วันนี้",monthNames:["มกราคม","กุมภาพันธ์","มีนาคม","เมษายน","พฤษภาคม","มิถุนายน","กรกฎาคม","สิงหาคม","กันยายน","ตุลาคม","พฤศจิกายน","ธันวาคม"],monthNamesShort:["ม.ค.","ก.พ.","มี.ค.","เม.ย.","พ.ค.","มิ.ย.","ก.ค.","ส.ค.","ก.ย.","ต.ค.","พ.ย.","ธ.ค."],dayNames:["อาทิตย์","จันทร์","อังคาร","พุธ","พฤหัสบดี","ศุกร์","เสาร์"],dayNamesShort:["อา.","จ.","อ.","พ.","พฤ.","ศ.","ส."],dayNamesMin:["อา.","จ.","อ.","พ.","พฤ.","ศ.","ส."],weekHeader:"Wk",dateFormat:"dd/mm/yy",firstDay:0,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("th",{buttonText:{month:"เดือน",week:"สัปดาห์",day:"วัน",list:"แผนงาน"},allDayText:"ตลอดวัน",eventLimitText:"เพิ่มเติม"})});!function(a){"function"==typeof define&&define.amd?define(["jquery","moment"],a):a(jQuery,moment)}(function(a,b){var c={1:"'inci",5:"'inci",8:"'inci",70:"'inci",80:"'inci",2:"'nci",7:"'nci",20:"'nci",50:"'nci",3:"'üncü",4:"'üncü",100:"'üncü",6:"'ncı",9:"'uncu",10:"'uncu",30:"'uncu",60:"'ıncı",90:"'ıncı"};(b.defineLocale||b.lang).call(b,"tr",{months:"Ocak_Şubat_Mart_Nisan_Mayıs_Haziran_Temmuz_Ağustos_Eylül_Ekim_Kasım_Aralık".split("_"),monthsShort:"Oca_Şub_Mar_Nis_May_Haz_Tem_Ağu_Eyl_Eki_Kas_Ara".split("_"),weekdays:"Pazar_Pazartesi_Salı_Çarşamba_Perşembe_Cuma_Cumartesi".split("_"),weekdaysShort:"Paz_Pts_Sal_Çar_Per_Cum_Cts".split("_"),weekdaysMin:"Pz_Pt_Sa_Ça_Pe_Cu_Ct".split("_"),longDateFormat:{LT:"HH:mm",LTS:"LT:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd, D MMMM YYYY LT"},calendar:{sameDay:"[bugün saat] LT",nextDay:"[yarın saat] LT",nextWeek:"[haftaya] dddd [saat] LT",lastDay:"[dün] LT",lastWeek:"[geçen hafta] dddd [saat] LT",sameElse:"L"},relativeTime:{future:"%s sonra",past:"%s önce",s:"birkaç saniye",m:"bir dakika",mm:"%d dakika",h:"bir saat",hh:"%d saat",d:"bir gün",dd:"%d gün",M:"bir ay",MM:"%d ay",y:"bir yıl",yy:"%d yıl"},ordinalParse:/\d{1,2}'(inci|nci|üncü|ncı|uncu|ıncı)/,ordinal:function(a){if(0===a)return a+"'ıncı";var b=a%10,d=a%100-b,e=a>=100?100:null;return a+(c[b]||c[d]||c[e])},week:{dow:1,doy:7}}),a.fullCalendar.datepickerLang("tr","tr",{closeText:"kapat",prevText:"<geri",nextText:"ileri>",currentText:"bugün",monthNames:["Ocak","Şubat","Mart","Nisan","Mayıs","Haziran","Temmuz","Ağustos","Eylül","Ekim","Kasım","Aralık"],monthNamesShort:["Oca","Şub","Mar","Nis","May","Haz","Tem","Ağu","Eyl","Eki","Kas","Ara"],dayNames:["Pazar","Pazartesi","Salı","Çarşamba","Perşembe","Cuma","Cumartesi"],dayNamesShort:["Pz","Pt","Sa","Ça","Pe","Cu","Ct"],dayNamesMin:["Pz","Pt","Sa","Ça","Pe","Cu","Ct"],weekHeader:"Hf",dateFormat:"dd.mm.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),a.fullCalendar.lang("tr",{buttonText:{next:"ileri",month:"Ay",week:"Hafta",day:"Gün",list:"Ajanda"},allDayText:"Tüm gün",eventLimitText:"daha fazla"})});!function(a){"function"==typeof define&&define.amd?define(["jquery","moment"],a):a(jQuery,moment)}(function(a,b){(b.defineLocale||b.lang).call(b,"zh-cn",{months:"一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月".split("_"),monthsShort:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),weekdays:"星期日_星期一_星期二_星期三_星期四_星期五_星期六".split("_"),weekdaysShort:"周日_周一_周二_周三_周四_周五_周六".split("_"),weekdaysMin:"日_一_二_三_四_五_六".split("_"),longDateFormat:{LT:"Ah点mm",LTS:"Ah点m分s秒",L:"YYYY-MM-DD",LL:"YYYY年MMMD日",LLL:"YYYY年MMMD日LT",LLLL:"YYYY年MMMD日ddddLT",l:"YYYY-MM-DD",ll:"YYYY年MMMD日",lll:"YYYY年MMMD日LT",llll:"YYYY年MMMD日ddddLT"},meridiemParse:/凌晨|早上|上午|中午|下午|晚上/,meridiemHour:function(a,b){return 12===a&&(a=0),"凌晨"===b||"早上"===b||"上午"===b?a:"下午"===b||"晚上"===b?a+12:a>=11?a:a+12},meridiem:function(a,b,c){var d=100*a+b;return 600>d?"凌晨":900>d?"早上":1130>d?"上午":1230>d?"中午":1800>d?"下午":"晚上"},calendar:{sameDay:function(){return 0===this.minutes()?"[今天]Ah[点整]":"[今天]LT"},nextDay:function(){return 0===this.minutes()?"[明天]Ah[点整]":"[明天]LT"},lastDay:function(){return 0===this.minutes()?"[昨天]Ah[点整]":"[昨天]LT"},nextWeek:function(){var a,c;return a=b().startOf("week"),c=this.unix()-a.unix()>=604800?"[下]":"[本]",0===this.minutes()?c+"dddAh点整":c+"dddAh点mm"},lastWeek:function(){var a,c;return a=b().startOf("week"),c=this.unix()0};u.prototype.open=function(A){var z=this;z.app.dropdown.close();$.get(A,function(B){$("body").prepend('
    '+B+"
    ");z.app.refresh();z.router.dispatch(this.app);z.afterOpen()})};u.prototype.close=function(z){if(this.isOpen()){if(z){z.preventDefault()}$("#popover-container").remove()}};u.prototype.onClick=function(B){B.preventDefault();B.stopPropagation();var A=B.currentTarget||B.target;var z=A.getAttribute("href");if(!z){z=A.getAttribute("data-href")}if(z){this.open(z)}};u.prototype.listen=function(){$(document).on("click",".popover",this.onClick.bind(this));$(document).on("click",".close-popover",this.close.bind(this));$(document).on("click","#popover-container",this.close.bind(this));$(document).on("click","#popover-content",function(z){z.stopPropagation()})};u.prototype.afterOpen=function(){var A=this;var z=$("#popover-content .popover-form");if(z){z.on("submit",function(B){B.preventDefault();$.ajax({type:"POST",url:z.attr("action"),data:z.serialize(),success:function(D,E,C){A.afterSubmit(D,C,A)}})})}$(document).on("click",".popover-link",function(B){B.preventDefault();$.ajax({type:"GET",url:$(this).attr("href"),success:function(D,E,C){A.afterSubmit(D,C,A)}})})};u.prototype.afterSubmit=function(B,A,z){var C=A.getResponseHeader("X-Ajax-Redirect");if(C){window.location=C==="self"?window.location.href.split("#")[0]:C}else{$("#popover-content").html(B);$("#popover-content input[autofocus]").focus();z.afterOpen()}};function s(){}s.prototype.listen=function(){var z=this;$(document).on("click",function(){z.close()});$(document).on("click",".dropdown-menu",function(D){D.preventDefault();D.stopImmediatePropagation();z.close();var B=$(this).next("ul");var E=$(this).offset();$("body").append(jQuery("
    ",{id:"dropdown"}));B.clone().appendTo("#dropdown");var F=$("#dropdown ul");F.addClass("dropdown-submenu-open");var C=F.outerHeight();var A=F.outerWidth();if(E.top+C-$(window).scrollTop()<$(window).height()||$(window).scrollTop()+E.top$(window).width()){F.css("left",E.left-A+$(this).outerWidth())}else{F.css("left",E.left)}});$(document).on("click",".dropdown-submenu-open li",function(A){if($(A.target).is("li")){$(this).find("a:visible")[0].click()}});$("textarea[data-mention-search-url]").textcomplete([{match:/(^|\s)@(\w*)$/,search:function(B,C){var A=$("textarea[data-mention-search-url]").data("mention-search-url");$.getJSON(A,{q:B}).done(function(D){C(D)}).fail(function(){C([])})},replace:function(A){return"$1@"+A+" "},cache:true}],{className:"textarea-dropdown"})};s.prototype.close=function(){$("#dropdown").remove()};function r(z){this.app=z}r.prototype.listen=function(){var z=this;$(".tooltip").tooltip({track:false,show:false,hide:false,position:{my:"left-20 top",at:"center bottom+9",using:function(A,B){$(this).css(A);var C=B.target.left+B.target.width/2-B.element.left-20;$("
    ").addClass("tooltip-arrow").addClass(B.vertical).addClass(C<1?"align-left":"align-right").appendTo(this)}},content:function(){var C=this;var A=$(this).attr("data-href");if(!A){return'
    '+$(this).attr("title")+"
    "}$.get(A,function B(F){var E=$(".ui-tooltip:visible");$(".ui-tooltip-content:visible").html(F);E.css({top:"",left:""});E.children(".tooltip-arrow").remove();var D=$(C).tooltip("option","position");D.of=$(C);E.position(D)});return''}}).on("mouseenter",function(){var A=this;$(this).tooltip("open");$(".ui-tooltip").on("mouseleave",function(){$(A).tooltip("close")})}).on("mouseleave focusout",function(A){A.stopImmediatePropagation();var B=this;setTimeout(function(){if(!$(".ui-tooltip:hover").length){$(B).tooltip("close")}},100)})};function m(){}m.prototype.showPreview=function(D){D.preventDefault();var A=$(".write-area");var C=$(".preview-area");var z=$("textarea");$("#markdown-write").parent().removeClass("form-tab-selected");$("#markdown-preview").parent().addClass("form-tab-selected");var B=$.ajax({url:$("body").data("markdown-preview-url"),contentType:"application/json",type:"POST",processData:false,dataType:"html",data:JSON.stringify({text:z.val()})});B.done(function(E){C.find(".markdown").html(E);C.css("height",z.css("height"));C.css("width",z.css("width"));A.hide();C.show()})};m.prototype.showWriter=function(z){z.preventDefault();$("#markdown-write").parent().addClass("form-tab-selected");$("#markdown-preview").parent().removeClass("form-tab-selected");$(".write-area").show();$(".preview-area").hide()};m.prototype.listen=function(){$(document).on("click","#markdown-preview",this.showPreview.bind(this));$(document).on("click","#markdown-write",this.showWriter.bind(this))};function f(z){this.app=z;this.keyboardShortcuts()}f.prototype.focus=function(){$(document).on("focus","#form-search",function(){if($("#form-search")[0].setSelectionRange){$("#form-search")[0].setSelectionRange($("#form-search").val().length,$("#form-search").val().length)}})};f.prototype.listen=function(){var z=this;$(document).on("click",".filter-helper",function(C){C.preventDefault();var B=$(this).data("filter");var A=$(this).data("append-filter");if(A){B=$("#form-search").val()+" "+A}$("#form-search").val(B);if($("#board").length){z.app.board.reloadFilters(B)}else{$("form.search").submit()}})};f.prototype.keyboardShortcuts=function(){var z=this;Mousetrap.bind("v o",function(B){var A=$(".view-overview");if(A.length){window.location=A.attr("href")}});Mousetrap.bind("v b",function(B){var A=$(".view-board");if(A.length){window.location=A.attr("href")}});Mousetrap.bind("v c",function(B){var A=$(".view-calendar");if(A.length){window.location=A.attr("href")}});Mousetrap.bind("v l",function(B){var A=$(".view-listing");if(A.length){window.location=A.attr("href")}});Mousetrap.bind("v g",function(B){var A=$(".view-gantt");if(A.length){window.location=A.attr("href")}});Mousetrap.bind("f",function(B){B.preventDefault();var A=document.getElementById("form-search");if(A){A.focus()}});Mousetrap.bind("r",function(B){B.preventDefault();var A=$(".filter-reset").data("filter");$("#form-search").val(A);if($("#board").length){z.app.board.reloadFilters(A)}else{$("form.search").submit()}})};function n(){this.board=new k(this);this.markdown=new m();this.search=new f(this);this.swimlane=new g();this.dropdown=new s();this.tooltip=new r(this);this.popover=new u(this);this.task=new a();this.project=new o();this.subtask=new e(this);this.column=new l(this);this.file=new w(this);this.keyboardShortcuts();this.chosen();this.poll();$(".alert-fade-out").delay(4000).fadeOut(800,function(){$(this).remove()});var z=false;$("select.task-reload-project-destination").change(function(){if(!z){$(".loading-icon").show();z=true;window.location=$(this).data("redirect").replace(/PROJECT_ID/g,$(this).val())}})}n.prototype.listen=function(){this.project.listen();this.popover.listen();this.markdown.listen();this.tooltip.listen();this.dropdown.listen();this.search.listen();this.task.listen();this.swimlane.listen();this.subtask.listen();this.column.listen();this.file.listen();this.search.focus();this.autoComplete();this.datePicker();this.focus()};n.prototype.refresh=function(){$(document).off();this.listen()};n.prototype.focus=function(){$("[autofocus]").each(function(z,A){$(this).focus()});$(document).on("focus",".auto-select",function(){$(this).select()});$(document).on("mouseup",".auto-select",function(z){z.preventDefault()})};n.prototype.poll=function(){window.setInterval(this.checkSession,60000)};n.prototype.keyboardShortcuts=function(){var z=this;Mousetrap.bindGlobal("mod+enter",function(){$("form").submit()});Mousetrap.bind("b",function(A){A.preventDefault();$("#board-selector").trigger("chosen:open")});Mousetrap.bindGlobal("esc",function(){z.popover.close();z.dropdown.close()})};n.prototype.checkSession=function(){if(!$(".form-login").length){$.ajax({cache:false,url:$("body").data("status-url"),statusCode:{401:function(){window.location=$("body").data("login-url")}}})}};n.prototype.datePicker=function(){$.datepicker.setDefaults($.datepicker.regional[$("body").data("js-lang")]);$(".form-date").datepicker({showOtherMonths:true,selectOtherMonths:true,dateFormat:"yy-mm-dd",constrainInput:false});$(".form-datetime").datetimepicker({controlType:"select",oneLine:true,dateFormat:"yy-mm-dd",constrainInput:false})};n.prototype.autoComplete=function(){$(".autocomplete").each(function(){var A=$(this);var B=A.data("dst-field");var z=A.data("dst-extra-field");if($("#form-"+B).val()==""){A.parent().find("input[type=submit]").attr("disabled","disabled")}A.autocomplete({source:A.data("search-url"),minLength:1,select:function(C,D){$("input[name="+B+"]").val(D.item.id);if(z){$("input[name="+z+"]").val(D.item[z])}A.parent().find("input[type=submit]").removeAttr("disabled")}})})};n.prototype.chosen=function(){$(".chosen-select").each(function(){var z=$(this).data("search-threshold");if(z===undefined){z=10}$(this).chosen({width:"180px",no_results_text:$(this).data("notfound"),disable_search_threshold:z})});$(".select-auto-redirect").change(function(){var z=new RegExp($(this).data("redirect-regex"),"g");window.location=$(this).data("redirect-url").replace(z,$(this).val())})};n.prototype.showLoadingIcon=function(){$("body").append(' ')};n.prototype.hideLoadingIcon=function(){$("#app-loading-icon").remove()};n.prototype.isVisible=function(){var z="";if(typeof document.hidden!=="undefined"){z="visibilityState"}else{if(typeof document.mozHidden!=="undefined"){z="mozVisibilityState"}else{if(typeof document.msHidden!=="undefined"){z="msVisibilityState"}else{if(typeof document.webkitHidden!=="undefined"){z="webkitVisibilityState"}}}}if(z!=""){return document[z]=="visible"}return true};n.prototype.formatDuration=function(z){if(z>=86400){return Math.round(z/86400)+"d"}else{if(z>=3600){return Math.round(z/3600)+"h"}else{if(z>=60){return Math.round(z/60)+"m"}}}return z+"s"};function d(){this.pasteCatcher=null}d.prototype.execute=function(){this.initialize()};d.prototype.initialize=function(){this.destroy();if(!window.Clipboard){this.pasteCatcher=document.createElement("div");this.pasteCatcher.id="screenshot-pastezone";this.pasteCatcher.contentEditable="true";this.pasteCatcher.style.opacity=0;this.pasteCatcher.style.position="fixed";this.pasteCatcher.style.top=0;this.pasteCatcher.style.right=0;this.pasteCatcher.style.width=0;document.body.insertBefore(this.pasteCatcher,document.body.firstChild);this.pasteCatcher.focus();document.addEventListener("click",this.setFocus.bind(this));document.getElementById("screenshot-zone").addEventListener("click",this.setFocus.bind(this))}window.addEventListener("paste",this.pasteHandler.bind(this))};d.prototype.destroy=function(){if(this.pasteCatcher!=null){document.body.removeChild(this.pasteCatcher)}else{if(document.getElementById("screenshot-pastezone")){document.body.removeChild(document.getElementById("screenshot-pastezone"))}}document.removeEventListener("click",this.setFocus.bind(this));this.pasteCatcher=null};d.prototype.setFocus=function(){if(this.pasteCatcher!==null){this.pasteCatcher.focus()}};d.prototype.pasteHandler=function(E){if(E.clipboardData&&E.clipboardData.items){var C=E.clipboardData.items;if(C){for(var D=0;D0){$("#file-upload-button").prop("disabled",false);$("#file-dropzone-inner").hide();var D=jQuery("